本地搭建SpringCloud Demo引入API Gateway模块,记录一些SpringCloud Gateway相关的知识。
一、Gateway
首先看一下Spring官网的微服务架构图:
可以看待网关位于所有服务的上层,所有服务的调用都需要经过网关。
Gateway旨在提供一种简单而有效的方式来对API进行路由,以及提供一些强大的过滤器功能,例如:熔断、限流、重试等。
Spring Cloud Gateway是基于异步非阻塞模型上进行开发,性能优秀,且具有动态路由、对路由指定Predicate和Filter、集成Hystrix的断路器功能、集成SpringCloud服务发现、请求限流、支持路由重写等特性。
Zuul 1.x以及过时,且其基于阻塞I/O实现,性能较差,Zuul 2.x咕咕咕,且没有和SpringCloud进行整合…
二、Spring Cloud Gateway
官方文档:https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/
网关的工作流程如下:
Clients make requests to Spring Cloud Gateway. If the Gateway Handler Mapping determines that a request matches a route, it is sent to the Gateway Web Handler. This handler runs the request through a filter chain that is specific to the request. The reason the filters are divided by the dotted line is that filters can run logic both before and after the proxy request is sent. All “pre” filter logic is executed. Then the proxy request is made. After the proxy request is made, the “post” filter logic is run.
首先客户端向网关发请求,网关根据路由映射匹配相应的路由,然后发给Gateway Web Handler,其通过指定的过滤器链将请求发到实际的服务执行逻辑,最后返回。其中的Filter过滤器可以在之前或之后执行,如pre
过滤器可以进行参数校验、权限校验、流量监控、日志输出、协议转换等,post
过滤器可以响应内容、响应头的修改,日志的输出,流量监控 等。
三、本地基础配置
路由的配置有两种方法,yml文件或者config配置类,下面是yml配置的方式:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 spring: application: name: cloud-gateway cloud: gateway: discovery: locator: enabled: true routes: - id: payment_route uri: lb://cloud-payment-service predicates: - Path=/payment/get/** - id: payment_route2 uri: lb://cloud-payment-service predicates: - Path=/payment/lb/**
根据微服务的名称cloud-payment-service进行动态路由,通过这种方式可以实现对服务的负载均衡,如下图可以看到轮询访问8001和8002服务。
四、网关熔断和限流
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 spring: application: name: cloud-gateway cloud: gateway: discovery: locator: enabled: true lower-case-service-id: true routes: - id: payment_route uri: lb://cloud-provider-hystrix-payment predicates: - Path=/payment/hystrix/ok/**, /payment/hystrix/timeout/**, /payment/hystrix/error/ filters: - name: Retry args: retries: 3 series: SERVER_ERROR methods: GET,POST - name: Hystrix args: name: localfallback fallbackUri: forward:/gateway/defaultfallback - name: RequestRateLimiter args: key-resolver: '#{@remoteAddrKeyResolver}' redis-rate-limiter.replenishRate: 1 redis-rate-limiter.burstCapacity: 3 redis-rate-limiter.requestedTokens: 1 redis: host: localhost port: 6379 database: 0
在本地添加对网关的熔断和限流。熔断使用的仍然是Hystrix,当下游服务宕机时,调用同一定义的处理逻辑defaultfallback。
1 2 3 4 5 6 7 8 @RestController public class FallbackController { @GetMapping(value = "/gateway/defaultfallback") public String defaultFallback () { return "defaultFallback:路由熔断......." ; } }
网关的限流采用的Redis的令牌桶,并定义了用于限流的键的解析器:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 @Component @Slf4j public class RemoteAddrKeyResolver implements KeyResolver { @Override public Mono<String> resolve (ServerWebExchange exchange) { String hostAddress = exchange.getRequest().getRemoteAddress().getAddress().getHostAddress(); log.info("hostAddress = " + hostAddress); String uriPath = exchange.getRequest().getURI().getPath(); log.info("uriPath = " + uriPath); return Mono.just(hostAddress); } }
我们用Apifox做个简单的测试,两个线程循环调用http://localhost:9527/payment/hystrix/ok/1
这个地址,结果如下,可以看到部分调用由于访问频繁被限流,其状态码对应为429。