spring-cloud-starter-dubbo不设置心跳间隔导致生产者重启no Provider问题记录

版本

spring-cloud-starter-dubbo-2.2.4.RELEASE

问题描述

生产者重启后,正常注册到注册中心,但是消费者调用接口是no provider,偶现,频繁出现

解决办法

先说原因和解决办法,有兴趣可以看下问题的排查过程。

原因

dubbo在建立连接后会起一个任务,检查连接的是否有效,如果已经时间,会重新连接。问题出在时间间隔上面。
从元数据读取heartbeat这个key,如果没有,那么使用默认的60秒,我们项目没有设置这个心跳时间,那么默认就是60秒。
而重试时间间隔默认为这个时间的三倍,也就是3分钟。此时也就问题就已经很明显,重连时间间隔太长。生产者重新启动后,还没有重新建立连接。此时调用DubboMetadataService.getExportedURLs的方法获取服务原数据还使用已经关闭的那个时效的连接,会失败报错

Caused by: org.apache.dubbo.remoting.RemotingException: message can not send, because channel is closed .

表现

查看日志,发现生产者有下线后,消费者会去重连,但是有时能重连成功,有时重连失败
连接失败
image.png
连接成功
image.png
经过观察,每次生产者启动后,都是因为重连失败会导致No Provider。

解决办法

dubbo:protocol:name: dubboheartbeat: 1000

这里设置1秒,那么3秒会进行一次检查,已经足够了在生产者启动暴露服务期间与生产者建立连接。
此时再查看元数据已经有了timeout

在这里插入图片描述
设置心跳时间后,重启生产者和消费者。问题解决,以后重启生产者不会再出现 No Provider的问题

问题排查过程

服务刷新角度排查

首先排查是不是因为是不是因为生产者注册到nacos服务变动,没有触发消费端的服务刷新。经过排查,正常触发了DubboMetaDataService的服务刷新,也正常触发了Dubbo Invoker的刷新。这俩监听器分别是com.alibaba.cloud.dubbo.registry.DubboCloudRegistry#subscribeDubboMetadataServiceURLs(org.apache.dubbo.common.URL, org.apache.dubbo.registry.NotifyListener)

com.alibaba.cloud.dubbo.registry.DubboCloudRegistry#subscribeURLs(org.apache.dubbo.common.URL, org.apache.dubbo.registry.NotifyListener)
执行顺序上没问题,因为spring cloud alibaba只注册DubboMetadataService到注册中心,消费者需要引用的生产者接口,是用过DubboMetadataService.getExportedURLs,做rpc调用生产者获取到的。因此需要先刷新DubboMetadataService对应的invoker再刷新消费者引用的的那些 invoker
但是在触发获取getExportedURLs时,发现有些情况获取到的结果是空

	private List<URL> getTemplateExportedURLs(URL subscribedURL,List<ServiceInstance> serviceInstances) {DubboMetadataService dubboMetadataService = getProxy(serviceInstances);List<URL> templateExportedURLs = emptyList();if (dubboMetadataService != null) {templateExportedURLs = getExportedURLs(dubboMetadataService, subscribedURL);}else {if (logger.isWarnEnabled()) {logger.warn("The metadata of Dubbo service[key : {}] still can't be found, it could effect the further "+ "Dubbo service invocation",subscribedURL.getServiceKey());}}return templateExportedURLs;}

生产者服务暴露时机排查

消费者正常通过DubboMetadataService.getExportedURL获取服务,返回空。首先怀疑生产者逻辑有问题。
经过排查,生产者保证了 首先暴露所有的服务后才注册元数据到注册中心
image.png
消费者rpc调用。在生产者DubboMetadataService的实现IntrospectiveDubboMetadataService上断电观察,发现这里返回的数据是没问题的

@Overridepublic String getExportedURLs(String serviceInterface, String group, String version) {List<URL> urls = getRepository().getExportedURLs(serviceInterface, group,version);return jsonUtils.toJSON(urls);}

消费者调用生产者排查

不得不说这个问题真的难查,在不断点的情况下很容易出现,但是加上断点,导致程序执行速度变慢,很难复现。、
最终查看日志发现在生产者重启后的报错

Caused by: org.apache.dubbo.remoting.RemotingException: message can not send, because channel is closed .

image.png
但是我生产已经启动了,dubbo端口也起来了。为什么还报这个错。

Caused by: org.apache.dubbo.remoting.RemotingException: message can not send, because channel is closed .

看到这里,下意识猜测是不是因为生产者下线并上线后,消费者用的还是旧链接,而没有重新建立连接。
查看日志,发现生产者有下线后,消费者会去重连,但是有时能重连成功,有时重连失败
连接失败
image.png
连接成功
image.png
经过观察,每次生产者启动后,都是因为重连失败会导致No Provider。
那么问题就找到了。至于怎么解决,看下这个ReconnectTimerTask的逻辑是怎么样的

public class ReconnectTimerTask extends AbstractTimerTask {private static final Logger logger = LoggerFactory.getLogger(ReconnectTimerTask.class);private final int idleTimeout;public ReconnectTimerTask(ChannelProvider channelProvider, Long heartbeatTimeoutTick, int idleTimeout) {super(channelProvider, heartbeatTimeoutTick);this.idleTimeout = idleTimeout;}@Overrideprotected void doTask(Channel channel) {try {Long lastRead = lastRead(channel);Long now = now();// Rely on reconnect timer to reconnect when AbstractClient.doConnect fails to init the connectionif (!channel.isConnected()) {try {logger.info("Initial connection to " + channel);((Client) channel).reconnect();} catch (Exception e) {logger.error("Fail to connect to " + channel, e);}// check pong at client} else if (lastRead != null && now - lastRead > idleTimeout) {logger.warn("Reconnect to channel " + channel + ", because heartbeat read idle time out: "+ idleTimeout + "ms");try {((Client) channel).reconnect();} catch (Exception e) {logger.error(channel + "reconnect failed during idle time.", e);}}} catch (Throwable t) {logger.warn("Exception when reconnect to remote channel " + channel.getRemoteAddress(), t);}}
}

发现这个任务会检查连接是否有效,如果连接无效,那么会重新连接。
这个任务的执行时机是通过dubbo的时间轮调用的。
关于时间轮的这里不展开了。看下这个定时任务的执行间隔是多少
在HeaderExchangeClient中建立连接后。会开启一个重试连接的任务。

    private void startReconnectTask(URL url) {if (shouldReconnect(url)) {AbstractTimerTask.ChannelProvider cp = () -> Collections.singletonList(HeaderExchangeClient.this);int idleTimeout = getIdleTimeout(url);long heartbeatTimeoutTick = calculateLeastDuration(idleTimeout);this.reconnectTimerTask = new ReconnectTimerTask(cp, heartbeatTimeoutTick, idleTimeout);IDLE_CHECK_TIMER.newTimeout(reconnectTimerTask, heartbeatTimeoutTick, TimeUnit.MILLISECONDS);}}

其中heartbeatTimeoutTick标识了重连检查的时间间隔

String HEARTBEAT_KEY = "heartbeat";
int DEFAULT_HEARTBEAT = 60 * 1000;
public static int getIdleTimeout(URL url) {int heartBeat = getHeartbeat(url);// idleTimeout should be at least more than twice heartBeat because possible retries of client.int idleTimeout = url.getParameter(Constants.HEARTBEAT_TIMEOUT_KEY, heartBeat * 3);if (idleTimeout < heartBeat * 2) {throw new IllegalStateException("idleTimeout < heartbeatInterval * 2");}return idleTimeout;}public static int getHeartbeat(URL url) {return url.getParameter(Constants.HEARTBEAT_KEY, Constants.DEFAULT_HEARTBEAT);}

可以看到超时时间是从,dubbo元数据读取heartbeat这个key,如果没有,那么使用默认的60秒,我们项目没有设置这个心跳时间,那么默认就是60秒。
而重试时间间隔默认为这个时间的三倍,3分钟。此时也就问题就已经很明显,重连时间间隔太长。生产者重新启动后,还没有重新建立连接。此时调用DubboMetadataService.getExportedURLs的方法获取服务原数据会失败,报错

Caused by: org.apache.dubbo.remoting.RemotingException: message can not send, because channel is closed .

等到了时间,重连成功后,又因为此时的nacos中的数据不再变化,不再触发服务变动,导致一直都是No Provider的状态。
那么解决这个办法也很简单,那就是设置心跳时间小一些。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/181850.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

探索Kosmos-2模型的神奇功能

Kosmos-2是一个多模态大语言模型&#xff0c;它可以理解和生成包含图像和文本的内容。它的特点是能够将文本中的指代表达式&#xff08;如“这个”、“那个”等&#xff09;与图像中的物体对应起来&#xff0c;实现局部理解和交互。如果你想使用Kosmos-2模型&#xff0c;你可以…

第 370 场 LeetCode 周赛题解

A 找到冠军 I 枚举求强于其他所有队的队 class Solution { public:int findChampion(vector<vector<int>> &grid) {int n grid.size();int res 0;for (int i 0; i < n; i) {int t 0;for (int j 0; j < n; j)if (j ! i)t grid[i][j];if (t n - 1) …

微信怎么批量保存大量照片

8-2 本文要解决的问题是自动或者快速地保存微信收到的图片的事情&#xff0c;如果你的工作中有一个事情是需要每天或者经常保存大量的从微信收到的图片或者视频的&#xff0c;也许本文适合你&#xff0c;本文介绍的方法&#xff0c;可以自动保存各个群或者人发来的图片和视频。…

STM32G030F6P6 芯片实验 (二)

STM32G030F6P6 芯片实验 (二) Hello World - GPIO LED 尝试了下, 从 0 开始建 MDK HAL M0plus Project, 成功点亮 LED了。 但是 ST-LINK跑着跑着, 码飞了! 不知飞哪去了。 只好拿 MX 建了个 MDK Base。 呼叫 SysTick HAL_Delay(), 切换 LED。 基本上都是一样的用法, 只是换…

2023年亚太杯APMCM数学建模大赛ABC题辅导及组队

2023年亚太杯APMCM数学建模大赛 ABC题 一元线性回归分析类 回归分析&#xff08;Regression Analysis)是确定两种或两种以上变量间相互依赖的定量关系的一种统计分析方法。   – 按涉及变量个数划分   • 一元回归分析   • 多元回归分析   – 按自变量和因变量之间关…

inno setup 运行时进行文件复制和替换

问题描述&#xff1a; 当我们采用 inno setup进行打包时&#xff0c;需要实现将安装包中的某个文件进行替换&#xff0c;而且我们知道在Winodws系统可以有xcopy和copy两个命令可以提供该功能&#xff1b;而xcopy命令进行文件复制时会有如下提示&#xff1a; 此时需要手动输入字…

基于社交网络算法的无人机航迹规划-附代码

基于社交网络算法的无人机航迹规划 文章目录 基于社交网络算法的无人机航迹规划1.社交网络搜索算法2.无人机飞行环境建模3.无人机航迹规划建模4.实验结果4.1地图创建4.2 航迹规划 5.参考文献6.Matlab代码 摘要&#xff1a;本文主要介绍利用社交网络算法来优化无人机航迹规划。 …

python自动化运维——模拟键盘鼠标重复性操作Pyautoui

一、程序样式展示 将程序与cmd.xls文件放在同一文件夹&#xff0c;每一步的截图也放在当前文件夹 通过图片在屏幕上面进行比对&#xff0c;找到点击处进行自动化操作 自动化rpa测试 二、核心点 1.Pyautoui模块&#xff1a;主要针对图片进行定位pyautogui.locateCenterOnScree…

初识JVM

1. JVM内存区域划分 jvm在启动的时候&#xff0c;会申请到一整个很大的内存区域。整个一大块区域&#xff0c;不太好用。为了更方便使用&#xff0c;把整个区域隔成了很多区域&#xff0c;每个区域都有不同的作用。 本地方法栈 此处提到的栈和数据结构中的栈不是一个东西&…

左偏树学习笔记

定义 堆&#xff0c;是一棵树&#xff0c;且每个节点的键值都大于等于 / 小于其父亲的键值。 左偏树是一种可合并的堆&#xff0c;可以以 O ( log ⁡ n ) O(\log n) O(logn) 的复杂度实现合并。 性质 左偏树满足堆的性质。 我们设定一个值 dist \text{dist} dist&#xf…

【触想智能】工业显示器上市前的检测项目分享

工业显示器在上市前&#xff0c;需要做一项重要的工作&#xff0c;那就是工业显示器出厂前的产品可靠性检测。 工业显示器选择的测试项目相比商用端更为严格&#xff0c;常见的性能测试项目包括高温老化、防尘防水、电磁静电干扰、防摔防撞等&#xff0c;在工业级应用领域&…

《 Hello 算法 》 - 免费开源的数据结构与算法入门教程电子书,包含大量动画、图解,通俗易懂

这本学习算法的电子书应该是我看过这方面最好的书了&#xff0c;代码例子有多种编程语言&#xff0c;JavaScript 也支持。 《 Hello 算法 》&#xff0c;英文名称是 Hello algo&#xff0c;是一本关于编程中数据解构和算法入门的电子书&#xff0c;作者是毕业于上海交通大学的…

New Maven Project

下面两个目录丢失了&#xff1a; src/main/java(missing) src/test/java(missing) 换个JRE就可以跑出来了 变更目录

项目级asp.net框架的LIMS实验室管理系统源码

LIMS可用于管理完整的实验程序&#xff0c;从样品登记到检验、校核、审核到最终批准报告&#xff0c;建立在过程质量控制的基础上&#xff0c;对检测流程进行有效全面的管理&#xff0c;对影响质量的人、机、料、法、环因素加以控制&#xff0c;同时为质量改进提供数据依据。进…

Oracle-Ogg经典模式升级为集成模式步骤

​前言: Oracle Ogg集成模式比起经典模式功能更加的强大&#xff0c;支持更多的数据类型&#xff0c;压缩表同步&#xff0c;XA事务&#xff0c;多线程模式&#xff0c;PDB模式同步&#xff0c;RAC环境下抽取配置简单等新功能&#xff0c;所以可以选择将经典模式升级转化为集成…

操作系统复习(3)处理机调度与死锁

一、概述 1.1了解调度的层次 调度是指&#xff0c;在一个队列中&#xff0c;按照某种方法&#xff08;算法&#xff09;&#xff0c;选择一个合适的个体的过程。进程调度的功能就是按一定策略、动态地把CPU分配给处于就绪队列中的某一进程&#xff0c;并使之执行。 作业调度&…

CN考研真题知识点二轮归纳(4)

持续更新&#xff0c;上期目录&#xff1a; CN考研真题知识点二轮归纳&#xff08;4&#xff09;https://blog.csdn.net/jsl123x/article/details/134135134?spm1001.2014.3001.5501 1.既可以扩展网段又是二层的设备 网段一般指一个计算机网络中使用同一物理层设备&#xff…

47基于matlab的水印提取,将水印和载体进行图像融合

基于matlab的水印提取&#xff0c;将水印和载体进行图像融合&#xff0c;成为一体&#xff0c;可对合成图像进行加噪处理&#xff0c;剪切处理&#xff0c;小波压缩处理&#xff0c;旋转处理等操作&#xff0c;最后对合成图像实现水印提取&#xff0c;程序已调通&#xff0c;可…

分析:如何多线程运行测试用例

这是时常被问到的问题&#xff0c;尤其是UI自动化的运行&#xff0c;过程非常耗时&#xff0c;所以&#xff0c;所以多线程不失为一种首先想到的解决方案。 多线程是针对的测试用例&#xff0c;所以和selenium没有直接关系&#xff0c;我们要关心的是单元测试框架。 unittest …

【电路笔记】-谐波

谐波 文章目录 谐波1、概述2、频谱分析3、已知信号4、未知信号5、总结 周期性信号并不总是完美的正弦模式&#xff0c;例如我们之前有关 正弦波的文章之一中介绍的那样。 有时&#xff0c;信号确实可以是简单正弦波的叠加&#xff0c;它们被称为复杂波形。 在本文中&#xff0…