7 审核、监控和预警
运营团队不能在部署环境中装配服务。要在部署过程中付出实质性的努力,以确保系统中的每个组件都可以生成性能数据、健康数据和吞吐量数据等。
在任何有配置变更发生的时候,都必须在审核日志中记录详细变更内容、变更人和变更时间。在生产环境出现异常时,第一个要回答的问题就是最近到底进行过哪些变更。离开了审核跟踪,那么这个答案就是“什么都没被改过”,而且情况往往会是,被人们忘掉的就是引发问题的变更。预警是一门艺术。人们总是倾向于对所有事件都做警报,因为开发人员认为这些事件可能值得关注。正是如此,多数服务的第一版通常都会产生长篇累牍的无用预警,结果再也没
有人去理睬。要提高效率,每个警报都得说明一个问题,否则运营团队会慢慢学会对这些警报置之不理。进行互动慢慢跳出需要警报的条件,保证所有关键性事件得到预警,以及在无需采取应对措施时没有警报。除此之外,要实现正确的预警别无灵丹妙药。要得到正确的预警标准,有两条度量标准很有用,也值得尝试:
一、警报和实际故障比(同时要设定一个较为接近的目标);
二、没有相应警报的系统健康问题数量(并设定一个近于0的目标)。
7.1 对所有资源进行检测。
对所有资源进行检测。测量通过系统的每一次用户交互或事务,报告异常情况。尝试“运行器(人为的工作负载,用来模拟生产环境中用户和服务的交互)”也是可以的,不过这还远远不够。如果只是单独使用运行器,我们发现需要花费数日才能检测到一个严重错误,因为运行器的标准工作负载也会被继续良好地处理,接下来还要再花几天才能查出原因。
7.2 数据是最有价值的资产。
数据是最有价值的资产。如果没有充分理解正常的操作行为,那么要对非正常行为做出响应就不是件容易的事情。我们需要汇集许多系统内发生的事件信息,才能知道系统是否真的正常运行。许多服务都经历过灾难性故障,而只有电话铃响起的时候,人们才意识到故障的发生。
7.3 从客户的角度看服务。
从客户的角度看服务。进行端到端的测试。虽然单有运行器不够,但还是需要它们来保证服务器的完整运行。保证例如新用户登录这样重要的复杂过程经过运行器的测试。避免误警,如果在某个运行器上的故障没被当作重要故障,那么变更测试对象,换到是重要故障的运行器上。重申一下,一旦人们开始对数据视而不见,真正的损失就会让人们措手不及。
7.4 检测是生产环境测试所必不可少的。
检测是生产环境测试所必不可少的。检测是生产环境测试所必不可少的。要在生产环境中实现安全的测试,就有必要进行全面监控和预警。如果某个组件开始出现故障,就必须快速检测出来。
7.5 延迟是最棘手的问题。
延迟是最棘手的问题。缓慢的I/O,以及尚未出现故障但处理缓慢的现象,都是很好的例子。这些问题发现起来很困难,所以一定要仔细检测,保证这样的现象可以检测出来。
7.6 要有足够的生产环境数据。
要有足够的生产环境数据。为了发现问题,数据是不可或缺的。在早期就要建立细粒度的监控机制,否则放到后面再翻新成本就高得多了。
我们所依赖的数据中最重要的包括:
l 对所有操作使用性能计数器。至少记录操作的延迟和每秒钟的操作次数。这些数值突然出现的此消彼长现象,是一个十分危险的信号。
l 审核所有操作。每次有人进行操作之后,尤其是那些明显的操作,一定要记入日志。这样做有两个目的:首先,可以对日志进行挖掘,找出用采取的操作类型(在我们的例子里是用户查询的种类);其次,一旦发现问题,这样做有助于调试问题。相关视点:如果每个人使用相同的账号管理系统的话,这么做带来不了多少好处。相反这是一个非常糟的办法,不过这种情况不多。
l 跟踪所有容错机制。容错机制会把故障隐藏起来。每次出现重试、某个数据被一处复制到另一处,以及机器或者服务重启这类现象时,都要进行跟踪。要了解容错机制在何时隐藏了小故障,这样就可以对这些小故障进行追溯,以防其变成大面积故障。我们曾经碰到过这样一个问题:一个跨2000台机器的服务在几天内慢慢地瘫痪,最后只剩400 台机器可用,而一开始这个问题却没有发现。
l 跟踪对重要实体的操作。为某个特殊实体的所有重要操作记录一份“审核日志”,不管这个实体是一个文档,或者一组文档。在运行数据分析时,常常能在数据中发现异常现象。要了解数据的来源及其经历的处理过程。到了后期才往项目加入这样的功能是非常困难的。
l 断言(asserts)。不要吝惜断言的使用,而且要贯彻在整个产品中。收集因此产生的日志或者崩溃转储(crashdump),并进行调查研究。对于在同一个进程边界内运行不同服务并且无法使用断言的系统,要写下跟踪记录。不管哪种实现,都要能够对错误进行标记,频繁挖掘不同问题的频率。
l 保留历史记录。历史性能和日志数据对于趋势的总结和问题的诊断都是非常必要的。
7.7 可配置的日志功能。
可配置的日志功能。对可配置的日志功能提供支持,这些日志记录可以有选择性开启或关闭,以便进行错误调试。在故障过程中,如果不得不部署带额外监控功能的新构建版本是非常危险的。
7.8 外部化健康信息,用于监控。
外部化健康信息,用于监控。考虑能实现外部监控服务健康程度的方式,并使对生产环境进行监控容易实现。
7.9 保证所有报告的错误可以应对。
保证所有报告的错误可以应对。问题总会发生,系统也总会出错。如果在代码中检测到无法恢复的错误,并且在日志或者报告中归为错误,那么错误信息应当指出错误可能发生的原因,并提供修复的建议。无法采取应对措施的错误报告毫无用处,而且时间一久这些错误报告会像“狼来了”一样被人们忽略,那时候真正的错误就可能被错过。
7.10 启用生产环境问题的快速诊断。
启用生产环境问题的快速诊断。
为诊断提供足够信息。当问题被标出时,要提供足够的信息,人们才可以对其进行诊断;否则门槛会非常高,标注也会被忽略。例如,不要只说“10个查询都没返回结果”,还得补上“列表在这里,还有问题出现的次数”。
证据链。保证存在一条贯穿始终的路径,可供开发人员诊断之用。通常这都是由日志实现的。
在生产环境中的调试。我们偏爱这样的一种模式:系统没有被包括运营团队在内的任何人触碰过,并且调试是通过镜像快照、内存转储并将所得数据发送到生产环境之外来实现的。当生产环境成为唯一选择是,开发人员就是最好的选择。要确保开发人员得到良好的培训,知晓生产环境的操作限制。我们的经验是,系统在生产环境中动的次数越少,客户通常也越开心。因此我们推荐,一定要多努一把力,尽量避免接触生产环境中的系统。
◇记录所有重要的操作。每次系统执行了重要的操作,特别是对网络请求和数据修改上,要进行记录。这既包括用户发送命令的事件,也包括系统内部的行为。有了这样的记录,调试问题的时候就会获益无穷。更重要的是,还可以开发出相应的挖掘工具,用来找出有用的集合,比如用户的查询都是什么样的(也就是说,用了哪些关键字,有多少关键字等等)。