XingyuFu
XingyuFu
我们这边也有类似的问题,3.0.12版本: 当provider机器因为缩容销毁时,正好有业务请求。 看了下,大体执行顺序是: 1. 线程A进行业务请求,根据invokers获取到这个invoker 2. 线程B收到注册中心的消息,重新设置invokers,并开始把这个invoker销毁 3. 线程A已得知这个invoker要销毁,打印了"Invoker for service ".... ", this invoker should not be used any longer" 4. 线程B销毁client,ReferenceCountExchangeClient里将原本的client销毁,并放了一个LazyConnectExchangeClient进去 5. 线程A正常执行invoke方法,使用LazyConnectExchangeClient建立连接,成功获得结果 之后这个LazyConnectExchangeClient,因为那台机器已经销毁了,就开始不断的重连任务,ReconnectTimerTask一直在打印重连失败的异常日志。 从打印的日志上,我能看到线程A执行成功,并返回了正常的结果。也能看到,线程A触发的连接建立和线程B触发的连接关闭在统一毫秒。 看起来,就像是线程B销毁了连接,但线程A的LazyConnectExchangeClient正好重新创建了一个,没被close。 这个时间线是我根据日志和代码逻辑梳理出的,虽然复现的概率不大,但毕竟发布频率高,最近开始有报了。 @AlbumenJ...
> May related with #11780 @AlbumenJ 这里做,的确能够解决销毁时client重连的问题了。 但对于invoker销毁时已经选择了这个invoker的请求,在竞争到读锁后会因为invoker的销毁抛出异常。所以这可能会引入新的问题:通常情况下的业务方,都不会接受“provider销毁时,consumer可能有请求失败”这种情况。 不知道针对抛出这个RpcException的情况,你们是否有别的改进?比如重新触发invoker的reselect?
有点像,但并不一样,因为下游的provider会在之后确实销毁。 但对于这个新创建的client而言,directory的invokers中没它,它的连接也是不通的,但因为没close,所以就会一直存在,属于“逃逸”。它没被管理起来,所以也不会被调用。但因为时间轮线程一直尝试重连,所以也不会被垃圾回收。 上面的https://github.com/apache/dubbo/pull/11780 的确可以有效地避免这个client被真正连接使用,所以它不会被放入时间轮线程里,就可以被回收。 但对于这样因为并发错误选择了invoker的请求,感觉直接异常中断,还是有损失的。想的是,是否可以把这部分的损失减少。
@AlbumenJ 我们把这个pr合了过来,但之后发现还会有这样的问题,依旧有重连已销毁provider ip的任务在不断执行。 问下,https://github.com/apache/dubbo/pull/10938 这个也是必须的吗?我看3.0.12版本也没有。