HeartBeatTask 类封装了心跳定时任务,需要了解的是 provider 和 consumer 都有可能发送心跳。

final class HeartBeatTask implements Runnable {
private static final Logger logger = LoggerFactory.getLogger( HeartBeatTask.class );
private ChannelProvider channelProvider;
private int heartbeat;
private int heartbeatTimeout; HeartBeatTask( ChannelProvider provider, int heartbeat, int heartbeatTimeout ) {
this.channelProvider = provider;
this.heartbeat = heartbeat;
this.heartbeatTimeout = heartbeatTimeout;
} public void run() {
try {
long now = System.currentTimeMillis();
for ( Channel channel : channelProvider.getChannels() ) {
if (channel.isClosed()) {
continue;
}
try {
Long lastRead = ( Long ) channel.getAttribute(
HeaderExchangeHandler.KEY_READ_TIMESTAMP );
Long lastWrite = ( Long ) channel.getAttribute(
HeaderExchangeHandler.KEY_WRITE_TIMESTAMP );
if ( ( lastRead != null && now - lastRead > heartbeat )
|| ( lastWrite != null && now - lastWrite > heartbeat ) ) {
Request req = new Request();
req.setVersion( "2.0.0" );
req.setTwoWay( true );
req.setEvent( Request.HEARTBEAT_EVENT );
channel.send( req );
}
if (lastRead != null && now - lastRead > heartbeatTimeout) {
//如果是 consumer 端
if (channel instanceof Client) {
((Client)channel).reconnect();
} else { // provider 端
channel.close();
}
}
} catch ( Throwable t ) {
}
}
} catch ( Throwable t ) {
logger.warn( "Unhandled exception when heartbeat, cause: " + t.getMessage(), t );
}
} interface ChannelProvider {
Collection<Channel> getChannels();
} }

对于 consumer,是在 HeaderExchangeClient 类中启动心跳定时器,而 provider,则是在 HeaderExchangeServer 中启动心跳定时器。

consumer发送请求时,更新 lastWrite 值,接收响应时,更新 lastRead 值。心跳定时器定时检查 lastRead 和 lastWrite,发送心跳、重连。

public class HeaderExchangeClient implements ExchangeClient {
private static final ScheduledThreadPoolExecutor scheduled =
new ScheduledThreadPoolExecutor(2, new NamedThreadFactory("dubbo-remoting-client-heartbeat", true));
// 心跳定时器
private ScheduledFuture<?> heatbeatTimer;
private int heartbeat;
private int heartbeatTimeout; public HeaderExchangeClient(Client client){
if (client == null) {
throw new IllegalArgumentException("client == null");
}
this.client = client;
this.channel = new HeaderExchangeChannel(client);
String dubbo = client.getUrl().getParameter(Constants.DUBBO_VERSION_KEY);
//heartbeat = 60000
this.heartbeat = client.getUrl().getParameter( Constants.HEARTBEAT_KEY, dubbo != null && dubbo.startsWith("1.0.") ? Constants.DEFAULT_HEARTBEAT : 0 );
//heartbeatTimeout = 180000
this.heartbeatTimeout = client.getUrl().getParameter( Constants.HEARTBEAT_TIMEOUT_KEY, heartbeat * 3 );
if ( heartbeatTimeout < heartbeat * 2 ) {
throw new IllegalStateException( "heartbeatTimeout < heartbeatInterval * 2" );
}
startHeatbeatTimer();
} public ResponseFuture request(Object request) throws RemotingException {
return channel.request(request);
} private void startHeatbeatTimer() {
stopHeartbeatTimer();
if ( heartbeat > 0 ) {
heatbeatTimer = scheduled.scheduleWithFixedDelay(
new HeartBeatTask( new HeartBeatTask.ChannelProvider() {
public Collection<Channel> getChannels() {
return Collections.<Channel>singletonList( HeaderExchangeClient.this );
}
}, heartbeat, heartbeatTimeout),
heartbeat, heartbeat, TimeUnit.MILLISECONDS );
}
}
}

在 HeartbeatHandler 类中设置 lastRead 和 lastWrite 值:

public class HeartbeatHandler extends AbstractChannelHandlerDelegate {
//省略其他代码
private void setReadTimestamp(Channel channel) {
channel.setAttribute(KEY_READ_TIMESTAMP, System.currentTimeMillis());
} private void setWriteTimestamp(Channel channel) {
channel.setAttribute(KEY_WRITE_TIMESTAMP, System.currentTimeMillis());
}
}

设置 lastWrite 的调用栈:

设置 lastRead 的调用栈:

dubbo 心跳的更多相关文章

  1. 分析dubbo心跳检测机制

    目的: 维持provider和consumer之间的长连接 实现: dubbo心跳时间heartbeat默认是60s,超过heartbeat时间没有收到消息,就发送心跳消息(provider,cons ...

  2. 9.7 dubbo心跳机制

    dubbo的心跳机制: 目的:检测provider与consumer之间的connection连接是不是还连接着,如果连接断了,需要作出相应的处理. 原理: provider:dubbo的心跳默认是在 ...

  3. dubbo心跳机制 (1)

    此文已由作者赵计刚授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. dubbo的心跳机制: 目的:检测provider与consumer之间的connection连接是不是还连 ...

  4. dubbo心跳机制 (3)

    此文已由作者赵计刚授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 二.consumer端心跳机制                       //创建ExchangeClie ...

  5. dubbo心跳机制 (2)

    此文已由作者赵计刚授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 来看一下HeaderExchangeServer.this.getChannels():   1     p ...

  6. dubbo、zookeeper心跳相关参数解析与测试

    dubbo consumer和provider的心跳机制 dubbo客户端和dubbo服务端之间存在心跳,目的是维持provider和consumer之间的长连接.由dubbo客户端主动发起,可参见d ...

  7. 【Dubbo 源码解析】05_Dubbo 服务发现&引用

    Dubbo 服务发现&引用 Dubbo 引用的服务消费者最终会构造成一个 Spring 的 Bean,具体是通过 ReferenceBean 来实现的.它是一个 FactoryBean,所有的 ...

  8. 第零章 dubbo源码解析目录

    第一章 第一个dubbo项目 第二章  dubbo内核之spi源码解析 2.1  jdk-spi的实现原理 2.2 dubbo-spi源码解析 第三章 dubbo内核之ioc源码解析 第四章 dubb ...

  9. Dubbo部分知识点总结

    Dubbo部分 Dubbo工作原理 dubbo工作原理第一层:service层,接口层,给服务提供者和消费者来实现的第二层:config层,配置层,主要是对dubbo进行各种配置的第三层:proxy层 ...

随机推荐

  1. tomcat热启动没问题, 访问项目报500解决办法

    新建maven项目 添加热启动 启动访问项目报错 报错提示 解决办法 思路:包冲突 在pom.xml中添加servlet <dependency> <groupId>javax ...

  2. [c/c++]指针(1)

    指针算是一种特殊的变量,它存储的是一个内存地址,你既可以通过它来给制定内存地址赋值 (可能会被操作系统收回或者与其它程序冲突),又可以提高运行速度 First Step: 声明一个指针变量 int* ...

  3. Dell Vostro5370安装Win10/Ubuntu18LTS

    如何安装Win10/Ubuntu双系统 测试环境: DELL PRECISION 7510: CPU:Intel Core i5-6300HQ HD:256G NVME SSD 操作步骤: 无损将硬盘 ...

  4. HDU 6148 Valley Numer (数位DP)题解

    思路: 只要把status那里写清楚就没什么难度T^T,当然还要考虑前导零! 代码: #include<cstdio> #include<cstring> #include&l ...

  5. Linux rhel7 下MySQL5.7.18详细安装文档

    Linux rhel7 下MySQL5.7.18详细安装文档 本文安装MySQL5.7使用的是vm虚拟机rhel7操作系统 ,ftp文件传输是FileZilla3.27,远程连接xssh5.0 1 登 ...

  6. BZOJ1355: [Baltic2009]Radio Transmission KMP

    Description 给你一个字符串,它是由某个字符串不断自我连接形成的. 但是这个字符串是不确定的,现在只想知道它的最短长度是多少. Input 第一行给出字符串的长度,1 < L ≤ 1, ...

  7. spark监控入门

    前言 Spark作为计算引擎每天承载了大量的计算任务,为了监控集群的资源使用情况,对spark的监控也在所难免,Spark的监控有3个入口,1. Rest; 2.另一个是Metrics; 3. Log ...

  8. ACMG遗传变异分类标准与指南

    2015年,美国权威机构——美国医学遗传学与基因组学学会(ACMG)编写和发布了<ACMG遗传变异分类标准与指南>.为帮助我国医疗工作者和遗传咨询从业者更好地理解ACMG遗传变异分类标准. ...

  9. ros 安装c++编译的可执行文件

    xxx为c++源文件名 install( TARGETS xxx ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} LIBRARY DESTI ...

  10. pyqt 实现的俄罗斯方块

    from PyQt5.QtWidgets import QMainWindow, QFrame, QDesktopWidget, QApplication from PyQt5.QtCore impo ...