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 的容器上运行。
-
Spring WebFlux是基于响应式流的,因此可以用来建立异步的、非阻塞的、事件驱动的服务。它采用Reactor作为首选的响应式流的实现库,不过也提供了对RxJava的支持。
-
由于响应式编程的特性,Spring WebFlux和Reactor底层需要支持异步的运行环境,比如Netty和Undertow;也可以运行在支持异步I/O的Servlet 3.1的容器之上,比如Tomcat(8.0.23及以上)和Jetty(9.0.4及以上)。
-
从图的纵向上看,spring-webflux上层支持两种开发模式:
-
类似于Spring WebMVC的基于注解(@Controller、@RequestMapping)的开发模式;
-
Java 8 lambda 风格的函数式开发模式。
-
-
Spring WebFlux也支持响应式的Websocket服务端开发。
限流
自带RequestRateLimiter
sentinel提供了适配器:sentinel-spring-cloud-gateway-adapter
熔断降级
引入 spring-cloud-starter-netflix-hystrix
即可
熔断:当HystrixCommand请求后端服务失败数量超过一定比例(默认50%), 断路器会切换到开路状态(Open). 这时所有请求会直接失败而不会发送到后端服务,断路器保持在开路状态一段时间后(默认5秒),自动切换到半开路状态(HALF-OPEN),这时会判断下一次请求的返回情况, 如果请求成功, 断路器切回闭路状态(CLOSED),否则重新切换到开路状态(OPEN)
降级:服务降级是指当请求后端服务出现异常的时候, 可以使用fallback方法返回的值
4种错误情况将触发fallback:
- 非HystrixBadRequestException异常
run()/construct()
运行超时- 熔断器启动
- 线程池/信号量已满
使用hystrix的几种方式:
spring-cloud-gateway-core
默认提供了一个HystrixGatewayFilterFactory
过滤器工厂,因此gateway
可以通过配置application.yml
的方式使用hystrix熔断器。
因为
hystrix
已经停止维护,gateway
在3.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了
合并请求
负载均衡
ribbon
feign集成了ribbon
负载均衡有好几种实现策略,常见的有:
- 随机 (Random)
- 轮询 (RoundRobin)
- 一致性哈希 (ConsistentHash)
- 哈希 (Hash)
- 加权(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
的请求会被转发到对应的服务
认证
动态发布
有两种实现思路:
- 先更新RouteDefinition再更新Route
- 直接更新Route
Spring cloud gateway本身提供了动态修改配置的endpoint,使用的是第一种方式。
外接配置中心,使用第一种方式:
- 注册一个监听器(@ApolloConfigChangeListener)
- 将监听事件反序列成RouteDefinition
RouteDefinition 👉🏿 Route 👉🏿 更新Route
- 调用RouteDefinitionWriter的add delete方法(更新内存中的RouteDefinition)
- RouteDefinitionRouteLocator将RouteDefinition转成Route,并实现了RouteLocator接口的getRoutes方法。
- 发起RefreshRoutesEvent事件(更新内存中的Route)
用数据库,使用第二种方式:
Spring Cloud Gateway Dynamic Routes from Database
数据库配置 👉🏿 Route 👉🏿 更新Route
- 暴露接口,更新数据库的配置
- 自定义一个RouteLocator,实现getRoutes方法(去数据库拿路由配置)
- 发起RefreshRoutesEvent事件(更新内存中的Route)
与通过RouteLocatorBuilder构造RouteLocator原理一致
CachingRouteLocator和CachingRouteDefinitionLocator都会监听RefreshRoutesEvent事件
评论