Skip to content

GatewayFilter 链

This content is not available in your language yet.

Gateway filter 是围绕 ServerWebExchange 的响应式责任链。过滤器既可以在下游调用前修改请求,也可以在 chain.filter(exchange) 返回后处理响应。

先给答案:GatewayFilter 链同时包住“转发前”和“转发后”两个阶段

Section titled “先给答案:GatewayFilter 链同时包住“转发前”和“转发后”两个阶段”

过滤器通过 Mono<Void> 的嵌套形成前置/后置结构:调用下一个过滤器前可以改请求,返回之后可以改响应。排序决定鉴权、限流、路由选择、转发和响应改写的先后,不能只看过滤器名称。

代理 URL、请求 body 和响应 body 都可能是一次性资源,过滤器如果读取后不重新包装,后续 Handler 会收到空数据;如果异常或取消路径没有释放资源,连接池也会被拖住。

FilteringWebHandler
+-- sort(GlobalFilter adapters + Route filters)
+-- Filter[0]
+-- Filter[1]
+-- RouteToRequestUrlFilter
+-- NettyRoutingFilter
+-- response filters unwind

FilteringWebHandler.java:99-124 合并全局过滤器和路由过滤器,使用 AnnotationAwareOrderComparator 排序。127-156 的 DefaultGatewayFilterChain 每次创建 index 加一的新链节点,并用 Mono.defer 延迟调用。

GatewayFilter.java:34-60 是路由级契约;GlobalFilter.java:35-44 是匹配路由后的全局契约。FilteringWebHandler.java:168-175 将 GlobalFilter 适配成 GatewayFilter,执行器只需要一种链模型。

RouteToRequestUrlFilter.java:39-95 读取 route URI,生成 GATEWAY_REQUEST_URL_ATTR,不负责网络 IO。NettyRoutingFilter.java:74-107 检查 scheme 和 already-routed 标记,避免重复代理。

NettyRoutingFilter.java:108-128 过滤请求 header、处理 Host 并发送 body;129-169 保存下游 response/connection 到 exchange 属性。响应超时处理位于 NettyRoutingFilter.java:171-178。

替代方案:把每种路由 filter 直接写成 Servlet Filter 或全局 WebFilter。 为什么不行:路由条件和默认 filter 无法自然绑定,代理前后的顺序也难以统一。 证据:FilteringWebHandler.java:107-124 把两类 filter 合并成一个排序列表,让路由级和系统级策略共享责任链。

场景 现象 原因 规避
忘记调用 chain 请求提前结束 filter 主动截断责任链 明确终止型或装饰型
already routed 残留 自定义 filter 不再转发 exchange 属性表示已路由 不要复制错误属性
Host 被清洗 下游虚拟主机失败 默认移除 Host 明确 preserveHostHeader

响应式责任链的关键是“前置动作 + 委托 + 后置动作”:异常、超时、指标和资源释放都应围绕委托形成对称结构。

面试锚点

  • GlobalFilter 如何进入 GatewayFilter 链?
  • Gateway 为什么拆出 RouteToRequestUrlFilter?
  • NettyRoutingFilter 如何避免重复路由?