Closed shawnliang1124 closed 4 months ago
@EvenLjj 请帮忙一起 check 下这个 issue
在SofaBoot环境下,我们会利用SofaBoot特有的 健康检查机制 来控制rpc服务向注册中心注册的时机。因为健康检查能很好的反应应用当前的情况。上述publishAllProviderConfig
就是这个机制的实现: 发布rpc服务时不通知注册中心,等待应用健康检查通过后,将所有rpc服务一并注册到注册中心。
而provider.delay
是SofaRpc自行设计的一个小trick, 该机制的实现逻辑就是在export
时直接返回成功, 随后异步处理发布动作。看起来和上述健康检查发布逻辑存在一定的冲突。我们reivew一下这里的逻辑看看如何做一下两个功能的兼容吧。
针对你目前提出的解决方案,更改 ProviderConfigContainer#publishAllProviderConfig方法,不把节点写上写注册中心,你可能需要注意上述两个机制发生的时间差,以确保最终至少有一个机制会正常向注册中心发布服务。
@EvenLjj 请帮忙一起 check 下这个 issue
确实存在这个问题,可以考虑在 ProviderConfigContainer#publishAllProviderConfig 中去识别这种延迟发布的 providerConfig,根据delay时间异步去注册中心注册服务。
@shawnliang1124 我修复了一版、可以拉一下我的代码验证一下功能哈。
Describe the bug
sofa-boot 3.2.0 版本,在Bolt协议下,provider指定配置provider.delay,provider启动后,consumer的调用会出现:RPC cannot find service
To Reproduce
provider使用双机部署,rpc provider侧使用bolt协议,配置provider.delay = 100000,在META-INF/sofa-rpc/rpc-config.json下配置,在一台未重启,另外一台provider启动成功后,consumer直接调用即可复现。
根因:
debug源码发现,ProviderConfigContainer#publishAllProviderConfig方法,会判断,如果provider指定的protocol方式不是dubbo,就会直接往注册中心写入provider的节点数据(不清楚作者为啥要做这个设计)
报错的provider代码在sofa-rpc 5.6版本的BoltServerProcessor#handleRequest 148行,invoker为空,导致抛异常:RPC cannot find service
回顾源码:Invoker 对象是DefaultProviderBootstrap#doExport() 方法中初始化, 但是因为sofa-boot设置了延迟暴露(provider.delay = 100000),doExport 方法则是100秒后才会被调用,故Invoker对象是在100秒后才会被初始化成功。
doExport方法。其中 server.registerProcessor(providerConfig, providerProxyInvoker) 就是做了Invoker 对象初始化的事情
可是sofa-boot的 ProviderConfigContainer#publishAllProviderConfig方法已经往注册中心写进去数据,导致consumer看到了该节点,故能直接发起调用provider,但是因为provider的延迟暴露时间设置,进而导致Invoker为空,导致Provider处理异常
Expected behavior
支持延迟暴露配置,并且不会产生RPC cannot find service 异常
Environment:
Additional context
解决方法:SOFA-BOOT 中,更改 ProviderConfigContainer#publishAllProviderConfig方法,不把节点写上写注册中心