服务闸道器 Spring Cloud GateWay 服务化和过滤器
前言
本文主要讲解了闸道器代理单个服务的使用语法,在实际的工作中,服务的相互呼叫都是依赖于服务中心提供的入口来使用,服务中心往往注册了很多服务,如果每个服务都需要单独配置的话,这将是一份很枯燥的工作。Spring Cloud Gateway 提供了一种预设转发的能力,只要将 Spring Cloud Gateway 注册到服务中心,Spring Cloud Gateway 预设就会代理服务中心的所有服务,下面用程式码演示。准备服务和注册中心
在介绍服务闸道器 zuul 的使用时,提供了 spring-cloud-eureka 、spring-cloud-producer 专案示例,本次演示我们将两个专案版本升级到 Finchley.SR2 后继续演示使用。spring-cloud-eureka(Eureka Server) 的 pom 档案更改,其它依赖包不变。
升级前:

升级后:

spring-cloud-producer(Eureka Client)的 pom 档案更改。因为配置中心需要作为服务注册到注册中心,所以需要升级 Eureka Client,其他依赖没有变动。
升级前:

升级后:

两个专案升级完依赖包后依次重启,访问注册中心地址 http://localhost:8000/ 即可看到名为 SPRING-CLOUD-PRODUCER的服务。
服务网关注册到注册中心
复制上一节的示例专案 cloud-gateway 重新命名为 cloud-gateway-eureka,新增 eureka 的客户端依赖包。
修改 application.yml 配置档案内容如下

配置说明:
spring.cloud.gateway.discovery.locator.enabled:是否与服务注册于发现元件进行结合,通过 serviceId 转发到具体的服务例项。预设为 false,设为 true 便开启通过服务中心的自动根据 serviceId 建立路由的功能。eureka.client.service-url.defaultZone指定注册中心的地址,以便使用服务发现功能logging.level.org.springframework.cloud.gateway 调整相 gateway 包的 log 级别,以便排查问题修改完成后启动 cloud-gateway-eureka 专案,访问注册中心地址 http://localhost:8000/ 即可看到名为 CLOUD-GATEWAY-EUREKA的服务。测试
将 Spring Cloud Gateway 注册到服务中心之后,闸道器会自动代理所有的在注册中心的服务,访问这些服务的语法为:http://闸道器地址:埠/服务中心注册 serviceId/具体的url比如我们的 spring-cloud-producer 专案有一个 /hello 的服务,访问此服务的时候会返回:hello world。
比如访问地址:http://localhost:9000/hello,页面返回:hello world!
按照上面的语法我们通过闸道器来访问,浏览器输入:http://localhost:8888/SPRING-CLOUD-PRODUCER/hello 同样返回:hello world!证明服务闸道器转发成功。
我们将专案 spring-cloud-producer 复制一份为 spring-cloud-producer-1,将/hello服务的返回值修改为 hello world smile !,修改埠号为 9001 ,修完完成后重启,这时候访问注册中心后台会发现有两个名为 SPRING-CLOUD-PRODUCER的服务。
在浏览器多次访问地址:http://localhost:8888/SPRING-CLOUD-PRODUCER/hello,页面交替返回以下资讯:
hello world!
hello world smile!
说明后端服务自动进行了均衡负载。
基于 Filter(过滤器) 实现的高阶功能
在服务闸道器Zuul高阶篇中大概介绍过 Filter 的概念。Spring Cloud Gateway 的 Filter 的生命周期不像 Zuul 的那么丰富,它只有两个:“pre” 和 “post”。
PRE: 这种过滤器在请求被路由之前呼叫。我们可利用这种过滤器实现身份验证、在丛集中选择请求的微服务、记录除错资讯等。POST:这种过滤器在路由到微服务以后执行。这种过滤器可用来为响应新增标准的 HTTP Header、收集统计资讯和指标、将响应从微服务传送给客户端等。Spring Cloud Gateway 的 Filter 分为两种:GatewayFilter 与 GlobalFilter。GlobalFilter 会应用到所有的路由上,而 GatewayFilter 将应用到单个路由或者一个分组的路由上。
Spring Cloud Gateway 内建了9种 GlobalFilter,比如 Netty Routing Filter、LoadBalancerClient Filter、Websocket Routing Filter 等,根据名字即可猜测出这些 Filter 的作者,具体大家可以参考官网内容:Global Filters
利用 GatewayFilter 可以修改请求的 Http 的请求或者响应,或者根据请求或者响应做一些特殊的限制。 更多时候我们会利用 GatewayFilter 做一些具体的路由配置,下面我们做一些简单的介绍。
快速上手 Filter 使用
我们以 AddRequestParameter GatewayFilter 来演示一下,如何在专案中使用 GatewayFilter,AddRequestParameter GatewayFilter 可以在请求中新增指定引数。application.yml配置示例

这样就会给匹配的每个请求新增上foo=bar的引数和值。
我们将以上配置融入到 cloud-gateway-eureka 专案中,完整的 application.yml 档案配置资讯如下:

这里的 routes 手动指定了服务的转发地址,设定所有的 GET 方法都会自动新增foo=bar,http://localhost:9000 是 spring-cloud-producer 专案,我们在此专案中新增一个 foo() 方法,用来接收转发中新增的引数 foo。

修改完成后重启 cloud-gateway-eureka、spring-cloud-producer 专案。访问地址http://localhost:9000/foo页面返回:hello null!,说明并没有接受到引数 foo;通过闸道器来呼叫此服务,浏览器访问地址http://localhost:8888/foo页面返回:hello bar!,说明成功接收到引数 foo 引数的值 bar ,证明闸道器在转发的过程中已经通过 filter 添加了设定的引数和值。
服务化路由转发
上面我们使用 uri 指定了一个服务转发地址,单个服务这样使用问题不大,但是我们在注册中心往往会使用多个服务来共同支撑整个服务的使用,这个时候我们就期望可以将 Filter 作用到每个应用的例项上,spring cloud gateway 工了这样的功能,只需要简单配置即可。为了测试两个服务提供者是否都被呼叫,我们在 spring-cloud-producer-1 专案中也同样新增 foo() 方法。

为了和 spring-cloud-producer 中 foo() 方法有所区别,这里使用了两个感叹号。同时将 cloud-gateway-eureka 专案配置档案中的 uri 内容修改如下:

修改完之后,重新启动专案 cloud-gateway-eureka、spring-cloud-producer-1,浏览器访问地址:http://localhost:8888/foo页面交替出现:

证明请求依据均匀转发到后端服务,并且后端服务均接收到了 filter 增加的引数 foo 值。
这里其实预设使用了全域性过滤器 LoadBalancerClient ,当路由配置中 uri 所用的协议为 lb 时(以uri: lb://spring-cloud-producer为例),gateway 将使用 LoadBalancerClient 把 spring-cloud-producer 通过 eureka 解析为实际的主机和埠,并进行负载均衡。