此文已由作者赵计刚授权网易云社区发布。

欢迎访问网易云社区,了解更多网易技术产品运营经验。

来看一下HeaderExchangeServer.this.getChannels():

  1     public Collection<Channel> getChannels() {
 2         return (Collection) getExchangeChannels();
 3     }
 4 
 5     public Collection<ExchangeChannel> getExchangeChannels() {
 6         Collection<ExchangeChannel> exchangeChannels = new ArrayList<ExchangeChannel>();
 7         Collection<Channel> channels = server.getChannels();
 8         if (channels != null && channels.size() > 0) {
 9             for (Channel channel : channels) {
10                 exchangeChannels.add(HeaderExchangeChannel.getOrAddChannel(channel));
11             }
12         }
13         return exchangeChannels;
14     }

实际上就是获取NettyServer中的全部channel连接。

获取到需要心跳检测的channel后,对每一个channel进行如下判断:

  • 如果在heartbeat内没有进行读操作或者写操作,则发送心跳请求

  • 如果正常消息和心跳在heartbeatTimeout都没接收到,consumer端会进行重连,provider端会关闭channel

这里比较关键的是lastRead和lastWrite的设置。先来看一下获取:

1 Long lastRead = (Long) channel.getAttribute(HeaderExchangeHandler.KEY_READ_TIMESTAMP);
2 Long lastWrite = (Long) channel.getAttribute(HeaderExchangeHandler.KEY_WRITE_TIMESTAMP);

说明有地方在设置这两个值到channel中。

从请求和响应处理来看,无论是请求还是响应都会按照这个顺序处理一遍。

1 MultiMessageHandler
2 -->handler: HeartbeatHandler
3    -->handler: AllChannelHandler
4          -->url: providerUrl
5          -->executor: FixedExecutor
6          -->handler: DecodeHandler
7             -->handler: HeaderExchangeHandler
8                -->handler: ExchangeHandlerAdapter(DubboProtocol.requestHandler)

其中HeartbeatHandler源码如下:

1 public class HeartbeatHandler extends AbstractChannelHandlerDelegate {
 2 
 3     private static final Logger logger = LoggerFactory.getLogger(HeartbeatHandler.class);
 4 
 5     public static String KEY_READ_TIMESTAMP = "READ_TIMESTAMP";
 6 
 7     public static String KEY_WRITE_TIMESTAMP = "WRITE_TIMESTAMP";
 8 
 9     public HeartbeatHandler(ChannelHandler handler) {
10         super(handler);
11     }
12 
13     public void connected(Channel channel) throws RemotingException {
14         setReadTimestamp(channel);
15         setWriteTimestamp(channel);
16         handler.connected(channel);
17     }
18 
19     public void disconnected(Channel channel) throws RemotingException {
20         clearReadTimestamp(channel);
21         clearWriteTimestamp(channel);
22         handler.disconnected(channel);
23     }
24 
25     public void sent(Channel channel, Object message) throws RemotingException {
26         setWriteTimestamp(channel);
27         handler.sent(channel, message);
28     }
29 
30     public void received(Channel channel, Object message) throws RemotingException {
31         setReadTimestamp(channel);
32         if (isHeartbeatRequest(message)) {
33             Request req = (Request) message;
34             if (req.isTwoWay()) {
35                 Response res = new Response(req.getId(), req.getVersion());
36                 res.setEvent(Response.HEARTBEAT_EVENT);
37                 channel.send(res);
38                 if (logger.isInfoEnabled()) {
39                     int heartbeat = channel.getUrl().getParameter(Constants.HEARTBEAT_KEY, 0);
40                     if (logger.isDebugEnabled()) {
41                         logger.debug("Received heartbeat from remote channel " + channel.getRemoteAddress()
42                                 + ", cause: The channel has no data-transmission exceeds a heartbeat period"
43                                 + (heartbeat > 0 ? ": " + heartbeat + "ms" : ""));
44                     }
45                 }
46             }
47             return;
48         }
49         if (isHeartbeatResponse(message)) {
50             if (logger.isDebugEnabled()) {
51                 logger.debug(
52                         new StringBuilder(32)
53                                 .append("Receive heartbeat response in thread ")
54                                 .append(Thread.currentThread().getName())
55                                 .toString());
56             }
57             return;
58         }
59         handler.received(channel, message);
60     }
61 
62     private void setReadTimestamp(Channel channel) {
63         channel.setAttribute(KEY_READ_TIMESTAMP, System.currentTimeMillis());
64     }
65 
66     private void setWriteTimestamp(Channel channel) {
67         channel.setAttribute(KEY_WRITE_TIMESTAMP, System.currentTimeMillis());
68     }
69 
70     private void clearReadTimestamp(Channel channel) {
71         channel.removeAttribute(KEY_READ_TIMESTAMP);
72     }
73 
74     private void clearWriteTimestamp(Channel channel) {
75         channel.removeAttribute(KEY_WRITE_TIMESTAMP);
76     }
77 
78     private boolean isHeartbeatRequest(Object message) {
79         return message instanceof Request && ((Request) message).isHeartbeat();
80     }
81 
82     private boolean isHeartbeatResponse(Object message) {
83         return message instanceof Response && ((Response) message).isHeartbeat();
84     }
85 }
  • 连接完成时:设置lastRead和lastWrite

  • 连接断开时:清空lastRead和lastWrite

  • 发送消息时:设置lastWrite

  • 接收消息时:设置lastRead

之后交由AllChannelHandler进行处理。之后会一直交由HeaderExchangeHandler进行处理。其对lastRead和lastWrite也做了设置和清理:

  1     public void connected(Channel channel) throws RemotingException {
 2         channel.setAttribute(KEY_READ_TIMESTAMP, System.currentTimeMillis());
 3         channel.setAttribute(KEY_WRITE_TIMESTAMP, System.currentTimeMillis()); 4         ...
 5     }
 6 
 7     public void disconnected(Channel channel) throws RemotingException {
 8         channel.setAttribute(KEY_READ_TIMESTAMP, System.currentTimeMillis());
 9         channel.setAttribute(KEY_WRITE_TIMESTAMP, System.currentTimeMillis());
10         ...
11     }
12 
13     public void sent(Channel channel, Object message) throws RemotingException {
14         Throwable exception = null;
15         try {
16             channel.setAttribute(KEY_WRITE_TIMESTAMP, System.currentTimeMillis());
17             ...
18         } catch (Throwable t) {
19             exception = t;
20         }
21     }
22 
23     public void received(Channel channel, Object message) throws RemotingException {
24         channel.setAttribute(KEY_READ_TIMESTAMP, System.currentTimeMillis());
25         ...
26     }
  • 连接完成时:设置lastRead和lastWrite

  • 连接断开时:也设置lastRead和lastWrite(为什么?)

  • 发送消息时:设置lastWrite

  • 接收消息时:设置lastRead

这里里有个疑问,从handler链来看,无论是请求还是响应都会按照handler链来处理一遍。那么在HeartbeatHandler中已经进行了lastWrite和lastRead的设置,为什么还要在HeaderExchangeHandler中再处理一遍?

最后,provider端认为连接断了,则会关闭channel。来看一下NettyChannel的close方法:

 1     public void close() {
 2         // 1 将close属性设为true
 3         try {
 4             super.close();
 5         } catch (Exception e) {
 6             logger.warn(e.getMessage(), e);
 7         }
 8         // 2 从全局NettyChannel缓存器中将当前的NettyChannel删掉
 9         try {
10             removeChannelIfDisconnected(channel);
11         } catch (Exception e) {
12             logger.warn(e.getMessage(), e);
13         }
14         // 3 清空当前的NettyChannel中的attributes属性
15         try {
16             attributes.clear();
17         } catch (Exception e) {
18             logger.warn(e.getMessage(), e);
19         }
20         // 4 关闭netty的channel,执行netty的channel的优雅关闭
21         try {
22             if (logger.isInfoEnabled()) {
23                 logger.info("Close netty channel " + channel);
24             }
25             channel.close();
26         } catch (Exception e) {
27             logger.warn(e.getMessage(), e);
28         }
29     }

从上边代码来看,假设consumer端挂了,provider端的心跳检测机制可以进行相关的资源回收,所以provider端的心跳检测机制是有必要的。

免费体验云安全(易盾)内容安全、验证码等服务

更多网易技术、产品、运营经验分享请点击

相关文章:
【推荐】 大咖分享 | 一文解锁首届云创大会干货——下篇(文末附演讲ppt文件免费下载)
【推荐】 Kafka实践、升级和新版本(0.10)特性预研

dubbo心跳机制 (2)的更多相关文章

  1. 9.7 dubbo心跳机制

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

  2. dubbo心跳机制 (1)

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

  3. dubbo心跳机制 (3)

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

  4. dubbo之心跳机制

    在网络传输中,怎么确保通道连接的可用性是一个很重要的问题,简单的说,在网络通信中有客户端和服务端,一个负责发送请求,一个负责接收请求,在保证连接有效性的背景下,这两个物体扮演了什么角色,心跳机制能有效 ...

  5. Dubbo之心跳机制 · 房东的小黑

    在网络传输中,怎么确保通道连接的可用性是一个很重要的问题,简单的说,在网络通信中有客户端和服务端,一个负责发送请求,一个负责接收请求,在保证连接有效性的背景下,这两个物体扮演了什么角色,心跳机制能有效 ...

  6. 分析dubbo心跳检测机制

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

  7. rabbitmq 的心跳机制&应用

    官方文档说: If a consumer dies (its channel is closed, connection is closed, or TCP connection is lost) w ...

  8. zookeeper心跳机制流程梳理

    zookeeper心跳机制流程梳理 Processor链Chain protected void setupRequestProcessors() { RequestProcessor finalPr ...

  9. 一个Socket连接管理池(心跳机制)

    一个Socket连接管理池(心跳机制) http://cuisuqiang.iteye.com/blog/1489661

随机推荐

  1. WPF基本概念入门

    关于数据类型,有原子类型,列表类型,字典类型等等,而wpf对应控件有contentControl,itemsControl,headerItemsControl等. 控件和类型一一对应,控件和类型之间 ...

  2. jira python操作,自动创建问题

    jira web api地址 http://jira.**.com/plugins/servlet/restbrowser http://jira.**.com/rest/api/2/issue/cr ...

  3. mongoTemplate操作内嵌文档

    关系型数据库中,表与表的关联关系有1:1,也有1:n的.在java的面向对象的世界里就是主对象嵌子对象,与主对象嵌集合<子对象>的两种形式. 主对象嵌子对象操作: 新增.修改都直接用如下方 ...

  4. explain之三:MYSQL EXPLAIN语句的extended 选项学习体会,分析诊断工具之二

    MySQL 的explain命令有一个extended选项,我想可以很多人都没有注意,因为它对命令的输出结果没有任何改变,只是增加了一个warning.这个 warning中显示了MySQL对SQL的 ...

  5. Caused by: java.lang.IncompatibleClassChangeError: Implementing class

    Caused by: java.lang.IncompatibleClassChangeError: Implementing class 可能是导入的jar包重复. 尤其在Maven引用中,请查看是 ...

  6. c# 几种singleton 实现

    http://csharpindepth.com/Articles/General/Singleton.aspx#introduction 4th在线看 https://www.manning.com ...

  7. 2015.4.21 SetWindowPos函数用法

    定义:[DllImport("user32.dll")] public static extern bool SetWindowPos(IntPtr hWnd, int hWndl ...

  8. iOS 模块分解— Runtime

    相信对于从事开发人员来说 runtime 这个名称都不陌生,就像我起初只知道「 runtime 叫运行时 」,后来知道 runtime 同样可以像 KVC 一样访问私有成员变量,还有「 给类动态添加属 ...

  9. HotSpotVM创建过程(JNI_CreateJavaVM)详解

    来自:<Java Performance>第3章 JVM Overview The HotSpot VM's implementation of the JNI_CreateJavaVM ...

  10. onclick事件没有反应的五种可能情况

    转自:https://blog.csdn.net/qujing_1120/article/details/76853039 onclick=”alert()” 事件没有反应的几种情况.第一:<i ...