10 API网关-Spring Cloud GateWay

使用网关的必须性

简单总结:

服务发现让服务消费者总能找到服务提供者

配置服务器从而高效管理微服务的配置

使用Ribbon完成负载均衡

使用Feign让远程调用更高有效

使用Resilience4j进行服务容错

使用Spring Cloud Stream完成MQ通信

本章来详细探讨网关

可以简单把API网关当做nginx,但是API网关不仅仅只有反向代理的功能,还有很多其他的功能

如果微服务架构不使用API网关可以吗?

浏览器直接把服务打到微服务上面?当然也是可以的,每一个服务集群都通过对应的nginx来转发。但是当微服务非常多的时候,多域名以及认证授权,都比较麻烦。

目前通常还是通过浏览器发送请求到API网关,通过网关转发请求,此外也可以通过网关完成协议转换、登录授权、跨域等各种问题。
在这里插入图片描述

API网关对比与选择

Zuul or Spring Cloud Gateway?

Zuul已经进入维护模式

Spring Cloud Gateway是什么?

  1. Spring Cloud出品的网关
  2. 底层是Netty、Reactor、WebFlux

Spring Cloud Gateway优点

  1. 是第一代网关zuul的1.6倍
  2. 功能强大,内置了很多实用功能,比如转发、监控、限流等
  3. 设计优雅 易于扩展 可以说是Spring产品的共同优点

Spring Cloud Gateway缺点

  1. 依赖Netty与Webflux,有一定的适应成本
  2. 不能在Servlet容器下工作,也不能构建WAR包
  3. 不支持Spring Boot 1.x

编写Spring Cloud Gateway

编写Spring Cloud Gateway

  1. 创建一个新的maven项目 ms-gateway
<?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">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.2.2.RELEASE</version>
		<relativePath /> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.cloud</groupId>
	<artifactId>ms-gateway</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>ms-gateway</name>
	<description>Demo project for Spring Boot</description>
	<properties>
		<java.version>1.8</java.version>
	</properties>
    	<dependencies>
    		<dependency>
    			<groupId>org.springframework.boot</groupId>
    			<artifactId>spring-boot-starter-test</artifactId>
    			<scope>test</scope>
    		</dependency>
    		<dependency>
    			<groupId>org.springframework.cloud</groupId>
    			<artifactId>spring-cloud-starter-consul-discovery</artifactId>
    		</dependency>
    		<dependency>
    			<groupId>org.springframework.boot</groupId>
    			<artifactId>spring-boot-starter-actuator</artifactId>
    		</dependency>
    		<dependency>
    			<groupId>org.springframework.cloud</groupId>
    			<artifactId>spring-cloud-starter-gateway</artifactId>
    		</dependency>
    		<dependency>
    			<groupId>org.springframework.boot</groupId>
    			<artifactId>spring-boot-devtools</artifactId>
    		</dependency>
    	</dependencies>
    
    	<dependencyManagement>
    		<dependencies>
    			<dependency>
    				<groupId>org.springframework.cloud</groupId>
    				<artifactId>spring-cloud-dependencies</artifactId>
    				<version>Hoxton.SR1</version>
    				<type>pom</type>
    				<scope>import</scope>
    			</dependency>
    		</dependencies>
    	</dependencyManagement>
    
    	<repositories>
    		<repository>
    			<id>spring-snapshots</id>
    			<name>Spring Snapshots</name>
    			<url>https://repo.spring.io/libs-snapshot</url>
    			<snapshots>
    				<enabled>true</enabled>
    			</snapshots>
    		</repository>
    		<repository>
    			<id>spring-milestones</id>
    			<name>Spring Milestones</name>
    			<url>https://repo.spring.io/libs-milestone</url>
    			<snapshots>
    				<enabled>false</enabled>
    			</snapshots>
    		</repository>
    		<repository>
    			<id>spring-releases</id>
    			<name>Spring Releases</name>
    			<url>https://repo.spring.io/libs-release</url>
    			<snapshots>
    				<enabled>false</enabled>
    			</snapshots>
    		</repository>
    	</repositories>
    
    	<build>
    		<plugins>
    			<plugin>
    				<groupId>org.springframework.boot</groupId>
    				<artifactId>spring-boot-maven-plugin</artifactId>
    			</plugin>
    			<plugin>
    				<groupId>org.apache.maven.plugins</groupId>
    				<artifactId>maven-compiler-plugin</artifactId>
    				<configuration>
    					<source>1.8</source>
    					<target>1.8</target>
    				</configuration>
    			</plugin>
    		</plugins>
    	</build>
    </project>
  1. 编写配置文件
    server:
      port: 8040
    spring:
      application:
        name: ms-gateway
      cloud:
        consul:
          host: localhost
          port: 8500
          discovery:
            instance-id: ${spring.application.name}-${server.port}-${spring.cloud.client.hostname}
            tags: JIFANG=NJ
        gateway:
          discovery:
            locator:
            # 让gateway从服务发现组件中找到微服务,并反向代理
              enabled: true
    management:
      endpoints:
        web:
          exposure:
            include: '*'
      endpoint:
        health:
          show-details: always
  1. 编写启动类
    package com.cloud.gateway;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    
    @SpringBootApplication
    public class MsGatewayApplication {
    
    	public static void main(String[] args) {
    		SpringApplication.run(MsGatewayApplication.class, args);
    	}
    }
  1. 启动微服务
  2. 查看consul控制台 http://localhost:8500/ui/dc1/services
    在这里插入图片描述
    可以看到用户微服务、课程微服务和网关微服务都已经注册到consul中了

实现对微服务的反向代理

http://localhost:8040/ms-class/lesssons/buy/1

    {"id":1,"title":"SpringCloud视频教程","cover":"xxx","price":5,"description":"SpringCloud视频教程","createTime":"2020-02-15T15:50:35.000+0000","videoUrl":"https://ke.qq.com/classroom/index.html"}

http://localhost:8040/ms-user/users/1

    {"id":1,"username":"itmuch","password":"1111","money":3,"role":"user","regTime":"2020-02-15T14:37:20.000+0000"}

转发规律:访问${gateway_url}/{微服务x}/** 会转发到微服务X的/**路径

Spring Cloud GateWay架构

核心概念

  1. 路由(Route)
    Spring Cloud Gateway的基础元素,可简单理解成一条转发的规则。包含:ID、目标URL、Predicate集合以及Filter集合
  2. 谓词(Predicate)
    即java.util.function.Predicate、Spring Cloud Gateway使用Predicate实现路由的匹配条件
  3. 过滤器(Filter)
    修改请求以及响应
    spring:      
      cloud:
        gateway:
          routes:
          - id: some_route
            uri: https://www.baidu.com
            predicates:
            - Path=/users/1
            filters:
            - AddRequestHeader=X-Request-Foo,Bar

比如上面的配置就表示一个路由,它表达的意思,如果访问Spring Cloud Gateway的路径/users/1,就会匹配到这个路由,这个路由会转发到https://www.baidu.com这个地址,并且使用AddRequestHeader去做相应的业务处理。而目前我们没有进行这样的配置,而是采用了默认的方式。其实Spring Cloud Gateway提供了灵活的配置。

架构剖析
在这里插入图片描述

相关源码:

GatewayHandlerMapping:

org.springframework.cloud.gateway.handler.RoutePredicateHandlerMapping

GatewayWebHandler:

org.springframework.cloud.gateway.handler.FilteringWebHandler.class

路由谓词工厂详解

内置路由谓词工厂

TIPS

本文基于Spring Cloud Hoxton M2编写,兼容Spring Cloud Finchley及更高版本。

这一节来详细探讨Spring Cloud Gateway的路由谓词工厂 (Route Predicate Factories),路由谓词工厂的作用是:符合Predicate的条件,就使用该路由的配置,否则就不管。 只要掌握这一句,掌握路由谓词工厂就比较轻松了。

TIPS

Predicate是Java 8提供的一个函数式编程接口。

本文探讨了Spring Cloud Gateway中内置的谓词工厂,包括:

谓词工厂
After
Before
Between
Cookie
Header
Host
Method
Path
Query
RemoteAddr

  1. 路由配置的两种形式

先来探讨Spring Cloud Gateway路由配置的两种姿势:

a 路由到指定URL

示例1:通配

    spring:
      cloud:
        gateway:
          routes:
          - id: {唯一标识}
            uri: http://www.itmuch.com

表示访问 GATEWAY_URL/** 会转发到 http://www.itmuch.com/**

TIPS

这段配置不能直接使用,需要和下面的Predicate配合使用才行。

示例2:精确匹配

    spring:
      cloud:
        gateway:
          routes:
          - id: {唯一标识}
            uri: http://www.itmuch.com/spring-cloud/spring-cloud-stream-pan-ta/

表示访问 GATEWAY_URL/spring-cloud/spring-cloud-stream-pan-ta/ 会转发到 http://www.itmuch.com/spring-cloud/spring-cloud-stream-pan-ta/

TIPS

这段配置不能直接使用,需要和下面的Predicate配合使用才行。

b 路由到服务发现组件上的微服务

示例1:通配

    spring:
      cloud:
        gateway:
          routes:
          - id: {唯一标识}
            # lb://表示从服务发现组件上找到指定微服务
            uri: lb://ms-user

表示访问 GATEWAY_URL/** 会转发到 ms-user 微服务的 /**

TIPS

这段配置不能直接使用,需要和下面的Predicate配合使用才行。

示例2:精确匹配

    spring:
      cloud:
        gateway:
          routes:
          - id: {唯一标识}
            # lb://表示从服务发现组件上找到指定微服务
            uri: lb://ms-user/shares/1

表示访问 GATEWAY_URL/shares/1 会转发到 ms-user 微服务的 /shares/1

TIPS

这段配置不能直接使用,需要和下面的Predicate配合使用才行。

谓词工厂详解

下面正式探讨路由谓词工厂。Spring Cloud Gateway提供了十来种路由谓词工厂。为网关实现灵活的转发提供了基石。

After

示例:

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

TIPS

  • 技巧:时间可使用 System.out.println(ZonedDateTime.now()); 打印,然后即可看到时区。例如:2019-08-10T16:50:42.579+08:00[Asia/Shanghai]
  • 时间格式的相关逻辑:
    • 默认时间格式:org.springframework.format.support.DefaultFormattingConversionService#addDefaultFormatters
    • 时间格式注册:org.springframework.format.datetime.standard.DateTimeFormatterRegistrar#registerFormatters

Before

示例:

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

Between

示例:

    spring:
      cloud:
        gateway:
          routes:
            - id: between_route
              uri: lb://ms-user
              predicates:
                # 当且仅当请求时的时间Between配置的时间时,才会转发到用户微服务
                # 因此,访问localhost:8040/** -> ms-user/**
                # eg. 访问http://localhost:8040/users/1 -> ms-user/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_route
              uri: lb://ms-user
              predicates:
                # 当且仅当带有名为somecookie,并且值符合正则ch.p的Cookie时,才会转发到用户微服务
                # 如Cookie满足条件,则访问http://localhost:8040/** -> ms-user/**
                # eg. 访问http://localhost:8040/users/1 -> ms-user/users/1
                - Cookie=somecookie, ch.p

Header

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

Host

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

Method

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

Path

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

TIPS

建议大家看下这一部分的官方文档,里面有个segment编程技巧。比较简单,留个印象。

https://cloud.spring.io/spring-cloud-static/Greenwich.SR2/single/spring-cloud.html#_path_route_predicate_factory

Query

示例1:

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

示例2:

    spring:
      cloud:
        gateway:
          routes:
            - id: query_route
              uri: lb://ms-user
              predicates:
                # 当且仅当请求带有名为foo的参数,且参数值符合正则ba.,才会转发到用户微服务
                # eg. 访问http://localhost:8040/users/1?baz=baz -> ms-user的/users/1?baz=baz
                - Query=foo, ba.

RemoteAddr

示例:

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

TIPS

建议大家看下这一部分的官方文档,有个小编程技巧。比较简单,留个印象。

https://cloud.spring.io/spring-cloud-static/Greenwich.SR2/single/spring-cloud.html#_remoteaddr_route_predicate_factory

相关代码
在这里插入图片描述

自定义路由谓词工厂

限制09:00-17:00才能访问

    package com.cloud.gateway.config;
    
    import java.time.LocalTime;
    
    public class TimeConfig {
    
    	private LocalTime startTime;
    	private LocalTime endTime;
    
    	public LocalTime getStartTime() {
    		return startTime;
    	}
    
    	public void setStartTime(LocalTime startTime) {
    		this.startTime = startTime;
    	}
    
    	public LocalTime getEndTime() {
    		return endTime;
    	}
    
    	public void setEndTime(LocalTime endTime) {
    		this.endTime = endTime;
    	}
    }
    package com.cloud.gateway.config;
    
    import java.time.LocalTime;
    import java.time.format.DateTimeFormatter;
    import java.time.format.FormatStyle;
    import java.util.Arrays;
    import java.util.List;
    import java.util.function.Predicate;
    
    import org.springframework.cloud.gateway.handler.predicate.AbstractRoutePredicateFactory;
    import org.springframework.stereotype.Component;
    import org.springframework.web.server.ServerWebExchange;
    
    /**
     * Spring Cloud Gateway的路由谓词工厂必须以RoutePredicateFactory结尾 配置文件就写 TimeBetween
     * <li>1.读取配置文件里面的配置,并注入到config参数里面来</li>
     * <li>2. 判断当前时间是否满足要求</li>
     */
    @Component
    public class TimeBetweenRoutePredicateFactory extends AbstractRoutePredicateFactory<TimeConfig> {
    
    	public TimeBetweenRoutePredicateFactory() {
    		super(TimeConfig.class);
    	}
    
    	@Override
    	public Predicate<ServerWebExchange> apply(TimeConfig config) {
    		LocalTime startTime = config.getStartTime();
    		LocalTime endTime = config.getEndTime();
    		LocalTime now = LocalTime.now();
    		return serverWebExchange -> now.isAfter(startTime) && now.isBefore(endTime);
    	}
    
    	@Override
    	public List<String> shortcutFieldOrder() {
    		// -TimeBetween:xxx,xxxx 会自动从配置中读取配置为startTime,endTime
    		return Arrays.asList("startTime", "endTime");
    	}
    	
    	public static void main(String[] args) {
    		DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedTime(FormatStyle.SHORT);
    		String format = formatter.format(LocalTime.now());
    		System.out.println(format);
    		// 下午10:19
    	}
    }
  spring:
    cloud:
      gateway:
        discovery:
          locator:
          # 让gateway从服务发现组件中找到微服务,并反向代理
            enabled: true
        routes:
        - id: between_route
          uri: lb://ms-class
          predicates:
          - TimeBetween=上午09:00,下午05:00

http://localhost:8040/ms-class/lesssons/buy/1 可以正常访问

http://localhost:8040/lesssons/buy/1 404

修改配置

     - TimeBetween=上午09:00,下午11:59

http://localhost:8040/lesssons/buy/1

    {"id":1,"title":"SpringCloud视频教程","cover":"xxx","price":5,"description":"SpringCloud视频教程","createTime":"2020-02-15T15:50:35.000+0000","videoUrl":"https://ke.qq.com/classroom/index.html"}

http://localhost:8040/ms-class/lesssons/buy/1 404

过滤器工厂详解

内置过滤器工厂

https://blog.csdn.net/m0_37607945/article/details/104521104

自定义过滤器工厂

  1. 自定义过滤器工厂的方式
    继承AbstractGatewayFilterFactory
    参考示例:org.springframework.cloud.gateway.filter.factory.RequestSizeGatewayFilterFactory
    继承AbstractNameValueGatewayFilterFactory (上面方法的简化)
    参考示例:org.springframework.cloud.gateway.filter.factory.AddRequestHeaderGatewayFilterFactory
  2. 核心API
   exchange.getRequest().mutate().xxx   // 修改request
   exchange.mutate().xxx       // 修改exchange
   chain.filter(exchange)         //  传递给下一个过滤器处理
   exchange.getResponse()    // 拿到响应
  1. 编写一个过滤器工厂

修改配置文件 添加配置

server:
  port: 8040
spring:
  application:
    name: ms-gateway
  cloud:
    consul:
      host: localhost
      port: 8500
      discovery:
        instance-id: ${spring.application.name}-${server.port}-${spring.cloud.client.hostname}
        tags: JIFANG=NJ
    gateway:
      discovery:
        locator:
        # 让gateway从服务发现组件中找到微服务,并反向代理
          enabled: true
      routes:
      - id: between_route
        uri: lb://ms-class
        predicates:
        - TimeBetween=上午09:00,下午11:59
        filters:
        - MyLog=aaa,bbb
management:
  endpoints:
    web:
      exposure:
        include: '*'
  endpoint:
    health:
      show-details: always

实现一个过滤器

 package com.cloud.gateway.config;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.cloud.gateway.filter.GatewayFilter;
    import org.springframework.cloud.gateway.filter.factory.AbstractNameValueGatewayFilterFactory;
    import org.springframework.http.server.reactive.ServerHttpRequest;
    import org.springframework.stereotype.Component;
    import org.springframework.web.server.ServerWebExchange;
    
    @Component
    public class MyLogGatewayFilterFactory extends AbstractNameValueGatewayFilterFactory {
    
    	private static final Logger logger = LoggerFactory.getLogger(MyLogGatewayFilterFactory.class);
    
    	@Override
    	public GatewayFilter apply(NameValueConfig config) {
    		return ((exchange, chain) -> {
                // 注意日志打印的地方
    			logger.info("请求进来了,key={},value={}", config.getName(), config.getValue());
    			// 修改request
    			ServerHttpRequest modifiedRequest = exchange.getRequest().mutate().build();
    			// 修改exchange
    			ServerWebExchange modifiedExchange = exchange.mutate().request(modifiedRequest).build();
    			// 传递到下一个过滤器
    			return chain.filter(modifiedExchange);
    		});
    	}
    }

启动项目

2020-02-26 17:21:55.405  INFO 14072 --- [  restartedMain] .e.DevToolsPropertyDefaultsPostProcessor : Devtools property defaults active! Set 'spring.devtools.add-properties' to 'false' to disable

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.2.2.RELEASE)

2020-02-26 17:21:56.684  INFO 14072 --- [  restartedMain] com.cloud.gateway.MsGatewayApplication   : No active profile set, falling back to default profiles: default
2020-02-26 17:21:58.072  WARN 14072 --- [  restartedMain] o.s.boot.actuate.endpoint.EndpointId     : Endpoint ID 'service-registry' contains invalid characters, please migrate to a valid format.
2020-02-26 17:21:58.217  INFO 14072 --- [  restartedMain] o.s.cloud.context.scope.GenericScope     : BeanFactory id=0a39ad9f-f451-3db9-836c-212717c66611
2020-02-26 17:21:58.367  INFO 14072 --- [  restartedMain] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.client.loadbalancer.reactive.LoadBalancerBeanPostProcessorAutoConfiguration' of type [org.springframework.cloud.client.loadbalancer.reactive.LoadBalancerBeanPostProcessorAutoConfiguration] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2020-02-26 17:21:58.370  INFO 14072 --- [  restartedMain] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.client.loadbalancer.reactive.LoadBalancerBeanPostProcessorAutoConfiguration$ReactiveLoadBalancerConfig' of type [org.springframework.cloud.client.loadbalancer.reactive.LoadBalancerBeanPostProcessorAutoConfiguration$ReactiveLoadBalancerConfig] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2020-02-26 17:21:58.373  INFO 14072 --- [  restartedMain] trationDelegate$BeanPostProcessorChecker : Bean 'deferringLoadBalancerExchangeFilterFunction' of type [org.springframework.cloud.client.loadbalancer.reactive.DeferringLoadBalancerExchangeFilterFunction] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2020-02-26 17:21:58.510  WARN 14072 --- [  restartedMain] c.n.c.sources.URLConfigurationSource     : No URLs will be polled as dynamic configuration sources.
2020-02-26 17:21:58.511  INFO 14072 --- [  restartedMain] c.n.c.sources.URLConfigurationSource     : To enable URLs as dynamic configuration sources, define System property archaius.configurationSource.additionalUrls or make config.properties available on classpath.
2020-02-26 17:21:58.516  WARN 14072 --- [  restartedMain] c.n.c.sources.URLConfigurationSource     : No URLs will be polled as dynamic configuration sources.
2020-02-26 17:21:58.516  INFO 14072 --- [  restartedMain] c.n.c.sources.URLConfigurationSource     : To enable URLs as dynamic configuration sources, define System property archaius.configurationSource.additionalUrls or make config.properties available on classpath.
2020-02-26 17:22:01.852  INFO 14072 --- [  restartedMain] o.s.c.g.r.RouteDefinitionRouteLocator    : Loaded RoutePredicateFactory [TimeBetween]
2020-02-26 17:22:01.852  INFO 14072 --- [  restartedMain] o.s.c.g.r.RouteDefinitionRouteLocator    : Loaded RoutePredicateFactory [After]
2020-02-26 17:22:01.852  INFO 14072 --- [  restartedMain] o.s.c.g.r.RouteDefinitionRouteLocator    : Loaded RoutePredicateFactory [Before]
2020-02-26 17:22:01.852  INFO 14072 --- [  restartedMain] o.s.c.g.r.RouteDefinitionRouteLocator    : Loaded RoutePredicateFactory [Between]
2020-02-26 17:22:01.852  INFO 14072 --- [  restartedMain] o.s.c.g.r.RouteDefinitionRouteLocator    : Loaded RoutePredicateFactory [Cookie]
2020-02-26 17:22:01.852  INFO 14072 --- [  restartedMain] o.s.c.g.r.RouteDefinitionRouteLocator    : Loaded RoutePredicateFactory [Header]
2020-02-26 17:22:01.852  INFO 14072 --- [  restartedMain] o.s.c.g.r.RouteDefinitionRouteLocator    : Loaded RoutePredicateFactory [Host]
2020-02-26 17:22:01.853  INFO 14072 --- [  restartedMain] o.s.c.g.r.RouteDefinitionRouteLocator    : Loaded RoutePredicateFactory [Method]
2020-02-26 17:22:01.853  INFO 14072 --- [  restartedMain] o.s.c.g.r.RouteDefinitionRouteLocator    : Loaded RoutePredicateFactory [Path]
2020-02-26 17:22:01.853  INFO 14072 --- [  restartedMain] o.s.c.g.r.RouteDefinitionRouteLocator    : Loaded RoutePredicateFactory [Query]
2020-02-26 17:22:01.853  INFO 14072 --- [  restartedMain] o.s.c.g.r.RouteDefinitionRouteLocator    : Loaded RoutePredicateFactory [ReadBodyPredicateFactory]
2020-02-26 17:22:01.853  INFO 14072 --- [  restartedMain] o.s.c.g.r.RouteDefinitionRouteLocator    : Loaded RoutePredicateFactory [RemoteAddr]
2020-02-26 17:22:01.853  INFO 14072 --- [  restartedMain] o.s.c.g.r.RouteDefinitionRouteLocator    : Loaded RoutePredicateFactory [Weight]
2020-02-26 17:22:01.853  INFO 14072 --- [  restartedMain] o.s.c.g.r.RouteDefinitionRouteLocator    : Loaded RoutePredicateFactory [CloudFoundryRouteService]
2020-02-26 17:22:02.402  INFO 14072 --- [  restartedMain] o.s.b.a.e.web.EndpointLinksResolver      : Exposing 19 endpoint(s) beneath base path '/actuator'
2020-02-26 17:22:02.696  WARN 14072 --- [  restartedMain] o.s.b.d.a.OptionalLiveReloadServer       : Unable to start LiveReload server
2020-02-26 17:22:03.712  WARN 14072 --- [  restartedMain] ockingLoadBalancerClientRibbonWarnLogger : You already have RibbonLoadBalancerClient on your classpath. It will be used by default. As Spring Cloud Ribbon is in maintenance mode. We recommend switching to BlockingLoadBalancerClient instead. In order to use it, set the value of `spring.cloud.loadbalancer.ribbon.enabled` to `false` or remove spring-cloud-starter-netflix-ribbon from your project.
2020-02-26 17:22:03.728  WARN 14072 --- [  restartedMain] eactorLoadBalancerClientRibbonWarnLogger : You have RibbonLoadBalancerClient on your classpath. LoadBalancerExchangeFilterFunction that uses it under the hood will be used by default. Spring Cloud Ribbon is now in maintenance mode, so we suggest switching to ReactorLoadBalancerExchangeFilterFunction instead. In order to use it, set the value of `spring.cloud.loadbalancer.ribbon.enabled` to `false` or remove spring-cloud-starter-netflix-ribbon from your project.
2020-02-26 17:22:03.747  INFO 14072 --- [  restartedMain] o.s.s.c.ThreadPoolTaskScheduler          : Initializing ExecutorService 'catalogWatchTaskScheduler'
2020-02-26 17:22:04.497  INFO 14072 --- [  restartedMain] o.s.b.web.embedded.netty.NettyWebServer  : Netty started on port(s): 8040
2020-02-26 17:22:04.510  INFO 14072 --- [  restartedMain] o.s.c.c.s.ConsulServiceRegistry          : Registering service with consul: NewService{id='ms-gateway-8040-B940-xquant-com', name='ms-gateway', tags=[JIFANG=NJ, secure=false], address='B940.xquant.com', meta=null, port=8040, enableTagOverride=null, check=Check{script='null', interval='10s', ttl='null', http='http://B940.xquant.com:8040/actuator/health', method='null', header={}, tcp='null', timeout='null', deregisterCriticalServiceAfter='null', tlsSkipVerify=null, status='null'}, checks=null}
2020-02-26 17:22:05.572  INFO 14072 --- [  restartedMain] com.cloud.gateway.MsGatewayApplication   : Started MsGatewayApplication in 11.431 seconds (JVM running for 12.614)

执行请求 :http://localhost:8040/lesssons/buy/1

控制台出现如下日志

2020-02-26 17:22:55.391  INFO 14072 --- [ctor-http-nio-3] c.c.g.config.MyLogGatewayFilterFactory   : 请求进来了,key=aaa,value=bbb
2020-02-26 17:22:55.706  INFO 14072 --- [ctor-http-nio-3] c.netflix.config.ChainedDynamicProperty  : Flipping property: ms-class.ribbon.ActiveConnectionsLimit to use NEXT property: niws.loadbalancer.availabilityFilteringRule.activeConnectionsLimit = 2147483647
2020-02-26 17:22:55.807  INFO 14072 --- [ctor-http-nio-3] c.n.u.concurrent.ShutdownEnabledTimer    : Shutdown hook installed for: NFLoadBalancer-PingTimer-ms-class
2020-02-26 17:22:55.808  INFO 14072 --- [ctor-http-nio-3] c.netflix.loadbalancer.BaseLoadBalancer  : Client: ms-class instantiated a LoadBalancer: DynamicServerListLoadBalancer:{NFLoadBalancer:name=ms-class,current list of Servers=[],Load balancer stats=Zone stats: {},Server stats: []}ServerList:null
2020-02-26 17:22:55.817  INFO 14072 --- [ctor-http-nio-3] c.n.l.DynamicServerListLoadBalancer      : Using serverListUpdater PollingServerListUpdater
2020-02-26 17:22:55.849  INFO 14072 --- [ctor-http-nio-3] c.netflix.config.ChainedDynamicProperty  : Flipping property: ms-class.ribbon.ActiveConnectionsLimit to use NEXT property: niws.loadbalancer.availabilityFilteringRule.activeConnectionsLimit = 2147483647
2020-02-26 17:22:55.861  INFO 14072 --- [ctor-http-nio-3] c.n.l.DynamicServerListLoadBalancer      : DynamicServerListLoadBalancer for client ms-class initialized: DynamicServerListLoadBalancer:{NFLoadBalancer:name=ms-class,current list of Servers=[192.168.56.1:8010],Load balancer stats=Zone stats: {unknown=[Zone:unknown;	Instance count:1;	Active connections count: 0;	Circuit breaker tripped count: 0;	Active connections per server: 0.0;]
},Server stats: [[Server:192.168.56.1:8010;	Zone:UNKNOWN;	Total Requests:0;	Successive connection failure:0;	Total blackout seconds:0;	Last connection made:Thu Jan 01 08:00:00 CST 1970;	First connection made: Thu Jan 01 08:00:00 CST 1970;	Active Connections:0;	total failure count in last (1000) msecs:0;	average resp time:0.0;	90 percentile resp time:0.0;	95 percentile resp time:0.0;	min resp time:0.0;	max resp time:0.0;	stddev resp time:0.0]
]}ServerList:ConsulServerList{serviceId='ms-class', tag=null}
2020-02-26 17:22:56.827  INFO 14072 --- [erListUpdater-0] c.netflix.config.ChainedDynamicProperty  : Flipping property: ms-class.ribbon.ActiveConnectionsLimit to use NEXT property: niws.loadbalancer.availabilityFilteringRule.activeConnectionsLimit = 2147483647

全局过滤器

https://blog.csdn.net/m0_37607945/article/details/104521185

过滤器执行顺序详解

全局过滤器 局部过滤器 执行顺序

结论1: 全局过滤器 order 越小 越靠前执行

结论2: 过滤器工厂的Order按配置顺序从1开始费赠

结论3:如果配置了默认过滤器,则由先执行相同Order的默认过滤器,再去执行过滤器工厂

结论4 :如需自行控制Order,可返回OrderedGatewayFilter

Spring Cloud Gateway的监控

http://localhost:8040/actuator/gateway/globalfilters 激活的过滤器以及Order

    {
    	"org.springframework.cloud.gateway.filter.RemoveCachedBodyFilter@70573abc": -2147483648,
    	"org.springframework.cloud.gateway.filter.GatewayMetricsFilter@131d6e20": 0,
    	"org.springframework.cloud.gateway.filter.AdaptCachedBodyGlobalFilter@4182d4e4": -2147482648,
    	"org.springframework.cloud.gateway.filter.NettyWriteResponseFilter@20bd4da6": -1,
    	"org.springframework.cloud.gateway.filter.LoadBalancerClientFilter@8466c15": 10100,
    	"org.springframework.cloud.gateway.filter.WebsocketRoutingFilter@ef97866": 2147483646,
    	"org.springframework.cloud.gateway.filter.NettyRoutingFilter@3f9f2779": 2147483647,
    	"org.springframework.cloud.gateway.filter.ForwardRoutingFilter@da88488": 2147483647,
    	"org.springframework.cloud.gateway.filter.RouteToRequestUrlFilter@4bcac667": 10000,
    	"org.springframework.cloud.gateway.filter.ForwardPathFilter@473238e6": 0
    }

http://localhost:8040/actuator/gateway/routefilters 展示所有的过滤器工厂 【GET】

http://localhost:8040/actuator/gateway/refresh 【POST】

http://localhost:8040/actuator/gateway/routes

http://localhost:8040/actuator/gateway/routes/between_route 展示指定id的路由的信息

    {
    	"predicate": "TimeBetweenRoutePredicateFactory$$Lambda$758/1478109756",
    	"route_id": "between_route",
    	"filters": ["[com.cloud.gateway.config.MyLogGatewayFilterFactory$$Lambda$761/1373266817@3a67c198, order = 1]"],
    	"uri": "lb://ms-class",
    	"order": 0
    }

只要为Spring Cloud Gateway添加Spring Boot Actuator( spring-boot-starter-actuator )的依赖,并将 gateway 端点暴露,即可获得若干监控端点,监控 & 操作Spring Cloud Gateway的方方面面。

management:
  endpoints:
    web:
      exposure:
        include: gateway

监控端点一览表:

TIPS
以下所有端点都挂在/actuator/gateway/ 下面。
例如:routes 的全路径是 /actuator/gateway/routes ,以此类推。

ID HTTP Method Description
globalfilters GET 展示所有的全局过滤器
routefilters GET 展示所有的过滤器工厂(GatewayFilter factories)
refresh POST【无消息体】 清空路由缓存
routes GET 展示路由列表,默认会展示详情,如果希望展示概要信息,添加 spring.cloud.gateway.actuator.verbose.enabled=false
routes/{id} GET 展示指定id的路由的信息
routes/{id} POST【消息体如下】 新增一个路由
routes/{id} DELETE【无消息体】 删除一个路由

其中,要想动态添加路由配置,只需发送POST请求,消息体如下:

    {
      "predicates": [
        {
          "name": "Path",
          "args": {
            "_genkey_0": "/test"
          }
        }
      ],
      "filters": [
        {
          "name": "AddRequestHeader",
          "args": {
            "_genkey_0": "X-Request-Foo",
            "_genkey_1": "Bar"
          }
        },
        {
          "name": "MyLog",
          "args": {
            "_genkey_0": "a",
            "_genkey_1": "b"
          }
        }
      ],
      "uri": "https://www.itmuch.com",
      "order": 0
    }

TIPS

技巧:消息体其实是有规律的,你可以先在配置文件中配置一个路由规则,然后访问 ${GATEWAY_URL}/actuator/gateway/routes 端点,找到每个路由id的对应段落,就可以作为这边的消息体啦。

如使用 POSTMAN 测试,可配置如下:
在这里插入图片描述

操作完成后,可再次访问 ${GATEWAY_URL}/actuator/gateway/routes 端点,可以看到,新的路由已被动态添加了。

TIPS

如果没有实时生效,使用refresh端点刷新一下路由信息即可。

发布了21 篇原创文章 · 获赞 1 · 访问量 333

猜你喜欢

转载自blog.csdn.net/m0_37607945/article/details/104522561
今日推荐