在微服务架构里,服务发现几乎是每个请求的“第一站”。想象一下,用户点个按钮下单,结果卡在服务查找上半秒,体验立马打折。这种延迟积少成多,轻则页面发愣,重则接口超时。优化服务发现延迟,不是锦上添花,而是系统流畅运行的基本功。
缓存机制:别每次都重新查
服务地址不会每秒都变,但很多客户端却每次调用前都去注册中心拉一遍列表。这就像每天上班都重新查一遍公司地址,其实记住一次就够了。引入本地缓存,设置合理的过期时间(比如30秒),能大幅减少网络往返。
service-discovery:
cache-ttl: 30s
refresh-interval: 20s
像 Nacos、Eureka 的 SDK 默认都有缓存策略,但默认值未必适合你的场景。高并发下可以适当延长刷新间隔,降低注册中心压力。
监听代替轮询:主动通知更高效
有些老系统还在定时轮询注册中心,比如每5秒问一次“有更新吗”。这种方式不仅延迟高,还浪费资源。现代服务发现组件都支持事件监听,服务上线或下线时,注册中心主动推消息过来。
以 Consul 为例,使用 long polling 可以实现近乎实时的更新:
curl "http://consul:8500/v1/health/service/payment?wait=5m&index=12345"
只要服务状态有变,连接立刻返回新数据,延迟从几秒降到毫秒级。
DNS 缓存调优:别让系统自己拖后腿
用了 Kubernetes?那很可能走的是 DNS 做服务发现。但 JVM 默认会缓存 DNS 永久不失效,一旦 Pod 重建 IP 变了,老连接就全断了。得在启动时加上:
-Dsun.net.inetaddr.ttl=10 -Dsun.net.inetaddr.negative.ttl=2
把缓存时间压到10秒内,既避免频繁解析,又不会僵住。
就近发现:物理距离决定响应速度
跨机房调用服务,延迟动不动上百毫秒。通过标签(label)和权重策略,让服务优先发现本机房的实例。Kubernetes 的 topologyKey 就能实现:
topologyKeys:
- "kubernetes.io/hostname"
- "topology.kubernetes.io/zone"
先找本节点,再找同可用区,层层兜底,响应自然更快。
预热与健康检查:别让新实例冷启动拖累整体
新服务刚启动,还没准备好就被流量打进来,不仅自己扛不住,还会让调用方超时。注册前加个就绪检查,确保依赖加载完成、数据库连通再注册自己。
同时,在发布前预热连接池,提前建立好与其他服务的连接通道,避免第一波请求卡在建连上。