影响到可用性的另一个关键点是注册中心需要尽快发现服务端宕机。在基本模型里面,如果服务端突然宕机,那么服务端是来不及通知注册中心的。所以注册中心需要有一种检测机制,判断服务端有没有崩溃。在服务端崩溃的情况下,要及时通知客户端,不然客户端就会继续把请求发送到已经崩溃的节点上。
这种检测就是利用心跳来进行的。当注册中心发现和服务端的心跳失败了,那么它就应该认为服务端可能已经崩溃了,就立刻通知客户端停止使用服务端。但是这种失败可能是偶发性的失败,比如说因为网络偶尔不稳定造成的。所以注册中心要继续保持心跳。如果几次心跳都失败了,那么就可以认为u服务端已经彻底不可用了。但是如果心跳再次恢复了,那么注册中心就要再次告诉客户端这个服务端是可用的。
回答到这里,亮点已经有了,不过可以稍微升华一下。
实际上,在所有有心跳机制的分布式系统里面判断节点是否崩溃都是一个棘手的问题。比如说心跳失败了要不要继续重试,是立刻重试还是间隔重试,重试的话试几次?
理论上来说,在心跳失败之后如果不进行重试就直接判定服务端崩溃,那么就难以处理偶发性网络不通的问题。而如果要重试,比如说在注册中心和服务端的模型里面,重试三次,而且重试间隔是十秒钟,那么注册中心确定服务端崩溃就需要三十秒。在三十秒内,客户端估计有成千上万的请求尝试发到崩溃的服务端,结果都失败了。
这个时候,面试官这时候,面试官很自然地就会觉得不要搞重试间隔,而是直接发起连续几次重试,这时候你就要无情地击碎这种幻想。
如果不考虑重试间隔的话,就难以避开偶发性的失败。比如说注册中心和服务端之间网络抖动,那么第一次心跳失败之后,你立刻重试多半也是失败的,因为此时网络很可能还是不稳定。
所以比较好的策略是立刻重试几次,如果都失败了就再间隔一段时间继续重试。所有的重试机制实际上也是要谨慎考虑重试次数和重试间隔的,确保在业务可以接受的范围内重试成功。不过再怎么样,从服务端崩溃到客户端知道,中间总是存在一个时间误差的,这时候就需要客户端来做容错了。
这个回答里面,最后的一句话,就是为了引出下面这个亮点:客户端容错。