微服务日志记录最佳实践

微服务架构是一种应用程序结构,它促进使用松散耦合的系统,允许您独立地开发、测试、部署和发布服务。这些服务是独特系统的一部分,使用微服务背后的想法是将大问题转化为小问题。通常,每个服务通过 HTTP 端点与其他服务交互,通过仅向其消费者公开合同来隐藏其技术堆栈的详细信息。服务 A 将调用服务 B,服务 B 同时调用服务 C。请求链完成后,服务 A 可能能够响应发起请求的最终客户。

微服务架构提供了许多巨大的好处,例如能够使用不同的技术堆栈、独立部署、一次解决一个小问题等等!但使用微服务的成本很高,因为它们很复杂……不仅在于它们的通信方式,而且还在于如何管理它们。当一项或多项服务失败时,情况会变得更加复杂。哪个服务失败了?为什么、在什么情况下?如果您没有良好的、有意义的日志,所有这些问题都很难回答。

老实说,我们都讨厌那些“未知”或“出了问题”的系统错误。我自己也一直在努力解决糟糕的日志记录策略带来的问题。让我分享一些在处理微服务时对我有帮助的最佳实践。

最新的 DZone 参考卡

NoSQL 迁移要点


将请求与唯一 ID 相关联
回想一下我在上一节中谈到的服务 A、B 和 C 之间的请求调用链。遵循这个想法,最好的做法是使用标识请求的唯一 ID 来标记每个调用。

例如,假设您正在记录每个服务的访问和错误日​​志。如果您在服务 B 中发现错误,那么了解该错误是由来自服务 A 的请求还是发送到服务 C 的请求引起的可能会很有用。

也许该错误的信息量足够大,您甚至不需要重现它。但如果情况并非如此,重现错误的正确方法是了解与服务 B 相关的服务中所有可能的请求。当您有关联请求 ID 时,您只需查找日志中的该 ID。您将从服务中获取所有日志,这些日志是对系统的主要请求的一部分。您还将了解主请求在哪个服务中花费最多的时间、该服务是否正在使用缓存、某个服务是否多次调用其他服务以及许多其他有趣的详细信息。

在响应中包含唯一 ID
微服务的用户有时肯定会遇到错误。不要错过找出导致错误原因的机会!您应该对客户端收到的响应进行编码,以便它包含唯一的 ID 以及有关错误的任何其他有用信息。正如我上面所讨论的,这个唯一 ID 可能与您用于关联请求的 ID 相同。


在请求的响应负载中拥有唯一的 ID 将帮助您和您的客户更快地识别问题。您将了解请求的参数——日期、时间和其他详细信息,这将帮助您更好地理解问题。使用标记请求的 ID 补充常见错误消息,例如“联系服务管理员报告问题”。这样您就可以了解导致错误的原因并防止将来再次发生。

将日志发送到集中位置
假设您已经将各种有用的信息添加到日志中。但将日志发送到集中位置至关重要。

想一想。如果您必须登录到每台单独的服务器来读取日志,那么与只有一个可以访问所有日志的位置相比,您将花费更多的时间来尝试关联问题。此外,随着时间的推移,系统通常会变得更加复杂,因此微服务的数量通常也会增加。让事情变得更加复杂的是,服务可以托管在不同的服务器或提供商上。

集中式日志记录正在成为常态,特别是在您使用云、容器或混合环境时,因为服务器可能会在没有任何通知的情况下终止。例如,如果出现意外错误,或者内存达到其消耗容量的 100%,容器将被终止。

您可以通过让代理每五分钟或在服务器终止之前拉动和推送日志来解决此问题。您还可以在服务器、sidecar 容器或其他进程可以集中日志的共享文件位置中配置 cronjob。避免自己构建解决方案堆栈的诱惑,因为集中日志记录是一个众所周知的问题,并且已经解决了。

将所有服务的日志集中在一处,可以轻松高效地关联问题。

构建您的日志数据
为日志数据定义一个定义的格式几乎是不可能的;某些日志可能需要比其他日志更多的字段,而那些不需要所有这些多余字段的日志将浪费字节。微服务架构通过使用不同的技术堆栈来解决这个问题,这会影响每个服务的日志格式。一项服务可能使用逗号来分隔字段,而其他服务则使用竖线或空格。

所有这些都会变得相当复杂。通过将日志数据结构化为JavaScript 对象表示法(JSON)等标准格式,可以简化日志解析过程。JSON 允许您的数据具有多个级别,以便在必要时您可以在单个日志事件中获取更多语义信息。

解析也比处理特定日志格式更直接。对于结构化数据,日志的格式是标准的,即使日志可以具有不同的字段。您还可以在集中位置创建搜索,例如查找“http_code”为 500 及以上的日志。使用结构化日志记录在微服务日志中采用标准但灵活的格式。

为每个请求添加上下文

我不了解你,但当出现问题时,我想知道一切!拥有有关问题的足够信息可以为您的请求提供重要的背景信息。了解可能导致问题的原因至关重要,并且拥有正确的上下文将帮助您更快地了解正在发生的情况。但是,向日志添加上下文可能会成为代码中的重复性任务,因为每个日志事件中都需要通用数据,例如日期和时间。因此,在代码中,日志记录看起来会更简单,因为您只需记录消息和其他独特区域。

您可能想要记录可以获得的所有数据。但让我给您一些特定的字段,可以帮助您找出真正需要记录的内容。

日期和时间。它不必是 UTC,只要时区对于需要查看日志的每个人来说都是相同的即可。
堆栈错误。您可以将异常对象作为参数传递给日志记录库。
服务名称或代码,以便您区分哪些日志来自哪个微服务。
发生错误的函数、类或文件名,这样您就不必猜测问题出在哪里。
外部服务交互名称 - 您将知道哪个对数据库的调用出现了问题。
服务器和客户端请求的IP地址。这些信息可以让您轻松发现不健康的服务器或识别DDoS 攻击。
应用程序的用户代理,以便您了解哪些浏览器或用户出现问题。
HTTP 代码以获得错误的更多语义。这些代码对于创建警报很有用。
当您需要解决系统中的问题时,将请求与日志结合起来可以节省您的时间。

将日志写入本地存储
将日志写入本地存储可能听起来与我之前所说的将日志发送到集中位置相矛盾,但请听我说完。当我第一次读到有关在其他地方发送日志时,我决定直接通过 HTTP 请求发送日志。这不是一个坏主意,但也不是一个好主意。有时我的出站网络流量过多。我最终影响了对其他更关键的微服务的调用。

将日志发送到本地存储时总是需要进行权衡。但我更喜欢这个选项,因为它有助于解耦日志记录并减少应用程序内的上下文切换。您可能希望将日志的存储卷与应用程序使用的存储卷分开,特别是如果它是数据库的话。例如, Amazon Web Services (AWS) 可以选择使用称为弹性文件系统(EFS)的服务来安装卷,该服务的作用类似于网络附加存储(NAS)。您可以启动另一台安装相同卷的服务器,然后将日志转发到集中位置。

尝试通过将所有应用程序日志发送到同一位置来使事情变得简单 - 使用 Docker 容器可以促进这种行为。将聚合、过滤和转发日志的职责转移到其他进程或服务。

记录有用且有意义的数据以避免后悔
这些只是帮助您记录微服务的一些普通的东西。如果您刚刚开始使用日志记录,这些实践可能没有多大意义并且看起来毫无用处。但是,一旦您使用微服务一段时间,它们就会为您省去很多麻烦。只要确保您始终评估您所记录的内容即可。当您进行故障排除时,您将更好地了解需要记录的重要内容,并对自己说“我希望我有 X 和 Y 信息,这样我就可以更轻松地发现这些奇怪的错误。”

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

千源万码

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值