wikiwikiwiki opened a new pull request #6959:
URL: https://github.com/apache/dubbo/pull/6959


   issue #6567 里面提到了这个问题,刚好也碰到了,修复一下。
   
   具体触发条件为:
   1. 启动一个普通consumer和一个provider,consumer可以正常调用。
   2. 关闭provider进程,观察注册中心,一直等到provider注册的url消失。
   3. 重启provider进程,consumer再次调用,报"safe guard client , should not be called 
,must have a bug."并且之后每5000次调用会触发一次。
   
   这个问题的根源是LazyConnectExchangeClient在两种情况下被使用,这两种情况需要表现的行为不一样,但是代码一样导致。
   
这两种情况一个是consumer主动设置为延迟连接,一个是consumer和provider断开连接时进行防御式编程,如果在连接关闭后还有请求过来就用这个延迟初始化的client处理一下。
   
   具体到上面的这个例子:
   
第一步consumer正常调用时,DubboProtocol里面referenceClientMap字段保存了consumer连接provider的ReferenceCountExchangeClient。
   
第二步关闭provider进程一直到provider注册url消失时,referenceClientMap字段里面的引用还在,但是ReferenceCountExchangeClient的replaceWithLazyClient方法被调用,内部的ExchangeClient换成了LazyConnectExchangeClient。
   第三步provider进程重启,consumer再次调用时,会重新获取到这个已经关闭的ReferenceCountExchangeClient。判断代码为
   ````
   referenceCountExchangeClient == null || 
referenceCountExchangeClient.isClosed()
   ````
   
而referenceCountExchangeClient.isClosed()会调用到LazyConnectExchangeClient的isClosed方法
   ````
   if (client != null) {
       return client.isClosed();
   } else {
       return false;
   }
   ````
   此时还没有延迟初始化,会直接返回false,导致后续的调用都会使用这个client,每5000报告一次warning。
   
   这个bug应该是在 #5532 
这个pr被合并后触发,原本LazyConnectExchangeClient在没有client时isClosed()方法会返回true,会在上面例子第三步时给清理掉。而在没有client时,isClosed()方法返回false,应该是针对consumer主动设置为延迟连接的情况;而consumer和provider断开连接时建立的那个LazyConnectExchangeClient的isClosed()方法应该始终返回true。
   
   具体修复方式为模仿replaceWithLazyClient方法里的方式,在场景不同时添加参数。
   通过增加一个LAZY_CLOSE_STATE_KEY,强制设置isClosed方法修改的返回值,isClosed()方法内容改为
   ````
           if (closeState != null) {
               return closeState;
           }
   
           if (client == null) {
               return false;
           } else {
               return client.isClosed();
           }
   ````


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]



---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to