可观测性模式

提示

此内容摘自电子书《为 Azure 构建云原生 .NET 应用程序》,可在 .NET 文档上获取,也可作为免费可下载的 PDF 脱机阅读。

Cloud Native .NET apps for Azure eBook cover thumbnail.

正如为了帮助应用程序中的代码布局而开发的模式一样,存在用于以可靠方式操作应用程序的模式。 维护应用程序的三种有用模式已经出现:日志记录、监视和警报。

何时使用日志记录

无论我们如何谨慎,应用程序在生产环境中几乎总是以意想不到的方式运行。 当用户报告应用程序出现问题时,能够在出现问题时查看应用的情况是有用的。 捕获有关应用程序在运行时所做操作的信息的一种经考验的好方法是让应用程序记下正在执行的操作。 这个过程称为日志记录。 生产环境中出现故障或问题时,目标应该是在非生产环境中重现发生故障的情况。 现成的日志记录可为开发人员提供一个可遵循的路线图,以便在可测试和试验的环境中重现问题。

用云原生应用程序进行日志记录时遇到的难题

在传统的应用程序中,日志文件通常存储在本地计算机上。 事实上,在类似 Unix 的操作系统上,有一个文件夹结构定义为保存任何日志,通常在 /var/log 下。

Logging to a file in a monolithic app.图 7-1。 在整体式应用中将日志记录到文件。

在云环境中,将日志记录到单台计算机上的平面文件的有用性大大减少。 生成日志的应用程序可能无法访问本地磁盘或本地磁盘可能是高度短暂的,因为容器是围绕物理计算机随机选择的。 即使是跨多个节点进行整体式应用程序的简单纵向扩展,也可能很难找到相应的基于文件的日志文件。

Logging to files in a scaled monolithic app.图 7-2。 在缩放的整体式应用中将日志记录到文件。

使用微服务体系结构开发的云原生应用程序也会对基于文件的记录器带来一些挑战。 用户请求现在可能跨在不同计算机上运行的多个服务,可能包括无服务器功能,且不能访问本地文件系统。 跨这些许多服务和计算机将用户或会话中的日志关联起来非常困难。

Logging to local files in a microservices app.图 7-3。 在微服务应用中将日志记录到本地文件。

最后,某些云原生应用程序中的用户数很高。 假设当每个用户登录到应用程序时,会生成一百行的日志消息。 对于单独的日志消息是可以管理的,但有超过 100,000 个用户,日志量变得足够大,这样便需要专用工具来支持日志的有效使用。

云原生应用程序中的日志记录

每种编程语言都有支持编写日志的工具,通常编写这些日志的开销较低。 许多日志记录库提供记录不同重要性种类的功能,可在运行时进行功能优化。 例如,Serilog library 是适用于 .NET 的常用结构化日志记录库,可提供以下日志记录级别:

  • 详细
  • 调试
  • 信息
  • 警告
  • 错误
  • 严重

这些不同的日志级别提供日志记录的粒度。 当应用程序在生产环境中正常运行时,可以将其配置为仅记录重要的消息。 当应用程序运行不正常时,可以提高日志级别,以收集更详细的日志。 这会在性能和调试简易性之间做出平衡。

日志记录工具的高性能和详细程度的可调节性应该会促使开发者经常进行记录。 很多开发者喜欢记录条目的模式和每个方法的出口。 这种方法可能听起来用力过猛,但开发者很少会希望减少日志记录。 实际上,仅出于围绕有问题的方法添加日志记录这一目的而执行部署并不少见。 在日志记录过多方面犯错,而不是在日志记录过少方面犯错。 某些工具可用于自动提供此类日志记录。

由于在云原生应用中使用基于文件的日志存在难题,因此最好使用集中式日志。 日志由应用程序收集,并发送到一个集中式日志记录应用程序,该应用程序用于编制索引和存储日志。 此类系统每天可以引入数十 GB 的日志。

构建跨许多服务的日志记录时,遵循一些标准做法也是有帮助的。 例如,在时间较长的交互开始时生成相关 ID,然后将其记录在与该交互相关的每个消息中,使得搜索所有相关消息变得更加容易。 只需查找单个消息,然后提取相关 ID 即可找到所有相关的消息。 另一个示例是确保每个服务的日志格式都是相同的,无论使用何种语言或日志记录库。 这一标准化使得读取日志变得更加容易。 图 7-4 演示了微服务体系结构如何在其工作流中利用集中式日志记录。

Logs from various sources are ingested into a centralized log store.图 7-4。 来自各种来源的日志会被引入到一个集中的日志存储中。

检测和响应潜在的应用运行状况问题的挑战

有些应用程序并不是任务关键型的。 也许它们只在内部使用,并且在出现问题时,用户可以与负责的团队联系,应用程序可以重新启动。 但是,客户通常对其使用的应用程序具有更高的期望。 你应在用户发现问题或用户通知你问题出现之前知晓应用程序的问题。 否则,当你首次发现问题时,你可能会发现愤怒的社交媒体帖子正在嘲笑你的应用程序,甚至是你所在的组织。

你可能需要考虑的一些情况包括:

  • 应用程序中的一个服务不断失败和重新启动,从而导致间歇性响应速度缓慢。
  • 在一天中的某个时间,你的应用程序的响应速度慢。
  • 最近的部署后,数据库的负载增至三倍。

正确实现后,监视可以让你了解将导致问题的条件,让你可以在这些条件导致严重的用户影响之前解决基本条件。

监视云原生应用

某些集中式日志记录系统采用额外的角色,在纯粹的日志以外收集遥测数据。 它们可以收集指标,例如运行数据库查询所用的时间、来自 web 服务器的平均响应时间,甚至是操作系统报告的 CPU 负载平均值和内存压力。 这些系统与日志结合使用,可提供系统中节点和整个应用程序的运行状况的整体视图。

还可以从应用程序中手动馈送监视工具的指标收集功能。 可以检测到特别关注的业务流(例如新用户注册或下订单),从而在中央监视系统中增加计数器。 这种情况会解锁监视工具,不仅监视应用程序的运行状况,而且还能监视业务的运作情况。

可以在日志聚合工具中构造查询,以查找特定的统计信息或模式,然后在自定义仪表板上以图形形式显示这些统计信息或模式。 通常情况下,团队将使用大型壁挂式显示屏,轮流显示与应用程序相关的统计信息。 这样一来,就很容易在问题发生时发现问题。

云原生监视工具提供应用的实时遥测和见解,无论它们是单进程整体式应用程序还是分布式微服务体系结构。 它们包括支持从应用收集数据的工具,以及用于查询和显示有关应用运行状况的信息的工具。

对云原生应用中的严重问题做出反应的挑战

如果需要对应用程序的问题做出响应,则需要通过某种方式向正确的人员发出警报。 这是第三个云原生应用程序可观测性模式,依赖于日志记录和监视。 你的应用程序需要有日志记录,以便能够诊断问题并在某些情况下馈送到监视工具。 它需要通过监视将应用程序指标和运行状况数据聚合到一个位置。 建立此项后,可以创建规则,当某些指标超出可接受的级别时,规则会触发警报。

通常,警报的层级位于监视之上,因此,某些条件会触发适当的警报,通知团队成员发生了紧急问题。 可能需要警报的一些情况包括:

  • 应用程序的某个服务在停机一分钟后没有响应。
  • 应用程序正在将不成功的 HTTP 响应返回到超过 1% 的请求。
  • 应用程序的关键终结点平均响应时间超过 2000 毫秒。

云原生应用中的警报

可以针对监视工具创建查询以查找已知的故障条件。 例如,查询可以在传入日志中搜索 HTTP 状态代码 500 的指示(这表示 Web 服务器上存在问题)。 一旦检测到其中一项,则可以将电子邮件或短信发送给可以发起调查的原始服务的所有者。

不过,通常情况下,单个 500 错误不足以确定是否出现了问题。 这可能意味着用户输错了密码或输入了一些格式不当的数据。 只有在检测到超过 500 错误平均数目时,才能创建警报查询以触发警报。

警报中最具破坏性的模式之一是触发过多的警报供人们调查。 服务所有者会很快变得对以前调查过且结果是良性的错误不敏感。 当发生真正的错误时,这些错误将在数百个误报的干扰中被忽略。 狼来了的寓言故事经常讲述给儿童,警告他们这样的风险。 请务必确保触发的警报指示真实问题。