可观测性是大规模微服务的必备能力之一,离开了可观测性,微服务运维一定会是一场灾难。本文介绍了 Salesforce 在构建服务可观测性方面采用的 5 项设计模式,帮助我们完整系统的理解服务可观测性的架构原则。原文:5 Design Patterns for Building Observable Services[1]
怎样让我们的服务容易被观察,让团队能够更方便的管理服务?本文介绍了 5 个通用设计模式,供开发人员参考。
软件开发中的设计模式是解决常见问题的可重复的解决方案和最佳实践。考虑在服务监控的场景下,如果使用得当,设计模式也可以帮助团队方便的管理服务,并在生产中排除故障。可以将服务监控设计模式分为三类:
如何知道服务正在运行,并且正在做应该做的事情?服务反应是否及时?是否存在潜在的服务问题?是否可以在问题影响到客户之前解决?
当出现问题时(比如服务无响应、速度变慢或使用了太多资源),是否配置了告警通知?
服务有什么问题吗?如果有问题发生,可能需要知道三件事:什么时候发生的,在哪里发生的,是什么原因导致的。在问题发生后,通过日志和跟踪来诊断问题,并更新服务,使这些问题不会对客户产生持久影响。
下面我们依次讨论不同类别的模式(以及反模式)。
健康检查有两种模式:由外向内的健康检查,验证服务是否正在运行,并确定服务的响应时间/延迟;由内向外的健康检查,跟踪应用程序和系统指标,可以在事故发生前发现潜在的问题(包括性能问题)。
在此模式中,可以运行健康检查服务或模拟测试工具来 ping 服务端点。可以用自己内部构建的工具,也可以用第三方工具,包括 NewRelic、Gomez 和 DataDog 等。服务对 ping 做出响应,并将检查的输出记录到时间序列度量系统(如 Argus[2]或任何用于此类服务的度量系统)中。一旦有了数据,就可以对一段时间内的服务运行状况和其他关键指标实现可视化,并在特定条件下发送告警信息。
概要模式如下所示。
由外向内运行健康检查的概要设计图
上述两组的组合还可以作为服务的综合可用性信号。
在此模式中,我们通过检测系统和应用程序指标,从而在潜在问题导致服务中断之前就察觉到它们。
要确定是否存在可能影响服务性能或可用性的潜在问题,需要收集有关应用程序和基础设施的指标。
由内向外运行健康检查的概要设计图
那么应该关注哪些应用程序指标呢?至少收集以下四种信号。
此外,对于服务使用的每种资源类型(例如 CPU、内存、磁盘空间、IOPS)收集如下系统指标。
收集这些指标还允许我们计算服务的可用性,这将回答一个关键问题:对客户而言,服务或特性是否可用?在大多数情况下,可以结合正常运行时间、时长(延时)和错误率指标来计算服务的可用性,以代表客户体验。例如,如果只根据正常运行时间来计算服务可用性,那么即使查询需要很长时间才能响应/网页需要很长时间才能加载,仍然会被认为是可用的。因此,采用诸如错误率和时延等额外指标对于恰当定义可用性是至关重要的。
日志数据对于故障排查非常有用,我们将很快讨论这个问题。然而,考虑到目前大多数应用程序生成的日志数据量很大,我们确实不希望基于日志数据生成度量指标。使用日志数据对度量建模开销很大(意味着需要花更多的钱),并且增加了提取、处理和反馈的时间,从而增加了 MTTD(平均检测时间),这两种后果都不可接受。我们在 Salesforce 建立了有效的指标收集工具供开发人员使用。
当服务出现问题时,告警和通知是服务所有者希望接收信息的主要方式。当服务和基础架构的关键运行状况和性能指标高于或低于指定的阈值(表明存在问题)时,应当配置告警。例如,服务的响应时间突然增加,超过了可接受的阈值,服务的可用性低于指定的阈值,违反了服务的 SLA。
告警的目的是通知相关人员介入补救流程、修复问题,并将服务恢复到正常状态,以便继续为客户服务。尽管在收到告警时可以通过触发自动工作流自动修复问题,但并不是所有的问题(特别是复杂的服务问题)都可以这样解决。自动修复可能有帮助的典型场景包括重新启动服务、增加/减少云环境中的计算资源、如果有任何未经授权的端口开放(安全漏洞)则终止实例等。
通过使用更复杂的技术(包括机器学习),可以主动发出告警并检测异常情况,从而为服务所有者提供更好的体验。主动告警允许我们在问题影响到客户之前采取补救措施。例如,根据当前的使用趋势,通知我们服务将在一周内耗尽磁盘空间,而不是等到磁盘只剩 10%空间时才通知我们。主动告警为修复问题提供了更多的时间,让我们不需要在凌晨 3 点出现告警的时候来修复问题。这种类型的告警可以创建一个问题单,以便服务所有者在第二天早上查看问题。检测异常可以减少告警噪声,并使服务所有者不必配置静态阈值来获得告警。当系统检测到给定指标的模式中有异常时,可以发出告警。还可以考虑周期性因素,从而减少假阳性(噪音),并在一段时间内自动调整阈值以及异常的定义。
一般的告警模式包括确定问题是否可以自动修复,或者是否需要人工干预,以避免违反公司与客户之间的服务水平协议(Service Level Agreement, SLA)。下面的流程图包含了自动修复和需要人工干预的修复。
启动自动补救还是调用人工操作的决策流程图
当服务出现问题时,需要有关出错原因、出错时间和出错地点的信息。对服务进行编码,以便此类信息可以用于故障诊断,有两个关键方法可以获得这些可用信息。
日志是帮助我们定位问题的好帮手,所以一定要记录服务的出错条件。可以在服务中包含日志库来捕获应用程序日志,并送到日志服务。我们在 Salesforce 使用 Splunk[3],不过也可以采用其他选择,比如 DataDog、NewRelic 等。
在定位故障时,可以使用应用程序和基础设施日志来帮助我们确定是什么导致了问题,以及如何减少问题再次发生的机会。
下图描述了日志系统的概要架构。
日志系统概要架构图
在微服务体系架构下,当发生事故或性能下降时,不仅仅需要知道哪里出错,还需要知道是哪个微服务引起了问题。
分布式跟踪允许我们通过 requestID 标识每个请求来获得这些信息。当出现问题时,可以查看其在请求流中发生的位置,以及判断该问题是与我们的服务相关还是与依赖的服务相关。我们在 Salesforce 已经将所有应用与自主开发的分布式跟踪服务(构建在 Zipkin 之上)Tracer 集成在一起,生成的 span 被发送到 Tracer 上,上下文通过 B3 报头[4]传播到下游应用,使用 Zipkin[5]或 OpenTelemetry[6]库实现可视化。
通过采用关于健康检查、告警和故障排除的设计模式,可以从头开始构建可观察服务。有很多工具和资源可以帮助我们开始。强烈推荐阅读谷歌的站点可靠性工程(SRE)一书[7],特别是导论[8]中的“监控”部分和第 6 章: 监控分布式系统[9]。此外,还可以查看我们的可观测性 101 系列[10],了解更多关于微服务监控的信息。
References: [1] 5 Design Patterns for Building Observable Services: https://engineering.salesforce.com/5-design-patterns-for-building-observable-services-d56e7a330419 [2] Argus: https://github.com/salesforce/Argus [3] Splunk: https://www.splunk.com/ [4] B3 propagation: https://github.com/openzipkin/b3-propagation [5] Zipkin: https://zipkin.io/ [6] OpenTelemetry: https://opentelemetry.io/ [7] Google SRE Book: https://landing.google.com/sre/sre-book/toc/ [8] Google SRE Book Instroduction: https://landing.google.com/sre/sre-book/chapters/introduction/ [9] Google SRE Book Monitoring distributed systems: https://landing.google.com/sre/sre-book/chapters/monitoring-distributed-systems/ [10] Salesforce Observability 101: https://engineering.salesforce.com/tagged/observability
你好,我是俞凡,在 Motorola 做过研发,现在在 Mavenir 做技术工作,对通信、网络、后端架构、云原生、DevOps、CICD、区块链、AI 等技术始终保持着浓厚的兴趣,平时喜欢阅读、思考,相信持续学习、终身成长,欢迎一起交流学习。 微信公众号:DeepNoMind
领取专属 10元无门槛券
私享最新 技术干货