当前位置: 首页 > 科技观察

Dubbo2.7应用级服务发现笔记

时间:2023-03-14 01:10:46 科技观察

背景本文记录了dubbo2.7应用级服务发现的问题,这里不再赘述。读者反映他们正在开发基于dubbo2.7应用级服务发现的dubbo网关。根据文章《dubbo应用级服务发现初体验》,他们写了一个democall,报noprovidererror。首先我觉得他们的想法很多,把dubbo应用级服务发现投入生产的公司并不多。其次,当时写文章的时候测试没有遇到什么问题,但是本着帮助读者解决问题的态度,我还是重新写了一个demo测试。问题定位我拿了一个平时用来测试的dubbodemo工程(不是dubbo源码里的demo),发现确实没有在zookeeper上注册,然后测试了不同的版本,发现都不能注册,在2.7.5~2.7。11版本不报错,2.7.12版本会报如下NPE错误2021-06-1613:17:31,086[Dubbo-framework-scheduler-thread-1]ERRORorg.apache.dubbo.config.bootstrap。DubboBootstrap(DubboBootstrap.java:1172)-[DUBBO]refreshmetadataandinstancefailed,dubboversion:2.7.12,currenthost:172.23.233.52java.lang.NullPointerExceptionatorg.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.calInstanceRevision(ServiceInstancejavadataUtils).2dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.lambda$refreshMetadataAndInstance$6(ServiceInstanceMetadataUtils.java:272)atjava.util.ArrayList.forEach(ArrayList.java:1259)atorg.apache.dubbo.registry.client.metadata.ServiceInstanceInstanceMetadataUtils。refreshMetadata和(ServiceInstanceMetadataUtils.java:271)atorg.apache.dubbo.config.bootstrap.DubboBootstrap.lambda$registerServiceInstance$20(DubboBootstrap.java:1170)atjava.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)在java.util.concurrent.FutureTask.runAndReset(FutureTask.java:308)在java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:180)atjava.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:294)atjava.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)atjava.util.concurrent.ThreadPoolExecutor$Worker.run(readThread.java:624)atjava.lang.Thread.run(Thread.java:748)推测是服务注册有问题。跟着errorstackdebug,很快定位到问题直接导致NPE位于org.apache.dubbo。registry.client.AbstractServiceDiscovery#register<=2.7.11版本@Overridepublicfinalvoidregister(ServiceInstanceserviceInstance)throwsRuntimeException{this.serviceInstance=serviceInstance;doRegister(serviceInstance);}在2.7.12版本代码顺序调整为@Overridepublicfinalvoidregister(ServiceInstanceserviceInstance)throwsRuntimeException{doRegister(serviceInstance);this.serviceInstance=serviceInstance;}为什么调了代码顺序就报错了?追查后发现,NPE的来源是this.serviceInstance为null,原来的代码在执行doRegister之前为其赋值调整后的代码先执行doRegister,然后赋值。但是,执行diRegister时会抛出异常。不幸的是,这个异常被吃掉了。doRegister的实现如下@Overridepublicfinalvoidregister(ServiceInstanceserviceInstance)throwsRuntimeException{assertDestroyed(REGISTER_ACTION);assertInitialized(REGISTER_ACTION);executeWithEvents(of(newServiceInstancePreRegisteredEvent(serviceDiscovery,serviceInstance)),()->serviceDiscovery.register(serviceInstance),of(newServiceInstanceRegisteredEvent)(serviceDiscovery,serviceInstance)));}并且这个executeWithEvents将以事件的形式发送异常;try{action.execute();}catch(Throwablee){dispatchEvent(newServiceDiscoveryExceptionEvent(this,serviceDiscovery,e));}afterEvent.ifPresent(this::dispatchEvent);}但是这个事件抛出后没有处理out,表示异常被吃掉了。这就是为什么之前的dubbo版本没有抛出异常,也无法注册服务的原因。这个例外是什么?va.lang.NoClassDefFoundError:org/apache/curator/x/discovery/ServiceDiscovery实际上只是少引入了一个依赖项。这个问题可以通过添加如下org.apache.dubbodubbo-registry-zookeeper${version}为什么我写文章的时候没有遇到这个问题?正好这次调试是基于一个demo工程。《dubbo应用级服务发现初体验》一文是直接在dubbo源码中修改demo。源码中已经引入了所有的依赖。这其实是一个小问题,但对于用户来说却相当迷惑。为什么没有报错但是注册不了服务?如果没有2.7.12报的偶发错误,排查起来可能会比较困难。于是提了个issue和社区的朋友们交流了一下,总结2.7.x的应用级服务发现不再维护,3.x继续维护。https://github.com/apache/dubbo/issues/8061提issue也是为了让有问题的用户搜索,少走弯路。顺便提了一个PR,加了一行log,方便直观的发现这个问题。https://github.com/apache/dubbo/pull/8066新版本(>=2.7.13)如果有朋友再遇到这个问题,会直接打印出错误,就像这样2021-06-1616:58:02,210[main]ERRORorg.apache.dubbo.registry.client.EventPublishingServiceDiscovery(EventPublishingServiceDiscovery.java:287)-[DUBBO]ExecuteactionthrowsanddispatchaServiceDiscoveryExceptionEvent,dubboversion:2.7.12,currenthost:172.23.233.52java.lang.BootstrapMethodError:javaFound.lang.:org/apache/curator/x/discovery/ServiceDiscoveryatorg.apache.dubbo.registry.zookeeper.ZookeeperServiceDiscovery.doRegister(ZookeeperServiceDiscovery.java:92)atorg.apache.dubbo.registry.client.AbstractServiceDiscovery.register(AbstractServiceDiscovery.java:33))atorg.apache.dubbo.registry.client.EventPublishingServiceDiscovery.lambda$register$0(EventPublishingServiceDiscovery.java:159)atorg.apache.dubbo.registry.client.EventPublishingServiceDiscovery.executeWithEvents(EventPublishingServiceDiscovery.java:285)atorg.apache.dubbo。registry.client.EventPublishingSserviceDiscovery.register(EventPublishingServiceDiscovery.java:157)atorg.apache.dubbo.config.bootstrap.DubboBootstrap.lambda$doRegisterServiceInstance$21(DubboBootstrap.java:1192)atjava.util.ArrayList.forEach(ArrayList.java:1259)...由于2.7.x版本的应用级服务发现不再更新,下次我会写一篇分析3.0版本应用级服务发现源码的文章~