设为首页 收藏本站
查看: 781|回复: 0

[经验分享] apache MINA之心跳协议运用

[复制链接]
累计签到:1 天
连续签到:1 天
发表于 2015-8-4 10:58:10 | 显示全部楼层 |阅读模式
摘要 心跳协议,对基于CS模式的系统开发来说是一种比较常见与有效的连接检测方式,最近在用MINA框架,原本自己写了一个心跳协议实现,后来突然发现MINA本身带有这样一个心跳实现,感于对框架的小小崇拜,在实践的同时研究了一下!
MINA TCP/IP SOCKET 心跳  
MINA本身提供了一个过滤器类: org.apache.mina.filter.keepalive . KeepAliveFilter ,该过滤器用于在IO空闲的时候发送并且反馈心跳包(keep-alive request/response)。

说到KeepAliveFilter这个类有必要先说一说其构造函数,即实例化该类需要些什么,该类构造函数中参数有三个分别是:
(1)KeepAvlieMessageFactory:   该实例引用用于判断接受与发送的包是否是心跳包,以及心跳请求包的实现
(2)IdleStatus:                              该过滤器所关注的空闲状态,默认认为读取空闲。 即当读取通道空闲的时候发送心跳包
(3)KeepAliveRequestTimeoutHandler: 心跳包请求后超时无反馈情况下的处理机制  默认为CLOSE  即关闭连接

首先需要实现接口   KeepAliveMessageFactory 。   该接口中的抽象方法有:

Modifier and Type  Method and Description   Object  getRequest(IoSession session)
Returns a (new) keep-alive request message.  Object  getResponse(IoSession session, Object request)
Returns a (new) response message for the specified keep-alive request.  boolean  isRequest(IoSession session, Object message)
Returns true if and only if the specified message is a keep-alive request message.  boolean  isResponse(IoSession session, Object message)
Returns true if and only if the specified message is a keep-alive response message;   
一般来说心跳机制主要分为以下四类:
1,active 活跃型:  当读取通道空闲的时候发送心跳请求,一旦该心跳请求被发送,那么需要在keepAliveRequestTimeout时间内接收到心跳反馈,否则KeepAliveRequestTimeoutHandler将会被调用,当一个心跳请求包被接受到后,那么心跳反馈也会立即发出。
针对活跃型心跳机制:  KeepAliveMessageFactory 类的实现方法中: getRequest ( IoSession  session)与 getResponse ( IoSession  session,  Object  request)必须返回非空。

  2, semi-active 半活跃型:当读取通道空闲的时候发送心跳请求,然而并不在乎心跳反馈有没有,当一个心跳请求包被接收到后,那么心跳反馈也会立即发出。
针对半活跃型心跳机制:   KeepAliveMessageFactory 类的实现方法中: getRequest ( IoSession  session)与 getResponse ( IoSession  session,  Object  request)必须返回非空。并且心跳包请求后超时无反馈的处理机制设置为KeepAliveRequestTimeoutHandler.NOOP(不做任何处理), KeepAliveRequestTimeoutHandler.LOG(只输出警告信息不做其他处理)

  3, passive 被动型:当前IO不希望主动发送心跳请求,但是当接受到一个心跳请求后,那么该心跳反馈也会立即发出。
针对被动型心跳机制:  KeepAliveMessageFactory 类的实现方法中: getRequest ( IoSession  session)必须反馈null 与 getResponse ( IoSession  session,  Object  request)必须反馈non-null.

4, deaf speaker 聋子型: 当前IO会主动发送心跳请求,但是不想发送任何心跳反馈。
  针对聋子型心跳机制:  KeepAliveMessageFactory 类的实现方法中: getRequest ( IoSession  session)必须反馈non-null与 getResponse ( IoSession  session,  Object  request)必须反馈null,将 KeepAliveRequestTimeoutHandler 设置为DEAF_SPEAKER.

5, sient-listener 持续监听型:既不想发送心跳请求也不想发送心跳反馈。
针对持续监听型心跳机制:  KeepAliveMessageFactory 类的实现方法中: getRequest ( IoSession  session)必须反馈null 与 getResponse ( IoSession  session,  Object  request)必须反馈null.


心跳包请求超时后的处理机制:接口 KeepAliveRequestTimeoutHandler ,一般该处理主要是针对能够发送心跳请求的心跳机制。
1.CLOSE:关闭连接
2,LOG:输出 警告信息
  3,NOOP:不做任何处理  
4,EXCEPTION:抛出异常
5,DEAF_SPEAKER:一个特殊的处理,停止当前过滤器对对心跳反馈监听,因此让过滤器丢失请求超时的侦测功能。(让其变成聋子)  
6,keepAliveRequestTimeout(KeepAliveFilter filter, IoSession session);   自定义处理



下面对客户端与服务端和分别举个例子:
服务器:
以被动型心跳机制为例,服务器在接受到客户端连接以后被动接受心跳请求,当在规定时间内没有收到客户端心跳请求时 将客户端连接关闭
主要代码如下:  


  KeepAliveMessageFactoryImpl kamfi = new KeepAliveMessageFactoryImpl();
         实现 方法: public boolean isRequest(IoSession session, Object message):判断是否心跳请求包  是的话返回true
                              public boolean isResponse(IoSession session, Object message):由于被动型心跳机制,没有请求当然也就不关注反馈 因此直接返回false
                               public Object getRequest(IoSession session): 被动型心跳机制无请求  因此直接返回null
                               public Object getResponse(IoSession session, Object request) : 根据心跳请求request 反回一个心跳反馈消息 non-nul
         说明:  KeepAliveMessageFactoryImpl  为 KeepAliveMessageFactory的一个实现类,其中的实现方法满足被动型心跳机制。
   
KeepAliveFilter kaf = new KeepAliveFilter(kamfi, IdleStatus.BOTH_IDLE);
        说明:实例化一个  KeepAliveFilter  过滤器,传入 KeepAliveMessageFactory引用,IdleStatus参数为 BOTH_IDLE,及表明如果当前连接的读写通道都空闲的时候在指定的时间间隔getRequestInterval后发送出发Idle事件。
   
kaf.setForwardEvent(true); //idle事件回发  当session进入idle状态的时候 依然调用handler中的idled方法
       说明:尤其 注意该句话,使用了 KeepAliveFilter之后,IoHandlerAdapter中的 sessionIdle方法默认是不会再被调用的! 所以必须加入这句话 sessionIdle才会被调用
   
kaf.setRequestInterval(heartPeriod);  //本服务器为被定型心跳  即需要每10秒接受一个心跳请求  否则该连接进入空闲状态 并且发出idled方法回调
       说明:设置心跳包请求时间间隔,其实对于被动型的心跳机制来说,设置心跳包请求间隔貌似是没有用的,因为它是不会发送心跳包的,但是它会触发 sessionIdle事件, 我们利用该方法,可以来判断客户端是否在该时间间隔内没有发心跳包,一旦 sessionIdle方法被调用,则认为 客户端丢失连接并将其踢出 。因此其中参数 heartPeriod其实就是服务器对于客户端的IDLE监控时间。
   
//kaf.setRequestTimeout(5); //超时时间   如果当前发出一个心跳请求后需要反馈  若反馈超过此事件 默认则关闭连接
acceptor.getFilterChain().addLast("heart", kaf);
      说明: 该过滤器加入到整个通信的过滤链中。

  


客户端:
客户端会定时发送心跳请求(注意定时时间必须小于,服务器端的IDLE监控时间),同时需要监听心跳反馈,以此来判断是否与服务器丢失连接。对于服务器的心跳请求不给与反馈。
主要代码如下:

ClientKeepAliveFactoryImpl ckafi = new ClientKeepAliveFactoryImpl();
    实现 方法:     public boolean isRequest(IoSession session, Object message): 服务器不会给客户端发送请求包,因此不关注请求包,直接返回false
                             public boolean isResponse(IoSession session, Object message):客户端关注请求反馈,因此判断mesaage是否是反馈包
                               public Object getRequest(IoSession session): 获取心跳请求包 non-null
                               public Object getResponse(IoSession session, Object request) : 服务器不会给客户端发送心跳请求,客户端当然也不用反馈  该方法返回null
        说明:  ClientKeepAliveFactoryImpl  为 KeepAliveMessageFactory的一个实现类。
   
  KeepAliveFilter kaf = new KeepAliveFilter(ckafi, IdleStatus.READER_IDLE,KeepAliveRequestTimeoutHandler.CLOSE);
   说明:实例化一个  KeepAliveFilter  过滤器,传入 KeepAliveMessageFactory引用,IdleStatus参数为 READER_IDLE ,及表明如果当前连接的读通道空闲的时候在指定的时间间隔getRequestInterval后发送出心跳请求,以及发出Idle事件。  KeepAliveRequestTimeoutHandler设置为CLOS表明,当发出的心跳请求在规定时间内没有接受到反馈的时候则调用CLOSE方式 关闭连接
   
   kaf.setForwardEvent(true);
   说明:继续调用 IoHandlerAdapter 中的 sessionIdle时间

   kaf.setRequestInterval(HEART_INTERVAL);
    说明:设置当连接的读取通道空闲的时候,心跳包请求时间间隔

   kaf.setRequestTimeout(HEART_TIMEOUT);
   说明:设置心跳包请求后 等待反馈超时时间。 超过该时间后则调用KeepAliveRequestTimeoutHandler.CLOSE
   
   connector.getFilterChain().addLast("heart", kaf);  
        说明: 该过滤器加入到整个通信的过滤链中。
  
转自:http://my.oschina.net/yjwxh/blog/174633

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-94008-1-1.html 上篇帖子: 解决Apache下访问PHP页面403 Forbidden错误 下篇帖子: Apache Velocity实现模板化的最简实例
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表