内容简介:网关 Spring-Cloud-Gateway 源码解析 —— 过滤器 (4.8) 之 WebClientHttpRoutingFilter
摘要: 原创出处 http://www.iocoder.cn/Spring-Cloud-Gateway/filter-web-client-http-routing/ 「芋道源码」欢迎转载,保留摘要,谢谢!
本文主要基于 Spring-Cloud-Gateway 2.0.X M4
- 1. 概述
- 2. 环境配置
- 3. WebClientHttpRoutingFilter
- 4. WebClientWriteResponseFilter
- 5. 和 NettyRoutingFilter 对比
- 666. 彩蛋
关注 微信公众号:【芋道源码】 有福利:
- RocketMQ / MyCAT / Sharding-JDBC 所有 源码分析文章列表
- RocketMQ / MyCAT / Sharding-JDBC 中文注释源码 GitHub 地址
- 您对于源码的疑问每条留言 都 将得到 认真 回复。 甚至不知道如何读源码也可以请教噢 。
- 新的 源码解析文章 实时 收到通知。 每周更新一篇左右 。
- 认真的 源码交流微信群。
1. 概述
本文主要分享 WebClientHttpRoutingFilter 的代码实现 。
WebClientHttpRoutingFilter ,Http 路由 网关过滤器。其根据 http://
或 https://
前缀( Scheme )过滤处理,使用基于 org.springframework.cloud.gateway.filter.WebClient
实现的 HttpClient 请求后端 Http 服务。
WebClientWriteResponseFilter ,与 WebClientHttpRoutingFilter 成对使用 的网关过滤器。其将 WebClientWriteResponseFilter 请求后端 Http 服务的 响应 写回客户端。
大体流程如下 :
2. 环境配置
目前 WebClientHttpRoutingFilter / WebClientWriteResponseFilter 处于 实验 阶段,建议等正式发布在使用。
OK,下面我们来看看怎么配置环境。
第一步,在 NettyConfiguration 注释掉 #routingFilter(...)
和 #nettyWriteResponseFilter()
两个 Bean 方法。
第二步,在 GatewayAutoConfiguration 打开 #webClientHttpRoutingFilter()
和 #webClientWriteResponseFilter()
两个 Bean 方法。
第三步,配置完成,启动 Spring Cloud Gateway 。
3. WebClientHttpRoutingFilter
org.springframework.cloud.gateway.filter.WebClientHttpRoutingFilter
,Http 路由 网关过滤器。
构造方法,代码如下 :
public class WebClientHttpRoutingFilter implements GlobalFilter, Ordered{ private final WebClient webClient; public WebClientHttpRoutingFilter(WebClient webClient){ this.webClient = webClient; } }
-
webClient
属性,默认情况下,使用org.springframework.web.reactive.function.client.DefaultWebClient
实现类。通过该属性, 请求后端的 Http 服务 。
#getOrder()
方法,代码如下 :
@Override public int getOrder(){ return Ordered.LOWEST_PRECEDENCE; }
- 返回顺序为
Integer.MAX_VALUE
。在 《Spring-Cloud-Gateway 源码解析 —— 过滤器 (4.1) 之 GatewayFilter 一览》「3. GlobalFilter」 ,我们列举了所有 GlobalFilter 的顺序。
#filter(ServerWebExchange, GatewayFilterChain)
方法,代码如下 :
1: @Override 2: public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain){ 3: // 获得 requestUrl 4: URI requestUrl = exchange.getRequiredAttribute(GATEWAY_REQUEST_URL_ATTR); 5: 6: // 判断是否能够处理 7: String scheme = requestUrl.getScheme(); 8: if (isAlreadyRouted(exchange) || (!scheme.equals("http") && !scheme.equals("https"))) { 9: return chain.filter(exchange); 10: } 11: 12: // 设置已经路由 13: setAlreadyRouted(exchange); 14: 15: ServerHttpRequest request = exchange.getRequest(); 16: 17: //TODO: support forms 18: // Request Method 19: HttpMethod method = request.getMethod(); 20: 21: // Request 22: RequestBodySpec bodySpec = this.webClient.method(method) 23: .uri(requestUrl) 24: .headers(httpHeaders -> { 25: httpHeaders.addAll(request.getHeaders()); 26: httpHeaders.remove(HttpHeaders.HOST); 27: }); 28: 29: // Request Body 30: RequestHeadersSpec<?> headersSpec; 31: if (requiresBody(method)) { 32: headersSpec = bodySpec.body(BodyInserters.fromDataBuffers(request.getBody())); 33: } else { 34: headersSpec = bodySpec; 35: } 36: 37: return headersSpec.exchange() 38: // .log("webClient route") 39: .flatMap(res -> { 40: ServerHttpResponse response = exchange.getResponse(); 41: 42: // Response Header 43: response.getHeaders().putAll(res.headers().asHttpHeaders()); 44: 45: // Response Status 46: response.setStatusCode(res.statusCode()); 47: 48: // 设置 Response 到 CLIENT_RESPONSE_ATTR 49: // Defer committing the response until all route filters have run 50: // Put client response as ServerWebExchange attribute and write response later NettyWriteResponseFilter 51: exchange.getAttributes().put(CLIENT_RESPONSE_ATTR, res); 52: return chain.filter(exchange); 53: }); 54: }
- 第 4 行 :获得
requestUrl
。 -
第 7 至 10 行 :判断 ForwardRoutingFilter 是否能够处理该请求,需要满足两个条件 :
-
http://
或者https://
前缀( Scheme ) 。 -
调用
ServerWebExchangeUtils#isAlreadyRouted(ServerWebExchange)
方法,判断该请求暂未被其他 Routing 网关处理。代码如下 :public static boolean isAlreadyRouted(ServerWebExchange exchange){ return exchange.getAttributeOrDefault(GATEWAY_ALREADY_ROUTED_ATTR, false); }
-
-
第 13 行 :设置该请求已经被处理。代码如下 :
public static void setAlreadyRouted(ServerWebExchange exchange){ exchange.getAttributes().put(GATEWAY_ALREADY_ROUTED_ATTR, true); }
-
第 17 行 :TODO 【3025】 目前暂不支持 forms 参数
- 第 22 至 35 行 : 创建 向后端服务的请求。
- 第 22 行 :设置 Method 属性。
- 第 24 至 27 行 :设置 Header 属性。
- 第 30 至 35 行 :设置 Body 属性。
- 第 37 行 : 发起 向后端服务的请求。
- 第 40 至 53 行 : 处理 返回自后端服务的相应。
- 第 43 行 :设置
response
的 Header 属性。 - 第 46 行 :设置
response
的 Status 属性。 - 第 51 行 :设置
res
到CLIENT_RESPONSE_ATTR
。后续 WebClientWriteResponseFilter 将响应 写回 给客户端。 - 第 52 行 :提交过滤器链继续过滤。
- 第 43 行 :设置
4. WebClientWriteResponseFilter
org.springframework.cloud.gateway.filter.WebClientWriteResponseFilter
,Http 回写 响应 网关过滤器。
#getOrder()
方法,代码如下 :
public static final int WRITE_RESPONSE_FILTER_ORDER = -1; @Override public int getOrder(){ return WRITE_RESPONSE_FILTER_ORDER; }
- 返回顺序为
-1
。在 《Spring-Cloud-Gateway 源码解析 —— 过滤器 (4.1) 之 GatewayFilter 一览》「3. GlobalFilter」 ,我们列举了所有 GlobalFilter 的顺序。
#filter(ServerWebExchange, GatewayFilterChain)
方法,代码如下 :
1: @Override 2: public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain){ 3: // NOTICE: nothing in "pre" filter stage as CLIENT_RESPONSE_ATTR is not added 4: // until the WebHandler is run 5: return chain.filter(exchange).then(Mono.defer(() -> { 6: // 获得 Response 7: ClientResponse clientResponse = exchange.getAttribute(CLIENT_RESPONSE_ATTR); 8: if (clientResponse == null) { 9: return Mono.empty(); 10: } 11: log.trace("WebClientWriteResponseFilter start"); 12: ServerHttpResponse response = exchange.getResponse(); 13: 14: return response.writeWith(clientResponse.body(BodyExtractors.toDataBuffers())).log("webClient response"); 15: })); 16: }
- 第 5 行 :调用
#then(Mono)
方法,实现 After Filter 逻辑。 - 第 7 至 11 行 :从
CLIENT_RESPONSE_ATTR
中,获得 ClientResponse 。 - 第 14 行 :将 ClientResponse 写回给客户端。
5. 和 NettyRoutingFilter 对比
在 《Spring-Cloud-Gateway 源码解析 —— 过滤器 (4.7) 之 NettyRoutingFilter》 中,我们知道 NettyRoutingFilter / NettyWriteResponseFilter 和 WebClientHttpRoutingFilter / WebClientHttpRoutingFilter 实现 一样 的功能。
那么为什么要再实现一次呢?
TODO 【3001】
666. 彩蛋
呼呼,主要的过滤器已经写完,后面熔断、限流过滤器的实现。
胖友,分享一波朋友圈可好!
以上所述就是小编给大家介绍的《网关 Spring-Cloud-Gateway 源码解析 —— 过滤器 (4.8) 之 WebClientHttpRoutingFilter》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- Spring Cloud(七):服务网关zuul过滤器
- 网关 Spring-Cloud-Gateway 源码解析 —— 过滤器 (4.3) 之 RouteToRequestUrlFilter
- 网关 Spring-Cloud-Gateway 源码解析 —— 过滤器 (4.5) 之 ForwardRoutingFilter
- 网关 Spring-Cloud-Gateway 源码解析 —— 过滤器 (4.6) 之 WebSocketRoutingFilter
- 网关 Spring-Cloud-Gateway 源码解析 —— 过滤器 (4.7) 之 NettyRoutingFilter
- 网关 Spring-Cloud-Gateway 源码解析 —— 过滤器 (4.4) 之 LoadBalancerClientFilter 负载均衡
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。