使用网关的必须性
简单总结:
服务发现让服务消费者总能找到服务提供者
配置服务器从而高效管理微服务的配置
使用Ribbon完成负载均衡
使用Feign让远程调用更高有效
使用Resilience4j进行服务容错
使用Spring Cloud Stream完成MQ通信
本章来详细探讨网关
可以简单把API网关当做nginx,但是API网关不仅仅只有反向代理的功能,还有很多其他的功能
如果微服务架构不使用API网关可以吗?
浏览器直接把服务打到微服务上面?当然也是可以的,每一个服务集群都通过对应的nginx来转发。但是当微服务非常多的时候,多域名以及认证授权,都比较麻烦。
目前通常还是通过浏览器发送请求到API网关,通过网关转发请求,此外也可以通过网关完成协议转换、登录授权、跨域等各种问题。
API网关对比与选择
Zuul or Spring Cloud Gateway?
Zuul已经进入维护模式
Spring Cloud Gateway是什么?
Spring Cloud Gateway优点
Spring Cloud Gateway缺点
编写Spring Cloud Gateway
编写Spring Cloud Gateway
<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.0modelVersion>
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-parentartifactId>
<version>2.2.2.RELEASEversion>
<relativePath />
parent>
<groupId>com.cloudgroupId>
<artifactId>ms-gatewayartifactId>
<version>0.0.1-SNAPSHOTversion>
<name>ms-gatewayname>
<description>Demo project for Spring Bootdescription>
<properties>
<java.version>1.8java.version>
properties>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-consul-discoveryartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-actuatorartifactId>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-gatewayartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-devtoolsartifactId>
dependency>
dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-dependenciesartifactId>
<version>Hoxton.SR1version>
<type>pomtype>
<scope>importscope>
dependency>
dependencies>
dependencyManagement>
<repositories>
<repository>
<id>spring-snapshotsid>
<name>Spring Snapshotsname>
<url>https://repo.spring.io/libs-snapshoturl>
<snapshots>
<enabled>trueenabled>
snapshots>
repository>
<repository>
<id>spring-milestonesid>
<name>Spring Milestonesname>
<url>https://repo.spring.io/libs-milestoneurl>
<snapshots>
<enabled>falseenabled>
snapshots>
repository>
<repository>
<id>spring-releasesid>
<name>Spring Releasesname>
<url>https://repo.spring.io/libs-releaseurl>
<snapshots>
<enabled>falseenabled>
snapshots>
repository>
repositories>
<build>
<plugins>
<plugin>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-maven-pluginartifactId>
plugin>
<plugin>
<groupId>org.apache.maven.pluginsgroupId>
<artifactId>maven-compiler-pluginartifactId>
<configuration>
<source>1.8source>
<target>1.8target>
configuration>
plugin>
plugins>
build>
project>
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
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);
}
}
实现对微服务的反向代理
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架构
核心概念
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
先来探讨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
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
* 1.读取配置文件里面的配置,并注入到config参数里面来
* 2. 判断当前时间是否满足要求
*/
@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
自定义过滤器工厂
org.springframework.cloud.gateway.filter.factory.RequestSizeGatewayFilterFactory
org.springframework.cloud.gateway.filter.factory.AddRequestHeaderGatewayFilterFactory
exchange.getRequest().mutate().xxx // 修改request
exchange.mutate().xxx // 修改exchange
chain.filter(exchange) // 传递给下一个过滤器处理
exchange.getResponse() // 拿到响应
修改配置文件 添加配置
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的对应段落,就可以作为这边的消息体啦。
操作完成后,可再次访问 ${GATEWAY_URL}/actuator/gateway/routes 端点,可以看到,新的路由已被动态添加了。
TIPS
如果没有实时生效,使用refresh端点刷新一下路由信息即可。