飞道的博客

GateWay 服务网关

320人阅读  评论(0)

介绍

Cloud全家桶中有个很重要的组件就是网关,在1.x版本中都是采用的Zuul网关;但在2.x版本中,zuul的升级一直跳票,SpringCloud最后自己研发了一个网关替代Zuul,那就是SpringCloud Gateway

  • Gateway是在Spring生态系统之上构建的API网关服务

  • Gateway旨在提供一种简单而有效的方式来对API进行路由,以及提供一些强大的过滤器功能,例如:熔断、限流、重试等

  • Gateway是基于WebFlux框架实现的,而WebFlux框架底层则使用了高性能的Reactor模式通信框架Netty

  • Gateway的目标提供统一的路由方式且基于 Filter链的方式提供了网关基本的功能,例如:安全,监控/指标,和限流。

作用

  • 方向代理

  • 鉴权

  • 流量控制

  • 熔断

  • 日志监控

  • ...

非阻塞异步模型

Gateway是基于异步非阻塞模型上进行开发的,性能方面不需要担心,是基于WebFlux框架实现的,WebFlux是一个典型非阻塞异步的框架,它的核心是基于Reactor的相关API实现的。相对于传统的web框架来说,它可以运行在诸如Netty,Undertow及支持Servlet3.1的容器上。非阻塞式+函数式编程(Spring 5必须让你使用Java 8)。

Spring WebFlux是Spring 5.0 引入的新的响应式框架,区别于Spring MVC,它不需要依赖Servlet APl,它是完全异步非阻塞的,并且基于Reactor来实现响应式流规范。

特性

  1. 基于Spring Framework 5,Project Reactor和Spring Boot 2.0进行构建;

  1. 动态路由:能够匹配任何请求属性;

  1. 可以对路由指定Predicate (断言)和Filter(过滤器);

  1. 集成Hystrix的断路器功能;

  1. 集成Spring Cloud 服务发现功能;

  1. 易于编写的Predicate (断言)和Filter(过滤器);

  1. 请求限流功能;

  1. 支持路径重写。

工作流程

  • Route(路由) - 路由是构建网关的基本模块,它由ID,目标URI,一系列的断言和过滤器组成,如断言为true则匹配该路由;

  • Predicate(断言) - 参考的是Java8的java.util.function.Predicate,开发人员可以匹配HTTP请求中的所有内容(例如请求头或请求参数),如果请求与断言相匹配则进行路由;

  • Filter(过滤) - 指的是Spring框架中GatewayFilter的实例,使用过滤器,可以在请求被路由前或者之后对请求进行修改。

web请求,通过一些匹配条件,定位到真正的服务节点。并在这个转发过程的前后,进行一些精细化控制。predicate就是我们的匹配条件;而fliter,就可以理解为一个无所不能的拦截器。有了这两个元素,再加上目标uri,就可以实现一个具体的路由了

官方文档:https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.2.1.RELEASE/reference/html/#gateway-how-it-works

  1. 客户端向Spring Cloud Gateway发出请求。然后在Gateway Handler Mapping 中找到与请求相匹配的路由,将其发送到GatewayWeb Handler。

  1. Handler再通过指定的过滤器链来将请求发送到我们实际的服务执行业务逻辑,然后返回。

  1. 过滤器之间用虚线分开是因为过滤器可能会在发送代理请求之前(“pre”)或之后(“post")执行业务逻辑。

  1. Filter在“pre”类型的过滤器可以做参数校验、权限校验、流量监控、日志输出、协议转换等,在“post”类型的过滤器中可以做响应内容、响应头的修改,日志的输出,流量监控等有着非常重要的作用。

核心逻辑:路由转发 + 执行过滤器链。

入门使用

依赖


   
  1. <!--gateway-->
  2. <dependency>
  3.     <groupId>org.springframework.cloud </groupId>
  4.     <artifactId>spring-cloud-starter-gateway </artifactId>
  5. </dependency>

YML


   
  1. server:
  2. port: 9127
  3. spring:
  4. application:
  5. name: cloud-gateway
  6. #############################网关配置###########################
  7. cloud:
  8. gateway:
  9. routes:
  10. - id: payment_routh #payment_route #路由的ID,没有固定规则但要求唯一,建议配合服务名
  11. uri: http://localhost:8001 #匹配后提供服务的路由地址
  12. #uri: lb://cloud-payment-service #匹配后提供服务的路由地址
  13. predicates:
  14. - Path=/payment/get/** # 断言,路径相匹配的进行路由
  15. - id: payment_routh2 #payment_route #路由的ID,没有固定规则但要求唯一,建议配合服务名
  16. uri: http://localhost:8001 #匹配后提供服务的路由地址
  17. #uri: lb://cloud-payment-service #匹配后提供服务的路由地址
  18. predicates:
  19. - Path=/payment/lb/** # 断言,路径相匹配的进行路由
  20. ####################################################################

添加网关后,直接访问网关所在地址会路由到具体服务

配置路由的两种方式

  • YML配置文件配置路由


   
  1. spring:
  2. application:
  3. name: cloud-gateway-gateway
  4. cloud:
  5. gateway:
  6. routes:
  7. # 路由的ID,没有固定规则,但要求唯一,建议配合服务名
  8. - id: payment_routh
  9. # 匹配后提供服务的路由地址
  10. uri: http://localhost:8001
  11. # 断言,路径相匹配的进行路由
  12. predicates:
  13. - Path=/payment/get/**
根据指定的路径,进行转发
  • 通过配置类来配置路由


   
  1. @Configuration
  2. public class GateWayConfig {
  3. @Bean
  4. public RouteLocator customRouteLocator (RouteLocatorBuilder routeLocatorBuilder){
  5. RouteLocatorBuilder. Builder routes = routeLocatorBuilder.routes();
  6. routes.route( "path_route_frx01",
  7. r -> r.path( "/guonei")
  8. .uri( "http://xxx/xxx")).build();
  9. return routes.build();
  10. }
  11. }
代码中注入RouteLocator的Bean

GateWay配置动态路由

默认情况下Gateway会根据注册中心注册的服务列表,以注册中心上微服务名为路径创建动态路由进行转发,从而实现动态路由的功能(不写死一个地址)。


   
  1. server:
  2. port: 9127
  3. spring:
  4. application:
  5. name: cloud-gateway
  6. #############################网关配置###########################
  7. cloud:
  8. gateway:
  9. discovery:
  10. locator:
  11. enabled: true #开启从注册中心动态创建路由的功能,利用微服务名进行路由
  12. routes:
  13. - id: payment_routh #payment_route #路由的ID,没有固定规则但要求唯一,建议配合服务名
  14. #uri: http://localhost:8001 #匹配后提供服务的路由地址
  15. uri: lb://cloud-payment-service #匹配后提供服务的路由地址
  16. predicates:
  17. - Path=/payment/get/** # 断言,路径相匹配的进行路由
  18. - id: payment_routh2 #payment_route #路由的ID,没有固定规则但要求唯一,建议配合服务名
  19. #uri: http://localhost:8001 #匹配后提供服务的路由地址
  20. uri: lb://cloud-payment-service #匹配后提供服务的路由地址
  21. predicates:
  22. - Path=/payment/lb/** # 断言,路径相匹配的进行路由
  23. ####################################################################
需要注意的是uri的协议为lb,表示启用Gateway的负载均衡功能。
lb://serviceName是spring cloud gateway在微服务中自动为我们创建的负载均衡uri。

常用的Predicate

Spring Cloud Gateway将路由匹配作为Spring WebFlux HandlerMapping基础架构的一部分。Spring Cloud Gateway包括许多内置的Route Predicate工厂。所有这些Predicate都与HTTP请求的不同属性匹配。多个RoutePredicate工厂可以进行组合。

常用的Route Predicate Factory

  • The After Route Predicate Factory


   
  1. spring:
  2. cloud:
  3. gateway:
  4. routes:
  5. - id: after_route
  6. uri: https://example.org
  7. predicates:
  8. # 这个时间后才能起效
  9. - After=2023-01-20T17:42:47.789-07:00[America/Denver]

可以通过下述方法获得上述格式的时间戳字符串


   
  1. import java.time.ZonedDateTime;
  2. public class T2
  3. {
  4. public static void main (String[] args)
  5. {
  6. ZonedDateTime zbj = ZonedDateTime.now(); // 默认时区
  7. System.out.println(zbj);
  8. //2022-08-20T21:02:40.570+08:00[Asia/Shanghai]
  9. }
  10. }
  • The Before Route Predicate Factory

  • The Between Route Predicate Factory


   
  1. spring:
  2. cloud:
  3. gateway:
  4. routes:
  5. - id: between_route
  6. uri: https://example.org
  7. # 两个时间点之间
  8. predicates:
  9. - Between=2023-01-20T17:42:47.789-07:00[America/Denver], 2017-01-21T17:42:47.789-07:00[America/Denver]
  • The Cookie Route Predicate Factory


   
  1. spring:
  2. cloud:
  3. gateway:
  4. routes:
  5. - id: cookie_route
  6. uri: http://localhost:8001
  7. predicates:
  8. - Cookie=chocolate, ch.p

   
  1. # 该命令相当于发get请求,且没带cookie
  2. curl http://localhost:9127/payment/lb
  3. # 带cookie的
  4. curl http://localhost:9127/payment/lb --cookie "chocolate=chip"
  • The Header Route Predicate Factory


   
  1. spring:
  2. cloud:
  3. gateway:
  4. routes:
  5. - id: header_route
  6. uri: http://localhost:8001
  7. predicates:
  8. - Header=X-Request-Id, \d+

   
  1. # 带指定请求头的参数的CURL命令
  2. curl http://localhost:9527/payment/lb -H "X-Request-Id:123"
  • The Host Route Predicate Factory

  • The Method Route Predicate Factory

  • The Path Route Predicate Factory

  • The Query Route Predicate Factory

  • The RemoteAddr Route Predicate Factory

  • The weight Route Predicate Factory

说白了,Predicate就是为了实现一组匹配规则,让请求过来找到对应的Route进行处理。

GateWay的Filter

路由过滤器可用于修改进入的HTTP请求和返回的HTTP响应,路由过滤器只能指定路由进行使用。Spring Cloud Gateway内置了多种路由过滤器,他们都由GatewayFilter的工厂类来产生。

生命周期

  • pre

  • post

种类

  • GatewayFilter - 有31种

  • 常用的GatewayFilter:AddRequestParameter GatewayFilter

  • GlobalFilter - 有10种

主要接口

  • GlobalFilter

  • Ordered

作用

  • 全局日志记录

  • 统一网关鉴权


   
  1. @Component
  2. @Slf4j
  3. public class MyLogGateWayFilter implements GlobalFilter, Ordered {
  4. @Override
  5. public Mono<Void> filter (ServerWebExchange exchange, GatewayFilterChain chain) {
  6. log.info( "***********come in MyLogGateWayFilter: "+ new Date());
  7. String name = exchange.getRequest().getQueryParams().getFirst( "uname");
  8. if(name== null){
  9. log.info( "*******用户名为null,非法用户,o(╥﹏╥)o");
  10. exchange.getResponse().setRawStatusCode(HttpStatus.HTTP_NOT_ACCEPTABLE);
  11. return exchange.getResponse().setComplete();
  12. }
  13. return chain.filter(exchange);
  14. }
  15. @Override
  16. public int getOrder () {
  17. return 0;
  18. }
  19. }


转载:https://blog.csdn.net/zhiwenganyong/article/details/128770409
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场