首页 » Web前端 » dubboproviderphp技巧_Dubbo No provider问题排查思路

dubboproviderphp技巧_Dubbo No provider问题排查思路

访客 2024-12-18 0

扫一扫用手机浏览

文章目录 [+]

不想看字的同学可直接划到底部查看思维导图

问题剖析

利用过Dubbo的朋友很多都碰到过如下报错:

dubboproviderphp技巧_Dubbo No provider问题排查思路

No provider available for the service org.newboo.basic.api.MyDemoService from registry 127.0.0.1:2181 on the consumer 127.0.0.1 using the dubbo version 2.7.6. Please check if the providers have been started and registered.

dubboproviderphp技巧_Dubbo No provider问题排查思路
(图片来自网络侵删)

从源码来看这个报错位于

org.apache.dubbo.rpc.cluster.support.AbstractClusterInvoker#checkInvokers

protected void checkInvokers(List<Invoker<T>> invokers, Invocation invocation) { if (CollectionUtils.isEmpty(invokers)) { throw new RpcException(RpcException.NO_INVOKER_AVAILABLE_AFTER_FILTER, "Failed to invoke the method " + invocation.getMethodName() + " in the service " + getInterface().getName() + ". No provider available for the service " + getDirectory().getConsumerUrl().getServiceKey() + " from registry " + getDirectory().getUrl().getAddress() + " on the consumer " + NetUtils.getLocalHost() + " using the dubbo version " + Version.getVersion() + ". Please check if the providers have been started and registered."); }}

当配置reference的check=false时调用它的代码位于

org.apache.dubbo.rpc.cluster.support.FailoverClusterInvoker#doInvoke

(为true时在启动时校验)

从代码能看出导致这个报错的直接缘故原由是:invokers为空

此处invoker对应一个provider URL,当没有provider可用时,invokers为空

排查思路

这个问题看似大略,但实际情形非常繁芜,碰到后无从下手,本文供应一种可行的排查思路。

排查大致分为两条线,provider端和consumer端。

provider端

出问题第一韶光排查provider,由于provider的情形比较少,可以大略地打消一部分情形。

provider出问题只有一种情形:未注册到注册中央

以是对应的排查思路是去看provider有没有注册成功:

如果有dubbo掌握台或者注册中央查询页面,直接查询一下即可如果没有可视化界面,比如zk、etcd可通过相应的客户端连上去查看是否注册成功

以zk为例,可通过 ls /dubbo/${service}/providers 查看注册上的provider

如果provider未注册成功,那么就须要排查,可能的缘故原由有:

provider未启动成功,启动一下即可provider虽然启动了,但注册失落败了,查看一下缺点日志,对症办理注册中央地址是否写错?环境是否同等?

如果provider已经注册,解释provider没问题,再看consumer。

consumer端

consumer端排查还需再细分,以是否订阅(拉取)到对应provider信息为界

如何查看consumer的订阅信息

consumer订阅信息可从缓存文件中查看,缓存文件默认按如下规则天生:

String defaultFilename = System.getProperty("user.home") + "/.dubbo/dubbo-registry-" + url.getApplication() + "-" + url.getAddress().replaceAll(":", "-") + ".cache";

例如:

~/.dubbo/dubbo-registry-ddog-my-demo-c0-127.0.0.1-2181.cache

有多个注册中央,将有多个缓存文件,文件内容如下:

#Dubbo Registry Cache#Wed Aug 11 20:26:15 CST 2021org.newboo.basic.api.MyDemoService=empty\://127.0.0.1/org.newboo.basic.api.MyDemoService?application\=ddog-my-demo-c0&category\=routers&check\=false&dubbo\=2.0.2&init\=false&interface\=org.newboo.basic.api.MyDemoService&loadbalance\=xxx&methods\=call&owner\=roshilikang&pid\=3084&qos.enable\=true&qos.port\=33333&release\=2.7.6&side\=consumer&sticky\=false×tamp\=1628684774590 empty\://127.0.0.1/org.newboo.basic.api.MyDemoService?application\=ddog-my-demo-c0&category\=configurators&check\=false&dubbo\=2.0.2&init\=false&interface\=org.newboo.basic.api.MyDemoService&loadbalance\=xxx&methods\=call&owner\=roshilikang&pid\=3084&qos.enable\=true&qos.port\=33333&release\=2.7.6&side\=consumer&sticky\=false×tamp\=1628684774590 dubbo\://127.0.0.1\:20880/org.newboo.basic.api.MyDemoService?anyhost\=true&application\=ddog-my-demo-p0&deprecated\=false&dubbo\=2.0.2&dynamic\=true&generic\=false&interface\=org.newboo.basic.api.MyDemoService&methods\=call&owner\=roshilikang&pid\=2058&release\=2.7.6&side\=provider&threads\=500×tamp\=1628684412247

搜索文件中是否有对应做事的provider

未成功订阅

如果没拿到信息(搜索不到对应的provider),解释订阅存在问题,检讨consumer日志是否有报错,注册中央地址,环境等配置是否有问题。

成功订阅

比如这个文件,存在

dubbo\://127.0.0.1\:20880/org.newboo.basic.api.MyDemoService?anyhost\=true&application\=ddog-my-demo-p0&deprecated\=false&dubbo\=2.0.2&dynamic\=true&generic\=false&interface\=org.newboo.basic.api.MyDemoService&methods\=call&owner\=roshilikang&pid\=2058&release\=2.7.6&side\=provider&threads\=500×tamp\=1628684412247

解释consumer已经拿到了provider信息

当consumer拿到provider,也不一定就能担保调用不会报No provider,有这么几种情形须要排查

检讨consumer的group、version是否和provider完备匹配,不匹配会报No provider是否被禁用,搜索缓存文件中是否有该做事对应的override URL,且disabled=trueconsumer是否配置了路由规则,如tag路由,条件路由等,路由规则可能导致No provider

group、version是否匹配,有一个不看代码就知道consumer的version、group配置的小技巧,如果consumer指定了version或group,报错信息如下(group=read,version=1.0):

No provider available from registry 127.0.0.1:2181 for service read/org.newboo.basic.api.MyDemoService:1.0 on consumer 127.0.0.1 use dubbo version 2.7.6

service前包含group,用斜线分隔,service后有version用冒号分隔。

以上可覆盖95%的场景,还有一种比较少见:consumer天生invoker失落败导致invokers为空;

此种情形请仔细检讨缺点日志,不明的报错须要关注。
此处列举一些碰到过的case

Dubbo 2.6.x中transport实现了netty和netty4,而在2.6.10版本中,netty transport扩展名字被改为了netty3;如果provider利用dubbo 2.6.10且指定了transport为netty3,低版本的dubbo调用时由于没有实现netty3的扩展而导致invoker天生失落败;此时consumer端看起来是拿到了provider的URL,但也会报No provider缺点与1类似,当自定义某些扩展只在provider利用时,provider的一些参数会通报给consumer,让consumer也利用相同扩展,但consumer不一定实现了该扩展,导致invoker天生失落败;比如自定义的dispatcher扩展。

注:可能你会问为什么provider的参数会通报给consumer?这合理吗?举个例子,如果provider指定序列化协议为json,那consumer是否也要按照provider的序列化协议json来传输数据呢?只能说没有万全的设计

总结

跟很多问题排查思路一样,根据已有征象一步步缩小排查范围,终极锁定根本缘故原由。
用一副思维导图来总结:

搜索关注"捉虫大师",后端技能分享,架构设计、性能优化、源码阅读、问题排查、踩坑实践。

相关文章