Dubbo3 服务发现的推空保护
推空保护是Dubbo服务发现新增的一个提升稳定性的功能,目的是当注册中心出现抖动,consumer接收到注册中心推送了空provider urls过来时,直接忽略掉,从而保护consumer维护的服务发现信息不受影响。
但是在某些场景下却是会出现异常,我们做个实验:
1、启动Provider A, ip为192.168.1.10
2、启动Provider B, ip为192.168.1.11
3、启动Consumer, 调用Provider A和Provider B, 此时正常调用
4、停掉Provider A 和Provider B
5、在ip为192.168.1.10的机器上重新启动Provider B
这时再在Consumer 调用Provider A和Provider B, 调用Provider B正常,但是调用Provider A 却会报错:
org.apache.dubbo.rpc.RpcException: Failed to invoke the method sayHello in the service org.apache.dubbo.springboot.demo.ProviderAService. Tried 3 times of the providers [192.168.1.9:20880] (1/1) from the registry 127.0.0.1:2181 on the consumer 192.168.1.9 using the dubbo version 3.0.8.1-SNAPSHOT. Last error is: Failed to invoke remote method: sayHello, provider: dubbo://192.168.1.9:20880/org.apache.dubbo.springboot.demo.ProviderAService?anyhost=true&application=dubbo-springboot-demo-provider&background=false&category=providers,configurators,routers&check=false&deprecated=false&dubbo=2.0.2&dynamic=true&generic=false&interface=org.apache.dubbo.springboot.demo.DService&methods=sayHello,sayHelloAsync&payload=10004&pid=19514&qos.enable=false®ister-mode=interface&release=3.0.8.1-SNAPSHOT&side=provider&sticky=false, cause: org.apache.dubbo.remoting.RemotingException: Fail to decode request due to: java.io.IOException: Service org.apache.dubbo.springboot.demo.DemoService with version 0.0.0 not found, invocation rejected.
java.io.IOException: Service org.apache.dubbo.springboot.demo.DemoService with version 0.0.0 not found, invocation rejected.
at org.apache.dubbo.remoting.transport.CodecSupport.checkSerialization(CodecSupport.java:166)
at org.apache.dubbo.rpc.protocol.dubbo.DecodeableRpcInvocation.decode(DecodeableRpcInvocation.java:138)
at org.apache.dubbo.rpc.protocol.dubbo.DecodeableRpcInvocation.decode(DecodeableRpcInvocation.java:93)
at org.apache.dubbo.remoting.transport.DecodeHandler.decode(DecodeHandler.java:57)
at org.apache.dubbo.remoting.transport.DecodeHandler.received(DecodeHandler.java:44)
at org.apache.dubbo.remoting.transport.dispatcher.ChannelEventRunnable.run(ChannelEventRunnable.java:57)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at org.apache.dubbo.common.threadlocal.InternalRunnable.run(InternalRunnable.java:41)
at java.lang.Thread.run(Thread.java:750)
at org.apache.dubbo.rpc.cluster.support.FailoverClusterInvoker.doInvoke(FailoverClusterInvoker.java:114)
at org.apache.dubbo.rpc.cluster.support.AbstractClusterInvoker.invoke(AbstractClusterInvoker.java:340)
at org.apache.dubbo.rpc.cluster.router.RouterSnapshotFilter.invoke(RouterSnapshotFilter.java:46)
at org.apache.dubbo.rpc.cluster.filter.FilterChainBuilder$CopyOfFilterChainNode.invoke(FilterChainBuilder.java:321)
at org.apache.dubbo.monitor.support.MonitorFilter.invoke(MonitorFilter.java:99)
at org.apache.dubbo.rpc.cluster.filter.FilterChainBuilder$CopyOfFilterChainNode.invoke(FilterChainBuilder.java:321)
at org.apache.dubbo.rpc.protocol.dubbo.filter.FutureFilter.invoke(FutureFilter.java:51)
at org.apache.dubbo.rpc.cluster.filter.FilterChainBuilder$CopyOfFilterChainNode.invoke(FilterChainBuilder.java:321)
at org.apache.dubbo.rpc.cluster.filter.support.ConsumerContextFilter.invoke(ConsumerContextFilter.java:110)
at org.apache.dubbo.rpc.cluster.filter.FilterChainBuilder$CopyOfFilterChainNode.invoke(FilterChainBuilder.java:321)
at org.apache.dubbo.rpc.cluster.filter.FilterChainBuilder$CallbackRegistrationInvoker.invoke(FilterChainBuilder.java:193)
at org.apache.dubbo.rpc.cluster.support.wrapper.AbstractCluster$ClusterFilterInvoker.invoke(AbstractCluster.java:92)
at org.apache.dubbo.rpc.cluster.support.wrapper.MockClusterInvoker.invoke(MockClusterInvoker.java:97)
at org.apache.dubbo.registry.client.migration.MigrationInvoker.invoke(MigrationInvoker.java:283)
at org.apache.dubbo.rpc.proxy.InvocationUtil.invoke(InvocationUtil.java:57)
at org.apache.dubbo.rpc.proxy.InvokerInvocationHandler.invoke(InvokerInvocationHandler.java:73)
at org.apache.dubbo.springboot.demo.DemoServiceDubboProxy1.sayHello(DemoServiceDubboProxy1.java)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:344)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:205)
at com.sun.proxy.$Proxy54.sayHello(Unknown Source)
at org.apache.dubbo.springboot.demo.consumer.ConsumerApplication.doSayHello(ConsumerApplication.java:61)
at org.apache.dubbo.springboot.demo.consumer.ConsumerApplication.main(ConsumerApplication.java:49)
观察日志发现,consumer并没有识别到Provider A目前并没有实例,仍然认为192.168.1.10也是Provider A的实例,将调用Provider A的请求发送过去,此时192.168.1.10服务器上运行的却是Provider B应用,无法处理该请求,就抛出异常。
如图所示,Consumer 第一次访问Provider A和Provider B时,consumer维护的信息和实际的部署信息是一致的
但是在Csonumser第二次访问Provider A和Provider B时,consumer维护的信息和实际的部署信息已经不一致了
出现这个情况的原因是dubbo3默认开启的推空保护(ZookeeperRegistry$RegistryChildListenerImpl.doNotify()方法会ZookeeperRegistry.toUrlsWithEmpty()方法获取Provider Urls,在该方法中会判断推空保护的开关),
本意是防止注册中心抖动,可是在某些场景下会引发问题,例如:
应用最后一台实例下线后,ip被回收,其它应用发布时从ip池获取到该ip并使用
这种情况在测试环境更容易出现,因为测试环境普遍都是一个实例。
如果要在测试环境避免这种情况,目前最好的办法是关闭推空保护:
- RegistryConfig.enableEmptyProtection 设置为false
- springboot 应用中配置参数 dubbo.registry.enable-empty-protection=false
这篇好文章是转载于:学新通技术网
- 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
- 本站站名: 学新通技术网
- 本文地址: /boutique/detail/tanhgcbfja
-
photoshop保存的图片太大微信发不了怎么办
PHP中文网 06-15 -
Android 11 保存文件到外部存储,并分享文件
Luke 10-12 -
word里面弄一个表格后上面的标题会跑到下面怎么办
PHP中文网 06-20 -
《学习通》视频自动暂停处理方法
HelloWorld317 07-05 -
photoshop扩展功能面板显示灰色怎么办
PHP中文网 06-14 -
微信公众号没有声音提示怎么办
PHP中文网 03-31 -
excel下划线不显示怎么办
PHP中文网 06-23 -
怎样阻止微信小程序自动打开
PHP中文网 06-13 -
excel打印预览压线压字怎么办
PHP中文网 06-22 -
TikTok加速器哪个好免费的TK加速器推荐
TK小达人 10-01