rpc远程服务之motan心跳机制的分析

简介

motan作为一个较轻量级的高性能、易于使用的分布式远程服务调用(RPC)框架,已经做的足够亲民。在他的官宣中,主要说了四大点:

1 支持通过spring配置方式集成,无需额外编写代码即可为服务提供分布式调用能力。

2 支持集成consul、zookeeper等配置服务组件,提供集群环境的服务发现及治理能力。

3 支持动态自定义负载均衡、跨机房流量调整等高级服务调度能力。

4 基于高并发、高负载场景进行优化,保障生产环境下RPC服务高可用。


从关注这个开源的框架开始,大概是0.3.0版本开始,2年过去了,已经到了1.0.0的版本了。其中一个比较重要的概念,客户端到服务端有效会话管理这一块儿。motan从最开始的客户端定时发送心跳包到目前根据客户端调用服务的失败次数来进行心跳探测,并同时配合服务重试调用,比较优雅的解决了netty长连接通道空闲回收之后,又重新申请的问题。在这个RPC框架里面,每个客户端去通过协议连接远端的服务的时候,是使用了通用链接池(GenericObjectPool.Config)管理netty的客户端服务访问请求:


这里请必要对这三个参数进行说明:

minEvictableIdleTimeMillis: 连接空闲的最小时间,达到此值后空闲连接将可能会被移除。负值(-1)表示不移除。

softMinEvictableIdleTimeMillis: 连接空闲的最小时间,达到此值后空闲链接将会被移除,且保留“minIdle”个空闲连接数。默认为-1.

timeBetweenEvictionRunsMillis:  “空闲链接”检测线程,检测的周期,毫秒数。如果为负值,表示不运行“检测线程”。默认为-1.

其中timeBetweenEvictionRunsMillis这个参数就是一个时间检测间隔,目前motan里面10分钟会主动把客户端创建的空闲通道关闭,然后再重新创建新的通道,唯一的风险就是刚好有服务调用的时候,如果没有启用重试,就会失败。接着再看softMinEvictableIdleTimeMillis,顾名思义,一个相对舒服最小连接时间,如果达到10分钟,会将空闲通道关闭,但是保留最小空闲的连接值,如果为0。softMinEvictableIdleTimeMillis等价于minEvictableIdleTimeMillis。最后说说minEvictableIdleTimeMillis,这个是一个比较大的区间,目前是60分钟,也就是说一个小时之内都没有请求发起,所有的空闲通道会被关闭。综上所述,minIdle这个参数其实还是比较重要的参数,一定要设一个相对较maxIdle告谱的值, maxIdle代表了连接池中最大可用连接。个人推荐minIdle=maxIdle(1/4)。至于为什么不设置为-1,各位看官可以想想,一个长连接,分配下来之后,在真空环境下,肯定是没有问题的。但是这种情况根本不存在,网络总会波动,掉线。所以搭上合适的空闲检测线程及相关的三个连接池参数,能最大程度规避一些因网络导致的问题。有些同学可能会说,其实还可以通过心跳来处理,就是还不到10分钟的时候,就先发一个心跳,这样,这个通道就会一直有效下去。但是这样也是理论的,如果在你处理心跳之前,因为网络波动,你的通道还是会坏掉,还是得重连,业务在那个时候,如果没有重试机制的话,瞬间还是会不可用的。所以,添加心跳实际是个伪命题,你可能还会说,增加心跳的频率。最终,对于一个真正高可用的应用,定时心跳终究是不可取的。不管客户端连接不可用而进行的定时心跳,最大的问题其实是信令风暴。

何为信令风暴?下面的内容摘自这个链接

互联网应用的心跳包除了宣告终端在线外,还有一项重要的任务,就是提供终端的即时地址,方便应用服务器的寻址。有了互联网应用的心跳机制,应用服务器可以及时下发(Push)用户相关的信息,比如微信中的短消息、图片或者语音等。心跳包也会带来很多副作用,比如终端更为费电,还可能给移动通信网络带来信令风暴。看起来很完美的心跳机制,为什么会给移动网络带来信令风暴呢?原来,移动通信网络中由于用户众多、资源稀缺,每个用户都是动态占用资源,比如IP地址以及 无线信道。每次发送心跳包,都需要移动通信网络为用户分配资源,分配的过程体现在信令的发送和接收上。一次心跳包的发送过程,牵涉的信令多达几十条。随着互联网APP的普及,大量的终端周期性地发送心跳包,效果类似于IP网络中的DDOS,必然对移动通信网络设备带来冲击,造成拥塞等情况,这种现 象就是信令风暴。另外 这里还有一篇说明微信的信令对移动的影响,所以选择合适的心跳策略对一个应用是何等重要。

motan目前的心跳探测+服务重试,我个人觉得是一个比较折中并且稳定的方案。

心跳探测:是指客户请求失败次数达到一个值之后,就发一个心跳去请求服务器,看连接通道是否有效。如果有效,就直接返回,如果无效,就进行重连。

服务重试:是为了解决应用中异常返回而抛出的MotanServiceException,可能的原因是服务端应用失败或者连接不可用引起的,这样服务进行重试。如果刚好是通道连接的问题,在进行重试之后,只要网络正常,肯定是可用的。

经上观点,属于个人意见,欢迎大家讨论。

你可能感兴趣的:(rpc远程服务之motan心跳机制的分析)