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

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

二、consumer端心跳机制

                      //创建ExchangeClient,对第一次服务发现providers路径下的相关url建立长连接
                      -->getClients(URL url)
                        -->getSharedClient(URL url)
                          -->ExchangeClient exchangeClient = initClient(url)
                            -->Exchangers.connect(url, requestHandler)
                              -->HeaderExchanger.connect(URL url, ExchangeHandler handler)
                                -->new DecodeHandler(new HeaderExchangeHandler(handler)))
                                  -->Transporters.connect(URL url, ChannelHandler... handlers)
                                    -->NettyTransporter.connect(URL url, ChannelHandler listener)
                                      -->new NettyClient(url, listener)
                                        -->new MultiMessageHandler(HeartbeatHandler(AllChannelHandler(handler)))
                                        -->getChannelCodec(url)//获取Codec2,这里是DubboCountCodec实例
                                        -->doOpen()//开启netty客户端
                                        -->doConnect()//连接服务端,建立长连接
                                -->new HeaderExchangeClient(Client client, boolean needHeartbeat)//上述的NettyClient实例,needHeartbeat:true
                                  -->startHeatbeatTimer()//启动心跳计数器

客户端在initClient(url)中设置了heartbeat参数(默认为60s,用户自己设置的方式见“一”中所讲),如下:

 1     /**
 2      * Create new connection
 3      */
 4     private ExchangeClient initClient(URL url) {
 5         ...
 6         // enable heartbeat by default
 7         url = url.addParameterIfAbsent(Constants.HEARTBEAT_KEY, String.valueOf(Constants.DEFAULT_HEARTBEAT));
 8 
 9         ...
10 
11         ExchangeClient client;
12         try {
13             // connection should be lazy
14             if (url.getParameter(Constants.LAZY_CONNECT_KEY, false)) {
15                 client = new LazyConnectExchangeClient(url, requestHandler);16             } else {
17                 client = Exchangers.connect(url, requestHandler);
18             }
19         } catch (RemotingException e) {
20             throw new RpcException("Fail to create remoting client for service(" + url + "): " + e.getMessage(), e);
21         }
22         return client;
23     }

与provider类似,来看一下最后开启心跳检测的地方。

 1 public class HeaderExchangeClient implements ExchangeClient {
 2     private static final ScheduledThreadPoolExecutor scheduled = new ScheduledThreadPoolExecutor(2, new NamedThreadFactory("dubbo-remoting-client-heartbeat", true));
 3     private final Client client;
 4     private final ExchangeChannel channel;
 5     // heartbeat timer
 6     private ScheduledFuture<?> heartbeatTimer;
 7     // heartbeat(ms), default value is 0 , won't execute a heartbeat.
 8     private int heartbeat;
 9     private int heartbeatTimeout;
10 
11     public HeaderExchangeClient(Client client, boolean needHeartbeat) {
12         if (client == null) {
13             throw new IllegalArgumentException("client == null");
14         }
15         this.client = client;
16         this.channel = new HeaderExchangeChannel(client);
17         String dubbo = client.getUrl().getParameter(Constants.DUBBO_VERSION_KEY);
18         this.heartbeat = client.getUrl().getParameter(Constants.HEARTBEAT_KEY, dubbo != null && dubbo.startsWith("1.0.") ? Constants.DEFAULT_HEARTBEAT : 0);
19         this.heartbeatTimeout = client.getUrl().getParameter(Constants.HEARTBEAT_TIMEOUT_KEY, heartbeat * 3);
20         if (heartbeatTimeout < heartbeat * 2) {
21             throw new IllegalStateException("heartbeatTimeout < heartbeatInterval * 2");
22         }
23         if (needHeartbeat) {
24             startHeatbeatTimer();
25         }
26     }
27 
28     private void startHeatbeatTimer() {
29         stopHeartbeatTimer();
30         if (heartbeat > 0) {
31             heartbeatTimer = scheduled.scheduleWithFixedDelay(
32                     new HeartBeatTask(new HeartBeatTask.ChannelProvider() {
33                         public Collection<Channel> getChannels() {
34                             return Collections.<Channel>singletonList(HeaderExchangeClient.this);
35                         }
36                     }, heartbeat, heartbeatTimeout),
37                     heartbeat, heartbeat, TimeUnit.MILLISECONDS);
38         }
39     }
40 
41     private void stopHeartbeatTimer() {
42         if (heartbeatTimer != null && !heartbeatTimer.isCancelled()) {
43             try {
44                 heartbeatTimer.cancel(true);
45                 scheduled.purge();
46             } catch (Throwable e) {
47                 if (logger.isWarnEnabled()) {
48                     logger.warn(e.getMessage(), e);
49                 }
50             }
51         }
52         heartbeatTimer = null;
53     }
54 }

主要看一下startHeartbeatTimer()方法,与provider相同,只是provider是获取NettyServer的所有的NettyChannel,而consumer只是获取当前的对象。

consumer的handler处理链与provider完全相同。

最后来看一下consumer的重连机制:AbstractClient#reconnect

  1     public void reconnect() throws RemotingException {
 2         disconnect(); 3         connect();
 4     }
 5 
 6     public void disconnect() {
 7         connectLock.lock();
 8         try {
 9             destroyConnectStatusCheckCommand();
10             try {
11                 Channel channel = getChannel();
12                 if (channel != null) {
13                     channel.close();
14                 }
15             } catch (Throwable e) {
16                 logger.warn(e.getMessage(), e);
17             }
18             try {
19                 doDisConnect();
20             } catch (Throwable e) {
21                 logger.warn(e.getMessage(), e);
22             }
23         } finally {
24             connectLock.unlock();
25         }
26     }
27 
28     protected void connect() throws RemotingException {
29         connectLock.lock();
30         try {
31             if (isConnected()) {
32                 return;
33             }
34             initConnectStatusCheckCommand();
35             doConnect();
36             if (!isConnected()) {
37                 throw new RemotingException(this, "Failed connect to server " + getRemoteAddress() + " from " + getClass().getSimpleName() + " "
38                         + NetUtils.getLocalHost() + " using dubbo version " + Version.getVersion()
39                         + ", cause: Connect wait timeout: " + getTimeout() + "ms.");
40             } else {
41                 if (logger.isInfoEnabled()) {
42                     logger.info("Successed connect to server " + getRemoteAddress() + " from " + getClass().getSimpleName() + " "
43                             + NetUtils.getLocalHost() + " using dubbo version " + Version.getVersion()
44                             + ", channel is " + this.getChannel());
45                 }
46             }
47             reconnect_count.set(0);
48             reconnect_error_log_flag.set(false);
49         } catch (RemotingException e) {
50             throw e;
51         } catch (Throwable e) {
52             throw new RemotingException(this, "Failed connect to server " + getRemoteAddress() + " from " + getClass().getSimpleName() + " "
53                     + NetUtils.getLocalHost() + " using dubbo version " + Version.getVersion()
54                     + ", cause: " + e.getMessage(), e);
55         } finally {
56             connectLock.unlock();
57         }
58     }

代码比较简单,先断连,再连接。

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

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

相关文章:
【推荐】 ApiDoc 一键生成注释

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

  1. 9.7 dubbo心跳机制

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

  2. dubbo心跳机制 (1)

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

  3. dubbo心跳机制 (2)

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

  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. Java基础--ThreadLocal

    Java中的ThreadLocal 可以看做以线程标识为key的Map,在多线程开发中使用非常方便. 示例 class ThreadEnv { // 用匿名内部类覆盖ThreadLocal的initi ...

  2. Oracle 文件

    参数文件 跟踪文件 告警文件 数据文件 临时文件 控制文件 重做日志文件 密码文件 闪回日志 dum文件 数据泵文件 1参数文件 Parameter file:告诉oracle实例在那里可以找到控制文 ...

  3. 开发工具:sublime text3安装Vue语法高亮插件

    一.将插件克隆到Sublime的packages目录 1.下载并解压插件(或直接git命令clone),得到vue-syntax-highlight-master文件夹 插件地址:https://gi ...

  4. JeeSite入门介绍(一)

    JeeSite特点:高效.高性能.强安全性属于开源.JavaEE快速开发平台:接私活的最佳助手: JeeSite是在Spring Framework基础上搭建的一个Java基础开发平台,以Spring ...

  5. phonegap 解决https访问问题

    ios报错 在AppDelegate.m文件在最后加入(在@end后面加空行): @implementation NSURLRequest(DataController) + (BOOL)allows ...

  6. C Primer Plus学习笔记(四)- 运算符、表达式和语句

    基本运算符 赋值运算符:= 在C语言中,=不是“相等”,而是赋值运算符,把左边的值赋给右边的变量 a = 2018; //把值2018赋给变量a 赋值表达式语句的目的是把值储存到内存位置上,用于储存值 ...

  7. myeclipse debug 工具栏不见了

    1.打开myeclipse,点击右上角的debug图标.如图: 点击debug页面右上角的三角形,把下拉菜单的Show Debug Toobar给勾上.如图: 3 这样debug工具的已经显示出来了

  8. eclipse利用mybatis-generator生成代码

    由于mybatis是半自动的ORM框架,表到POJO的映射可以由mybatis-generator完成,映射文件也可以由它生成,下面介绍生成步骤: 1.新建maven项目:File->Other ...

  9. Hadoop YARN: 1/1 local-dirs are bad: /var/lib/hadoop-yarn/cache/yarn/nm-local-dir; 1/1 log-dirs are bad: /var/log/hadoop-yarn/containers hdfs硬盘90% yarn unhealthy

    1/1 local-dirs are bad: /var/lib/hadoop-yarn/cache/yarn/nm-local-dir; 1/1 log-dirs are bad: /var/log ...

  10. resin容器更改JDK

    更改resin的jdk版本,找到resin的配置文件:Resin\contrib\init.resin文件,找到 JAVA_HOME=@JAVA_HOME@ RESIN_HOME=@resin_hom ...