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

说说DataStreamAPI应用实例

时间:2023-03-21 14:21:30 科技观察

本文转载自微信公众号《数据仓库宝贝库》,作者张立兵。转载本文请联系数据仓库宝贝图书馆公众号。不想看课文的同学可以直接拉到最下方查看思维导图问题分析。很多用过Dubbo的朋友都遇到过如下错误:Noprovideravailablefortheserviceorg.newboo.basic.api.MyDemoServicefromregistry127.0.0.1:2181onconsumer127.0.0.1usingthedubboversion2.7.6。请检查提供程序是否已经启动和注册。从源码来看,这个错误位于org.apache.dubbo.rpc.cluster.support.AbstractClusterInvoker#checkInvokersprotectedvoidcheckInvokers(List>invokers,Invocationinvocation){if(CollectionUtils.isEmpty(invokers)){thrownewRpcException(RpcException(RpcException.NO_INVOKER_AVAILABLE_AFTER_FILTER,"Failedtoinvokethemethod"+invocation.getMethodName()+"intheservice"+getInterface().getName()+".Noprovideravailablefortheservice"+getDirectory().getConsumerUrl().getServiceKey()+"fromregistry"+getDirectory().getUrl().getAddress()+"ontheconsumer"+NetUtils.getLocalHost()+"usingthedubboversion"+Version.getVersion()+"。请检查提供商是否已经tartedandregistered.");}}当配置引用的check=false时,调用它的代码位于org.apache.dubbo.rpc.cluster.support.FailoverClusterInvoker#doInvoke(为true时启动时检查)从代码来看,这个错误的直接原因是:invokers为空,这里invoker对应一个providerURL,当没有provider时,invokers为空,排查这个问题看似简单,实际情况却很复杂,而且遇到后无从下手,本文提供AFeasibleTroubleshootingIdea故障排查大致分为两条线,provider端和consumer端,如果provider端有问题,第一时间排查provider,因为provider的情况比较少,有些情况可以简单排除,provider的问题只有一种情况:没有到注册中心注册,所以对应的排查思路是看如果提供者注册成功:如果有dubbo控制台或者注册中心查询页面,直接查询即可。如果没有可视化界面,比如zk、etcd,可以使用对应的Connect客户端查看是否注册成功。以zk为例,可以通过ls/dubbo/${service}/providers查看注册的provider。如果provider没有注册成功,需要检查。可能的原因是:provider没有启动成功,直接启动即可。尽管提供程序已启动,但注册失败。检查错误日志并解决问题。是不是注册中心地址错了?环境是否一致?如果provider已经注册了,说明provider没问题,再看consumer。Consumer端consumer端调查需要进一步细分,以是否订阅(pull)对应的provider信息为界Howtoviewconsumersubscriptioninformationconsumer订阅信息可以从缓存文件中查看,默认生成按照如下规则:tringdefaultFilename=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有多个注册中心,会有多个缓存文件。文件内容如下:#DubboRegistryCache#WedAug1120:26:15CST2021org.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\=1628684774590empty\://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\=1628684774590dubbo\://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是否搜索文件如果对应服务的提供者订阅失败,如果没有获取到信息(找不到对应的提供者),说明订阅有问题。检查消费日志是否有错误,注册中心地址、环境等配置是否有问题。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,不一定保证调用不会报Noprovider。有几种情况需要检查消费者的组和版本是否与提供者完全匹配。如果它们不匹配,将报告Noprovider。有服务对应的overrideURL,disabled=true。consumer是否配置了路由规则,比如tag路由,条件路由等,路由规则可能会导致Noprovidergroup和version不匹配,不看代码也能知道consumer的版本和group配置提示,如果消费者指定版本或组,错误信息如下(组=读取,版本=1.0):Noprovideravailablefromregistry127.0.0.1:2181forserviceread/org.newboo.basic.api.MyDemoService:1.0在consumer127.0.0.1上使用dubboversion2.7.6服务包含服务前的组,以斜线分隔,服务后的版本以冒号分隔。以上可以覆盖95%的场景,还有一种比较少见:消费者生成调用者失败,调用者为空;这种情况请仔细查看错误日志,需要注意未知错误报告。下面是遇到的一些情况。Dubbo2.6.x中的transport实现了netty和netty4,在2.6.10版本中,nettytransport扩展名改为netty3;如果provider使用dubbo2.6.10,指定transport为Netty3,由于没有实现netty3的扩展,低版本的dubbo无法生成invoker;这个时候consumer端好像已经拿到了provider的url,但是也会报Noprovider的错误。类似1,当自定义一些extension时,只有使用provider的时候,才会将provider的一些参数传递给consumer,这样consumer也可以使用相同的extension,但是consumer不一定实现了extension,导致未能生成调用程序;例如自定义调度程序扩展。注意:你可能会问为什么要将提供者的参数传递给消费者?这合理吗?比如提供者指定序列化协议为json,那么消费者是否也按照提供者的序列化协议json传输数据?只能说没有完美的设计总结,这和很多排查思路一样。根据现有现象,逐步缩小排查范围,最终查明根源。用思维导图总结一下: