架构思想之-高可用场景怎么做服务的故障发现,故障恢复
架构思想之-高可用场景怎么做服务的故障发现,故障恢复
从现有的一套微服务开始
简述一下上面流程
- 各个订单服务向zk (这里只是注册中心,也可以是eurake、consul、nacos等)注册自己的服务。注册的时候其实就是上报当前服务的ip:port:name等
- 网关(服务的消费方)watch zk的节点,就能感知到那些服务注册进来了
- 网关层可以通过zk拿到下游服务的基本属性,然后向每个服务建立长连接。即可
简单思考一下上面这一套有什么问题?
- 如果服务A挂了怎么办?难道网关还一直向他发请求?
- 那如果服务A只是假死怎么办?(例如发生了死循环)
- 服务A出故障了怎么让他恢复?
- 服务A恢复了网关又怎么感知到?
基于以上问题我们一个个来分享处理思路。
1. 如果服务A挂了怎么办?难道网关还一直向他发请求?网关怎么知道服务A挂掉了?
假设服务A是真的死了(机器都挂了等)。其实服务A与zk之间是有保持心跳的。默认每3s发送一次心跳。当zk连续2次没有发送心跳,我们就认为这台服务真的挂了。那么那么服务A在zk上注册的节点(临时节点)就会消失。自然网关层就能watch到。就可以在本地把连接服务A的长连接踢掉即可。
但是在这6s钟期间,我们网关其实是不知道服务A挂了。那这时候就要依靠网关层自己要做好一些熔断/降级/重试机制,即快速将请求失败返回。或者转移到另外一台服务上。
2、那如果服务A只是假死怎么办?(例如发生了死循环)
例如,你的用户程序发生了死循环,但是整个进程并没有挂掉。此时zk心跳肯定还是能保持的。也就是说没法依靠zk的心跳机制来帮我们实现。此时我们可以让上层服务(网关)来帮我们实现。
例如:网关那边每次请求服务A时,保存几秒中的请求返回信息。每隔1s统计一下该服务的正确率。如果错误率达到一定比例。上层服务(网关)可以帮忙去删除服务A在zk上注册的信息。
3、服务A出故障了怎么让他恢复?
上面讲到上层服务(网关)帮服务A,注销服务了。那么服务A不可能一直让他挂着肯定得重启它,让他恢复啊。
例如:如果服务真的宕机了。那么直接重启就完事。
但是假死的情况就得自己来完成了。上面说到网关会帮服务A注销。服务A自己肯定也能感知到自己被注销了(假死,那zk客户端肯定也是在的)。所以就得依靠zk客户端来帮我们重启这个服务。
步骤:
- jstack 3次(每次隔几秒)
- sleep 6s以上( 不一定必须)
- kill 进程
- start 服务
思考:为什么要这么做?后面来讲。
4、网关怎么知道服务恢复了呢?
这个就比较简单了。服务A重启后,重新注册到zk上。其他上层系统自然就能感知到了。
解答:
为什么要jstack?为什么是3次?
jstack 是为了保留上次故障的线程栈。为了后面复盘问题。
3次并且每次 还隔几秒。其实是为了保留对照。例如:死循环,对照3次立马就可以看到线程是不是停在同一个方法上。
为什么要sleep 6秒?
如果如果上游系统没有帮我们删除节点的话。就可以通过sleep 6s ,主要是为了断掉心跳。主要是因为zk心跳3s,2次才会被认为服务挂了。