根本原因是客户端未启用服务端主动通知(notify)机制,仍依赖默认30秒轮询拉取,导致故障后无法实时感知实例变更;需服务端开启enableNotify/enableSet、客户端使用taf协议栈并建立长连接监听。
为什么 TAF 的 Service 配置改了,客户端却没感知到故障转移?
根本原因不是配置写错了,而是客户端压根没收到服务端推送的最新实例列表——taf 的故障转移依赖服务发现的实时性,而默认的轮询拉取间隔(如 30s)和缓存机制会让客户端“卡”在旧节点上。
-
TafRegistry客户端默认用pull模式同步服务列表,updateInterval配置项控制拉取频率,不显式设置就走默认值,容易导致故障后长达半分钟无响应 - 若服务端用了
setWeight(0)下线节点,但客户端缓存未刷新,仍会按旧负载策略发请求过去,报ConnectException或超时 - 服务端
ServerConfig.xml中的<service></service>节点必须开启enableSet和enableNotify,否则注册中心不会主动推送变更
如何让客户端真正「感知」到故障并自动切走?
靠拉取不够快,得启用服务端主动通知(notify)+ 客户端长连接监听,这是透明故障转移的核心链路。
- 服务端
ServerConfig.xml中对应<service name="xxx"></service>必须包含:enableNotify="true"、enableSet="true" - 客户端初始化时需显式启用 notify:调用
CommunicatorFactory.getCommunicator().stringToProxy(...)前,确保Communicator的配置里有locator = taf.tarsregistry://xxx:17890且协议头是taf.(不是tars.) - 客户端日志里要能看到
NotifyThread started和定期的recv notify: service=xxx, set=...,没这行说明 notify 链路断了
set 隔离与 weight=0 的区别:什么时候该用哪个?
两者都可下线节点,但触发时机和传播路径完全不同,混用会导致客户端行为不一致。
-
set是 TAF 的逻辑分组隔离机制,通过set=shanghai等标识做路由隔离;调用AdminAdapter.setSetDisable("shanghai", true)后,所有带该set的节点会被整体剔除,客户端 notify 会立刻收到全量变更 -
weight=0是单节点权重设为零,仅影响负载均衡器的选择概率,不触发服务列表变更通知;客户端仍会保留在本地缓存中,直到下次 pull 才可能剔除 - 线上应急推荐优先用
setDisable,它快、准、可逆;日常灰度可用weight配合短拉取间隔,但别指望它实现秒级故障转移
客户端连不上注册中心时,故障转移还生效吗?
不生效。TAF 的「透明」是建立在注册中心可用前提下的,离线状态下客户端只能靠本地缓存兜底,而缓存不会自动剔除已宕机节点。
- 客户端启动时若连不上
taf.tarsregistry,会加载本地cache/目录下的servant.list,但这个文件不会随服务端变化自动更新 - 配置项
locatorRefreshInterval控制重试注册中心的间隔,默认 60s,期间所有新请求都可能打到已失效节点 - 关键业务建议加一层健康检查:在
ProxyCallback的onTimeout或onException中,手动调用refreshServantList()强制触发一次 pull
最常被忽略的是 notify 链路的双向校验:服务端开了 enableNotify,不代表客户端就能收到;得确认客户端用的是 taf 协议栈、注册中心地址拼写正确、防火墙放通了 notify 回调端口(通常是随机高位端口,不是 17890),缺一不可。










