Martian-cloud 4.0.2, 丢弃心跳机制,解决网络压力问题

323 阅读4分钟

首先,有人可能对 Martian-cloud 不了解,甚至是第一次听说,所以有兴趣的朋友可以先看下详细的原理

www.bilibili.com/read/cv8314…

好了下面切入主题,本次升级,所解决的问题正如标题所说,通过丢弃心跳机制,来解决网络压力

网络压力主要来自两个方面

  1. 定时随机去别的服务拉取一次接口,并将自己的接口广播出去
  2. 发送心跳包

第一个点,仔细计算下来,其实并没太大的压力,原因如下:

首先,定时随机去别的服务拉取一次接口,这个是每个服务只会随机向一个服务发送拉取请求,也就是这个行为在整个一套微服务中可以产生的最大请求数为 N,有几台服务就最多可以产生几个请求,而且这些请求很难会刚好都请求到一台服务器,并且频率为 3 秒,所以我个人认为,这是在可接受范围内的。

其次,将自己的接口广播出去,这个虽然是广播给自己已知的所有其他服务,但是播过一次的服务就不会再播了,随着时间的累计,这个行为最终会停止,不再发起广播,而且这个过程很快。

那么,网络压力的大头,主要来自第二个点

第二个点,怎么解决呢?我思考了好几天,脑袋都大了,还是没想出解决方案。

后来心一横,干脆不要心跳了,但是不要心跳的话,服务下线了怎么通知其他服务啊? 这就是今天要分享的内容。

心跳机制丢弃后如何实现下线通知

首先这个做法 只能保证每个服务本地的接口缓存数据 的最终一致性,而不是实时的,但是这并不是分布式存储,所以无伤大雅。

还有一点,可能会影响一些性能,这个性能的牺牲,能不能被接受,就要看具体的场景了。

一、首先是自私机制

所谓的自私机制,就是每个服务只顾自己,不管别人,每个服务如果发现自己本地缓存的接口连接不上,那就会从本地把他下掉,至于别人,他是不管的。

二、 投票机制(最大票数可配置)

这是每个服务的内部投票,跟外面无关,如果一个服务发现他本地缓存的某个接口连接不上,那么他就会给这个接口指向的服务投一票,让它从本机下线,当调通后会把票数清 0,当票数积累到一定程度时,这个服务的所有接口都会被从当前服务上清理掉。 [每个服务都有一套这样的机制,来维护自己的本地接口缓存]

三、 如果(下线某个服务的决定)是误判怎么办

有一个补偿机制,就是每个服务在下掉别的服务的时候,都会给被下掉的那个服务发一个通知,让他把自己从已广播列表中移除(比如 A 服务调不通 B 服务的接口,当票数累积到一定程度后,A 会把 B 的接口全部清理掉,清理后 A 会给 B 发一个通知,让 B 把 A 从已广播列表移除,这样如果 B 服务没挂,那么 B 在下一次轮询时 会把接口重新广播给 A )

如果 B 服务明明没挂,但是 A 服务连续调不通,而且连下线通知都无法通知到 B 服务,那我只能说 B 服务活该了,即使是误判也比留着报错影响性能好吧。

四、 调不通的情况有很多,不一定是服务挂了,那么什么样的情况会给服务投下线票

很简单,当调用接口时,出现了以下三种异常,就会投票

  • ConnectException,连接不上,这不是 404 之类的,而是根本连不上这个 ip:port
  • UnknownHostException,无法解析地址,提供的 ip:port 无法被解析识别
  • SocketTimeoutException,连接超时,不是 read time out,而是 connect time out

五、 然后是垃圾回收机制

垃圾回收很简单,就是定时去本地缓存中扫描出被下线的服务的接口,然后删除掉。

上面这这一套机制,可以保证当服务宕机以后,接口会自动从其他的服上下线

官方网站

mars-framework.com/index.html