拓冰建站拓冰建站
首页 / 资讯中心 / 正文

Spring Cloud Gateway Actuator端点实战:路由与过滤器排查指南

网关这东西平时安安静静躺在流量入口最忙的时候也没几个人会盯着它看。可一旦线上出问题突然冒出来一堆 502 Bad Gateway或者改完路由半天不生效你就会发现自己对这个“流量总闸门”的运行状态几乎一无所知。我自己的习惯是任何准备接入生产流量入口的 Spring Cloud Gateway第一件事就是把 Actuator 管理端点打开尤其是路由和过滤器相关的端点。原因很简单这些端点能把网关内部的运行逻辑直接摊开给你看路由有没有加载、过滤器链是什么顺序、哪条路由真正匹配了请求一目了然排查问题的时间能从小时级缩短到分钟级。这篇文章就从实际运维和开发的角度完整讲清楚如何给 Gateway 启用 Actuator暴露路由、过滤器等管理端点。内容包括配置方式、端点含义、使用场景、安全加固和排错实战适合用 Spring Cloud Gateway 做微服务网关的开发者以及负责网关日常维护的平台工程师。无论你是刚接触网关的新人还是被线上故障折腾过的老手这篇文章都能给你一套可以直接拿去用的排查方法。1. 为什么路由、过滤器也要有管理端点1.1 网关排错的核心痛点先聊一个真实的场景。某个周五晚上业务群突然有人喊“下单接口 502 了”。你登录网关机器翻日志、查监控、看配置中心折腾了半小时发现有一条新上线的路由规则写错了正则导致请求匹配到了旧服务。这个过程中最浪费时间的一步不是看日志而是“确认网关当前到底加载了哪些路由”。没有管理端点的时候路由信息散落在配置文件和配置中心里而网关运行时的实际状态很难直接观测。配置中心里改了不生效、多个路由顺序调整后匹配结果不一样、过滤器加了但没执行——这些问题靠肉眼比对配置和日志既慢又容易漏。尤其是微服务架构下网关路由动辄几十条过滤器链层层嵌套真正出问题时你需要的不是猜测而是一份“运行时快照”。Actuator 就是来补这个缺口的。它不是网关特有的一套新东西而是 Spring Boot 自带的监控能力在 Spring Cloud Gateway 里被扩展出了专用的 gateway 端点组专门用来暴露路由定义、过滤器链、谓词工厂等运行时信息。简单说它相当于给网关装了一块仪表盘把内部状态直接给你看。1.2 Actuator 在 Gateway 中的角色Actuator 本身能暴露很多端点比如 health、info、metrics、loggers 等。Spring Cloud Gateway 在 Actuator 基础上增加了一组以 gateway 为根路径的端点包括/actuator/gateway/routes列出当前所有路由定义/actuator/gateway/routes/{id}查看某条路由的详情/actuator/gateway/routes/{id}/combinedfilters查看该路由完整的过滤器链全局过滤器路由过滤器/actuator/gateway/globalfilters列出容器内所有全局过滤器/actuator/gateway/routefilters列出所有路由过滤器工厂/actuator/gateway/predicates列出所有谓词工厂/actuator/gateway/refresh执行路由刷新POST这些端点相当于把网关的配置文件“运行时化”了。配置文件里写的是什么和运行时真正加载的是什么很多时候并不完全一致而这个差异正是故障的根源。有了这些端点你可以直接对比配置文件与运行时状态快速定位问题。2. 环境准备与依赖引入三步快速启用2.1 版本选型与依赖坐标先看版本。Spring Cloud Gateway 的 Actuator 端点能力在不同版本里表现有细微差异尤其是 Spring Boot 3.x 之后一些返回数据结构变了。建议先确认自己的版本组合避免后面踩坑。Spring Cloud 版本对应 Spring Boot 版本最低 Java 版本2021.0.x (Jubilee)2.6.x / 2.7.xJava 82022.0.x (Kilburn)3.0.x / 3.1.xJava 172023.0.x (Leyton)3.2.x / 3.3.xJava 172024.0.x3.4.x / 3.5.xJava 17 / 21我这个项目里用的是 Spring Cloud 2023.0.x Spring Boot 3.2.xJava 21下面的演示都基于这套组合。如果你还在用 Spring Boot 2.x端点的使用方式基本一致只是返回结构上有差异我会在文中单独标注。依赖只需要两个spring-cloud-starter-gateway本身是网关运行必须的spring-boot-starter-actuator就是我们要引入的管理端点依赖。Maven 配置如下dependency groupIdorg.springframework.cloud/groupId artifactIdspring-cloud-starter-gateway/artifactId /dependency dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-actuator/artifactId /dependency注意一点Gateway 是基于 WebFlux 的spring-cloud-starter-gateway已经内置了响应式 Web 基础依赖不需要额外引入spring-boot-starter-web否则会冲突。这是很多新手容易踩的第一个坑。2.2 暴露端点的最小配置引入依赖之后默认情况下 Actuator 只暴露 health 端点其他端点需要显式配置。这里的原则是“最小暴露”只把我们需要管理的端点暴露出去不要图省事用include: *把所有端点一股脑打开。management: endpoints: web: exposure: include: gateway,health,info endpoint: health: show-details: never这段配置做了两件事一是把gateway端点和基础的health、info端点暴露出来二是关闭 health 的详情展示避免敏感信息外泄。配置完成后启动应用访问http://localhost:8080/actuator正常情况下能看到一个 JSON 列表里面包含_links列出了所有可访问的端点链接。如果列表里有gateway相关链接说明 Actuator 端点已经成功暴露。3. 核心管理端点逐项解读路由与过滤器3.1 路由端点查看、刷新与格式化先看最常用的路由端点。执行下面的命令curl http://localhost:8080/actuator/gateway/routes在 Spring Boot 3.x Spring Cloud 2023.0.x 环境下返回的是RouteDefinition列表大概是这个样子[ { id: order-service, predicates: [ { args: { _genkey_0: /api/order/** }, name: Path } ], filters: [ { args: { _genkey_0: 1 }, name: StripPrefix } ], uri: lb://order-service, metadata: {} } ]这里有个重要区别在 Spring Boot 2.x 的旧版本里/actuator/gateway/routes返回的是一组包含了route_object路由对象、order、route_id的格式对象里能看到完整的routeDefinition。而 3.x 之后返回的直接就是 RouteDefinition 本身predicates 和 filters 以名称加参数的形式展示。查看单条路由详情可以加路由 IDcurl http://localhost:8080/actuator/gateway/routes/order-service如果路由不存在会返回 404。这个接口在排查“某条路由到底有没有加载”的场景下非常好用不用再去翻配置中心的历史记录。想查看某条路由的完整过滤器链用 combinedfilters 端点curl http://localhost:8080/actuator/gateway/routes/order-service/combinedfilters返回结果会把全局过滤器和该路由自己的过滤器合并展示顺序从上到下就是实际执行顺序。这个端点对排查过滤器不生效、顺序错乱的问题非常有价值。3.2 过滤器与谓词工厂端点网关的过滤器体系分两层全局过滤器和路由过滤器。全局过滤器对所有路由生效路由过滤器只对匹配了该路由的请求生效。这两个概念经常有人搞混导致排查问题时走弯路。/actuator/gateway/globalfilters端点会列出容器里注册的所有全局过滤器包括 Spring Cloud Gateway 内置的NettyRoutingFilter、LoadBalancerClientFilter、WebsocketRoutingFilter等以及你在代码里自定义的全局过滤器。每个过滤器都会显示顺序值这个值决定了它在过滤器链中的执行顺序。/actuator/gateway/routefilters端点列出的是所有可用的路由过滤器工厂比如AddRequestHeaderGatewayFilterFactory、StripPrefixGatewayFilterFactory、RetryGatewayFilterFactory。这个端点主要价值在于查看当前网关支持哪些过滤器工厂确认你是否用对了类名和参数格式。/actuator/gateway/predicates端点列出所有谓词工厂即路由匹配条件的工厂类。当你配置的路由匹配规则不生效时先确认谓词工厂是否存在、参数格式是否正确能省去大量查文档的时间。4. 实操全过程从写配置到观察管理端点4.1 准备一个可运行的最小网关纸上谈兵没意思直接跑一个最小实例来看效果。先建一个 Spring Boot 项目引入前面提到的两个依赖然后写一个简单的配置server: port: 8080 spring: application: name: gateway-demo cloud: gateway: routes: - id: order-service uri: http://localhost:8081 predicates: - Path/api/order/** filters: - StripPrefix1 - AddRequestHeaderX-Source, gateway-demo - id: user-service uri: http://localhost:8082 predicates: - Path/api/user/** filters: - StripPrefix1这个配置里定义了两条路由分别指向两个本地服务同时给 order 路由加了两个过滤器一个剥掉请求路径的第一段前缀一个加一个自定义请求头。启动网关后直接在浏览器或者 Postman 里访问这些管理端点就能看到运行时的真实数据。4.2 本地验证管理端点启动完成后一个个验证curl http://localhost:8080/actuator/gateway/globalfilters返回结果里能看到一堆全局过滤器每个都带 order 属性。举例来说NettyRoutingFilter的 order 是2147483647也就是Integer.MAX_VALUE它通常在过滤器链的最后面负责把请求真正转发到下游。如果你自定义了全局过滤器会发现它出现在列表里这就能立即确认自定义过滤器是否被成功注册。再看路由过滤器curl http://localhost:8080/actuator/gateway/routefilters返回的是一个过滤器工厂列表里面会包含配置里用到的StripPrefixGatewayFilterFactory和AddRequestHeaderGatewayFilterFactory。最关键的是 routes 列表curl http://localhost:8080/actuator/gateway/routes如果你看到两条路由都在列表里且 filters 和 predicates 内容和配置文件一致说明配置已经生效。如果配置里改了但这里没更新说明路由没有刷新需要继续看刷新端点。4.3 结合动态刷新场景Spring Cloud Gateway 从配置中心动态拉取配置时有两种情况。第一种是配置中心支持 webhook 推送网关收到变更事件后自动刷新。第二种是没有推送机制需要手动刷新。这时候/actuator/gateway/refresh就有用了curl -X POST http://localhost:8080/actuator/gateway/refresh执行后返回 200 表示刷新成功。这个端点不会重启应用只刷新路由定义缓存速度非常快很适合在需要临时调整路由规则、又不想重启网关的场景下使用。不过要注意这个刷新端点只能刷新 Gateway 自己加载的路由。如果你用的是 Nacos 或 Apollo 这类配置中心还要确保配置监听的自动刷新机制是正常的否则有时改了配置中心网关并没有感知这时候手动调一次 refresh 就能恢复。5. 安全加固管理端点不能裸奔5.1 典型风险与教训熟悉 Spring Boot 的人都知道Actuator 端点如果暴露到公网且未做任何保护等于把运行时数据拱手送人。网上那些 “Spring Boot Actuator 漏洞” 的新闻多半就是某个版本把 heapdump、env、beans 等敏感端点暴露了攻击者通过这些端点拿到内存快照、环境变量、Bean 列表等敏感信息。Gateway 的 gateway 端点组虽然不如 heapdump 那么致命但也会泄露内网服务名、路由结构、过滤器参数、下游服务地址等。一旦攻击者知道你的内部路由结构再配合其他漏洞就很容易精准攻击你的内网服务。比如/actuator/gateway/routes返回的 uri 可能包含lb://order-service这样的内部服务名攻击者可以根据这些信息猜测内网服务布局。这绝对是不能接受的风险。5.2 四个实用加固手段我用过的有效加固方案按优先级排序第一最小化暴露。exposure.include只配gateway,health,info不要图方便用*。其他端点比如heapdump、env、beans、configprops默认不暴露就永远不要打开。第二引入 Spring Security 做访问控制。在网关项目里加spring-boot-starter-security依赖然后配置只允许特定角色访问/actuator/**。简单方式如下Configuration public class ActuatorSecurityConfig { Bean public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) { return http .securityMatcher(/actuator/**) .authorizeExchange(exchanges - exchanges .pathMatchers(/actuator/health).permitAll() .anyExchange().authenticated() ) .httpBasic(Customizer.withDefaults()) .formLogin(Customizers.withDefaults()) .build(); } }用 Basic Auth 做一层基本保护虽然简单但比完全不设防要强得多。第三把管理端口和业务端口分离。配置management.server.port8081让 Actuator 单独跑在另一个端口通过防火墙或安全组只允许内网 IP 访问这个端口。这样即使公网请求打过来也摸不到管理端点。第四关闭 health 详情和敏感信息输出。management.endpoint.health.show-detailsnever避免 health 端点返回数据库连接、磁盘空间等详情。如果有自定义的健康指示器注意不要在里面打印版本号、Redis 地址等信息。6. 常见问题与排错实录6.1 请求 /actuator/gateway/routes 返回 404这个现象很常见90% 的情况是management.endpoints.web.exposure.include没配置或者没有写gateway。Spring Boot 默认只暴露 health其他端点全部隐藏。先检查 application.yml确认 include 里有没有gateway这个词。另一个可能原因是新版 Spring Cloud Gateway 的端点路径变了。在 Spring Cloud 2021.0.x 及以前路径是/actuator/gateway/routes到了 2023.0.x 依然保持这个路径但在某些大版本里比如引入了httproutes端点时路径会多出/actuator/gateway/httproutes。如果发现/actuator/gateway/routes返回 404可以试试访问/actuator根路径看返回的_links里有没有gateway-routes根据实际链接调整。6.2 网关 502 时如何利用管理端点定位502 Bad Gateway 是网关排错里最常见的故障之一。出现 502意味着网关本身收到了请求但转发到下游时失败了。定位步骤可以这样走第一步先看路由有没有匹配上。调用/actuator/gateway/routes确认目标路由是否存在路径谓词是否写对。如果请求路径和路由谓词不匹配网关会直接返回 404而不是 502所以一旦出现 502路由大概率是匹配上了。第二步看过滤器链是否正常。调用/actuator/gateway/routes/{id}/combinedfilters确认会不会有哪个过滤器在转发前抛了异常。比如RetryGatewayFilterFactory配置了重试重试三次后仍然连不上下游就会表现为 502。第三步看下游地址是否正确。routes 端点返回的 uri 就是你配置的转发目标。如果目标写成了http://localhost:1572实际该端口没有服务在监听网关必然 502。这时候打开路由的 uri 一眼就能发现问题。我遇到过几次 502 都是因为配置中心里 uri 被误改或者下游服务缩容后没同步更新网关路由。用管理端点把路由加载情况打出来问题基本就锁定在“路由配置正确但下游不可用”还是“路由配置本身就是错的”这两类之间。6.3 数据结构差异与脚本解析写自动化脚本调用这些端点时最大的坑就是数据结构版本差异。前面说过Spring Boot 2.x 和 3.x 下 routes 端点的返回格式不同。如果你的巡检脚本写死了 JSON 层级升级网关版本后很可能直接解析失败。我常用的做法是写一个通用的解析逻辑先判断响应里是route_id字段还是id字段再决定从哪个字段读取路由信息。另外combinedfilters的返回结构在不同版本里也不完全一致建议脚本里只取过滤器的 name 和 order不要依赖固定顺序。这里给一个小技巧如果只是想快速确认某个路径前缀是否被正确的路由匹配直接看 routes 端点里 predicates 的 args 值里面就是匹配路径表达式。用 grep 或者 jq 过滤一下会比翻日志快很多。6.4 管理端点本身的权限控制问题有时候明明加了 Spring Security访问 Actuator 端点却还是返回 403而不是让你输入用户名密码。这通常是因为过滤器的顺序问题Spring Security 的过滤器链排在 Gateway 的全局过滤器之前如果 authorization 规则把未认证请求直接拒绝了就会表现为 403。排查时先去掉自定义规则用最简单的 permitAll 验证端点可访问再逐步加上权限限制。还有一个容易忽略的点WebFlux 环境下 Spring Security 配置类和 WebMvc 环境下写法不同参考示例代码时要注意区分。另外生产环境里如果网关前面还有一层 Nginx 或其他入口代理访问管理端点还可能受到代理层路径转发的影响。比如 Nginx 配置了/actuator前缀剥离实际管理端点的访问路径就变了这时候从网关本地直接 curllocalhost:8080/actuator/gateway/routes是最可靠的验证方式。最后说点实在的管理端点这东西用好了是排查利器用不好就是个安全隐患。我在实际运维中最大的体会是先把最小暴露和安全认证做好再谈其他。不然线上裸奔着暴露路由和过滤器信息跟把网关的图纸贴在门口没什么两样。平时我会把这些端点整理成一个速查表写进团队的排障手册遇到问题直接按图索骥效率比临时查文档高太多。最后再分享一个个人习惯我会写一个定时脚本每天凌晨把/actuator/gateway/routes和/actuator/gateway/globalfilters的快照备份一份保留最近 7 天。这样万一某次配置变更导致线上问题可以快速对比“昨天的路由快照”和“今天的路由快照”差哪里基本一眼就能看出来。这个习惯救过我好几次建议所有正式环境都配上。
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门