ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

SpringCloud系列(八)最详细最全面详述统一网关 Gateway 路由与过滤器实战

SpringCloud系列(八)最详细最全面详述统一网关 Gateway 路由与过滤器实战 1. 从一次 404 说起微服务统一入口到底难在哪如果你正在做 SpringCloud 微服务大概率遇到过这种场景订单服务、用户服务、商品服务各自跑在不同的端口上前端同学每次联调都要问你要一堆地址改一个环境就得重新配一遍。更麻烦的是认证逻辑散落在每个服务里加个限流要改五六个工程。这时候就需要一个统一入口把所有请求先收拢到一处再按规则分发出去——这就是 SpringCloud Gateway 要解决的问题。Gateway 是 Spring Cloud 生态里的第二代网关基于 Spring5 的 WebFlux 实现走的是响应式编程路线和早期基于 Servlet 阻塞模型的 Zuul 相比在高并发场景下资源占用更低。它能做的事情可以概括成三件把外部请求按规则路由到对应微服务并做负载均衡、在请求进出时执行过滤器链做鉴权或改写、对流量做限流保护后端。适合谁适合已经拆出多个微服务、需要一个统一入口来收口认证、路由和限流的团队也适合正在学 SpringCloud 想搞懂网关到底怎么落地的同学。这篇文章不讲空概念直接给你能复制的路由断言、过滤器、限流配置片段然后一步步启动网关逐条验证路由转发和过滤是否生效。中间会穿插我实际踩过的坑比如断言路径写错导致 404、全局过滤器 order 值冲突、跨域配置不生效这些。你跟着做一遍基本就能把统一网关跑起来。2. 动手前先把 TaoToken 配好模型调用与网关调试的配合在正式写 Gateway 配置之前先说一个容易被忽略但很实用的点调试网关时经常需要快速验证接口返回、生成测试数据、或者让模型帮你分析一段报错日志。这时候如果本地没有一个顺手的模型调用入口来回切工具会很打断节奏。我的做法是先把 TaoToken 配好它提供统一的 API 入口兼容常见的模型调用格式配一次就能在多个工具里复用。TaoToken 的官网入口是 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content API 地址是 https://taotoken.net/api 注意 API 地址后面不加 UTM 参数。如果你只是想在网页里对话验证模型可以直接用模型对话入口如果是要长期写代码、跑 Agent建议看 Coding Plan需要管理密钥就去 API Keys 页面接入细节看接入文档。这里重点说配置三件套Base URL、Key、Model ID。不管你用的是 Cline、Codex 还是 Claude Code核心都是这三样。以 Cline 的 MCP 配置为例你需要在配置文件里写清楚{ mcpServers: { taotoken: { command: npx, args: [-y, taotoken/mcp-server], env: { TAOTOKEN_BASE_URL: https://taotoken.net/api, TAOTOKEN_API_KEY: 你的Key, TAOTOKEN_MODEL_ID: 你的模型ID } } } }如果你用的是 Codex配置写在auth.json里结构类似{ base_url: https://taotoken.net/api, api_key: 你的Key, model: 你的模型ID }Claude Code 的话在 settings 里配置 Base URL 和 KeyModel ID 按你实际使用的填。这三件套缺一不可少一个就会出现 401 或者模型找不到的报错。配好之后你在调试 Gateway 时遇到看不懂的报错可以直接把日志贴给模型让它帮你定位效率会高不少。需要说明的是TaoToken 在这里的角色是帮你做模型调用和调试辅助不是替代你的编辑器或网关本身。Gateway 的路由和过滤逻辑还是得你自己在工程里写TaoToken 只是让你在写和调的过程中有个顺手的工具。3. 可复制的 Gateway 路由与过滤器配置这一节是核心直接给你能粘贴进项目的配置。先建一个 Gateway 服务pom.xml 里引入两个依赖dependency groupIdorg.springframework.cloud/groupId artifactIdspring-cloud-starter-gateway/artifactId /dependency dependency groupIdcom.alibaba.cloud/groupId artifactIdspring-cloud-starter-alibaba-nacos-discovery/artifactId /dependency启动类加EnableDiscoveryClient然后重点在application.yml里写路由。下面这份配置包含路由断言、路由过滤器、默认过滤器和限流你可以直接改服务名用server: port: 10010 spring: application: name: gateway cloud: nacos: server-addr: 127.0.0.1:8848 gateway: routes: - id: user-service-route uri: lb://userservice predicates: - Path/user/** filters: - AddRequestHeaderX-Request-From, gateway - id: order-service-route uri: lb://orderservice predicates: - Path/order/** - MethodGET,POST default-filters: - AddResponseHeaderX-Response-From, gateway globalcors: cors-configurations: [/**]: allowedOrigins: * allowedMethods: * allowedHeaders: *几个关键点解释一下。uri里的lb://userservice表示走负载均衡到 Nacos 里注册的userservice服务lb就是 loadBalance。predicates下的Path/user/**是路径断言意思是/user开头的请求才匹配这条路由。filters下的AddRequestHeader是路由过滤器只对当前这条路由生效default-filters下的对所有路由生效。globalcors是跨域配置[/**]表示对所有路径生效。如果你要做限流Gateway 内置了RequestRateLimiter过滤器配合 Redis 使用。先在 pom 里加 Redis 响应式依赖dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-data-redis-reactive/artifactId /dependency然后在路由的 filters 里加限流配置filters: - name: RequestRateLimiter args: redis-rate-limiter.replenishRate: 10 redis-rate-limiter.burstCapacity: 20 key-resolver: #{ipKeyResolver}replenishRate是每秒补充的令牌数burstCapacity是令牌桶容量key-resolver指向你定义的限流键解析器 Bean。在配置类里加一个Bean public KeyResolver ipKeyResolver() { return exchange - Mono.just( exchange.getRequest().getRemoteAddress().getHostString() ); }这样就是按客户端 IP 限流每个 IP 每秒 10 个请求突发最多 20 个。超过的请求会返回 429。再说全局过滤器。路由过滤器在 yml 里配就行但要做鉴权这种复杂逻辑得自己写全局过滤器。实现GlobalFilter和Ordered接口Component public class AuthGlobalFilter implements GlobalFilter, Ordered { Override public MonoVoid filter(ServerWebExchange exchange, GatewayFilterChain chain) { String token exchange.getRequest().getQueryParams().getFirst(authorization); if (!admin.equals(token)) { exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED); return exchange.getResponse().setComplete(); } return chain.filter(exchange); } Override public int getOrder() { return 0; } }这个过滤器会检查请求参数里authorization是否等于admin不是就返回 401。getOrder()返回 0值越小优先级越高。路由过滤器和默认过滤器的 order 由 Spring 按声明顺序从 1 递增全局过滤器由你自己定。当 order 值相同时执行顺序是默认过滤器 路由过滤器 全局过滤器。4. 启动网关逐条验证路由转发与过滤生效配置写完启动 Nacos、userservice、orderservice 和 Gateway 四个服务。启动顺序建议先 Nacos再业务服务最后 Gateway这样 Gateway 启动时能拉到服务列表。验证第一条路由转发。浏览器或 curl 访问http://localhost:10010/user/1如果 userservice 有对应的接口应该能正常返回数据。这一步验证的是Path/user/**断言和lb://userservice负载均衡是否生效。如果返回 404先检查 userservice 是否注册到 Nacos、服务名是否写对、路径是否匹配。验证第二条路由过滤器。访问http://localhost:10010/user/1在 userservice 的接口里打印请求头看有没有X-Request-From: gateway。有就说明AddRequestHeader过滤器生效了。这一步很多人会漏因为过滤器生效了但接口没打印请求头就以为没生效其实是业务代码没读。验证第三条默认过滤器。看响应头里有没有X-Response-From: gateway用 curl 的-i参数能看到。这个对所有路由生效访问/order/**也应该有。验证第四条全局过滤器。访问http://localhost:10010/user/1不带参数应该返回 401带上?authorizationadmin再访问应该正常返回。这一步验证全局过滤器的鉴权逻辑。验证第五条限流。快速连续访问超过 20 次应该能看到部分请求返回 429。可以用ab或wrk压测也可以写个循环 curl。验证第六条跨域。前端页面发 ajax 请求到网关浏览器控制台不应该报 CORS 错误。如果报错检查globalcors配置的路径和 allowedOrigins 是否正确。我实测下来最容易出问题的是断言路径。比如你写Path/user/**但实际请求是/userservice/user/1那就匹配不上。断言匹配的是网关收到的原始路径不是转发后的路径。还有lb://后面的服务名必须和 Nacos 里注册的spring.application.name完全一致大小写敏感。5. 常见报错排查401、404、429 与 OAuth 问题这一节对照真实报错来排查。先说 401如果你访问网关返回 401大概率是全局过滤器拦截了。检查你的AuthGlobalFilter逻辑看是不是所有请求都被要求带 authorization 参数。如果是调试阶段可以先把全局过滤器的 order 调大或者临时注释掉确认其他功能正常后再加回来。404 是最常见的。分几种情况一是路由断言没匹配上检查 Path 写的是否和请求路径一致二是服务没注册到 Nacos去 Nacos 控制台看服务列表三是lb://后面的服务名写错。还有一种隐蔽情况是 Gateway 和 spring-webmvc 依赖冲突Gateway 基于 WebFlux如果项目里同时引入了 spring-boot-starter-web会导致 Gateway 不工作。检查 pom把 web 依赖排除掉。429 是限流触发了。如果你没配限流却出现 429检查是不是 Redis 里有限流键残留或者RequestRateLimiter配置的replenishRate太小。调大replenishRate和burstCapacity再试。local proxy failed这类报错通常出现在你本地通过代理工具访问外部服务时检查你的网络配置确保 Gateway 转发目标可达。如果是用 TaoToken 调试模型时遇到检查 Base URL 是否写成了https://taotoken.net/api注意不要多加斜杠或路径。reading choices报错一般出现在模型返回格式解析时说明返回结构和你预期的不一致。检查 Model ID 是否填对以及请求体格式是否符合接口要求。OAuth 相关问题如果你在网关做 OAuth2 鉴权常见的是 token 校验失败。检查 token 是否过期、签名密钥是否一致、Authorization头格式是否是Bearer xxx。Gateway 里做 OAuth 一般用TokenRelay过滤器把 token 透传给下游服务配置filters: - TokenRelay如果出现OAuth2AuthorizationRequestRedirectFilter相关报错检查你的安全配置是否放行了回调路径。再说一个配置三件套的坑。如果你在 Cline 或 Codex 里配 TaoTokenBase URL、Key、Model ID 任何一个写错都会报错。Base URL 是https://taotoken.net/apiKey 在 API Keys 页面生成Model ID 按你实际用的模型填。三个都对了才能正常调用。如果报 401先查 Key如果报模型不存在查 Model ID如果报连接失败查 Base URL。6. 把统一网关落到你的项目里到这里路由断言、路由过滤器、默认过滤器、全局过滤器、限流、跨域这几块都跑通了。你现在的 Gateway 已经能作为微服务的统一入口把认证、路由、限流收口到一处。接下来可以做的优化方向把全局过滤器的鉴权逻辑换成真实的 JWT 校验把限流键从 IP 换成用户 ID 或接口维度把跨域配置按环境区分而不是全放开。如果你在调试过程中需要快速验证接口、分析报错日志可以配好 TaoToken 的模型对话或 Coding Plan把日志贴进去让它帮你定位。接入文档里有详细的配置说明API Keys 页面可以管理你的密钥。需要长期写代码或跑 Agent 的话Coding Plan 会更合适。最后留一个我踩过的坑Gateway 的default-filters和路由下的filters同时配了同名过滤器时路由下的会覆盖默认的不是叠加。比如你在 default-filters 里配了AddRequestHeaderX-A, 1在路由 filters 里又配了AddRequestHeaderX-A, 2最终请求头里只有X-A: 2。要叠加就写不同名字的请求头。这个细节在官方文档里不明显但实际配的时候很容易踩。
返回列表