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. SQL去重之distinct和group by的应用

    遇到一个需求,要去重查出某张表的字段一和字段二,但是查出来的结果要按照表中记录的创建时间排序. 于是,第一时间就想到了使用distinct这个去重专用语法了: select distinct col1 ...

  2. jdbc连接池c3p0/dbcp强制连接超过设置时间后失效

    通常来说,各种技术实现的优化参数或者选项或者歪门邪道之所以能被想出来,通常是因为开发者或者实现的贡献者曾经遇到过导致此结果的问题,所以才出了对应的策略选项. 在有些情况下,比如存在客户端或者服务端连接 ...

  3. git_如何查看两个版本之间那些文件被修改

    需求 由于工程比较庞大,接近500M,每部署一次如果都全量部署,不仅仅磁盘空间耗费较大,最主要是要等很长时间, 之前就一直有这个问题,但是也就没有弄,上周领导发话了,这个问题必须要解决了 前记 增加带 ...

  4. FJNUOJ the greed of Yehan(最长路 + 权值乘积转化)题解

    Description During the trip, Yehan and Linlin pass a cave, and there is a board at the door, which s ...

  5. Unity3D学习笔记(一):Unity3D简介

    Unity3D简介一.什么是Unity.U3D?全面整合的专业引擎 二.这个软件能做什么?1.内容:3D2D游戏,教育,建筑,网页,VRAR,家庭娱乐系统2.媒体:PC平台,主机,移动,VR 1.UE ...

  6. rg.apache.ibatis.binding.BindingException: Mapper method 'com.dao.Cameao.getOnlineDayRation attempted to return null from a method with a primitive return type (float)

    本文为博主原创,未经允许不得转载: 异常展示如下: org.apache.ibatis.binding.BindingException: Mapper method 'com.dao.Cameao. ...

  7. 【Coursera】Third Week(2)

    拾遗 Steve Jobs与World Wide Web 如果你有仔细观察Robert Cailliau的视频的话,你会发现他工作所用的电脑为NeXT电脑. Jobs 也对web 产生了一定的影响,众 ...

  8. 2018提高组训练Day2

    A 算法 1 对于每组询问,暴力的算出每个二次函数的取值. 时间复杂度 \(O(nq)\).期望得分 \(20\) 分. 算法 2 当 \(x>0\) 时,要求 \(a_ix^2+b_ix\) ...

  9. Java I/O学习 标准的I/O重定向

    public class Test{ /* * 标准的I/O重定向 * System.setIn(InputStream) * System.setOut(PrintStream) * System. ...

  10. Ubuntu下配置JDK

    1. 首先你需要到oracle官网下载最新版本的JDK.跑到oracle官网,自己到Download下面找找吧 2.转到下载路径,对下载后的文件解压缩,比如我下载的文件名为jdk-7u7-linux- ...