健康检查(health check),是服务反馈其是否正常运行的一种方式。对企业而言,服务健康检查的重要性不言而喻,大部分企业虽然设置了相关健康检查却没有起到应有的作用,那么该如何创建有意义的健康检查,可以参考以下几点。

1、考虑业务用例

在不同的语境中,健康检查有不同的含义。对于公开HTTP API的Web服务,我们只需要监控内部服务器发生错误的比例就能够满足日常需求。而对于其他服务,例如需要定期运行的任务或需要使用事件订阅服务的应用类型,健康状态可能意味着完全不同的情况,如果定期运行的任务存在问题,则意味着这个任务完全不可用,也不会被触发;而事件订阅服务,如果消息队列存在阻塞,那么订阅者则不能及时收到消息通知。所以我们要从业务本身出发来设计你的健康检查。

2、检查下游依赖项

健康检查不只依赖于服务本身,还关联到下游服务,如数据库、第三方API等。例如健康检查发现Web服务不可用,但因为并非服务本身出现问题,所以无法给出具体的原因。我们需要考虑从更多场景来获取信息,而不仅仅只关注服务本身。例如,可能不是服务的问题,而是数据库方面的问题:

1)数据库的JDBC连接池能够获取连接吗?

2)后台服务是否可以从数据库查询到需要的数据?

3)数据库查询请求是否在可接受的时间内完成?

3、返回有意义的数据

健康检查主要是用于监控服务的各类应用场景(可视化、决策、负载均衡、警报等)。监控检查所展现的内容应该是以软件工程标准化格式返回监控数据(如XML、JSON等),它和公司的所有服务返回请求数据类型应保持一致,监控数据要能够明确地说明检查的内容,如哪些检查失败以及失败的原因等。随着应用服务部署与路由策略在微服务中变得愈加复杂,这些信息将变得非常宝贵,能够在系统发生问题时及时地提供给我们详细的、有价值的信息,便于我们追踪问题的根因。

4、合理区分状态类型

针对不同状态,我们处理的方式也不尽相同。我们的服务也有类似情况:服务无响应时,可能需要我们重启服务;如果服务接口面临大量并发请求,则需要匹配负载均衡策略。

当我们要对某种不健康的状态做出响应时,就需要考虑清楚具体实施方案。例如系统存在某个问题时,可能需要回滚版本,也可能只需要重新启动服务,减少流量,或呼叫我们待命的工程师帮助修复问题。这在很大程度上取决于我们健康检查如何区分不同服务状态。

5、考虑不同的检查点

像K8S这样的编排平台,包含活动检查和准备状态检查。准备状态检查指的是我们的服务在正式运转前需要检查的一些配置和状态。例如它可能会检查如下内容。

  • 系统是否可以建立到数据库的连接?
  • 系统工作时需要的所有重要缓存都准备好了吗?

而活动检查则是指系统正常运转后,能否继续维持正常运行的检查活动。这取决于以下因素。

1)当前系统的错误率可以被接受吗?2)当前系统是否内存不足?3)当前系统是否存在内存泄漏?

6、区分整体和单个服务的健康

如微服务整体工作状况良好,但某个服务的单个节点因硬件问题发生故障,健康检查也相应地反馈了问题,并且这个服务的其他节点仍可提供服务,服务整体并没有受到任何影响,那么我们不能因为部分服务失效,就断定服务整体已经失控,关键是如何从所有正常的服务中快速找出损坏的服务,并在不影响用户的情况下快速替换或修复它们。

7、不要公开健康检查的端点

健康检查运行状况一般都会包含调试级别的信息。这些信息可能会泄露系统内部架构的重要细节,比如服务使用什么版本的依赖,基于什么框架设计等。我们对待服务的隐私就应该像对待客户的隐私一样,所以也要注意这方面的安全问题。黑客很可能从这些端点中找出破绽,进而利用这些漏洞发动网络入侵。

8、健康检查应具有高效的响应

假设我们有一个访问量巨大的服务,每秒都可能面对成千上万的请求量。面对这种服务时健康检查的端点也可能会超时,如果响应时间过长,系统可能会错误判断服务失效。因此,我们需要遵循一些简单的检查模式。使用超时机制来确保延迟在可接受的范围内。更好的做法是,定期在后台快速访问运行状况端点,并立即返回当前最新状态检查,并始终保持状态是集中的、最新的。

9、监控运行状况检查的历史记录

运行状况检查可以生成非常有用的时间序列数据。我们可以利用这些数据进行分析,帮助我们日后在不同方面进行改进工作。例如,每当生成运行状况报告时,将指标发送到可观测的系统。通过监测系统图表以及数据分析,我们能够回答以下问题。

1)实例准备好需要多长时间?

2)系统正常运行多久了?

3)多久就会有部分不健康的状态?原因是什么?

4)健康检查收到多少请求?

通过这些数据我们能够及时防止问题发生,确定宕机的根本原因,进而优化应用程序中的关键领域问题。