目录:
1.词汇表
2.工作原理
3.配置路由谓词工厂和网关过滤工厂
········一. 熔断
········二. 限流
········三. 重试
········四. 请求大小
········五. 默认过滤器(全局)
········六. 全局过滤器
················1).结合全局过滤器和网关过滤器排序
········七. HTTP超时配置
················1).全局超时
················2).单个路由超时
········八. CORS跨域
········九. 执行器API
················1).详细执行器格式
················2).检索路由过滤器
························1>.全局过滤器
························2>.路由过滤器
················3).刷新路由缓存
················4).检索网关中定义的路由
················5).检索关于特定路由的信息
················6).创建和删除特定路线
················7).重述:所有端点的列表
* Spring Cloud Gateway是基于Spring Boot 2.x,Spring WebFlux和Project Reactor 构建的。因此,当您使用Spring Cloud Gateway时,许多您熟悉的同步库(例如,Spring Data和Spring Security)和模式可能不适用。如果您不熟悉这些项目,建议您在使用Spring Cloud Gateway之前先阅读它们的文档以熟悉一些新概念。
* Spring Cloud Gateway需要Spring Boot和Spring Webflux提供的Netty运行时。它在传统的Servlet容器中或作为WAR构建时不能工作。
1.词汇表
- 路线:网关的基本构建块。它由ID,目标URI,谓词集合和过滤器集合定义。如果聚合谓词为true,则匹配路由。
- 谓词:这是Java 8 Function谓词。输入类型是Spring Framework ServerWebExchange。这使您可以匹配HTTP请求中的所有内容,例如标头或参数。
- Filter:这些是使用特定工厂构造的Spring Framework GatewayFilter实例。在这里,您可以在发送下游请求之前或之后修改请求和响应。
2.工作原理
下图从总体上概述了Spring Cloud Gateway的工作方式:
客户端向Spring Cloud Gateway发出请求。如果网关处理程序映射确定请求与路由匹配,则将其发送到网关Web处理程序。该处理程序通过特定于请求的过滤器链来运行请求。筛选器由虚线分隔的原因是,筛选器可以在发送代理请求之前和之后运行逻辑。所有“前置”过滤器逻辑均被执行。然后发出代理请求。发出代理请求后,将运行“后”过滤器逻辑。
3.配置路由谓词工厂和网关过滤工厂
spring:
cloud:
gateway:
routes:
- id: remoteaddr_route #唯一标识
uri: https://example.org #转发路径
predicates: #谓词集合
- After=2017-01-20T17:42:47.789-07:00[America/Denver] #匹配在指定日期时间之后发生的请求
- Before=2017-01-20T17:42:47.789-07:00[America/Denver] #匹配在指定日期时间之前发生的请求
- Between=2017-01-20T17:42:47.789-07:00[America/Denver], 2017-01-21T17:42:47.789-07:00[America/Denver] #匹配在指定日期之后及指定日期之前的请求
- Header=X-Request-Id, \d+ #标头路由谓词工厂
- Host=**.somehost.org,**.anotherhost.org #主机路由谓词工厂
- Cookie=mycookie,mycookievalue #cookie路由谓词工厂
- Method=GET,POST #方法路由(该路由支持post和get)
- Path=/red/{segment},/blue/{segment} #路径路由(匹配/red/..或/blue/..的路由)
- Query=green #查询路由(匹配带green参数的路由)
- Query=red, gree. # 如果请求包含一个red查询参数,其值与gree(正则)匹配,则前面的路由将匹配。
- RemoteAddr=192.168.1.1/24 #远程地址路由(如果请求的远程地址是192.168.1.10,则此路由匹配。)
#===========
- id: weight_high
uri: https://weighthigh.org
predicates:
- Weight=group1, 8
- id: weight_low
uri: https://weightlow.org
predicates:
- Weight=group1, 2
备注:
1.要设置时间可以搜索 "America/Denver时间"来根据情况设置
重要:
* 1).当spring cloud 的版本为Hoxton.RELEASE,gateway的版本显示为2.2.0,这个时候 - Method=GET,POST配置只有GET生效,spring cloud的版本改为Hoxton.SR3全部生效
一. 熔断
Netflix已经将Hystrix置于维护模式。我们建议您使用带有Resilience4J的Spring Cloud断路器网关过滤器,因为对Hystrix的支持将在未来的版本中被移除
Resilience4j 是受Netflix的Hysrix项目启发,专门为Java 8 和函数式编程设计的轻量级容错框架。
**Hystrix是Netflix的一个实现断路器模式的库。Hystrix网关过滤器允许您将断路器引入网关路由,保护您的服务免受级联故障的影响,并允许您在下游故障时提供后备响应。**
- 使用断路器功能
- 1).第一步在gateway服务中导入pom依赖
<!--hystrix-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
- 2).在application.yml中配置
- id: FallbackController # 断路器
uri: lb://data
predicates:
- Path=/fall
filters:
- name: Hystrix
args:
name: fallbackcmd
fallbackUri: forward:/defaultFallback
- id: defaultFallback # 熔断方法
uri: lb://data
predicates:
- Path=/defaultFallback
hystrix:
command:
fallbackcmd:
execution:
isolation:
thread:
timeoutInMilliseconds: 5000 #超时时间,若不设置超时时间则有可能无法触发熔断
- 3).配置回调方法
@RestController
public class HystrixController {
@GetMapping("/defaultFallback")
public Map<String,Object> fallback() {
Map<String,Object> map = new HashMap<String,Object>();
map.put("Code",100);
map.put("Message","服务暂时不可用");
return map;
}
}
-
备注:
在上面2).yml配置中触发熔断后转发路由,需要转发到一个新的实例上,这样才能正常的触发熔断。
二. 限流
重要:
使用限流功能,必须配合Redis使用(切记切记!!!)
在本地测试不写redis的配置会默认去连接localhost:6379,找不到将无法正常使用限流功能。
- 使用限流功能
- 1).第一步在gateway服务中导入pom依赖
<!--限流-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis-reactive</artifactId>
<version>${spring-boot.version}</version>
</dependency>
2).在application.yml中配置
示例代码:
- id: RateLimiterOneController
uri: lb://data
predicates:
- Path=/RateLimiterOne/demo
filters:
- name: RequestRateLimiter # 使用限流名称必须是这个
args:
redis-rate-limiter.replenishRate: 10 # 允许用户每秒执行多少请求
redis-rate-limiter.burstCapacity: 20 # 用户在一秒内允许的最大求请数,设置为0将阻塞所有请求
redis-rate-limiter.requestedTokens: 1 # 表示一个请求需要多少个令牌
Key-resolver: "#{@userKeyResolver}" # 没有这个参数请求将无法进入(方法在gateway启动类中)
#如设置replenishRate =1 requestedTokens = 60和burstCapacity = 60将导致限制1请求/分钟
3).配置限流的方式
备注:
gateway了解到的限流的方式有三种分别为(用户),(uri),(Hostname)
- 方式一:
@SpringBootApplication
@EnableDiscoveryClient
public class GatawayApplication {
public static void main(String[] args) {
SpringApplication.run(GatawayApplication.class, args);
}
/**
* 根据用户维度限流(用户,uri,主机名三选一)
* @return
*/
@Bean
KeyResolver userKeyResolver() {
return exchange -> Mono.just(exchange.getRequest().getQueryParams().getFirst("user"));
}
/**
* 根据hostname限流
* @return
*/
// @Bean
// KeyResolver hostAddrKeyResolver() {
// return exchange -> Mono.just(exchange.getRequest().getRemoteAddress().getAddress().getHostAddress());
// }
/**
* 根据uri限流
* @return
*/
// @Bean
// KeyResolver uriKeyResolver() {
// return exchange -> Mono.just(exchange.getRequest().getURI().getPath());
// }
}
- 方式二:
@Component
public class MyKeyResolver {
/**
* 根据用户维度限流(用户,uri,主机名三选一)
* @return
*/
@Bean
KeyResolver userKeyResolver() {
return exchange -> Mono.just(exchange.getRequest().getQueryParams().getFirst("user"));
}
}
.....
测试结果:
如上面yml的配置,一个主机/用户/uri每秒只能请求10次,超出10次将返回429的错误。
三. 重试
当将重试过滤器与任何具有主体的HTTP方法一起使用时,主体将被缓存,并且网关将受到内存的限制。正文被缓存在由定义的请求属性中
ServerWebExchangeUtils.CACHED_REQUEST_BODY_ATTR
。对象的类型是org.springframework.core.io.buffer.DataBuffer
。
The following defaults are configured for Retry
filter, if enabled:
retries
: Three timesseries
: 5XX seriesmethods
: GET methodexceptions
:IOException
andTimeoutException
backoff
: disabled
- id: RetryController
uri: lb://data
predicates:
- Path=/Retry/test
filters:
- name: Retry
args:
retries: 3 # 重试次数(默认为3次)
statuses: BAD_GATEWAY,INTERNAL_SERVER_ERROR # 应重试的 HTTP状态码
methods: GET,POST # 应该重试的HTTP方法
#series: # 要重试的一系列状态代码
exceptions: java.io.IOException # 应重试的引发异常的列表
#backoff: # 为重试配置的指数回退(默认关闭)
#firstBackoff: 10ms
#maxBackoff: 50ms
#factor: 3
#basedOnPreviousValue: false # 是否基于以前的数值为基础
四. 请求大小
当请求大小大于允许的限制时,RequestSize GatewayFilter工厂可以限制请求到达下游服务。过滤器接受maxSize参数。maxSize是一个Datasize类型,因此可以将值定义为一个数字,后跟一个可选的DataUnit后缀,如“KB”或“MB”。字节的默认值是“B”。这是允许的尺寸限制。
spring:
cloud:
gateway:
routes:
- id: request_size_route
uri: http://localhost:8080/upload
predicates:
- Path=/upload
filters:
- name: RequestSize
args:
maxSize: 5000000
- RequestSize GatewayFilter工厂将响应状态设置为413负载太大,并在请求因大小而被拒绝时附加一个报头errorMessage。下面的例子显示了这样一个错误消息:
errorMessage` : `Request size is larger than permissible limit. Request size is 6.0 MB where permissible limit is 5.0 MB
五. 默认过滤器(全局)
要添加过滤器并将其应用于所有路由,可以使用
spring.cloud.gateway.default-filters
。此属性采用过滤器列表。
spring:
cloud:
gateway:
default-filters:
- AddResponseHeader=X-Response-Default-Red, Default-Blue
- PrefixPath=/httpbin
六. 全局过滤器
GlobalFilter接口具有与网关过滤器相同的签名。这些是有条件地应用于所有路由的特殊过滤器。
- 注意:
- 这个接口和它的用法可能会在将来的milestone版本中发生变化
1).结合全局过滤器和网关过滤器排序
gateway没有zuul那样丰富的生命周期,只有 “pre” 和 “post”
由于Spring Cloud Gateway对筛选逻辑执行的“前置”和“后置”阶段进行了区分,因此优先级最高的筛选器是“前置”阶段的第一个筛选器,是“后置”阶段的最后一个筛选器。
方式一:
@Component
public class CustomGlobalFilter implements Ordered, GlobalFilter {
/**
* 执行时机,返回数值越小越先执行
* @return
*/
@Override
public int getOrder() {
return -1;
}
/**
* 过滤器
* @param exchange 当前服务器交换
* @param chain 提供委托到下一个筛选器的方法
* @return
*/
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
String user = exchange.getRequest().getQueryParams().getFirst("user");
// 判断参数中有user这个参数,将继续执行,没有将返回,本次请求结束
if (StringUtils.isBlank(user)) {
System.err.println("没有用户");
return null;
}
System.err.println("first....");
return chain.filter(exchange);
}
}
方式二:
@Bean
@Order(2)
public GlobalFilter first() {
return (exchange,chain) ->{
System.err.println("前置--one.....");
return chain.filter(exchange).then(Mono.fromRunnable(() -> {
System.err.println("后置---1.....");
}));
};
}
2).Forward Routing Filter
3).LoadBalancerClient Filter
4).Netty Routing Filter
5).Netty Write Response Filter
6).RouteToRequestUrl Filter
7).Websocket Routing Filter
8).Gateway Metrics Filter
9).Marking An Exchange As Routed
参考文章:
http://www.imooc.com/article/290821
七. HTTP超时配置
可以为所有路由配置Http超时(响应和连接),并为每个特定路由覆盖Http超时
1).全局超时
要配置全局http超时:
connect-timeout
必须以毫秒为单位指定。
response-timeout
必须指定为java.time.Duration
spring:
cloud:
gateway:
httpclient: # 全局配置
connect-timeout: 1000 # 连接超时
response-timeout: 5s # 响应超时
2).单个路由超时
要配置每个路由超时:
connect-timeout
必须以毫秒为单位指定。
response-timeout
必须以毫秒为单位指定。
- id: per_route_timeouts
uri: https://example.org
predicates:
- name: Path
args:
pattern: /delay/{timeout}
metadata:
response-timeout: 200
connect-timeout: 200
八. CORS跨域
方式一:
package com.ntimes.gateway.Cors;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.reactive.CorsWebFilter;
import org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource;
/**
* @author FEI
* @apiNote 跨域配置
*/
@Configuration
public class CorsConfig {
@Bean
public CorsWebFilter corsWebFilter() {
UrlBasedCorsConfigurationSource urlBasedCorsConfigurationSource = new UrlBasedCorsConfigurationSource();
//cors跨域配置对象
CorsConfiguration corsConfiguration = new CorsConfiguration();
//是否允许携带cookie
corsConfiguration.setAllowCredentials(true);
//允许跨域访问的域名,可填写具体域名,*代表允许所有访问
corsConfiguration.addAllowedOrigin("*");
//允许访问类型:get post 等,*代表所有类型
corsConfiguration.addAllowedMethod("*");
// 允许访问头
corsConfiguration.addAllowedHeader("*");
//配置源对象
urlBasedCorsConfigurationSource.registerCorsConfiguration("/**", corsConfiguration);
//cors 过滤器对象 注意!CorsWebFilter不要导错包
return new CorsWebFilter(urlBasedCorsConfigurationSource);
}
}
方式二:
spring:
cloud:
gateway:
globalcors:
cors-configurations:
'[/**]':
allowedOrigins: "https://docs.spring.io"
allowedMethods:
- GET
九. 执行器API
网关执行器端点允许您监视Spring云网关应用程序并与之交互。要进行远程访问,必须在应用程序属性中通过HTTP或JMX启用和公开端点。
- 第一步导入依赖
<!--执行器-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
- 第二步增加配置
# 执行器配置
# 默认为true
management.endpoint.gateway.enabled=true
management.endpoints.web.exposure.include=gateway
备注:
除了以上配置不用再配置别的信息
1).详细执行器格式
Spring Cloud Gateway增加了一种新的、更详细的格式。它为每个路由添加了更多的细节,允许您查看与每个路由关联的谓词和过滤器,以及任何可用的配置。
- 示例:
- http://127.0.0.1:9001/actuator/gateway/routes
[
{
"predicate": "(Hosts: [**.addrequestheader.org] && Paths: [/headers], match trailing slash: true)",
"route_id": "add_request_header_test",
"filters": [
"[[AddResponseHeader X-Response-Default-Foo = 'Default-Bar'], order = 1]",
"[[AddRequestHeader X-Request-Foo = 'Bar'], order = 1]",
"[[PrefixPath prefix = '/httpbin'], order = 2]"
],
"uri": "lb://testservice",
"order": 0
}
]
- 默认情况下启用此功能。要禁用它,请设置以下属性:
spring.cloud.gateway.actuator.verbose.enabled=false
2).检索路由过滤器
1>.全局过滤器
要检索应用于所有路由的全局过滤器
- 示例:
- GET请求
- http://127.0.0.1:9001/actuator/gateway/globalfilters
{
"org.springframework.cloud.gateway.filter.LoadBalancerClientFilter@77856cc5": 10100,
"org.springframework.cloud.gateway.filter.RouteToRequestUrlFilter@4f6fd101": 10000,
"org.springframework.cloud.gateway.filter.NettyWriteResponseFilter@
"org.springframework.cloud.gateway.filter.ForwardRoutingFilter@10
"org.springframework.cloud.gateway.filter.NettyRoutingFilter@1fbd
"org.springframework.cloud.gateway.filter.ForwardPathFilter@33a71
"org.springframework.cloud.gateway.filter.AdaptCachedBodyGlobalFilter@135064ea": 2147483637,
"org.springframework.cloud.gateway.filter.WebsocketRoutingFilter@23c05889": 2147483646
}
- 该响应包含已就位的全局筛选器的详细信息。对于每个全局过滤器,都有一个过滤器对象的字符串表示形式(例如
org.springframework.cloud.gateway.filter.LoadBalancerClientFilter@77856cc5
)和过滤器链中的相应顺序。
2>.路由过滤器
要检索应用于路由的网关过滤器工厂
- 示例:
- GET请求
- http://127.0.0.1:9001/actuator/gateway/routefilters
{
"[AddRequestHeaderGatewayFilterFactory@570ed9c configClass = AbstractNameValueGatewayFilterFactory.NameValueConfig]": null,
"[SecureHeadersGatewayFilterFactory@fceab5d configClass = Object]": null,
"[SaveSessionGatewayFilterFactory@4449b273 configClass = Object]": null
}
- 响应包含应用于任何特定路由的GatewayFilter工厂的详细信息。对于每个工厂,对应的对象都有一个字符串表示(例如,[SecureHeadersGatewayFilterFactory@fceab5d configClass = Object1)。注意,null值是由于端点控制器的实现不完整造成的,因为它试图在过滤器链中设置对象的顺序,而这并不适用于GatewayFilter工厂对象。
3).刷新路由缓存
若要清除路由缓存,请向/actuator/gateway/routes 发送PoST请求。请求返回一个没有响应体的200。
4).检索网关中定义的路由
要检索网关中定义的路由
- 示例:
- GET请求
- http://127.0.0.1:9001/actuator/gateway/routes
[{
"route_id": "first_route",
"route_object": {
"predicate": "org.springframework.cloud.gateway.handler.predicate.PathRoutePredicateFactory$$Lambda$432/1736826640@1e9d7e7d",
"filters": [
"OrderedGatewayFilter{delegate=org.springframework.cloud.gateway.filter.factory.PreserveHostHeaderGatewayFilterFactory$$Lambda$436/674480275@6631ef72, order=0}"
]
},
"order": 0
},
{
"route_id": "second_route",
"route_object": {
"predicate": "org.springframework.cloud.gateway.handler.predicate.PathRoutePredicateFactory$$Lambda$432/1736826640@cd8d298",
"filters": []
},
"order": 0
}]
- 响应包含网关中定义的所有路由的详细信息。下表描述了响应的每个元素(每个都是一个路由)的结构:
Path | Type | Description |
---|---|---|
route_id | String | The route ID. |
route_object.predicate | Object | The route predicate. |
route_object.filters | Array | The GatewayFilter factories applied to the route. |
order | Number | The route order. |
5).检索关于特定路由的信息
要检索关于单个路由的信息
- 示例:
- GET
- http://127.0.0.1:9001/actuator/gateway/routes/{id }
{
"id": "first_route",
"predicates": [{
"name": "Path",
"args": {"_genkey_0":"/first"}
}],
"filters": [],
"uri": "https://www.uri-destination.org",
"order": 0
}]
- 下表描述了响应的结构:
Path | Type | Description |
---|---|---|
id | String | 路由 ID. |
predicates | Array | 路由谓词的集合。每个项目都定义给定谓词的名称和自变量 |
filters | Array | 应用于路线的过滤器集合。 |
uri | String | 路由的目标URI。 |
order | Number | 路线顺序。 |
6).创建和删除特定路线
创建路由:
- 示例:
- POST
- http://127.0.0.1:9001/gateway/routes/{id_route_to_create}
- JSON格式同上
删除路由:
- 示例:
- DELETE
- http://127.0.0.1:9001/gateway/routes/{id_route_to_delete}
7).重述:所有端点的列表
下面的表格总结了Spring Cloud Gateway执行器端点(注意每个端点都有
/actuator/gateway
作为基本路径)
D | HTTP Method | Description |
---|---|---|
globalfilters | GET | 显示应用于路由的全局过滤器列表 |
routefilters | GET | 显示GatewayFilter 应用于特定路线的工厂列表。 |
refresh | POST | 清除路由缓存 |
routes | GET | 显示网关中定义的路由列表 |
routes/{id} | GET | 显示有关特定路线的信息 |
routes/{id} | POST | 将新路由添加到网关 |
routes/{id} | DELETE | 从网关中删除现有路由 |