微服务系统中的服务非常多。如果每个服务都自己做鉴权、限流、日志输出,则非常不科学。所以可以通过网关的过滤器来处理这些工作。在用户访问各个服务前,应在网关层统一做好鉴权、限流等工作。
根据生命周期可以将Spring Cloud Gateway中的Filter分为"PRE"和"POST"两种:
**PRE:**代表在请求被路由之前执行该过滤器。此种过滤器可用来实现参数校验、权限校验、流量监控、日志输出、协议转换等工能
**POST:**代表在请求被路由到微服务之后执行该过滤器。此种过滤器可用来实现响应头的修改(如添加标准的HTTP Header)、收集统计信息和指标、将响应发送给客户端、输出日志、流量监控等功能
根据作用范围,Filter可以分为以下两种:
**GatewayFilter:**网关过滤器。此种过滤器只应用在单个路由或者一个分组的路由上
**GlobalFilter:**全局过滤器。此种过滤器会应用在所有的路由上
网关过滤器允许以某种方式修改传入的HTTP请求,或输出的HTTP响应。网关过滤器作用于特定路由。Spring Cloud Gateway内置了许多过滤器工厂来编写网关过滤器。
它用于在请求头中添加自定义的键值对。
它用于在请求中添加请求参数的键值对。
它用于在响应头中添加键值对。
它用于将断路器引入网关路由中,让服务免受级联故障的影响,并在故障时提供回退响应。在使用时需要一个名为"HystrixCommand"的参数。
它用于使简单的Prefix参数。
它用于设置路由过滤器的请求属性,检查是否发送原始主机头或由HTTP客户端确定主机头。
它用于确定当前请求是否允许继续。如果不允许,则返回提示"HTTP 429 -Too Many Requests"。
它用于接收请求的状态和URL的参数。该状态是一个重定向的300系列的HTTP代码,如301。URL是Location头部的值。
它用于从转发的请求中删除请求头。
它用于删除请求头,它需要请求头名。
它用于删除响应头,它需要响应头名。
它用于使用Java正则表达式重写请求路径。
它用于在转发到下游之前强制执行保存Session操作。
它用于为响应添加安全头。
它提供了一种方法,该方法允许通过路径的模板来操作请求路径。它使用了Spring框架的URI模板,支技多种匹配。
它用于设置响应头,需要有一个Key-Value对。
它用于设置请求响应状态,它需要一个Status参数,该参数的值必须是有效的Spring HttpStatus。例如,整型的404或枚举类型的字符串NOT_FOUND。
它用于剥离前缀。它需要parts参数,表明在请求被发送到下游之前从请求路径中剥离的元素数量。
它用于进行重试,它需要Retries、Statuses、Methods和Series参数
**Retries:**重试次数
**Statuses:**重试的HTTP状态代码,用org.springframework.http.HttpStatus表示
**Methods:**重试的HTTP方法,用org.springframework.http.HttpMethod表示
**Series:**重试的状态代码,用org.springframework.http.HttpStatus.Series表示
它用于限制请求的大小。当请求超过限制时启用,限制请求到达下游服务。该过滤器将RequestSize作为参数。
全局过滤器由一系列特殊的过滤器组成。它会应用到所有路由中。
它在exchange的属性中查找URI。如果URI是forward协议,则它将用Spring DispatcherHandler处理请求。
它在exchange的属性中查找URI。如果URI是lb协议,则它用Spring Cloud LoadBalancerClient将名称(lb://myservice中的myservice)解析为实际的主机和端口,并替换URI中的相同属性。
如果ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR中的URI使用的是HTTP或HTTPS协议,则运行Netty路由过滤器。它用Netty HttpClient发出下游代理请求。
如果在ServerWebUtils.CLIENT_RESPONSE_ATTR的值存在Netty HttpClientResponse,则运行Netty写响应过滤器。它在所有其他过滤器完成后运行,并将代理响应写回到网关客户端的响应数据中。
如果在ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR的值中存在Route对象,则运行路由到请求地址。
如果ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR值的URI是ws协议或wss协议,则运行Websocket路由过滤器。它利用Spring Web Socket底层代码将Web Socket请求转发到下游。
要启用它需要添加spring-boot-starter-actuator的依赖。默认情况下,只要属性spring.cloud.gateway.metrics.enabled未设置为false,网关指标过滤器就会运行。此过滤器会添加一个名为"gateway.requests"的指标(Metrics),其中包含以下属性:
routeId:路由ld
routeUri:API将被路由到的URI
outcome:由HttpStatus.Series分类的结果
status:HTTP请求返回给客户端的状态
当请求进入并匹配到一个路由时,Filtering Web Handler会将GlobalFilter的所有实例和GatewayFilter的所有路由特定实例添加到过滤器链中。这个组合的过滤器链由org.springframework.core.Ordered接口排序。
网关在路由了ServerWebExchange后,会通过将gatewayAlreadyRouted添加到exchange属性来将该交换标识为"路由"。一旦请求被标识为路由,则其他路由过滤器会跳过该请求。
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
#id:自定义路由ID
spring.cloud.gateway.routes[0].id=addrequestheader_route1
#uri:目标服务地址
spring.cloud.gateway.routes[0].uri=http://localhost:50006
#predicates:路由条件。Predicate根据输入参数返回一个布尔值。其包含多种默认方法来将Predicate组合成复杂的路由逻辑
spring.cloud.gateway.routes[0].predicates[0]=Path=/hello
public class TokenFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
//从请求中token参数
String token = exchange.getRequest().getQueryParams().getFirst("token");
//如果为null或空直接返回401未认证错误
if (StringUtils.isEmpty(token)){
exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
return exchange.getResponse().setComplete();
}
//如果包含则放行
return chain.filter(exchange);
}
@Override
public int getOrder() {
return -100;
}
}
@Configuration
public class GatewayConfig {
@Bean
public TokenFilter tokenFilter(){
return new TokenFilter();
}
}
访问:http://localhost:50024/hello