spring cloud 之 gateway

网关介绍

在微服务架构体系中,一个系统会被拆分为很多个微服务,那么作为客户端要如何去调用这么多的微服务呢?如果没有网关的存在,我们只能在客户端记录每个微服务的地址,然后分别调用,当然这样是不现实的

现有网关介绍

Kong

   基于Nginx+Lua开发,性能高,稳定,有多个可用的插件(限流、鉴权等等)可以开箱即用,只支持http调用

Zuul

 Netflix开源的网关,功能丰富,使用JAVA开发,易于二次开发,性能不如nginx

Spring Cloud Gateway

Spring公司为了替换Zuul而开发的网关服务,spring Cloud Gateway是Spring公司基于Spring 5.0,Spring Boot 2.0 和 Project Reactor ,webFlux,底层基于Netty等技术开发的网关,其不仅提供统一的路由方式,并且基于 Filter 链的方式提供了网关基本的功能

前置知识请参考本专栏webFlux 或者传送门

网关的作用

spring cloud 之 gateway_第1张图片

1、能针对客户端提供统一入口(类似于守门员、门卫)

2、实现统一鉴权

3、实现流量控制

4、实现服务熔断降级 

Spring Cloud Gateway的核心概念

路由Route

是 gateway 中最基本的组件之一,路由是网关的基本单元,由ID、URI、一组Predicate、一组Filter组成,根据Predicate进行匹配转发,具体包含如下信息:

id:路由标识符,区别于其他 Route。
uri:路由指向的目的地 uri,即客户端请求最终被转发到的微服务。
order:用于多个 路由之间的排序,数值越小排序越靠前,匹配优先级越高。
predicate:断言的作用是进行条件判断,只有断言都返回真,才会真正的执行路由。
filter:过滤器用于修改请求和响应信息。

列举一下配置:

routes:
  # 路由的名字
  - id: cloud-test-service
  # lb指的是从nacos中按照名称获取微服务,并遵循负载均衡策略
    uri: lb://cloud-test-service
  # 断言符合这个规定的才进行1转发
    predicates:
      - Path=/common/**
    filters:
      # 将第一层去掉
      - StripPrefix=1
      # 这里使用内置的过滤器,修改返回状态
      - SetStatus=2000

转发规则 

Predicate(谓语、断言)   路由转发的判断条件,目前SpringCloud Gateway支持多种方式,常见如:Path、Query、Method、Header等,写法必须遵循 key=vlue的形式  
Filter(过滤器) 过滤器是路由转发请求时所经过的过滤逻辑,可用于修改请求、响应内容

Predicate 就是为了实现一组匹配规则,方便让请求过来找到对应的 Route 进行处理,接下来我们接下 Spring Cloud GateWay 内置几种 Predicate 的使用

规则 实例  说明
Path   - Path=/gate/,/rule/ 当请求的路径为gate、rule开头的时,进行转发
Before  - Before=2017-01-20T17:42:47.789-07:00[America/Denver]  在某个时间之前的请求才会被转发
After - After=2017-01-20T17:42:47.789-07:00[America/Denver]  在某个时间之后的请求才会被转发
Between - Between=2017-01-20T17:42:47.789-07:00[America/Denver],2017-01-21T17:42:47.789-07:00[America/Denver]  在某个时间段之间的才会被转发
Cookie  - Cookie=chocolate, ch.p 名为chocolate的表单或者满足正则ch.p的表单才会被匹配到进行请求转发
Header  - Header=X-Request-Id, \d+  携带参数X-Request-Id或者满足\d+的请求头才会匹配
Host  - Host=www.sltech.com 当主机名为www.sltech.com的时候,转发
Method  - Method=GET 只有GET方法才会匹配转发请求,还可以限定POST、PUT等请求方式
server:
  port: 8080
spring:
  cloud:
    gateway:
      routes:
      - id: query_route
        uri: https://example.org
        predicates:
        - Query=smile

 这样配置,只要请求中包含 smile 属性的参数即可匹配路由

server:
  port: 8080
spring:
  application:
    name: api-gateway
  cloud:
    gateway:
      routes:
        - id: gateway-service
          uri: https://www.baidu.com
          order: 0
          predicates:
            - Host=**.foo.org
            - Path=/headers
            - Method=GET
            - Header=X-Request-Id, \d+
            - Query=foo, ba.
            - Query=baz
            - Cookie=chocolate, ch.p

 路由断言规则可以组合使用

 过滤器

过滤器规则

过滤规则 实例  说明
PrefixPath - PrefixPath=/app 在请求路径前加上app
RewritePath - RewritePath=/test, /app/test 访问localhost:10010/test,请求会转发到localhost:10010/app/test
SetPath   SetPath=/app/{path}  通过模板设置路径,转发的规则时会在路径前增加app,{path}表示原请求路径
RedirectTo - RedirectTo=303, https://acme.org 重定向定义返回码和地址
RemoveRequestHeader  - RemoveRequestHeader=X-Request-Foo 去掉请求头信息 X-Request-Foo

举一个例子,不一一列举 :

spring:
  cloud:
    gateway:
      routes:
      - id: removerequestheader_route
        uri: https://example.org
        filters:
        - RemoveResponseHeader=X-Request-Foo

PRE: 这种过滤器在请求被路由之前调用。我们可利用这种过滤器实现身份验证、在集群中选择 请求的微服务、记录调试信息等

POST:这种过滤器在路由到微服务以后执行。这种过滤器可用来为响应添加标准的HTTP Header、收集统计信息和指标、将响应从微服务发送给客户端等

Gateway 的Filter从作用范围可分为两种: GatewayFilter与GlobalFilter:    

  • GatewayFilter:应用到单个路由或者一个分组的路由上。
  • GlobalFilter:应用到所有的路由上

过滤器生效顺序

        GlobalFilter 的功能其实和 GatewayFilter 是相同的,只是 GlobalFilter 的作用域是所有的路由配置,而不是绑定在指定的路由配置上。多个 GlobalFilter 可以通过 @Order 或者 getOrder() 方法指定执行顺序,order值越小,执行的优先级越高。

        由于过滤器分为 pre 和 post 两种类型,pre 类型过滤器如果 order 值越小,那么它就应该在pre过滤器链的顶层,post 类型过滤器如果 order 值越小,那么它就应该在 post 过滤器链的底层:

spring cloud 之 gateway_第2张图片

Spring Cloud Gateway的搭建及过滤器实现

项目搭建

新建springBoot项目,版本2.3.5.RELEASE,我这里cloud版本是Hoxton.SR12


        
        
            org.springframework.cloud
            spring-cloud-starter-gateway
        
        
        
            com.alibaba.cloud
            spring-cloud-starter-alibaba-nacos-discovery
        
        
        
            org.springframework.cloud
            spring-cloud-starter-openfeign
        

添加配置 

server:
  port: 10010
spring:
  application:
    name: could-gateway-server
# 必须加这句话,让gateway可以发现注册中心的服务
  cloud:
    gateway:
      discovery:
        locator:
          enabled: true
      routes:
        # 路由的名字
        - id: cloud-test-service
        # lb指的是从nacos中按照名称获取微服务,并遵循负载均衡策略
          uri: lb://cloud-test-service
        # 断言符合这个规定的才进行1转发
          predicates:
            - Path=/common/**
          filters:
            # 将第一层去掉
            - StripPrefix=1
            # 这里使用内置的过滤器,修改返回状态
            - SetStatus=2000
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848

添加过滤器 

局部过滤器

局部过滤器需要继承AbstractGatewayFilterFactory,重写apply方法,过滤器名称必须叫xxxGatewayFilterFactory,配置的路由的时候可以直接配置xxx

import lombok.Data;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;
 
@Component
public class myParamGateWayFilterFactory extends AbstractGatewayFilterFactory {
    @Override
    public String name() {
        return "mycustomlocalfiter";
    }
 
    public MyCustomLocalFiterFactory() {
        super(ParamsConfig.class);
    }
 
    @Override
    public GatewayFilter apply(ParamsConfig config) {
        return (exchange, chain) -> {
            return chain.filter(exchange).then(Mono.fromRunnable(() -> {
                System.out.println("name=" + config.getParamName() + ";value=" + config.getParamValue());
            }));
        };
    }
 
 
    @Data
    public static class ParamsConfig {
        private String paramName;
 
        private String paramValue;
 
    }
}

应用到路由上

     filters: 
            - StripPrefix=1
            - name: myParam
              args:
                paramname: "this is paramName"
                paramvalue: "this is paramValue"

全局过滤器 

全局过滤器交给spring容器管理,无需任何配置即可生效,全局过滤器针对所有路由有效,

注意:写在then之中的是后置逻辑,见下方示例: 
public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain)
 {
       log.info("BFilter前置逻辑");
       return chain.filter(exchange).then(Mono.fromRunnable(() ->
        {
             log.info("BFilter后置逻辑");
        }));
}

前置过滤器

@Component
public class MyCustomGlobalFilter implements GlobalFilter, Ordered {
    @Override
    public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        System.out.println("this is custom pre filter");
        return chain.filter(exchange).then();
    }
 
    @Override
    public int getOrder() {
        return 0;
    }
}

后置过滤器

@Component
public class MyCustomGlobalFilter implements GlobalFilter, Ordered {
    @Override
    public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        // 写在then中
        return chain.filter(exchange).then(Mono.fromRunnable(() -> {
            System.out.println("this is post filter");
        }));
    }
 
    @Override
    public int getOrder() {
        return 0;
    }
}


 

你可能感兴趣的:(springCloud,spring,cloud,gateway,java)