Spring Cloud:Gateway基础知识

简介

SpringCloud Gateway是SpringCloud的一个全新项目,基于Spring5+springboot2+project Reactor等技术开发的网关,它旨在为微服务架构提供一中简单有效的统一的Api路由管理方式,且基于Filter链的方式提供了网关基本的功能,如安全,监控,指标,限流。
Spring Cloud Gateway使用的webflux中的reactor-netty响应式编程组件,底层使用了Netty通讯框架。
GateWay具有如下特性:

  • 基于Spring5+springboot2+project Reactor等技术构建。
  • 可以对路由指定Predicate(断言)和filter(过滤器)。
  • 集成Hystrix的断路器功能。
  • 集成SpringCloud服务发现功能。
  • 易于编写的Predicate(断言)和filter(过滤器);
  • 请求限流功能。
  • 支持路径重写。

三大核心概念

路由(Route)是构建网关的基本模块,它由ID,目标URI,一系列断言和过滤器组成,如果断言为true则匹配该路由。
断言(Predicate),开发人员可以匹配HTTP请求中的所有内容,例如请求头或请求参数,如果请求与断言相匹配则进行路由
过滤(Filter),指的是Spring框架中的GatewayFilter的实例,使用过滤器,可以在请求被路由前或者后对请求进行修改
官网截图:

核心逻辑:路由转发+执行过滤器链

Gateway环境搭建

yml配置方式

pom依赖:需要移除springboot的web场景启动器,否则会报错,无法启动

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>

配置文件yml,在配置文件中配置了网关

server:
  port: 9527

spring:
  application:
    name: cloud-gateway
  cloud:
    gateway:
      routes:
        - id:  payment_routh
          uri: http://localhost:8001
          predicates:
            - Path=/payment/get/**
        - id:  payment_routh2
          uri: http://localhost:8001
          predicates:
            - Path=/payment/create

eureka:
  client:
    #是否将自己注册到Eureka Server 默认为true
    register-with-eureka: true
    #是否从EurekaServer抓取已有的注册信息,默认为true,单节点无所谓,集群必须设置true才能配合ribbon做负载均衡
    fetch-registry: true
    service-url:
      #设置eureka server交互的地址查询服务和注册服务都需要依赖这个地址
      defaultZone: http://localhost:7001/eureka
  instance:
    hostname: cloud-gateway-service

然后我们通过9527端口就可以访问服务了:

编码方式配置

新写一个Gateway配置类:

@Configuration
public class GatewayConfig {

    @Bean
    public RouteLocator customRouteLocator(RouteLocatorBuilder routeLocatorBuilder){
        RouteLocatorBuilder.Builder routes = routeLocatorBuilder.routes();
        routes.route("path_route_wj",r->{
            //意思是访问localhost:9527/guonei,将会转发到http://news.baidu.com/guonei
                    return r.path("/guonei").uri("http://news.baidu.com/guonei");
        }).build();
        return routes.build();
    }
}

我们在浏览器输入localhost:9527/guonei并访问,观察效果:

Gateway实现动态路由

yml配置
需要注意的是:uri的协议为lb,表示启用Gateway的负载均衡功能.
lb://serverName是Spring cloud Gateway在微服务中自动为我们创建的负载均衡uri

spring:
  application:
    name: cloud-gateway
  cloud:
    gateway:
      routes:
        - id:  payment_routh
          #uri: http://localhost:8001
          uri: lb://CLOUD-PAYMENT-SERVICE
          predicates:
            - Path=/payment/get/**
        - id:  payment_routh2
          #uri: http://localhost:8001
          uri: lb://CLOUD-PAYMENT-SERVICE
          predicates:
            - Path=/payment/create
      discovery:
        locator:
          #开启从注册中心动态创建路由的功能,利用微服务名进行路由
          enabled: true

常用的断言

当我们启动Gateway服务时,发现控制台打印了一串Predicate

官方文档有详细说明:https://docs.spring.io/spring-cloud-gateway/docs/2.2.5.RELEASE/reference/html/#gateway-request-predicates-factories
这里不做过多介绍。

filter

filter分为两种,一个是GatewayFilter,一种是GlobalFilter。

GatewayFilter

没啥好说的,官网写的很清楚。https://docs.spring.io/spring-cloud-gateway/docs/2.2.5.RELEASE/reference/html/#gatewayfilter-factories
举例:

spring:
  application:
    name: cloud-gateway
  cloud:
    gateway:
      routes:
        - id:  payment_routh
          #uri: http://localhost:8001
          uri: lb://CLOUD-PAYMENT-SERVICE
          predicates:
            - Path=/payment/get/**
            #- After=2020-09-06T21:57:48.289+08:00[Asia/Shanghai]
          filters:
            #过滤器工厂会在匹配的请求头上加上一对请求头,名称为X-Request-red值是blue
            - AddRequestHeader=X-Request-red, blue

自定义全局GlobalFilter:

需要实现两个接口,GlobalFilter和Ordered。

@Slf4j
@Component
public class MyGlobalFilter implements GlobalFilter, Ordered {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        String name = exchange.getRequest().getQueryParams().getFirst("name");
        if(StringUtils.isBlank(name)){
            log.info("非法用户");
            exchange.getResponse().setStatusCode(HttpStatus.BAD_REQUEST);
            return exchange.getResponse().setComplete();
        }
        return chain.filter(exchange);
    }

    @Override
    public int getOrder() {
        return 0;
    }
}

运行效果:

原文地址:https://www.cnblogs.com/wwjj4811/p/13622633.html