1. 网关是一个Api服务器,是系统的唯一入口。为每个客户端提供一个定制的Restful API。同时它还需要具有一些业务之外的责任:鉴权。静态响应等处理。网关的最主要在作用就是路由的转发 。但是 在我们平时的使用过程中,直接请求http 协议的 api 会存在很多问题。例如:安全问题,流量问题 等等。所以gateway 还需要做一些额外的 事情来保证我们的流程是安全的、可靠的。<br />![](https://cdn.nlark.com/yuque/0/2021/png/21509632/1627092337248-4e754453-a973-4549-b3d1-e4a4a50afb76.png#align=left&display=inline&height=596&margin=%5Bobject%20Object%5D&originHeight=596&originWidth=450&size=0&status=done&style=none&width=450)<br /> 客户端向Spring Cloud Gateway发出请求。网关处理程序映射确定请求与路由匹配,则将其发送到网关Web处理程序。该处理程序通过特定于请求的过滤器链运行请求。

引入网关

  1. 导包

    <dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-gateway</artifactId>
    </dependency>
    
  2. 开启默认路由设置

    spring:
    cloud:
     gateway:
       discovery:
         locator:
           enabled: true
    
  3. 默认路由配置的访问方式:http://网关ip:port/具体服务名/**

    rotue(路由)

    路由就是将不同的请求映射到不同的后端集群中,这是网关的核心功能,它由ID,目标URI,谓词集合和过滤器集合定义。

    routes: 
    - id: #定义需要路由的服务唯一标识
    uri: #定义服务的访问地址,可以是当前nacos上的服务:lb://服务名,也可以上网络服务http://
    filters:#定义一组过滤器
    - xxx
    predicates: #定义一组谓词工厂
    - Path=/news/**
    

    10.3 Prendicate(谓词工厂)

    用来指定路由规则
    Gateway - 图1

    After

    spring:
    cloud:
     gateway:
       routes:
       - id: after_user          
         uri: lb://user-server
         predicates:
         # 当且仅当请求时的时间After配置的时间时,才会转发到用户微服务
         # 目前配置不会进该路由配置,所以返回404
         # 将时间改成 < now的时间,则访问localhost:8040/** -> user-center/**
         # eg. 访问http://localhost:8040/users/1 -> user-center/users/1
         - After=2030-01-20T17:42:47.789-07:00[America/Denver]
    

    Before

    spring:
    cloud:
     gateway:
       routes:
       - id: before_user
       uri: lb://user-server         
        predicates:
       # 当且仅当请求时的时间Before配置的时间时,才会转发到用户微服务
       # 目前配置不会进该路由配置,所以返回404
       # 将时间改成 > now的时间,则访问localhost:8040/** -> user-center/**
       # eg. 访问http://localhost:8040/users/1 -> user-center/users/1
       - Before=2018-01-20T17:42:47.789-07:00[America/Denver]
    

    Between

    spring:
    cloud:
     gateway:
       routes:
       - id: between_user         
         uri: lb://user-server
         predicates:
         # 当且仅当请求时的时间Between配置的时间时,才会转发到用户微服务
         # 因此,访问localhost:8040/** -> user-center/**
         # eg. 访问http://localhost:8040/users/1 -> user-center/users/1
         - Between=2017-01-20T17:42:47.789-07:00[America/Denver], 
                   2027-01-21T17:42:47.789-07:00[America/Denver]
    

    Cookie

    spring:
    cloud:
     gateway:
       routes:
       - id: cookie_user
         uri: lb://user-server
         predicates:
         # 当且仅当带有名为somecookie,并且值符合正则ch.p的Cookie时,才会转发到用户服务
         # 如Cookie满足条件,则访问http://localhost:8040/** -> user-center/**
         # eg. 访问http://localhost:8040/users/1 -> user-center/users/1
         - Cookie=somecookie, ch.p
    

    Header

    spring:
    cloud:
     gateway:
       routes:
       - id: header_user
         uri: lb://user-server
         predicates:
         # 当且仅当带有名为X-Request-Id,并且值符合正则\d+的Header时,才会转发到用户服务
         # 如Header满足条件,则访问http://localhost:8040/** -> user-center/**
         # eg. 访问http://localhost:8040/users/1 -> user-center/users/1
         - Header=X-Request-Id, \d+
    

    Host

    spring:
    cloud:
     gateway:
       routes:
       - id: host_user
         uri: lb://user-server
         predicates:
         # 当且仅当名为Host的Header符合**.somehost.org或**.anotherhost.org时,才会转发用户微服务
         # 如Host满足条件,则访问http://localhost:8040/** -> user-center/**
         # eg. 访问http://localhost:8040/users/1 -> user-center/users/1
         - Host=**.somehost.org,**.anotherhost.org
    

    Method

    spring:
    cloud:
     gateway:
       routes:
       - id: method_user
         uri: lb://user-server
         predicates:
         # 当且仅当HTTP请求方法是GET时,才会转发用户微服务
         # 如请求方法满足条件,访问http://localhost:8040/** -> user-center/**
         # eg. 访问http://localhost:8040/users/1 -> user-center/users/1
         - Method=GET
    

    Path

    spring:
    cloud:
     gateway:
       routes:
       - id: path_user
         uri: lb://user-server
         predicates:
         # 当且仅当访问路径是/users/*或者/some-path/**,才会转发用户微服务
         # segment是一个特殊的占位符,单层路径匹配
         # eg. 访问http://localhost:8040/users/1 -> user-center/users/1
         - Path=/users/{segment},/some-path/**
    

    Query

    spring:
    cloud:
     gateway:
       routes:
       - id: query_user
         uri: lb://user-server
         predicates:
         # 当且仅当请求带有baz的参数,才会转发到用户微服务
         # eg. 访问http://localhost:8040/users/1?baz=xx -> user-center的/users/1
         - Query=baz
    

    RemoteAddr

    spring:
    cloud:
     gateway:
       routes:
       - id: remoteaddr_user
         uri: lb://user-server
         predicates:
         # 当且仅当请求IP是192.168.1.1/24网段,例如192.168.1.10,才会转发到用户微服务
         # eg. 访问http://localhost:8040/users/1 -> user-center的/users/1
         - RemoteAddr=192.168.1.1/24
    

    filter

    过滤器,用来在请求与相应之间做统一的逻辑处理,生命周期有两个层次,一个是请求过来可以过滤,响应回去也可以过滤,过滤器分为全局过滤器以及局部过滤器。
    我们可以创建过滤器工厂来定义过滤器而方便配置

    AddRequestHeaderGatewayFilterFactory

    spring:
    cloud:
     gateway:
       routes:
       - id: add_request_header_route
         uri: https://example.org
         filters:
         #为原始请求添加名为 X-Request-Foo ,值为 Bar 的请求头。
         - AddRequestHeader=X-Request-Foo, Bar
    

    AddRequestParameterGatewayFilterFactory

    spring:
    cloud:
     gateway:
       routes:
       - id: add_request_parameter_route
         uri: https://example.org
         filters:
         #为原始请求添加请求参数 foo=bar
         - AddRequestParameter=foo, bar
    

    AddResponseHeaderGatewayFilterFactory

    spring:
    cloud:
     gateway:
       routes:
       - id: add_response_header_route
         uri: https://example.org
         filters:
         #添加名为 X-Request-Foo ,值为 Bar 的响应头。
         - AddResponseHeader=X-Response-Foo, Bar
    

    DedupeResponseHeaderGatewayFilterFactory

    spring:
    cloud:
     gateway:
       routes:
       - id: dedupe_response_header_route
         uri: https://example.org
         filters:
         -DedupeResponseHeader=Access-Control-Allow-Credentials Access-Control-Allow-Origin,RETAIN_FIRST
    

    PrefixPathGatewayFilterFactory

    spring:
    cloud:
     gateway:
       routes:
       - id: prefixpath_route
         uri: https://example.org
         filters:
         #为匹配的路由添加前缀。例如:访问${GATEWAY_URL}/hello 会转发到https://example.org/mypath/hello
         - PrefixPath=/mypath
    

    PreserveHostHeaderGatewayFilterFactory

    spring:
    cloud:
     gateway:
       routes:
       - id: preserve_host_route
         uri: https://example.org
         filters:
         #如果不设置,那么名为 Host 的Header由Http Client控制;如果设置了,那么会设置一个请求属性
         #路由过滤器会检查从而去判断是否要发送原始的、名为Host的Header。
         - PreserveHostHeader
    

    RequestRateLimiterGatewayFilterFactory

    spring:
    cloud:
     gateway:
       routes:
       - id: requestratelimiter_route
         uri: https://example.org
         filters:
         - name: RequestRateLimiter
           args:
             redis-rate-limiter.replenishRate: 10
             redis-rate-limiter.burstCapacity: 20
    

    RedirectToGatewayFilterFactory

    spring:
    cloud:
     gateway:
       routes:
       - id: prefixpath_route
         uri: https://example.org
         filters:
         # 配置成HTTP状态码, URL的形式
         - RedirectTo=302, http://www.itmuch.com
    

    RemoveRequestHeaderGatewayFilterFactory

    spring:
    cloud:
     gateway:
       routes:
       - id: removerequestheader_route
         uri: https://example.org
         filters:
         #为原始请求删除名为 X-Request-Foo 的请求头
         - RemoveRequestHeader=X-Request-Foo
    

    RemoveResponseHeaderGatewayFilterFactory

    spring:
    cloud:
     gateway:
       routes:
       - id: removeresponseheader_route
         uri: https://example.org
         filters:
         #删除名为 X-Request-Foo 的响应头
         - RemoveResponseHeader=X-Response-Foo
    

    RewritePathGatewayFilterFactory

    spring:
    cloud:
     gateway:
       routes:
       - id: rewritepath_route
         uri: https://example.org
         predicates:
         - Path=/foo/**
         filters:
         # 配置成原始路径正则, 重写后的路径的正则
         - RewritePath=/foo/(?<segment>.*), /$\{segment}
    

    重写请求路径。如上配置,访问 /foo/bar 会将路径改为/bar 再转发,也就是会转发到 https://example.org/bar 。需要注意的是,由于YAML语法,需用$\ 替换 $ 。

    RewriteResponseHeaderGatewayFilterFactory

    spring:
    cloud:
     gateway:
       routes:
       - id: rewriteresponseheader_route
         uri: https://example.org
         filters:
         - RewriteResponseHeader=X-Response-Foo, password=[^&]+, password=***
    

    如果名为 X-Response-Foo 的响应头的内容是/42?user=ford&password=omg!what&flag=true,则会被修改为/42?user=ford&password=*&flag=true。

    SaveSessionGatewayFilterFactory

    spring:
    cloud:
     gateway:
       routes:
       - id: save_session
         uri: https://example.org
         predicates:
         - Path=/foo/**
         filters:
         - SaveSession
    

    在转发到后端微服务请求之前,强制执行 WebSession::save 操作。用在那种像 Spring Session 延迟数据存储(笔者注:数据不是立刻持久化)的,并希望在请求转发前确保session状态保存情况。
    如果你将Spring Secutiry于Spring Session集成使用,并想确保安全信息都传到下游机器,你就需要配置这个filter。

    SetPathGatewayFilterFactory

    spring:
    cloud:
     gateway:
       routes:
       - id: setpath_route
         uri: https://example.org
         predicates:
         - Path=/foo/{segment}
         filters:
         - SetPath=/{segment}
    

    采用路径template参数,通过请求路径的片段的模板化,来达到操作修改路径的母的,运行多个路径 片段模板化。
    如上配置,访问${GATEWAY_PATH}/foo/bar ,则对于后端微服务的路径会修改为 /bar 。

    SetResponseHeaderGatewayFilterFactory

    spring:
    cloud:
     gateway:
       routes:
       - id: setresponseheader_route
         uri: http://example.org
         filters:
         - SetResponseHeader=X-Response-Foo, Bar
    

    如果后端服务响应带有名为 X-Response-Foo 的响应头,则将值改为替换成 Bar 。

    SetStatusGatewayFilterFactory

    spring:
    cloud:
     gateway:
       routes:
       - id: setstatusstring_route
         uri: http://example.org
         filters:
         - SetStatus=BAD_REQUEST
       - id: setstatusint_route
         uri: http://example.org
         filters:
         - SetStatus=401
    

    修改响应的状态码,值可以是数字,也可以是字符串。但一定要是Spring HttpStatus 枚举类中的值。 如上配置,两种方式都可以返回HTTP状态码401。

    StripPrefixGatewayFilterFactory

    spring:
    cloud:
     gateway:
       routes:
       - id: nameRoot
         uri: http://nameservice
         predicates:
         - Path=/name/**
         filters:
         - StripPrefix=2
    

    数字表示要截断的路径的数量。如上配置,如果请求的路径为 /name/bar/foo ,则路径会修改为/foo , 也就是会截断2个路径

    RetryGatewayFilterFactory

    spring:
    cloud:
     gateway:
       routes:
       - id: retry_test
         uri: http://localhost:8080/flakey
         predicates:
         - Host=*.retry.com
         filters:
         - name: Retry
           args:
             retries: 3
             statuses: BAD_GATEWAY
    

    针对不同的响应做重试,可配置如下参数:
    retries: 重试次数
    statuses: 需要重试的状态码,取值在 org.springframework.http.HttpStatus 中
    methods: 需要重试的请求方法,取值在 org.springframework.http.HttpMethod 中
    series: HTTP状态码系列,取值在 org.springframework.http.HttpStatus.Series 中

    RequestSizeGatewayFilterFactory

    spring:
    cloud:
     gateway:
       routes:
       - id: request_size_route
       uri: http://localhost:8080/upload
       predicates:
       - Path=/upload
       filters:
       - name: RequestSize
         args:
           # 单位字节
           maxSize: 5000000
    

    为后端服务设置收到的最大请求包大小。如果请求大小超过设置的值,则返回 413 Payload Too Large ,默认值是5M

    自定义过滤器

  4. 全局过滤器:所有的路由都生效。实现GlobalFilter接口,Ordered接口是用来规定执行顺序

    @Component
    public class MyGlobaleFilter implements GlobalFilter ,Ordered{
     @Override
     public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
         System.out.println("========全局拦截器===========");
         return chain.filter(exchange);
     }
     @Override
     public int getOrder() {
         return 1;
     }
    }
    
  5. 过自定义过滤器工厂来实现局部过滤

    //继承父类接口的泛型规定了参数对象类型
    @Component
    public class AuthenticationGatewayFilterFactory extends 
          AbstractGatewayFilterFactory<AuthenticationGatewayFilterFactory.Config> {
     //构造方法对参数对象进行说明
     public AuthenticationGatewayFilterFactory() {
         super(Config.class);
     }
     //用来指定参数的顺序,当前无
     @Override
     public List<String> shortcutFieldOrder() {
         return Arrays.asList();
     }
         //用来接收参数的类,该过滤器不需要参数
     public static class Config {}
     //创建过滤器对象,能够从config里面获取传递的参数
     @Override
     public GatewayFilter apply(Config config) {
         return (exchange,chain) -> {
             System.out.println(“====进入认证过滤器====”);
             return chain.filter(exchange);
         };
     }
    }
    

    7月23日

  6. 网关的概念以及特点

    网关是一个Api服务器,是系统的唯一入口。为每个客户端提供一个定制的Restful API。同时它还需要具有一些业务之外的责任:鉴权。静态响应等处理。网关的最主要在作用就是路由的转发 。但是 在我们平时的使用过程中,直接请求http 协议的 api 会存在很多问题。例如:安全问题,流量问题 等等。所以gateway 还需要做一些额外的 事情来保证我们的流程是安全的、可靠的。

    客户端向Spring Cloud Gateway发出请求。网关处理程序确定请求与路由匹配,则将其发送到网关Web处理程序。该处理程序通过特定于请求的过滤器链运行请求。
    特点

  • 动态路由,能够匹配任何请求属性;
  • 可以对路由指定Predicate(断言)和Filter(过滤器),且易于编写;
  • 集成Hystrix的断路器功能;
  • 集成SpringCloud服务发现功能;
  • 请求限流功能;
  • 支持路径重写
  1. Gateway与Zuul的区别

Zuul:
使用的是阻塞式的 API,不支持长连接,比如 websockets。
底层是servlet,Zuul处理的是http请求
没有提供异步支持,流控等均由hystrix支持。
依赖包spring-cloud-starter-netflix-zuul。
Gateway:
底层依然是servlet,但使用了webflux,多嵌套了一层框架
依赖spring-boot-starter-webflux和/ spring-cloud-starter-gateway
提供了异步支持,提供了抽象负载均衡,提供了抽象流控,并默认实现了RedisRateLimiter。
3. 路由里面的谓词工厂是什么
用来指定路由规则
Gateway - 图2
4. 全局过滤器与局部过滤器的区别
全局处理器:所有的路由都生效。实现GlobalFilter接口,Ordered接口是用来规定执行顺序
局部处理器extends AbstractGatewayFilterFactory 继承父类接口的泛型规定了参数对象类型

  1. 两种过滤器各自的实现流程
    全局过滤器:所有的路由都生效。实现GlobalFilter接口,Ordered接口是用来规定执行顺序
    @Component
    public class MyGlobaleFilter implements GlobalFilter ,Ordered{
     @Override
     public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
         System.out.println("========全局拦截器===========");
         return chain.filter(exchange);
     }
     @Override
     public int getOrder() {
         return 1;
     }
    }
    

自定义过滤器:工厂来实现局部过滤

//继承父类接口的泛型规定了参数对象类型
@Component
public class AuthenticationGatewayFilterFactory extends 
         AbstractGatewayFilterFactory<AuthenticationGatewayFilterFactory.Config> {
    //构造方法对参数对象进行说明
    public AuthenticationGatewayFilterFactory() {
        super(Config.class);
    }
    //用来指定参数的顺序,当前无
    @Override
    public List<String> shortcutFieldOrder() {
        return Arrays.asList();
    }
        //用来接收参数的类,该过滤器不需要参数
    public static class Config {}
    //创建过滤器对象,能够从config里面获取传递的参数
    @Override
    public GatewayFilter apply(Config config) {
        return (exchange,chain) -> {
            System.out.println(“====进入认证过滤器====”);
            return chain.filter(exchange);
        };
    }
}