封面

分布式日志管理:从单体最佳实践到云原生范式演进

最近在维护一个小项目时遇到了个有趣的问题,走了一遍单体到云原生的日志演化路线。

事情是这样的:花糕的手头有个项目,最开始就是个简单的服务,单机部署。这种简单的项目我并不想扔进k8s,不然还要容器化,写deployment,太麻烦了,我就选择了最简单的部署方式————单机部署,部署程序选择了 pm2。

单机部署

最开始的日志采集方案特别朴实:项目根目录下创建个 logs 文件夹,用 winston 配置好日志轮转,按大小和时间分割文件。

这种方案的好处是显而易见的:简单、直接、自包含。部署的时候不需要考虑外部依赖,出了问题直接 tail -f logs/app.log 就能看到实时日志,查历史问题翻翻轮转的文件就行。对于一个小项目来说,这完全够用了。

事实上,如果没有后续的事情,这种方式仍然是单机部署的最佳实践。但,事与愿违。

集群与高可用

随着这个项目的演进,功能的增加,也开始有高可用的需求了,要保障服务稳定,集群是很好的选择,考虑到之前单机部署就使用的 pm2,于是我便直接选用了 pm2 的集群模式进行部署,并做了 zero down time 不停机滚动升级。

事情看着很美好,但噩梦才刚刚开始,一切都正常,直到我开始查看日志,有的实例在悲鸣!它写不进去日志!

我一共启动了3个实例来做集群,只有一个实例能正常写日志,另外两个都在哀嚎,很快花糕就找到了原因————文件锁,日志文件被实例A独占了,B和C只能看着A写。

如果解除文件锁,那也是不合理的,这样全都写一起,日志内容会很混乱,几个进程抢着操作同一个文件,就不能给他们每实例一个日志吗?

答对了,这是我的解决方案:进程隔离

进程隔离

既然多个进程抢一个文件不行,那就给每个进程分配独立的日志文件呗。我修改了 winston 的配置,给每个实例用pid做区分:logs/app-${process.pid}.log

这个方案解决了写入冲突的问题,每个进程安安静静地写自己的文件,互不干扰。但新的问题随之而来:现在我有3个实例,每个实例一个 applog,一个 errorlog,加起来我有6个日志文件了,查问题的时候要在几个文件之间跳来跳去,非常的困难。

真正的痛点:分散的日志

这种体验真的很糟糕。

相比之下,喵御宅主站的日志就舒服很多,高可用集群,以及高度的自治运维和自动化,自动采集日志传输给日志服务,我只需要在日志服务看日志就行。

我着实不想把这个小东西扔k8s里面去,于是继续探索。

轻量级的中心化方案

经过一番思考,我决定采用一个相对轻量的方案:让应用程序把日志输出到 stdout,然后借助 pm2 内置的日志管理功能(pm2 logs 命令即可查看所有进程的合并输出,并且 pm2 本身也支持配置日志文件的路径和轮转),再通过 Filebeat 把日志采集走,然后花糕就又回到了他喜欢的 elastic search,不过其实不采集,直接用pm2看也可以,pm2本身的轮转功能已经足够支持了。

这样一来,pm2 会自动捕获并合并所有进程的 stdout 输出到统一的日志流中,我又能回到单文件日志的简单时代了。但这次是有区别的:应用程序本身不再关心日志的存储,只负责输出;pm2 负责收集和管理日志文件。

进一步的思考

解决了这个问题后,我开始反思整个过程。其实这就是一个典型的"技术选型要匹配业务规模"的案例。

对于大型分布式系统,ELK Stack 这样的重型武器是必要的,它们提供了强大的搜索、分析、告警能力。但对于小项目来说,可能一个简单的日志合并方案就够了。

更有趣的是,即使在云原生时代,理解这些"原始"的日志管理方式仍然是有价值的。它们帮助你理解问题的本质:多进程并发写入、日志分散查看困难、存储和轮转管理、文件锁、进程隔离等等。当我们真正理解了这些基础问题,才能更好地欣赏现代日志管理系统的设计思路。

技术选型没有标准答案,关键是要匹配当前的需求和团队能力。有时候,用"落后"的技术解决当前的问题,比过度设计要明智得多。

这次经历也让我重新思考了微服务和单体应用的边界。很多时候我们把 容器化、负载均衡、k8s、分布式日志这些东西当成了标配,但实际上大部分应用可能永远都用不到这些复杂的基础设施。

日志管理就是一个很好的例子。从本地文件到分布式聚合,每一步的演进都是为了解决特定规模下的特定问题。理解这个演进过程,比单纯地记住"最佳实践"要有价值得多。

也许当这个项目继续增长,我最后还是会把它丢进 k8s 集群做大规模负载,但到那个时候,这个项目的日志功能也不需要做任何改动,它已经符合了云原生时代下的标准。

发布评论
全部评论(3)
avatarauth
花糕作者#1111395
该评论已被用户自己删除
avatarauth
花糕作者#1111394
该评论已被用户自己删除
avatar
ききょう#1038889

哇奥[stick-1]