微服务当前这么火爆的程度,如果不能学会一种微服务框架技术。怎么能升职加薪,增加简历的筹码?spring cloud 和 Dubbo 需要单独学习。说没有时间?没有精力?要学俩个框架?而Spring Cloud alibaba只需要你学会一个就会拥有俩种微服务治理框架技术。何乐而不为呢?加油吧!骚猿年
上一篇我们讲述了gateway 的路由功能其实也类似与zuul服务的路由转发。
今天主要讲一下断言机制。
内置的断言工厂
介绍 Spring Cloud Gateway将路由作为Spring WebFlux HandlerMapping基础架构的一部分进行匹配。Spring Cloud Gateway包括许多内置的Route Predicate工厂。所有这些断言都与HTTP请求的不同属性匹配。多个Route Predicate工厂可以合并,也可以通过逻辑合并
可以看到gateway 提供如此之多丰富的断言,方式。
- 比如说时间控住的,我们能想到秒杀场景。
- ip 的我们能想到金丝雀测试
- 权重我们可以使用灰度等等场景的应用
具体使用还得参照业务场景来选择更适合我们的业务场景。
gateway 过滤器 分为全局过滤器,个性化过滤器
gateway 已经给我们提供了非常丰富的过滤器
-
AddRequestHeader GatewayFilter工厂采用名称和值参数。
这会将X-Request-Foo:Bar标头添加到所有匹配请求的下游请求的标头中。 spring:
cloud:
gateway:
routes:
- id: add_request_header_route
uri: https://example.org
filters:
- AddRequestHeader=X-Request-Foo, Bar AddRequestHeader知道用于匹配路径或主机的URI变量。URI变量可用于该值,并将在运行时扩展。 spring:
cloud:
gateway:
routes:
- id: add_request_header_route
uri: https://example.org
predicates:
- Path=/foo/{segment}
filters:
- AddRequestHeader=X-Request-Foo, Bar-{segment}
-AddResponseHeader GatewayFilter工厂采用名称和值参数。
spring:
cloud:
gateway:
routes:
- id: add_request_parameter_route
uri: https://example.org
filters:
- AddRequestParameter=foo, bar
这将添加foo=bar到所有匹配请求的下游请求的查询字符串中。
AddRequestParameter知道用于匹配路径或主机的URI变量。URI变量可用于该值,并将在运行时扩展。
spring:
cloud:
gateway:
routes:
- id: add_request_parameter_route
uri: https://example.org
predicates:
- Host: {segment}.myhost.org
filters:
- AddRequestParameter=foo, bar-{segment}
-
AddResponseHeader GatewayFilter工厂采用名称和值参数。
spring:
cloud:
gateway:
routes:
- id: add_response_header_route
uri: https://example.org
filters:
- AddResponseHeader=X-Response-Foo, Bar这会将X-Response-Foo:Bar标头添加到所有匹配请求的下游响应的标头中。
AddResponseHeader知道用于匹配路径或主机的URI变量。URI变量可用于该值,并将在运行时扩展。
spring:
cloud:
gateway:
routes:
- id: add_response_header_route
uri: https://example.org
predicates:
- Host: {segment}.myhost.org
filters:
- AddResponseHeader=foo, bar-{segment} -
DedupeResponseHeader GatewayFilter工厂采用一个name参数和一个可选strategy参数。name可以包含标题名称列表,以空格分隔。
spring:
cloud:
gateway:
routes:
- id: dedupe_response_header_route
uri: https://example.org
filters:
- DedupeResponseHeader=Access-Control-Allow-Credentials Access-Control-Allow-Origin如果网关CORS逻辑和下游逻辑都添加了重复的值Access-Control-Allow-Credentials和Access-Control-Allow-Origin响应标头,则这将删除它们。
DedupeResponseHeader过滤器还接受可选strategy参数。可接受的值为RETAIN_FIRST(默认值)RETAIN_LAST,和RETAIN_UNIQUE
-
Hystrix是Netflix的一个库,用于实现断路器模式。Hystrix GatewayFilter允许您将断路器引入网关路由,保护您的服务免受级联故障的影响,并允许您在下游故障的情况下提供后备响应
要在项目中启用Hystrix GatewayFilters,请spring-cloud-starter-netflix-hystrix从Spring Cloud Netflix添加依赖项。Hystrix GatewayFilter工厂需要一个name参数,它是的名称HystrixCommand。
spring:
cloud:
gateway:
routes:
- id: hystrix_route
uri: https://example.org
filters:
- Hystrix=myCommandName
这会将其余的过滤器包装在HystrixCommand带有命令名的中myCommandName。
Hystrix过滤器还可以接受可选fallbackUri参数。当前,仅forward:支持计划的URI。如果调用了后备,则请求将被转发到与URI相匹配的控制器。
spring:
cloud:
gateway:
routes:
- id: hystrix_route
uri: lb://backing-service:8088
predicates:
- Path=/consumingserviceendpoint
filters:
- name: Hystrix
args:
name: fallbackcmd
fallbackUri: forward:/incaseoffailureusethis
- RewritePath=/consumingserviceendpoint, /backingserviceendpoint
/incaseoffailureusethis调用Hystrix后备时,它将转发到URI。请注意,此示例还通过lb目标URI 上的前缀演示了(可选)Spring Cloud Netflix Ribbon负载平衡。
主要方案是对fallbackUri网关应用程序中的内部控制器或处理程序使用。但是,也可以将请求重新路由到外部应用程序中的控制器或处理程序,如下所示:
spring:
cloud:
gateway:
routes:
- id: ingredients
uri: lb://ingredients
predicates:
- Path=//ingredients/**
filters:
- name: Hystrix
args:
name: fetchIngredients
fallbackUri: forward:/fallback
- id: ingredients-fallback
uri: http://localhost:9994
predicates:
- Path=/fallback
在此示例中,fallback网关应用程序中没有终结点或处理程序,但是另一个应用程序中有一个终结点或处理程序,在下注册localhost:9994。
如果将请求转发给后备,则Hystrix网关过滤器还会提供Throwable引起请求的。它已ServerWebExchange作为 ServerWebExchangeUtils.HYSTRIX_EXECUTION_EXCEPTION_ATTR属性添加到,可以在网关应用程序中处理后备时使用。
对于外部控制器/处理程序方案,可以添加带有异常详细信息的标头。您可以在FallbackHeaders GatewayFilter Factory部分中找到有关它的更多信息。
Hystrix设置(例如超时)可以使用全局默认值配置,也可以使用Hystrix Wiki上说明的应用程序属性在逐条路由的基础上进行配置。
要为上述示例路由设置5秒超时,将使用以下配置:
hystrix.command.fallbackcmd.execution.isolation.thread.timeoutInMilliseconds: 5000
- 该FallbackHeaders工厂可以让你在转发到请求的头部添加猬执行异常的详细信息fallbackUri在以下情况下在外部应用程序
spring:
cloud:
gateway:
routes:
- id: ingredients
uri: lb://ingredients
predicates:
- Path=//ingredients/**
filters:
- name: Hystrix
args:
name: fetchIngredients
fallbackUri: forward:/fallback
- id: ingredients-fallback
uri: http://localhost:9994
predicates:
- Path=/fallback
filters:
- name: FallbackHeaders
args:
executionExceptionTypeHeaderName: Test-Header
在此示例中,在运行时发生执行异常后HystrixCommand,该请求将转发到在上fallback运行的应用中的端点或处理程序localhost:9994。具有异常类型,消息和-if available-根本原因异常类型和消息的标头将由FallbackHeaders过滤器添加到该请求。
通过设置下面列出的参数的值及其默认值,可以在配置中覆盖标头的名称:
- executionExceptionTypeHeaderName("Execution-Exception-Type")
- executionExceptionMessageHeaderName("Execution-Exception-Message")
- rootCauseExceptionTypeHeaderName("Root-Cause-Exception-Type")
- rootCauseExceptionMessageHeaderName("Root-Cause-Exception-Message")
您可以在Hystrix GatewayFilter Factory部分中找到有关Hystrix如何与Gateway一起工作的更多信息。
-
MapRequestHeader GatewayFilter工厂采用'fromHeader'和'toHeader'参数。它创建一个新的命名标头(toHeader),并从传入的HTTP请求中从现有的命名标头(fromHeader)中提取值。如果输入标头不存在,则过滤器不起作用。如果新的命名标头已经存在,则其值将使用新值进行扩充。
spring:
cloud:
gateway:
routes:
- id: map_request_header_route
uri: https://example.org
filters:
- MapRequestHeader=Bar, X-Request-Foo
这会将X-Request-Foo:标头添加到下游请求的标头中,其中包含来自传入的HTTP请求Bar标头的更新值。
- PrefixPath GatewayFilter工厂采用单个prefix参数。
spring:
cloud:
gateway:
routes:
- id: prefixpath_route
uri: https://example.org
filters:
- PrefixPath=/mypath
这将/mypath作为所有匹配请求的路径的前缀。因此,对的请求/hello将发送给/mypath/hello。
-
PreserveHostHeader GatewayFilter工厂没有参数。此过滤器设置请求属性,路由过滤器将检查该请求属性,以确定是否应发送原始主机头,而不是由HTTP客户端确定的主机头。
spring:
cloud:
gateway:
routes:
- id: preserve_host_route
uri: https://example.org
filters:
- PreserveHostHeader RequestRateLimiter GatewayFilter Factory使用一种RateLimiter实现来确定是否允许继续当前请求。如果不是,HTTP 429 - Too Many Requests则返回状态(默认)。此过滤器采用一个可选keyResolver参数和特定于速率限制器的参数。
Redis RateLimiter GatewayFilter工厂 redis实现基于Stripe所做的工作。它需要使用spring-boot-starter-data-redis-reactiveSpring Boot启动器。
RedirectTo GatewayFilter工厂采用status和url参数。状态应该是300系列重定向http代码,例如301。URL应该是有效的URL。这将是Location标题的值
RemoveHopByHopHeadersFilter GatewayFilter工厂从转发的请求中删除标头。被删除的头的默认列表来自IETF。
RemoveRequestHeader GatewayFilter工厂采用一个name参数。它是要删除的标题的名称。
RemoveResponseHeader GatewayFilter工厂采用一个name参数。它是要删除的标题的名称。
RemoveRequestParameter GatewayFilter工厂采用一个name参数。它是要删除的查询参数的名称。
RewritePath GatewayFilter工厂采用路径regexp参数和replacement参数。这使用Java正则表达式提供了一种灵活的方式来重写请求路径。
RewriteLocationResponseHeader GatewayFilter工厂Location通常会修改响应标头的值,以摆脱后端特定的详细信息。这需要stripVersionMode,locationHeaderName,hostValue,和protocolsRegex参数。
该RewriteResponseHeader GatewayFilter厂需要name,regexp和replacement参数。它使用Java正则表达式以灵活的方式重写响应标头值。
SaveSession GatewayFilter Factory 在向下游转发呼叫之前强制执行WebSession::save操作。这在将Spring Session之类的东西与惰性数据存储一起使用时特别有用,并且需要确保在进行转发呼叫之前已保存会话状态。
SetPath GatewayFilter工厂采用路径template参数。通过允许路径的模板段,它提供了一种操作请求路径的简单方法。这使用了Spring Framework中的uri模板。允许多个匹配段。
SetRequestHeader GatewayFilter工厂采用name和value参数。
SetResponseHeader GatewayFilter工厂采用name和value参数
SetStatus GatewayFilter工厂采用单个status参数。它必须是有效的Spring HttpStatus。它可以是整数值404或枚举的字符串表示形式NOT_FOUND
StripPrefix GatewayFilter工厂采用一个参数parts。该parts参数指示在向下游发送请求之前,要从请求中剥离的路径中的零件数
重试GatewayFilter工厂
RequestSize GatewayFilter工厂 当请求大小大于允许的限制时,RequestSize GatewayFilter Factory可以限制请求到达下游服务。过滤器将RequestSize参数作为请求的允许大小限制(以字节为单位
修改请求正文GatewayFilter工厂 该过滤器被认为是BETA,API将来可能会更改 此过滤器可用于在网关将请求主体发送到下游之前修改请求主体。
默认过滤器 如果您想添加过滤器并将其应用于所有路由,则可以使用spring.cloud.gateway.default-filters。该属性采用过滤器列表
全局过滤器 该GlobalFilter接口具有与相同的签名GatewayFilter。这些是特殊过滤器,有条件地应用于所有路由。(此界面和用法可能会在将来的里程碑中更改)。
全局过滤器和GatewayFilter的组合订购
因为spring cloud gateway 提供的内置过滤器太多了。不在这里一一介绍
可以查看官方的文档 进行了解学习
https://cloud.spring.io/spring-cloud-gateway/reference/html/
接下来讲一下,全局过滤器GlobalFilter接口。
- GlobalFilter 和 GatewayFilter 的 #filter(ServerWebExchange, GatewayFilterChain) 方法签名一致;
- GlobalFilter会作用于所有的路由上;
- 在未来的里程碑版本中可能作一些调整;
可以看一下默认的实现的全局过滤器 ,除去AuthorizeFilter过滤器都是默认的过滤器
具体的里面的作用,其实上面的已经有了简单的描述不在复述。有兴趣的同学可以看看里面的实现,都是利用过滤器做转发或者一些对流量请求的修改、鉴权、等操作
可以通过actuator 模块监控查询 GlobalFilter实现类
1、pom引入spring-boot-starter-actuator 。因为之前就直接在parent pom 进行了引入操作。不再次引入
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
2、配置文件bootstrap.yml中开启监控管理端点
management:
endpoints:
web:
exposure:
include: "*"
endpoint:
health:
show-details: ALWAYS
3、请求浏览器 http://localhost:9000/actuator/gateway/globalfilters
{
org.springframework.cloud.gateway.filter.AdaptCachedBodyGlobalFilter@4b957db0: -2147482648,
org.springframework.cloud.gateway.filter.WebsocketRoutingFilter@273fa9e: 2147483646,
com.xian.cloud.filter.AuthorizeFilter@4b03cbad: 0,
org.springframework.cloud.gateway.filter.ForwardRoutingFilter@8840c98: 2147483647,
org.springframework.cloud.gateway.filter.NettyRoutingFilter@5c313224: 2147483647,
org.springframework.cloud.gateway.filter.NettyWriteResponseFilter@1e1e837d: -1,
org.springframework.cloud.gateway.filter.RouteToRequestUrlFilter@5d71b500: 10000,
org.springframework.cloud.gateway.filter.LoadBalancerClientFilter@5b29ab61: 10100,
org.springframework.cloud.gateway.filter.GatewayMetricsFilter@527a8665: -2147473648,
org.springframework.cloud.gateway.filter.ForwardPathFilter@626b639e: 0
}
观察这些实现类。都是实现 GlobalFilter、Ordered俩个接口
实现自己的全局过滤器
创建 AuthorizeFilter
package com.xian.cloud.filter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpHeaders;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
/**
* <Description>
*
* @author xianliru@100tal.com
* @version 1.0
* @createDate 2019/11/04 18:06
*/
@Component
@Slf4j
public class AuthorizeFilter implements GlobalFilter, Ordered {
private static final String AUTHORIZE_TOKEN = "Authorization";
private static final String AUTHORIZE_UID = "uid";
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpRequest request = exchange.getRequest();
HttpHeaders headers = request.getHeaders();
ServerHttpRequest.Builder mutate = request.mutate();
String token = headers.getFirst( AUTHORIZE_TOKEN );
String uid = headers.getFirst( AUTHORIZE_UID );
String method = request.getMethodValue();
log.info( "AuthorizeFilter token 全局过滤器 token:{},uid:{}",token,uid );
if (token == null) {
token = request.getQueryParams().getFirst( AUTHORIZE_TOKEN );
}
if(StringUtils.isNotBlank(token)){
//TODO 权限验证
}
return chain.filter( exchange );
}
@Override
public int getOrder() {
return 0;
}
}
然后启动服务。
curl http://localhost:9000/client/client/test
日志打印
[2019-11-05 19:30:52.802] [INFO ] com.xian.cloud.filter.AuthorizeFilter - AuthorizeFilter token 全局过滤器 token:null,uid:null
下一篇我们将介绍定制的过滤器,针对下游服务对应过滤器
摘自参考 spring cloud 官方文档
服务器nacos 地址 http://47.99.209.72:8848/nacos
往期地址 spring cloud alibaba 地址
Spring Cloud Alibaba (nacos 注册中心搭建)
Spring Cloud Alibaba 使用nacos 注册中心
Spring Cloud Alibaba nacos 配置中心使用
Spring Cloud alibaba网关 sentinel zuul 四 限流熔断
如何喜欢可以关注分享本公众号。
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。转载请附带公众号二维码