ocelot路由匹配严格,路径斜杠、大小写、参数顺序不匹配即404且不报错;需规范downstreampathtemplate以/开头、upstream通配符用{xxx};忽略大小写需显式配置;调试需开启debug日志;负载均衡生效需启用服务发现;jwt鉴权后用户信息需downstreamheadertransform手动映射;consul启动慢因默认超时仅5秒,应配置globalconfiguration中pollinginterval。

路由配置写不对,Ocelot直接 404 不报错
默认情况下 Ocelot 对路由匹配非常严格:路径末尾斜杠、大小写、查询参数顺序都可能让匹配失败。它不会告诉你“哪个路由没命中”,只会静默返回 404。
实操建议:
- 用
DownstreamPathTemplate时,确保以/开头,比如"/api/values/{id}",不能写成"api/values/{id}" -
UpstreamPathTemplate中的通配符必须用大括号,{id}有效,:id或$id无效 - 如果想忽略大小写,显式加配置:
"UseServiceDiscovery": false, "DownstreamScheme": "http", "DownstreamHostAndPort": { "Host": "localhost", "Port": 5000 }, "DownstreamPathTemplate": "/api/{everything}", "UpstreamPathTemplate": "/api/{everything}", "UpstreamHttpMethod": [ "Get" ],再配合ReRoutes的Key字段做唯一标识,避免歧义 - 调试时打开日志(
Microsoft.AspNetCore.Ocelot日志级别设为Debug),关键线索在Ocelot.RequestIdMiddleware和Ocelot.DownstreamRouteFinder输出里
LoadBalancerOptions 配置后负载均衡不生效
很多人写了 "LoadBalancerOptions": { "Type": "LeastConnection" },但请求始终打到同一个下游服务——问题往往不在配置本身,而在服务发现或健康检查没启用。
实操建议:
- 只有启用了服务发现(如
Consul或Eureka)且UseServiceDiscovery设为true,LoadBalancerOptions才会参与决策;纯静态DownstreamHostAndPort列表下,负载均衡逻辑被跳过 -
Type可选值是LeastConnection、RoundRobin、Random,注意大小写敏感,roundrobin会静默退化为默认行为 - 若用
Consul,确保下游服务注册时带了健康检查端点,否则Ocelot会把不健康的实例也纳入轮询池 - 验证是否生效:调用几次接口后查
Ocelot日志里的DownstreamHostAndPort字段,看 IP/Port 是否变化
JWT 鉴权通过了,但 DownstreamHeaderTransform 拿不到用户信息
Ocelot 默认不会把 HttpContext.User 的 Claims 自动注入下游请求头。即使你用了 AuthenticationOptions 配置了 JWT Bearer,下游服务收不到 X-User-Id 这类自定义头。
实操建议:
- 必须手动配置
DownstreamHeaderTransform,例如:"DownstreamHeaderTransform": { "X-User-Id": "UserId" },其中UserId是ClaimsPrincipal中 Claim 的Type名(不是值) - Claim Type 要和下游期望一致,常见坑:JWT 中是
http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier,但你写了nameidentifier,结果映射失败 - 如果要用自定义逻辑(比如拼接多个 Claim),得写中间件,在
PreAuthenticationMiddleware阶段往HttpContext.Items塞值,再用DownstreamHeaderTransform引用,格式是"X-Custom": "{Items:MyCustomValue}"
Ocelot + Consul 启动慢、偶发路由丢失
这不是代码 bug,而是默认重试与超时策略太激进:Ocelot 初始化时会同步拉取 Consul 服务列表,但默认只等 5 秒,超时就放弃,后续靠定时刷新补救——这就导致刚启动那几秒路由不可用,且没有明确错误提示。
实操建议:
- 在
ocelot.json的根节点加"GlobalConfiguration": { "BaseUrl": "http://localhost:5000", "ServiceDiscoveryProvider": { "Host": "localhost", "Port": 8500, "Type": "Consul", "PollingInterval": 3000 } },重点是PollingInterval控制刷新频率,别设太小( - 首次加载失败不致命,但你要在程序启动后主动触发一次手动刷新(用
IOcelotCache或IServiceDiscoveryProvider接口),否则依赖首次请求触发的延迟可能高达 3 秒 - Consul ACL 开启后,
Ocelot不支持 Token 认证自动续期,Token 过期会导致后续所有服务发现失败,得自己加后台任务定期刷新
最常被忽略的是:Ocelot 的路由缓存是基于配置文件哈希+服务发现响应联合生成的,任意一环变动(比如 Consul 里某个服务临时下线又上线),都可能导致整个路由表重建——这期间新请求会 fallback 到 404,而不是等待重建完成。











