178 服务网关GateWay—局部过滤器(GatewayFilter)

服务网关GateWay---局部过滤器GatewayFilter

    • 1 网关过滤器
    • 2 局部过滤器(GatewayFilter)
    • 3 AddRequestParameter Filter 示例
    • 4 StripPrefix Filter

1 网关过滤器

在微服务架构下,后端微服务可能都需要做一些重复相同的事情,如:认证鉴权、限流、黑白名单、日志收集等。对于这些需求当有了网关之后,就可以统一的在网关中实现即可,避免代码冗余。

在这里插入图片描述
? 要实现这些功能,则需要通过网关的过滤器进行实现。网关的过滤器类型分为两种:局部过滤器(GatewayFilter)、全局过滤器(GlobalFilter)。
在这里插入图片描述

2 局部过滤器(GatewayFilter)

? 局部过滤器只会应用到单个路由或者一个分组的路由上。Spring Cloud Gateway默认已经提供了很多局部过滤器供我们使用。

过滤器名称 作用
AddRequestHeader GateWayFilterFactory 添加请求头
AddRequestParameter GateWayFilterFactory 添加请求参数
AddRresponseHeader GateWayFilterFactory 添加响应头
Hystrix GateWayFilterFactory Hystrix过滤器
PrefixPath GateWayFilterFactory 路径前缀过滤器
PreserveHostHeader GateWayFilterFactory 保留请求头过滤器
RequestRateLimiter GateWayFilterFactory 请求限流过滤器
RedirectTo GateWayFilterFactory 重定向过滤器
RemoveNonProxyHeaders GateWayFilterFactory 删除重定向请求头过滤器
RemoveRequestHeader GateWayFilterFactory 删除请求头过滤器
RemoveResponseHeader GateWayFilterFactory 删除响应头过滤器
RewritePath GateWayFilterFactory 重写路径过滤器
SaveSession GateWayFilterFactory 保存session过滤器
SetPath GateWayFilterFactory 设置路径过滤器
SetStatus GateWayFilterFactory 设置状态过滤器
SetResponseHeader GateWayFilterFactory 设置响应头过滤器
Retry GateWayFilterFactory 重试过滤器
StripPrefix GateWayFilterFactory 忽略请求前缀过滤器
? 官方文档对于这些过滤器的使用方式都已经做了说明,官方文档地址:https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#gatewayfilter-factories

3 AddRequestParameter Filter 示例

1)修改网关服务的application.yml

spring:
  cloud:
    gateway:
      routes:
        - id: user-service #服务标识,不允许出现重复
          #uri: http://localhost:8001/ #实际服务访问路径
          uri: lb://user-service #动态路由
          predicates:
            - Path=/user/** #匹配方式
          filters: # 添加局部过滤器
            - AddRequestParameter=company,it   #company=it

2)修改UserController接收请求参数

@RequestMapping("/hello")
public String hello(String company){
    return "hello user service,company : "+company;
}

3)访问网关测试 http://localhost:8500/user/hello/

“hello user service,company : it”;

4 StripPrefix Filter

(1)问题呈现

我们之前用/user/**这样的映射路径代表user-service这个服务。因此请求user-service服务的一切路径要以/user/**开头

比如,访问:localhost:8500/user/2会被代理到:localhost:8081/user/2

现在,我们在user-service中的com.it.user.controller中定义一个新的接口:

package com.it.user.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("address")
public class AddressController {

    @GetMapping("me")
    public String myAddress() {
        return "我的地址";
    }
}

这个接口的路径是/address/me,并不是以/user/开头。当访问:localhost:8500/address/me时,并不符合映射路径,因此会得到404.

无论是 /user/**还是/address/**都是user-service中的一个controller路径,都不能作为网关到user-service的映射路径。

因此我们需要定义一个额外的映射路径,例如:/user-service,配置如下:

spring:
cloud:
gateway:
routes:
- id: user-service # 当前路由的唯一标识
uri: lb://user-service # 路由的目标微服务,user-service:代表服务id
predicates: # 断言
- Path=/user-api/** # 按照路径匹配的规则
那么问题来了:

当我们访问:http://localhost:8500/user-api/user/it时,映射路径/user-service指向用户服务,会被代理到:http://localhost:8081/user-api/user/it

当我们访问:http://localhost:8500/user-api/address/me时,映射路径/user-service指向用户服务,会被代理到:http://localhost:8081/user-api/address/me

这个/user-api是gateway中的映射路径,不应该被代理到微服务,怎办吧?

(2)去除路由前缀

解决思路很简单,当我们访问http://localhost:8500/user-api/user/1时,网关利用/user-api这个映射路径匹配到了用户微服务,请求代理时,只要把/user-api这个映射路径去除不就可以了吗。

恰好有一个过滤器:StripPrefixFilterFactory可以满足我们的需求。

https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.2.3.RELEASE/reference/html/#the-stripprefix-gatewayfilter-factory

我们修改刚才的路由配置:

filters: # 过滤项

  • StripPrefix=1
    此时,网关做路由的代理时,就不会把/user-service作为目标请求路径的一部分了。

也就是说,我们访问:http://localhost:8500/user-api/user/it,会代理到:http://localhost:8081/user/it

我们访问:http://localhost:8500/user-api/address/me,会代理到:http://localhost:8081/address/me