新上一个服务,全网关都重启
路由写在网关的 application.yml 里,每上一个新服务、每改一条转发规则,都要改配置、提发版、重启网关。网关是全站入口,重启一次全站抖一下,发布窗口越来越难约。路由规则的变更频率,本该是分钟级;而网关的重启频率,应该是月级——中间的差距,靠动态路由抹平。
动态路由的三种做法
三条路线各有脾气:配置中心驱动——路由定义放 Nacos,监听变更热刷新,实现简单、天然有版本与灰度能力;数据库驱动——路由表入库加管理界面,运营也能改,但要自己做校验与缓存同步;注册中心自动映射——按服务名自动生成路由,零配置,但规则表达力弱。多数团队的答案:配置中心为主,复杂路由辅以数据库。
@Component
public class DynamicRouteListener {
// 监听配置中心 gateway-routes 数据变更
public void onRouteChange(String newRoutes) {
List<RouteDefinition> defs = parse(newRoutes);
validate(defs); // 先校验,坏配置拒收
inMemoryRepository.save(defs); // 更新内存路由定义
publisher.publishEvent(new RefreshRoutesEvent(this)); // 通知重建路由
}
}
// 校验这一步不能省:一条坏路由,可以挂掉整个网关两个必须做的防护:变更校验——坏配置拒收,路由解析失败不能影响存量路由;变更审计——谁改的、改了什么、何时生效,全部留痕。动态生效的另一面是坏配置也动态生效,闸门要在写入前。
灰度发布:按什么分流
灰度的本质:让一部分请求走新版本,其余走旧版本,出问题影响面可控。分流依据按精度递进:按权重——随机 5% 走新版,适合验证基本功能;按用户——内部账号或白名单用户先体验,适合内部试用;按维度——特定地域、特定 App 版本,适合放量验证。实现上通常两层配合:网关按 Header/权重决定打给哪组实例,实例分组靠注册中心元数据(version: gray)标记。
// 网关灰度断言:Header 带 gray=true 的请求走灰度实例
.uri("lb://order-service")
.predicates(p -> p.header("X-Gray", "true"))
.filters(f -> f.setProperty("version", "gray"))
// 注册中心元数据分组
spring.cloud.nacos.discovery.metadata.version=gray灰度链路的完整性
只灰度第一跳是最常见的半成品:请求打到了灰度订单服务,订单再调库存——库存还是旧版,新旧数据格式一冲突就翻车。灰度标签必须沿着调用链全链路透传:网关打标,Feign 拦截器带着标签调下游,下游按标签选同版本实例;走消息队列的链路要把标签放进消息头。漏一跳,灰度就变成了"薛定谔的版本"——出问题时你都不知道用户走的哪版。
灰度观察期看三个指标:错误率、P99 延迟、核心业务指标,异常立即切回。网关这块收尾了,接下来进入观测篇:一次调用穿过八个服务,问题到底出在哪一跳。
评论 (0)