广饶县城乡规划建设局网站,网站安全建设目的是什么,直播带货实训总结报告,免费域名建站系列目录
【Spring Cloud Alibaba】#xff08;一#xff09;微服务介绍 及 Nacos注册中心实战 【Spring Cloud Alibaba】#xff08;二#xff09;微服务调用组件Feign原理实战 【Spring Cloud Alibaba】#xff08;三#xff09;OpenFeign扩展点实战 源码详解 【Spri…
系列目录
【Spring Cloud Alibaba】一微服务介绍 及 Nacos注册中心实战 【Spring Cloud Alibaba】二微服务调用组件Feign原理实战 【Spring Cloud Alibaba】三OpenFeign扩展点实战 源码详解 【Spring Cloud Alibaba】四Dubbo框架介绍 及 整合Dubbo和OpenAI实战【文末附源码】 本文目录系列目录前言一、启动报错1. 两种场景2. 报错信息3. 排查问题4. 补充说明二、一直重连报错1. 两种场景2. 报错信息3. 排查问题4. 补充说明总结最后前言
书接上文关于Dubbo真心好用真心强大但是人红是非多偶尔还能听到关于Dubbo的各种坑的说法。
比如消费方启动报错Failed to check the status of the service xxx. No provider available for the service。。。
再比如消费方启动成功后但一直与提供方重连报错Fail to connect to HeaderExchangeClient。。。
你真的以为这是Dubbo的坑吗?
加一个小插曲我想做一下调查当你遇到技术问题时你会怎么做? 报错了没见过管它三七二十一网上直接搜施展搜索大法~~~ 然后网上各种文章鱼龙混杂运气好直接解决运气不好方法试个遍也没效果… 向同事请教一次一次请教倍感无奈… 对报错快速排查一下(运气好直接解决)不行再有针对性的查找资料遇到难点再向同事(或CSDN大佬)请教。
本文就以这两个Dubbo常见问题入手带你进入源码分析如何排查问题 一起拉开有趣的程序人生Let’s go! 一、启动报错
1. 两种场景
在消费方启动时可能会遇到以下两种场景
没有可用的服务提供方即注册中心没有注册 依赖的提供方 例如提供方正在部署中或者提供方也是启动报错网络不通导致消费方与提供方连接不上 例如Local环境与DEV环境的网不通因为服务器上通常都是部署在Docker里. 不管怎么样得先让服务启动起来吧~~~ 2. 报错信息
那么消费方启动失败会抛出 IllegalStateException报错信息大致如下 Error creating bean with name ‘xxxBean’: Injection of DubboReference dependencies is failed; nested exception is java.lang.IllegalStateException: Failed to check the status of the service xxxInterfaceName. No provider available for the service xxxInterfaceName from the url xxxUrl to the consumer xxxLocalhost use dubbo version xxxVersion 例如我未启动提供者重现的报错截图如下
3. 排查问题
搜索报错信息Failed to check the status of the service可以快速定位到报错的源码如下图
看到if判断条件 shouldCheck()方法了吧? 从命名就可以看出来这是判断是否应该检查进去看看 没有几行代码我想你能想到
① isCheck() 没有配置默认为null
② 由于① 为null所以主要看getConsumer()
③ 如果① 和②均没配置第3步默认设为true即检查是否可用
所以对于我们来说主要可配置点在 getConsumer().isCheck() ,
即ConsumerConfig类的isCheck()方法
public Boolean isCheck() {return check;
}ConsumerConfig类从名子可以看出来消费者配置类.
稍微找一找就可以找到在EnableDubbo注解上有一个EnableDubboConfig注解里面注释写着 再到注释对应的源码里验证一下如果你从EnableDubboConfig上的DubboConfigConfigurationRegistrar进去可以看到DubboConfigConfiguration 再跟进去从这里就可以找到对应的源码ConsumerConfig类绑定的配置前缀为dubbo.consumer如下图
4. 补充说明
综上配置dubbo.consumer.check false 就代表消费方启动时不检查提供方是否可用
application.properties
dubbo.consumer.check false这里补充说明如下 Dubbo服务消费方在启动时缺省会检查依赖的服务提供方是否可用不可用时会抛出异常阻止 Spring 初始化完成以便上线时能及早发现问题默认 checktrue。 可以通过 checkfalse 关闭检查比如测试时有些服务不关心或者出现了循环依赖必须有一方先启动。 二、一直重连报错
1. 两种场景
当通过checkfalse启动消费方后还可能会遇到以下两种场景
网络不通导致消费方与提供方连接不上上面提到的第2点 例如Local环境与DEV环境的网不通因为服务器上通常都是部署在Docker里。获取到的是已下线的提供方 例如消费方启动时提供方也在重新部署这时就有可能获取到刚下线的提供方.。 大部分情况等待一小会会自动更新为新部署的提供方但是偶尔也存在一直无法更新过来的情况。 如果对报错的提供方 不关心就真的不想看到一直重连的报错! 2. 报错信息
消费方启动成功但与提供方连接失败会一直报错并抛出 RemotingException报错信息大致如下 header.ReconnectTimerTask : [DUBBO] Fail to connect to HeaderExchangeClient [channelorg.apache.dubbo.remoting.transport.netty4.NettyClient [xxx - /xxx:20880]], dubbo version: xxxVersion, current host: xxxLocalhost org.apache.dubbo.remoting.RemotingException: client(url: xxxURL) failed to connect to server /xxx:20880 client-side timeout 3000ms (elapsed: 3012ms) from netty client xxx using dubbo version xxxVersion 例如我这里消费方在本地环境提供方在DEV环境重现的报错截图如下 3. 排查问题
全局或者直接到报错的ReconnectTimerTask类中搜索报错信息Fail to connect to可以快速定位到报错的源码如下 打印的e根据报错信息可以确定是这里 ReconnectTimerTask从名子就可以看出来是重连的定时任务所以如果想不让它不报错就需要看看是否可以不启动这个定时器这样自然就不会打印ERROR了是这个逻辑吧?
OK那我们得先找到启动定时器的地方怎么找
对先查找一下ReconnectTimerTask的类的引用很快就定位到了HeaderExchangeClient.startReconnectTask(URL url)方法看名子就知道开始重连任务。 OK到这我不说你应该也发现了这里有个if判断条件shouldReconnect(url)方法和第一个问题的shouldCheck都是统一命名规则想都不用想可以肯定就在这里控制它
我们看一下代码就一行url.getParameter内部是从Map中查找reconnect找不到默认会设为true
String RECONNECT_KEY reconnect;
private boolean shouldReconnect(URL url) {return url.getParameter(Constants.RECONNECT_KEY, true);
}那么问题来了, reconnect参数在哪配置
这里向上查找引用的话链路有点深所以为了看的更清晰我们可以打个断点看下调用堆栈。
这样一下就找到了入口ReferenceConfig.get方法这里代码更少主要就是调用init()方法。 转到init()方法的313行传入的正是一个map如下图调试发现里面竟然有checkfalse所以猜测还是与ConsumerConfig(消费者配置类)有关方里里再向上找一找还真找到了ConsumerConfig类的对象consumer从名子appendParameters就知道它是往map里追加consumer的配置所以就这样配置上了 所以我们在dubbo.consumer下面配一下试试
application.properties
dubbo.consumer.reconnect false不出所料生效了如下图
4. 补充说明
综上配置dubbo.consumer.reconnect false 就代表消费方不重连提供方
实际上这里有一个机制就是Dubbo的重连机制也是为了能及早发现问题所以生产环境建议不要修改此配置
而这个配置多用于开发环境用于忽略不关心的服务
那么对于关心的服务需要调用的话怎么做
可以考虑以下两种做法
做法1. 对网络不通的环境进行服务隔离
可以通过配置Nacos服务发现group隔离服务注册例如
spring.cloud.nacos.discovery.groupXXX_GROUP这样就可以做到本地环境只调本地服务DEV环境只调DEV服务只需要配置相同组名即可
做法2. 不做服务隔离在实际调用失败后做容错处理
因为调用链路可能会错综复杂有时环境隔离成本太高这时就可以转为HTTP请求对Nginx或Gateway发起HTTP调用这也是对上述两种场景RPC调用异常的兜底方案 总结
Java的开源框架我们有时可以不用跟的太深一样可以快速搞定一些问题
搜索报错文本定位源码位置通过查找引用、打断点找入口分析是什么原因导致走到报错位置通过名子或注释了解方法的意图通过主流程快速找出解决问题的关键点 最后
虽然框架源码一直在变但方法万变不离其宗套路都是相通的你更值得学习的是排查问题的方法更重要的是养成独立解决问题的习惯相信你可以做到
如果你学会了排查问题的方法那么你以后就会很独立也会被你的领导和同事看到你有两把刷子说不准还能成为疑难杂症专家即使你在遇到难题问了师傅他也会觉得你问的有水平他也会为帮你解决这个问题漏了一手而沾沾自喜
所以遇到问题不是坏事 多解决问题问题会让你的经验越来越丰富也会让你对吃饭的框架越来越熟悉这些都是你的财富也可以写进简历让面试官更喜欢你。不过友情提醒尺度把控好项目中遇到问题切勿死磕切勿陷入细节影响项目进度 那么对于Dubbo RPC调用异常转HTTP调用你知道怎么实现吗这也是我计划将在本专栏下文分享的内容如果感觉不错欢迎订阅本专栏后面还有更多的【Spring Cloud Alibaba】实战知识陆续放出。
关注我 天罡gg 分享更多干货 https://blog.csdn.net/scm_2008 大家的「关注❤️ 点赞 收藏⭐」就是我创作的最大动力谢谢大家的支持我们下文见