Spring Cloud Gateway

一、介绍

1,概念

  SpringCloud Gateway是在Spring生态系统之上构建的API网关服务,基于Spring5、Spring Boot2和Project Reactor等技术。SpringCloud Gateway作为Spring Cloud生态系统中的网关,目标是替代Zuul。SpringCloud Gateway是基于WebFlux框架实现的,而WebFlux框架底层则是使用了高性能的Reactor模型通信框架Netty。

  SpringCloud Gateway的目标是提供统一的路由方式且基于Filter链的方式提供网关基本的功能,例如:安全、监控/指标和限流。

                

2,核心

  Route(路由)

 网关配置的基本组成模块,和Zuul的路由配置模块类似。一个Route模块由一个 ID,一个目标 URI,一组断言和一组过滤器定义。如果断言为真,则路由匹配,目标URI会被访问。

  Predicate(断言)

 这是一个 Java 8 的 Predicate,可以使用它来匹配来自 HTTP 请求的任何内容,例如 headers 或参数。断言的输入类型是一个 ServerWebExchange。

  Filter(过滤)

 和Zuul的过滤器在概念上类似,可以使用它拦截和修改请求,并且对上游的响应,进行二次处理。过滤器为org.springframework.cloud.gateway.filter.GatewayFilter类的实例。

二、案例使用

源码:cloud-gateway-gateway9527

通用pom

<!--新增gateway-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-gateway</artifactId>
    <version>2.2.1.RELEASE</version>
</dependency>

启动类

@SpringBootApplication
@EnableEurekaClient
public class GateWayMain9527 {
    public static void main(String[] args) {
            SpringApplication.run( GateWayMain9527.class,args);
        }
}

1,采用yaml配置

server:
  port: 9527
spring:
  application:
    name: cloud-gateway
  cloud:
    gateway:
      routes:
        - id: payment_routh #路由的ID,没有固定规则但要求唯一,建议配合服务名
          uri: http://localhost:8001   #匹配后提供服务的路由地址
          predicates:
            - Path=/payment/get1/**   #断言,路径相匹配的进行路由
        - id: payment_routh2
          uri: http://localhost:8001
          predicates:
            - Path=/payment/lb/**   #断言,路径相匹配的进行路由
#注入到eureka
eureka:
  instance:
    hostname: cloud-gateway-service
  client:
    service-url:
      register-with-eureka: true
      fetch-registry: true
      defaultZone: http://eureka7001.com:7001/eureka

测试:

  http://localhost:8001/payment/get/1   直接访问

  http://localhost:9527/payment/get/1   通过gateway路由访问

2,代码(注入RouteLocator)

@Configuration
public class GatewayConfig {
    @Bean
    public RouteLocator customRouteLocator(RouteLocatorBuilder routeLocatorBuilder) {
        RouteLocatorBuilder.Builder routes = routeLocatorBuilder.routes();
        //routeId:path_rote_guonei     http://localhost:9527/guonei ==> http://news.baidu.com/guoji
        routes.route("path_rote_guonei", r -> r.path("/guonei").uri("http://news.baidu.com/guoji"))
            .route("path_rote_guoji", r -> r.path("/guoji").uri("http://news.baidu.com/guoji")).build();
        return routes.build();
    }
}

3,动态路由

server:
  port: 9527
spring:
  application:
    name: cloud-gateway
  cloud:
    gateway:
      discovery:
        locator:
          enabled: true  #开启从注册中心动态创建路由的功能,利用微服务名进行路由
      routes:
        - id: payment_routh #路由的ID,没有固定规则但要求唯一,建议配合服务名
          #uri: http://localhost:8001   #匹配后提供服务的路由地址
          uri: lb://cloud-payment-service  #对应eureka中微服务的示例名称
          predicates:
            - Path=/payment/get/**   #断言,路径相匹配的进行路由
#          filters:
#            - PrefixPath=/payment #去掉指定的前缀  例如:原始访问 http://localhost:9527/payment/get/1  现在只需要输入网址 http://localhost:9527/get/1
#            - StripPrefix=1 #去掉路径中的一段  当为1是去掉1个 例如:原始访问 http://localhost:9527/payment/get/1  现在需要输入网址(/123会被去除) http://localhost:9527/123/payment/get/1
        - id: payment_routh2
          #uri: http://localhost:8001   #匹配后提供服务的路由地址
          uri: lb://cloud-payment-service
          predicates:
            - Path=/payment/lb/**   #断言,路径相匹配的进行路由

三、Predicate与Filter

1,Predicate

  predicate就是为了实现一组匹配规则,让请求过来找到对应的Route进行处理。

spring:
  application:
    name: cloud-gateway
  cloud:
    gateway:
      discovery:
        locator:
          enabled: true  #开启从注册中心动态创建路由的功能,利用微服务名进行路由
      routes:
        - id: payment_routh2
          #uri: http://localhost:8001   #匹配后提供服务的路由地址
          uri: lb://cloud-payment-service
          predicates:
            - Path=/payment/lb/**   #断言,路径相匹配的进行路由
            #- After=2020-03-08T10:59:34.102+08:00[Asia/Shanghai]  #After在什么时间之后 Before在什么时间之前
            #- Between=2020-03-08T10:59:34.102+08:00[Asia/Shanghai] ,  2020-03-08T10:59:34.102+08:00[Asia/Shanghai] #在什么时间之间
            #- Cookie=username,xcc #并且Cookie是username=xcc才能访问
            #- Header=X-Request-Id, d+ #请求头中要有X-Request-Id属性并且值为整数的正则表达式
            #- Host=**.xcc.com
            #- Method=GET
            #- Query=username, d+ #要有参数名称并且是正整数才能路由

2,Filter

/**
 * 自定义filter,过滤掉非法的请求
 */
@Slf4j
@Component
public class MyLogGateWayFilter implements GlobalFilter, Ordered {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        log.info("***************com in MyLogGateWayFilter: "+ LocalDateTime.now());
        String uname = exchange.getRequest().getQueryParams().getFirst("uname");
        if (StrUtil.isEmpty(uname)) {
            log.info("**************用户名为Null,非法用户****************");
            exchange.getResponse().setStatusCode(HttpStatus.NOT_ACCEPTABLE); //设置状态码
            return exchange.getResponse().setComplete();
        }
        return chain.filter(exchange);
    }

    @Override
    public int getOrder() {
        return 0; //order值越小则优先级越高 ; 值越大则优先级越低
    }
}

测试

错误请求:
http://localhost:9527/payment/get/1
#***************com in MyLogGateWayFilter: 2020-10-12T17:06:00.169
#**************用户名为Null,非法用户****************
正确请求:
http://localhost:9527/payment/get/1?uname=xcc
原文地址:https://www.cnblogs.com/bbgs-xc/p/13799767.html