网关设计

Spring cloud gateway 👉 webflux 👉 project reactor 👉 netty 👉 epoll

上述流程图指出Spring cloud gateway关键技术依赖。

webflux基于 spring 5.x 和 reactor-netty 构建,不依赖于 Servlet 容器,但是可以在支持 Servlet 3.1 Non-Blocking IO API 的容器上运行。

webflux

  • Spring WebFlux是基于响应式流的,因此可以用来建立异步的、非阻塞的、事件驱动的服务。它采用Reactor作为首选的响应式流的实现库,不过也提供了对RxJava的支持。

  • 由于响应式编程的特性,Spring WebFlux和Reactor底层需要支持异步的运行环境,比如Netty和Undertow;也可以运行在支持异步I/O的Servlet 3.1的容器之上,比如Tomcat(8.0.23及以上)和Jetty(9.0.4及以上)。

  • 从图的纵向上看,spring-webflux上层支持两种开发模式:

    1. 类似于Spring WebMVC的基于注解(@Controller、@RequestMapping)的开发模式;

    2. Java 8 lambda 风格的函数式开发模式。

  • Spring WebFlux也支持响应式的Websocket服务端开发。

webflux2

限流

自带RequestRateLimiter

sentinel提供了适配器:sentinel-spring-cloud-gateway-adapter

熔断降级

引入 spring-cloud-starter-netflix-hystrix 即可

熔断:当HystrixCommand请求后端服务失败数量超过一定比例(默认50%), 断路器会切换到开路状态(Open). 这时所有请求会直接失败而不会发送到后端服务,断路器保持在开路状态一段时间后(默认5秒),自动切换到半开路状态(HALF-OPEN),这时会判断下一次请求的返回情况, 如果请求成功, 断路器切回闭路状态(CLOSED),否则重新切换到开路状态(OPEN)

降级:服务降级是指当请求后端服务出现异常的时候, 可以使用fallback方法返回的值

4种错误情况将触发fallback:

  1. 非HystrixBadRequestException异常
  2. run()/construct()运行超时
  3. 熔断器启动
  4. 线程池/信号量已满

使用hystrix的几种方式:

因为hystrix 已经停止维护, gateway3.x 版本后移除了HystrixGatewayFilterFactory,官方推荐使用Resilience4J 替代

  • 引入 hystrix-core 包后,通过注解 @HystrixCommand(fallbackMethod = "指定fallback方法") 使用。 👉🏿 使用详情
  • 因为 Feign 整合了 hystrix,因此如果你使用了Feign,通过注解 @FeignClient(value = "service-hi",fallback = 指定Fallback类) 使用。 👉🏿 使用详情

缓存

hystrix

业务隔离

通过hystrix做隔离

隔离:将请求封装在HystrixCommand中,然后这些请求在一个独立的线程中执行,每个依赖服务维护一个小的线程池(或信号量),在调用失败或超时的情况下可以断开依赖调用或者返回指定逻辑

  • 不同服务通过使用不同线程池,彼此间将不受影响,达到隔离效果。
  • 隔离本地代码或可快速返回远程调用(如memcached,redis)可以直接使用信号量隔离,降低线程隔离开销.

总结:command group一般来说,可以是对应一个服务,多个command key对应这个服务的多个接口,多个接口的调用共享同一个线程池。如果说你的command key,要用自己的线程池,可以定义自己的threadpool key,就ok了

合并请求

Spring Cloud Hystrix的请求合并

负载均衡

ribbon

feign集成了ribbon

负载均衡有好几种实现策略,常见的有:

  1. 随机 (Random)
  2. 轮询 (RoundRobin)
  3. 一致性哈希 (ConsistentHash)
  4. 哈希 (Hash)
  5. 加权(Weighted)

ribbon所有的负载均衡策略均实现IRule接口,可以自定义

系统提供了几种策略:

内置负载均衡规则类 规则描述
RoundRobinRule 简单轮询服务列表来选择服务器。它是Ribbon默认的负载均衡规则。
AvailabilityFilteringRule 对以下两种服务器进行忽略:
(1)在默认情况下,这台服务器如果3次连接失败,这台服务器就会被设置为“短路”状态。短路状态将持续30秒,如果再次连接失败,短路的持续时间就会几何级地增加。
注意:可以通过修改配置loadbalancer.<clientName>.connectionFailureCountThreshold来修改连接失败多少次之后被设置为短路状态。默认是3次。
(2)并发数过高的服务器。如果一个服务器的并发连接数过高,配置了AvailabilityFilteringRule规则的客户端也会将其忽略。并发连接数的上线,可以由客户端的<clientName>.<clientConfigNameSpace>.ActiveConnectionsLimit属性进行配置
WeightedResponseTimeRule 为每一个服务器赋予一个权重值。服务器响应时间越长,这个服务器的权重就越小。这个规则会随机选择服务器,这个权重值会影响服务器的选择。
ZoneAvoidanceRule 以区域可用的服务器为基础进行服务器的选择。使用Zone对服务器进行分类,这个Zone可以理解为一个机房、一个机架等。
BestAvailableRule 忽略那些短路的服务器,并选择并发数较低的服务器。
RandomRule 随机选择一个可用的服务器。
Retry 重试机制的选择逻辑

适配注册中心

Eureka、Zookeeper、Nacos以及Consul都已经集成好了。

形如 http://abc.com/服务名/xxx 的请求会被转发到对应的服务

认证

动态发布

在这里插入图片描述

有两种实现思路:

  1. 先更新RouteDefinition再更新Route
  2. 直接更新Route

Spring cloud gateway本身提供了动态修改配置的endpoint,使用的是第一种方式。

外接配置中心,使用第一种方式:

  1. 注册一个监听器(@ApolloConfigChangeListener)
  2. 将监听事件反序列成RouteDefinition

RouteDefinition 👉🏿 Route 👉🏿 更新Route

  1. 调用RouteDefinitionWriter的add delete方法(更新内存中的RouteDefinition)
  2. RouteDefinitionRouteLocator将RouteDefinition转成Route,并实现了RouteLocator接口的getRoutes方法。
  3. 发起RefreshRoutesEvent事件(更新内存中的Route)

用数据库,使用第二种方式:

Spring Cloud Gateway Dynamic Routes from Database

数据库配置 👉🏿 Route 👉🏿 更新Route

  1. 暴露接口,更新数据库的配置
  2. 自定义一个RouteLocator,实现getRoutes方法(去数据库拿路由配置)
  3. 发起RefreshRoutesEvent事件(更新内存中的Route)

与通过RouteLocatorBuilder构造RouteLocator原理一致

CachingRouteLocator和CachingRouteDefinitionLocator都会监听RefreshRoutesEvent事件

聚合接口(服务编排)

日志

泛化调用

安全

Websocket

参考

Hystrix使用入门手册(中文)

浅析如何设计一个亿级网关

百亿流量API网关的设计与实现

SpringCloud gateway (史上最全)

(5)Spring WebFlux快速上手——响应式Spring的道法术器

API网关基石:泛化调用

基于 Hystrix 信号量机制实现资源隔离

Hystrix信号量模式支持超时时间吗

版权

评论