网关Spring Cloud Gateway的配置和使用

 2023-09-15 阅读 17 评论 0

摘要:文章目录1. 什么是Spring Cloud Gateway?2. Gateway与zuul的区别3. Gateway的配置和使用①:常用的路由断言工厂②:常用的过滤器工厂(GatewayFilters)③:全局过滤器配置(Global Filters)4. 网关高可用解决方案 1. 什

文章目录

    • 1. 什么是Spring Cloud Gateway?
    • 2. Gateway与zuul的区别
    • 3. Gateway的配置和使用
      • ①:常用的路由断言工厂
      • ②:常用的过滤器工厂(GatewayFilters)
      • ③:全局过滤器配置(Global Filters)
    • 4. 网关高可用解决方案

1. 什么是Spring Cloud Gateway?

       Spring Cloud Gateway 是 Spring Cloud官方推出的第二代网关框架,定位于取代 Netflix Zuul。相比 Zuul 来说,Spring Cloud Gateway 提供更优秀的性能,更强大的有功能。

配置网关,       Spring Cloud Gateway是由 WebFlux + Netty + Reactor 实现的响应式的 API 网关。它不能在传统的 servlet 容器中工作,也不能构建成 war 包。

Gateway 的核心概念如下:

  • 路由(route) :
    • 路由是网关中最基础的部分,路由信息包括一个ID、一个目的URI、一组断言工厂、一组Filter组成。如果断言为真,则说明请求的URL和配置的路由匹配。
  • 断言(predicates) :
    • Java8中的断言函数,允许开发者去定义匹配Http request中的任何信息,比如请求头和参数等。
  • 过滤器(Filter)
    • SpringCloud Gateway中的filter分为Gateway FilIerGlobal Filter。Filter可以对请求和响应进行处理。

       路由route是想要访问的目标地址,断言predicates是匹配请求中的一些信息,满足条件才允许访问目标地址,而Gateway FilIer网关过滤器可以为请求做某些扩展,比如添加一些请求头、请求参数等等,但Gateway FilIer只能作用于对应路由下的请求!

       而GlobalFilter 全局过滤器和 GatewayFilter 网关过滤器虽然有一样的接口定义,只不过, GlobalFilter 会作用于所有路由。

网关怎么设置才能上网、       
Gateway 的工作原理如下:

在这里插入图片描述
其实Gateway对请求的处理与spring mvc的处理差不多!也是一套流程下来的

框架Gatewayspring mvc
请求分发DispatcherHandlerDispatcherServlet
请求映射HandlerMappingHandlerMapping
请求适配HanderAdaperHanderAdaper
请求处理WebHanderHander

       

2. Gateway与zuul的区别

       Spring Cloud Gateway是Spring Cloud 的一个子项目。而zuul则是netflix公司的项目,只是spring将zuul集成在 Spring Cloud 中使用而已。因为zuul2.0连续跳票和zuul1.0的性能表现不是很理想,所以催生了spring团队开发了Gateway项目。

网关地址一般是多少,Zuul:

  • 使用的是阻塞式的 API,不支持长连接,比如 websockets
  • 底层是servlet,Zuul处理的是http请求
  • 没有提供异步支持,流控等均由hystrix支持。
  • 依赖包spring-cloud-starter-netflix-zuul

Gateway:

  • Spring Boot和Spring Webflux提供的Netty底层环境,不能和传统的Servlet容器一起使用,也不能打包成一个war包。
  • 依赖spring-boot-starter-webfluxspring-cloud-starter-gateway
  • 提供了异步支持,提供了抽象负载均衡,提供了抽象流控,并默认实现了RedisRateLimiter

相同点:

  • 底层都是servlet
  • 两者均是web网关

不同点:

  • win10以太网没有ip配置、适用性

    • gateway 对比 zuul 多依赖了spring-webflux,在spring的支持下,功能更强大,内部实现了限流、负载均衡等,扩展性也更强,但同时也限制了仅适合于Spring Cloud套件
    • zuul则可以扩展至其他微服务框架中,其内部没有实现限流、负载均衡等。
  • 是否支持异步

    • zuul仅支持同步
    • gateway支持异步。理论上gateway则更适合于提高系统吞吐量(但不一定能有更好的性能),最终性能还需要通过严密的压测来决定
  • 框架设计的角度

    • gateway具有更好的扩展性,并且其已经发布了2.0.0的RELESE版本,稳定性也是非常好的
  • 性能

    • gateway是基于spring-webflux的响应式、非阻塞编程,且支持异步,底层通过netty通信,性能较高。与Spring紧密集成,所以将会是一个更好的开发体验。
    • Zuul 1.x,是一个基于阻塞io的API Gateway。Zuul已经发布了Zuul 2.x,基于Netty,也是非阻塞的,支持长连接,但Spring Cloud暂时还没有整合计划。

没有有效的ip配置,       

3. Gateway的配置和使用

  • ①:引入依赖
    注意:由于Gateway不能在传统的 servlet 容器中工作,也不能构建成 war 包,会和spring-webmvc的依赖冲突,所以不能引入 web 环境依赖
   <properties><java.version>1.8</java.version><spring-cloud.version>Hoxton.SR8</spring-cloud.version><spring-cloud-alibaba.version>2.2.5.RELEASE</spring-cloud-alibaba.version></properties><dependencyManagement><dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-dependencies</artifactId><version>${spring-cloud.version}</version><type>pom</type><scope>import</scope></dependency><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-alibaba-dependencies</artifactId><version>${spring-cloud-alibaba.version}</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><!-- gateway网关 --><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId></dependency><!-- nacos服务注册与发现 --><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency>
  • ②:编写yml配置文件
spring:application:name: mall-gateway# 配置nacos注册中心地址cloud:nacos:discovery:server-addr: 127.0.0.1:8848gateway:discovery:locator:# 默认为false,设为true开启通过微服务创建路由的功能,即可以通过微服务名访问服务# http://localhost:8888/mall-order/order/findOrderByUserId/1enabled: false# 是否开启网关enabled: true# 网关配置跨域globalcors:cors-configurations:'[/**]':allowedOrigins: "*"allowedMethods:- GET- POST- DELETE- PUT- OPTION# 设置路由:路由id、路由到微服务的uri、断言routes:- id: order_route  #路由ID,全局唯一,建议配合服务名
#       # uri: http://localhost:8020  #目标微服务的请求地址和端口uri: lb://mall-order  #lb 整合负载均衡器ribbon,loadbalancerpredicates:
#        # Path路径匹配- Path=/order/**# 测试 http://localhost:8888/order/findOrderByUserId/1# 匹配在指定的日期时间之后发生的请求  入参是ZonedDateTime类型- After=2021-05-16T20:50:57.511+08:00[Asia/Shanghai]# Cookie匹配- Cookie=username, fox# Header匹配  请求中带有请求头名为 x-request-id,其值与 \d+ 正则表达式匹配- Header=X-Request-Id, \d+#自定义CheckAuth断言工厂- name: CheckAuthargs:name: fox- CheckAuth=abc#配置过滤器工厂filters:- AddRequestHeader=X-Request-color, red  #添加请求头- AddRequestParameter=color, blue   # 添加请求参数- PrefixPath=/mall-order  # 添加前缀 对应微服务需要配置context-path#- RedirectTo=302, http://baidu.com  #重定向到百度- CheckAuth=aaa,  #配置自定义的过滤器工厂- id: user_routeuri: lb://mall-user  #lb 整合负载均衡器ribbon,loadbalancerpredicates:- Path=/user/**

启动应用!配置即可生效

       

①:常用的路由断言工厂

       更多路由断言工厂请参考spring官网 https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#gateway-request-predicates-factories,下面仅列出几种常用的断言类型!

  • 设置网关?时间匹配:可以用在限时抢购的一些场景中。

     # 匹配在指定的日期时间之后发生的请求  入参是ZonedDateTime类型        - After=2021-01-31T22:22:07.783+08:00[Asia/Shanghai]
    

    其中 获取ZonedDateTime类型的指定日期时间代码如下:

    ZonedDateTime zonedDateTime = ZonedDateTime.now();//默认时区
    // 用指定时区获取当前时间
    ZonedDateTime zonedDateTime2 = ZonedDateTime.now(ZoneId.of("Asia/Shanghai"));
    
  • Cookie匹配:请求头必须加上 Cookie :aaa,否则请求失败!

    # Cookie匹配        
    - Cookie=username, aaa
    
  • Header匹配:请求头必须加上 X-Request-Id:2(整数),否则请求失败!

     # Header匹配  请求中带有请求头名为 x-request-id,其值与 \d+ 正则表达式匹配        - Header=X-Request-Id, \d+
    
  • 路径匹配:只有是 order/** 的请求,才能通过断言

    # 测试:http://localhost:8888/order/findOrderByUserId/1        
    - Path=/order/**   #Path路径匹配
    
  • 自定义路由断言工厂
    上面所有的断言配置都继承自AbstractPredicateFactory抽象工厂,如下所示:
    在这里插入图片描述
           所以当我们有个性化需求需要自定义自定义路由断言工厂时,也可参照上述配置进行定制,需要继承 AbstractRoutePredicateFactory 类,重写 apply 方法的逻辑。在 apply 方法中可以通过 exchange.getRequest() 拿到 ServerHttpRequest 对象,从而可以获取到请求的参数、请求方式、请求头等信息。

    注意: 命名需要以 RoutePredicateFactory 结尾

    自定义断言工厂:判断参数name是否是aaa!

    /*** 自定义RoutePredicateFactory*/
    @Component
    @Slf4j
    public class CheckAuthRoutePredicateFactory extends AbstractRoutePredicateFactory<CheckAuthRoutePredicateFactory.Config> {public CheckAuthRoutePredicateFactory() {super(Config.class);}@Overridepublic Predicate<ServerWebExchange> apply(Config config) {return new GatewayPredicate() {@Overridepublic boolean test(ServerWebExchange serverWebExchange) {log.info("调用CheckAuthRoutePredicateFactory" + config.getName());if(config.getName().equals("aaa")){return true;}return false;}};}/*** 快捷配置* @return*/@Overridepublic List<String> shortcutFieldOrder() {return Collections.singletonList("name");}/*** 需要定义一个内部类,该类用于封装application.yml中的配置*/public static class Config {private String name;public String getName() {return name;}public void setName(String name) {this.name = name;}}
    }
    

    yml中配置

            predicates:- Path=/order/**# 自定义CheckAuth断言工厂- name: CheckAuthargs:name: aaa# 自定义CheckAuth断言工厂快捷配置! 二选一# - CheckAuth=aaa
    

       

②:常用的过滤器工厂(GatewayFilters)

       SpringCloudGateway 内置了很多的过滤器工厂,我们通过一些过滤器工厂可以进行一些业务逻辑处理器,比如添加剔除响应头,添加或去除参数等

  • 添加请求头

    filters:
    - AddRequestHeader=X-Request-color, red  #添加请求头
    
  • 添加请求参数

    filters:
    - AddRequestParameter=color, blue   # 添加请求参数
    
  • 为匹配的路由统一添加前缀

    filters:
    - PrefixPath=/mall-order  # 添加前缀 比如某个微服务需要配置context-path
    
  • 重定向操作

    filters:
    - RedirectTo=302, http://baidu.com  #重定向到百度
    
  • 自定义过滤器工厂
    与自定义断言工厂类似,自定义过滤器工厂需要继承AbstractNameValueGatewayFilterFactory抽象类,且自定义类名必须要以GatewayFilterFactory结尾并交给spring管理。重写apply方法后如下:

    自定义过滤器工厂:为当前路由下的请求添加参数namesex参数,参数值为 aaa

    @Component
    @Slf4j
    public class CheckAuthGatewayFilterFactory extends AbstractNameValueGatewayFilterFactory {@Overridepublic GatewayFilter apply(NameValueConfig config) {return (exchange, chain) -> {log.info("调用CheckAuthGatewayFilterFactory==="+ config.getName() + ":" + config.getValue());// TODOreturn chain.filter(exchange);};}
    }
    

    yml配置

    spring:cloud:gateway:routes:- id: order_route  #路由ID,全局唯一,建议配合服务名uri: lb://mall-order  #lb 整合负载均衡器ribbon,loadbalancerfilters:- CheckAuth=aaa,男  #配置自定义的过滤器工厂
    

       

③:全局过滤器配置(Global Filters)

       GlobalFilter 接口和 GatewayFilter 有一样的接口定义,只不过 GlobalFilter 会作用于所有路由。比如:LoadBalancerClientFilter负载均衡过滤器 lb://mall-order。自定义的全局过滤器需要实现GlobalFilter接口,并重写filter方法!
在这里插入图片描述

注意:全局过滤器(Global Filters)不需要在yml中配置!!

官方声明:GlobalFilter的接口定义以及用法在未来的版本可能会发生变化。

  • 自定义校验token的全局过滤器

    @Component
    @Order(-1)
    @Slf4j
    public class CheckAuthFilter implements GlobalFilter {@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {//校验请求头中的tokenList<String> token = exchange.getRequest().getHeaders().get("token");log.info("token:"+ token);if (token.isEmpty()){return chain.filter(exchange);}// TODO token校验return chain.filter(exchange);}
    }
    
  • 自定义IP全局过滤器,黑白名单

    @Component
    @Slf4j
    public class CheckIPFilter implements GlobalFilter, Ordered {// 执行顺序控制!@Overridepublic int getOrder() {return 0;}@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {HttpHeaders headers = exchange.getRequest().getHeaders();//模拟对 IP 的访问限制,即不在 IP 白名单中就不能调用的需求if (getIp(headers).equals("127.0.0.1")) {log.info("======非法访问======");ServerHttpResponse response = exchange.getResponse();byte[] bytes = new String("======非法访问======").getBytes();response.setStatusCode(HttpStatus.NOT_ACCEPTABLE);DataBuffer buffer = response.bufferFactory().wrap(bytes);response.getHeaders().add("Content-Type","application/json;charset=UTF-8");return exchange.getResponse().writeWith(Mono.just(buffer));}return chain.filter(exchange);}private String getIp(HttpHeaders headers) {return headers.getHost().getHostName();}
    }
    

    测试结果: 如果请求ip127.0.0.1则不允许访问!如果是localhost就可以访问!

       

4. 网关高可用解决方案

       为了保证 Gateway 的高可用性,可以同时启动多个 Gateway 实例进行负载,在 Gateway 的上游使用 Nginx 进行负载转发以达到高可用。
在这里插入图片描述

版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。

原文链接:https://hbdhgg.com/5/59698.html

发表评论:

本站为非赢利网站,部分文章来源或改编自互联网及其他公众平台,主要目的在于分享信息,版权归原作者所有,内容仅供读者参考,如有侵权请联系我们删除!

Copyright © 2022 匯編語言學習筆記 Inc. 保留所有权利。

底部版权信息