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. poj 2773 Happy 2006 - 二分答案 - 容斥原理

    Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 11161   Accepted: 3893 Description Two ...

  3. libcurl HTTP POST请求向服务器发送json数据

    转载:http://blog.csdn.net/dgyanyong/article/details/14166217 转载:http://blog.csdn.net/th_gsb/article/de ...

  4. 移动端Css初始化

    @charset "utf-8"; /* 禁用iPhone中Safari的字号自动调整 */ html { -webkit-text-size-adjust: %; -ms-tex ...

  5. [SpringBoot] - 发送带附件的邮件

    <!--发送email依赖--> <dependency> <groupId>org.springframework.boot</groupId> &l ...

  6. mysql删除sql表添加别名及删除sql的注意事项

    本文为博主原创,未经允许不得转载: 根据平常的习惯,个人会将操作的表后面添加一个别名,无论是使用还是不使用的时候,均是为了 修改还是扩展sql的时候更加安全,方便,快捷. 今天在写删除的sql时,对表 ...

  7. 【TCP/IP详解 卷一:协议】第十九章 TCP的交互数据流

    19.1 引言 前一章我们介绍了TCP连接的建立与释放:三握四挥,以及状态转移图. TCP报文段分为:交互数据,以及成块数据(下一章介绍). 交互数据:例如telnet,ssh,这种类型的协议在大多数 ...

  8. 为什么Rebase是有害的

    Rebase Considered Harmful Merge的两种方式 向上游提交"干净"的patch.不包含历史信息--日常提交.BUG fix.与上游的Merge记录等.就如 ...

  9. C#学习 day1 c#基础

    C#是一门编程语言,为什么我今天开始学C#了,下学期有门C#的课,以及有一个经验丰富的老学长正在做C#项目,由于之前学过C++和C基础,所以,C#的基础部分我查看文档来尝试能否自学归纳,而不是一直依靠 ...

  10. const 学习笔记

    #include<stdlib.h> #include<iostream> using namespace std; int main(){ // const 仅仅起到是否为常 ...