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

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

二、consumer端心跳机制

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

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

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

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

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

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

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

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

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

    下载Gradle https://gradle.org/releases/ https://services.gradle.org/distributions/gradle-4.4.1-bin.zip ...

  2. clone对象的克隆

    用一句简单的话来说就是浅拷贝,只是对指针的拷贝,拷贝后两个指针指向同一个内存空间,深拷贝不但对指针进行拷贝,而且对指针指向的内容进行拷贝,经深拷贝后的指针是指向两个不同地址的指针. 等多 http:/ ...

  3. DotNetBar笔记

    1.TextBoxDropDown  这是一个绝对TMD坑爹的狗屁玩意儿.键盘的四个事件全部不好使.但是这个玩意儿有个好处就是他的DropDownControl属性可以用来制作ComboGrid. 然 ...

  4. PAT 垃圾箱分布(30分)dijstra

    垃圾箱分布 时间限制 200 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 陈越 大家倒垃圾的时候,都希望垃圾箱距离自己比较近,但是谁都不愿意守着垃圾 ...

  5. Oracle 文件

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

  6. MySQL 学习五 SQL实用函数

    0 select now() 显示当前时间. 1 select char_length('andyqan')   显示字符长度. 2 日期格式化         select date_format( ...

  7. 【转】前端上传组件Plupload使用指南

    http://www.cnblogs.com/2050/p/3913184.html Plupload有以下功能和特点: 1.拥有多种上传方式:HTML5.flash.silverlight以及传统的 ...

  8. Python类(五)-反射

    反射即通过字符串映射或修改程序运行时的状态.属性.方法 有4个方法: hasattr(): hasattr(object,string):object为实例化的对象,string为字符串 判断对象ob ...

  9. AJAX——XMLHttpRequest对象的使用

    AJAX是web2.0即动态网页的基础,而XMLHttpRequest对象又是AJAX的核心.XMLHttpRequest对象负责将用户信息以异步通信地发送到服务器端,并接收服务器响应信息和数据 一. ...

  10. 微信开发准备(二)--springmvc+mybatis项目结构的搭建

    转自:http://www.cuiyongzhi.com/post/34.html 前面一篇有说道如何在MyEclipse中搭建maven项目,这里将继续介绍如何在搭建好的基础maven项目中引入我们 ...