Spring Cloud Gateway服务网关 ,SpringCloud Gateway作为Spring Cloud生态系统中的网关,目标是替代Zuul, 在Spring Cloud 2.0以上版本中,没有对新版本的Zuul 2.0以上最新高性能版本进行集成,仍然还是使用的Zuul 1.x非Reactor模式的老版本。而为了提升网关的能,SpringCloud Gateway是基于WebFlux框架实现的,而WebFlux框架底层则使用了高性能的Reactor模式通信框架Netty。Spring Cloud Gateway的目标提供统-的路由方式且基于Filter 链的方式提供了网关基本的功能,例如:安全,监控/指标,和限流。

1. Gateway特性

Spring Cloud Gateway有下面几种特性

  1. 基于Spring]Framework 5, Project Reactor和Spring Boot 2.0进行构建;
  2. 动态路由:能够匹配任何请求属性;
  3. 可以对路由指定Predicate (断言)和Filter (过滤器) ;
  4. 集成Hystrix的断路器功能;
  5. 集成Spring Cloud服务发现功能;
  6. 易于编写的Predicate (断言)和Filter (过滤器) ;
  7. 请求限流功能;
  8. 支持路径重写。

2. Gataway 相关概念

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

3. Gateway简单实用

新建 cloud-gateway-gateway9527 服务

3.1 pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>live.yremp.springcloud</artifactId>
        <groupId>live.yremp</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>cloud-gateway-gateway9527</artifactId>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>
        <!--eureka client-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
    </dependencies>
</project>

3.2 application.yml

server:
  port: 9527

spring:
  application:
    name: cloud-gateway
  cloud:
    gateway:
      routes:
        - id: payment-route1
          uri: http://localhost:8001
          predicates:
          - Path=/payment/get/**
        - id: payment-route2
          uri: http://localhost:8001
          predicates:
          - Path=/payment/lb/**

eureka:
  instance:
    hostname: cloud-gateway-service
  client:
    register-with-eureka: true
    fetch-registry: true
    service-url:
      #defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka
      defaultZone: http://eureka7001.com:7001/eureka

3.3 主启动类

package live.yremp.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;

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

3.4 路由测试

访问8001项目的 payment/get/{id} 接口

访问8001项目的 /payment/lb/ 接口

3.5 代码配置路由

除了配置文件,还可以用代码的形式配置路由,下面以代码配置访问百度国际/国内 为例,新建一个Gateway配置类,经行路由配置:

package live.yremp.springcloud.config;

import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class GatewayConfig {
    @Bean
    public RouteLocator customerRouteLocator1(RouteLocatorBuilder r){
        RouteLocatorBuilder.Builder routes = r.routes();
        routes.route("live.yremp.route1",x->x.path("/guonei").uri("http://news.baidu.com/guonei"));
        return routes.build();
    }
    @Bean
    public RouteLocator customerRouteLocator2(RouteLocatorBuilder r){
        RouteLocatorBuilder.Builder routes = r.routes();
        routes.route("live.yremp.route2",x->x.path("/guoji").uri("http://news.baidu.com/guoji"));
        return routes.build();
    }
}

3.6 访问测试

4. 动态路由配置

默认情况下Gateway会根据注册中心注册的服务列表,以注册中心,上微服务名为路径创建动态路由进行转发,从而实现动态路由的功能。

4.1 修改配置文件

server:
  port: 9527

spring:
  application:
    name: cloud-gateway
  cloud:
    gateway:
      discovery:
        locator:
          enabled: true  #开启从注册中心创建动态路由的功能
      routes:
        - id: payment-route1
#          uri: http://localhost:8001
          uri: lb://cloud-payment-service #微服务名称访问
          predicates:
          - Path=/payment/get/**
        - id: payment-route2
#          uri: http://localhost:8001
          uri: lb://cloud-payment-service #微服务名称访问
          predicates:
          - Path=/payment/lb/**

eureka:
  instance:
    hostname: cloud-gateway-service
  client:
    register-with-eureka: true
    fetch-registry: true
    service-url:
      #defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka
      defaultZone: http://eureka7001.com:7001/eureka

4.2 重启服务测试

修改完配置文件,重启服务,测试接口访问情况以及负载均衡情况

可以实现使用微服务名称从注册中心动态的路由访问微服务

5. 常用内置 Predicate

Gateway有很多内置的Predicate,例如After、Before、Between、Cookie、Header、Host、Method、Path、Query、RemoteAddr、Weight等等。他们之间是AND的关系,同时满足路由规则才能被访问到。

5.1 After

After设置的时间之后才能访问,先设置一个已经过时的时间测试

server:
  port: 9527

spring:
  application:
    name: cloud-gateway
  cloud:
    gateway:
      discovery:
        locator:
          enabled: true  #开启从注册中心创建动态路由的功能
      routes:
        - id: payment-route1
#          uri: http://localhost:8001
          uri: lb://cloud-payment-service
          predicates:
          - Path=/payment/get/**
        - id: payment-route2
#          uri: http://localhost:8001
          uri: lb://cloud-payment-service
          predicates:
          - Path=/payment/lb/**
          - After=2020-07-15T13:02:37.008+08:00[Asia/Shanghai] #在这个时间之后这个请求才能访问

eureka:
  instance:
    hostname: cloud-gateway-service
  client:
    register-with-eureka: true
    fetch-registry: true
    service-url:
      #defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka
      defaultZone: http://eureka7001.com:7001/eureka

测试访问

修改为一个未来的时间

server:
  port: 9527

spring:
  application:
    name: cloud-gateway
  cloud:
    gateway:
      discovery:
        locator:
          enabled: true  #开启从注册中心创建动态路由的功能
      routes:
        - id: payment-route1
#          uri: http://localhost:8001
          uri: lb://cloud-payment-service
          predicates:
          - Path=/payment/get/**
        - id: payment-route2
#          uri: http://localhost:8001
          uri: lb://cloud-payment-service
          predicates:
          - Path=/payment/lb/**
          - After=2020-07-15T16:02:37.008+08:00[Asia/Shanghai] #在这个时间之后这个请求才能访问

eureka:
  instance:
    hostname: cloud-gateway-service
  client:
    register-with-eureka: true
    fetch-registry: true
    service-url:
      #defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka
      defaultZone: http://eureka7001.com:7001/eureka

再次测试访问,404错误

5.2 Before

表示在指定的时间之前才能访问

-Before=2020-07-15T16:02:37.008+08:00[Asia/Shanghai]

5.3 Between

-Between=2020-07-15T16:02:37.008+08:00[Asia/Shanghai],2020-07-15T17:02:37.008+08:00[Asia/Shanghai]

5.4 Cookie

配置之后需要带有特定的Cookie才能访问

- id: payment-route2
#          uri: http://localhost:8001
          uri: lb://cloud-payment-service
          predicates:
          - Path=/payment/lb/**
          - After=2020-07-15T12:02:37.008+08:00[Asia/Shanghai] #在这个时间之后这个请求才能访问
          - Cookie=username,yremp #需要带有指定的Cookie才能访问

使用 下面命令带上Cookie访问

curl http://localhost:9527/payment/lb --cookie "username=yremp"

如果不带cookie则会返回404错误

curl http://localhost:9527/payment/lb 

6. Filter过滤器

实际上自定义过滤器使用的更多

package live.yremp.springcloud.filter;

import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.lang.annotation.Annotation;

@Component
public class MyGatewayFilter implements GlobalFilter, Ordered {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        System.out.println("*****************开始执行自行定义过滤器");
        String username=exchange.getRequest().getQueryParams().getFirst("username");
        if(username==null){
            System.out.println("*****************用户名为null,非法请求");
            exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
            return exchange.getResponse().setComplete();
        }
        return chain.filter(exchange);
    }

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

测试一下请求参数里面必须有username

如果没有

标签云

ajax AOP Bootstrap cdn Chevereto CSS Docker Editormd GC Github Hexo IDEA JavaScript jsDeliver JS樱花特效 JVM Linux Live2D markdown Maven MyBatis MyBatis-plus MySQL Navicat Oracle Pictures QQ Sakura SEO Spring Boot Spring Cloud Spring Cloud Alibaba SpringMVC Thymeleaf Vue Web WebSocket Wechat Social WordPress Yoast SEO 代理 分页 图床 小幸运 通信原理

Spring Cloud Gateway服务网关
Spring Cloud Gateway服务网关