阿里三面:你的日志采集系统是怎么做的?用了那些高大上的技术呢?

2024-05-02 08:08

本文主要是介绍阿里三面:你的日志采集系统是怎么做的?用了那些高大上的技术呢?,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

点击上方 "zhisheng"关注, 星标或置顶一起成长

Flink 从入门到精通 系列文章

来源:jm.taobao.org/2018/06/13/日志采集中的关键技术分析/

  • 概述

  • 业界现状

  • 从头开始写一个日志采集Agent

  • 如何发现一个文件?

  • 点位文件高可用

  • 如何识别一个文件?

  • 如何知道文件内容更新了?

  • 如何安全的释放文件句柄?

  • 总结


概述

日志从最初面向人类演变到现在的面向机器发生了巨大的变化。最初的日志主要的消费者是软件工程师,他们通过读取日志来排查问题,如今,大量机器日夜处理日志数据以生成可读性的报告以此来帮助人类做出决策。在这个转变的过程中,日志采集Agent在其中扮演着重要的角色。

作为一个日志采集的Agent简单来看其实就是一个将数据从源端投递到目的端的程序,通常目的端是一个具备数据订阅功能的集中存储,这么做的目的其实是为了将日志分析和日志存储解耦,同一份日志可能会有不同的消费者感兴趣,获取到日志后所处理的方式也会有所不同,通过将数据存储和数据分析进行解耦后,不同的消费者可以订阅自己感兴趣的日志,选择对应的分析工具进行分析。像这样的具备数据订阅功能的集中存储业界比较流行的是Kafka,对应到阿里巴巴内部就是DataHub还有阿里云的LogHub。而数据源端大致可以分为三类,一类就是普通的文本文件,另外一类则是通过网络接收到的日志数据,最后一类则是通过共享内存的方式,本文只会谈及第一类。一个日志采集Agent最为核心的功能大致就是这个样子了。在这个基础上进一步又可以引入日志过滤、日志格式化、路由等功能,看起来就好像是一个生产车间。从日志投递的方式来看,日志采集又可以分为推模式和拉模式,本文主要分析的是推模式的日志采集。

推模式是指日志采集Agent主动从源端取得数据后发送给目的端,而拉模式指的是目的端主动向日志采集Agent获取源端的数据

业界现状

目前业界比较流行的日志采集主要有FluentdLogstashFlumescribe等,阿里巴巴内部则是LogAgent、阿里云则是LogTail,这些产品中Fluentd占据了绝对的优势并成功入驻CNCF阵营,它提出的统一日志层(Unified Logging Layer)大大的减少了整个日志采集和分析的复杂度。Fluentd认为大多数现存的日志格式其结构化都很弱,这得益于人类出色的解析日志数据的能力,因为日志数据其最初是面向人类的,人类是其主要的日志数据消费者。为此Fluentd希望通过统一日志存储格式来降低整个日志采集接入的复杂度,假想下输入的日志数据比如有M种格式,日志采集Agent后端接入了N种存储,那么每一种存储系统需要实现M种日志格式解析的功能,总的复杂度就是M*N,如果日志采集Agent统一了日志格式那么总的复杂度就变成了M + N。这就是Fluentd的核心思想,另外它的插件机制也是一个值得称赞的地方。LogstashFluentd类似是属于ELK技术栈,在业界也被广泛使用,关于两者的对比可以参考这篇文章Fluentd vs. Logstash: A Comparison of Log Collectors

unified-logging-pluggable.png

从头开始写一个日志采集Agent

作为一个日志采集Agent在大多数人眼中可能就是一个数据“搬运工”,还会经常抱怨这个“搬运工”用了太多的机器资源,简单来看就是一个tail -f命令,再贴切不过了,对应到Fluentd里面就是in_tail插件。笔者作为一个亲身实践过日志采集Agent的开发者,希望通过本篇文章来给大家普及下日志采集Agent开发过程中的一些技术挑战。为了让整篇文章脉络是连续的,笔者试图通过“从头开始写一个日志采集Agent”的主题来讲述在整个开发过程中遇到的问题。

如何发现一个文件?

当我们开始写日志采集Agent的时候遇到的第一个问题就是怎么发现文件,最简单的方式就是用户直接把要采集的文件罗列出来放在配置文件中,然后日志采集Agent会读取配置文件找到要采集的文件列表,最后打开这些文件进行采集,这恐怕是最为简单的了。但是大多数情况日志是动态产生的,会在日志采集的过程中动态的创建出来, 提前罗列到配置文件中就太麻烦了。正常情况下用户只需要配置一个日志采集的目录和文件名字匹配的规则就可以了,比如Nginx的日志是放在/var/www/log目录下,日志文件的名字是access.logaccess.log-2018-01-10…..类似于这样的形式,为了描述这类文件可以通过通配符或者正则的表示来匹配这类文件例如:access.log(-[0-9]{4}-[0-9]{2}-[0-9]{2})?有了这样的描述规则后日志采集Agent就可以知道哪些文件是需要采集的,哪些文件是不用采集的。接下来会遇到另外一个问题就是如何发现新创建的日志文件?,定时去轮询下目录或许是个不错的方法,但是轮询的周期太长会导致不够实时,太短又会耗CPU,你也不希望你的采集Agent被人吐槽占用太多CPU吧。Linux内核给我们提供了高效的Inotify的机制,由内核来监测一个目录下文件的变化,然后通过事件的方式通知用户。但是别高兴的太早,Inotify并没有我们想的那么好,它存在一些问题,首先并不是所有的文件系统都支持Inotify,此外它不支持递归的目录监测,比如我们对A目录进行监测,但是如果在A目录下面创建了B目录,然后立刻创建C文件,那么我们只能得到B目录创建的事件,C文件创建的事件就会丢失,最终会导致这个文件没有被发现和采集。对于已经存在的文件Inotify也无能为力,Inotify只能实时的发现新创建的文件。Inotify manpage中描述了更多关于Inotify的一些使用上的限制以及bug。如果你要保证不漏采那么最佳的方案还是Inotify+轮询的组合方式。通过较大的轮询周期来检测漏掉的文件和历史文件,通过Inotify来保证新创建的文件在绝大数情况下可以实时发现,即使在不支持Inotify的场景下,单独靠轮询也能正常工作。到此为止我们的日志采集Agent可以发现文件了,那么接下来就需要打开这个文件,然后进行采集了。但是天有不测风云,在我们采集的过程中机器Crash掉了,我们该如何保证已经采集的数据不要再采集了,能够继续上次没有采集到的地方继续呢?

基于轮询的方式其优点就是保证不会漏掉文件,除非文件系统发生了bug,通过增大轮询的周期可以避免浪费CPU、但是实时性不够。Inotify虽然很高效,实时性很好但是不能保证100%不丢事件。因此通过结合轮询和Inotify后可以相互取长补短。

点位文件高可用

点位文件? 对就是通过点位文件来记录文件名和对应的采集位置。那如何保证这个点位文件可以可靠的写入呢? 因为可能在文件写入的那一刻机器Crash了导致点位数据丢掉或者数据错乱了。要解决这个问题就需要保证文件写入要么成功,要么失败,绝对不能出现写了一半的情况。Linux内核给我们提供了原子的rename。一个文件可以原子的rename成另外一个文件,利用这个特性可以保证点位文件的高可用。假设我们已经存在一份点位文件叫做offset,每一秒我们去更新这个点位文件,将采集的位置实时的记录在里面,整个更新的过程如下:

  • 将点位数据写入到磁盘的offset.bak文件中

  • fdatasync确保数据写入到磁盘

  • 通过rename系统调用将offset.bak更名为offset

通过这个手段可以保证在任何时刻点位文件都是正常的,因为每次写入都会先确保写入到临时文件是成功的,然后原子的进行替换。这样就保证了offset文件总是可用的。在极端场景下会导致1秒内的点位没有及时更新,日志采集Agent启动后会再次采集这1秒内的数据进行重发,这基本上满足需求了。

但是点位文件中记录了文件名和对应的采集位置这会带来另外一个问题,如果在进程Crash的过程中,文件被重命名了该怎么办? 那启动后岂不是找不到对应的采集位置了。在日志的这个场景下文件名其实非常不可靠,文件的重命名、删除、软链等都会导致相同的文件名在不同时刻其实指向的是不同的文件,而且将整个文件路径在内存中保存其实是非常耗费内存的。Linux内核提供了inode可以作为文件的标识信息,而且保证同一时刻Inode是不会重复的,这样就可以解决上面的问题,在点位文件中记录文件的inode和采集的位置即可。日志采集Agent启动后通过文件发现找到要采集的文件,通过获取Inode然后从点位文件中查找对应的采集位置,最后接着后面继续采集即可。那么即使文件重命名了但是它的Inode不会变化,所以还是可以从点位文件中找到对应的采集位置。但是Inode有没有限制呢? 当然有,天下没有免费的午餐,不同的文件系统Inode会重复,一个机器可以安装多个文件系统,所以我们还需要通过dev(设备号)来进一步区分,所以点位文件中需要记录的就是dev、inode、offset三元组。到此为止我们的采集Agent可以正常的采集日志了,即使Crash了再次启动后仍然可以继续进行采集。但是突然有一天我们发现有两个文件居然是同一个Inode,Linux内核不是保证同一时刻不会重复的吗?难道是内核的bug?注意我用的是“同一时刻”,内核只能保证在同一时刻不会重复,这到底是什么意思呢? 这便是日志采集Agent中会遇到的一个比较大的技术挑战,如何准确的标识一个文件。

如何识别一个文件?

如何标识一个文件算是日志采集Agent中一个比较有挑战的技术问题了,我们先是通过文件名来识别,后来发现文件名并不可靠,而且还耗费资源,后来我们换成了dev+Inode,但是发现Inode只能保证同一时刻Inode不重复,那这句话到底是什么意思呢? 想象一下在T1时刻有一个文件Inode是1我们发现了并开始采集,一段时间后这个文件被删除了,Linux内核就会将这个Inode释放掉,新创建一个文件后Linux内核会将刚释放的Inode又分配给这个新文件。那么这个新文件被发现后会从点位文件中查询上次采集到哪了,结果就会找到之前的那个文件记录的点位了,导致新文件是从一个错误的位置进行采集。如果能给每一个文件打上一个唯一标识或许就可以解决这个问题,幸好Linux内核给文件系统提供了扩展属性xattr,我们可以给每一个文件生成唯一标识记录在点位文件中,如果文件被删除了,然后创建一个新的文件即使Inode相同,但是文件标识不一样,日志采集Agent就可以识别出来这是两个文件了。但是问题来了,并不是所有的文件系统都支持xattr扩展属性。所以扩展属性只是解了部分问题。或许我们可以通过文件的内容来解决这个问题,可以读取文件的前N个字节作为文件标识。这也不失为一种解决方案,但是这个N到底取多大呢? 越大相同的概率越小,造成无法识别的概率就越小。要真正做到100%识别出来的通用解决方案还有待调研,姑且认为这里解了80%的问题吧。接下来就可以安心的进行日志采集了,日志采集其实就是读文件了,读文件的过程需要注意的就是尽可能的顺序读,充份利用Linux系统缓存,必要的时候可以用posix_fadvise在采集完日志文件后清除页缓存,主动释放系统资源。那么什么时候才算采集完一个文件呢? 采集到末尾返回EOF的时候就算采集完了。可是一会日志文件又会有新内容产生,如何才知道有新数据了,然后继续采集呢?

inode.png

如何知道文件内容更新了?

Inotify可以解决这个问题、通过Inotify监控一个文件,那么只要这个文件有新增数据就会触发事件,得到事件后就可以继续采集了。但是这个方案存在一个问题就是在大量文件写入的场景会导致事件队列溢出,比如用户连续写入日志N次就会产生N个事件,其实对于日志采集Agent只要知道内容就更新就可以了,至于更新几次这个反而不重要, 因为每次采集其实都是持续读文件,直到EOF,只要用户是连续写日志,那么就会一直采集下去。另外Intofy能监控的文件数量也是有上限的。所以这里最简单通用的方案就是轮询去查询要采集文件的stat信息,发现文件内容有更新就采集,采集完成后再触发下一次的轮询,既简单又通用。通过这些手段日志采集Agent终于可以不中断的持续采集日志了,既然是日志总会有被删除的一刻,如果在我们采集的过程中被删除了会如何? 大可放心,Linux中的文件是有引用计数的,已经打开的文件即使被删除也只是引用计数减1,只要有进程引用就可以继续读内容的,所以日志采集Agent可以安心的继续把日志读完,然后释放文件的fd,让系统真正的删除文件。但是如何知道采集完了呢? 废话,上面不是说了采集到文件末尾就是采集完了啊,可是如果此刻还有另外一个进程也打开了这个文件,在你采集完所有内容后又追加了一段内容进去,而你此时已经释放了fd了,在文件系统上这个文件已经不在了,再也没办法通过文件发现找到这个文件,打开并读取数据了,这该怎么办?

如何安全的释放文件句柄?

Fluentd的处理方式就是将这部分的责任推给用户,让用户配置一个时间,文件删除后如果在指定的时间范围内没有数据新增就释放fd,其实这就是间接的甩锅行为了。这个时间配置的太小会造成丢数据的概率增大,这个时间配置的太大会导致fd和磁盘空间一直被占用造成短时间自由浪费的假象。这个问题的本质上其实就是我们不知道还有谁在引用这个文件,如果还有人在引用这个文件就可能会写入数据,此时即使你释放了fd资源仍然是占用的,还不如不释放,如果没有任何人在引用这个文件了,那其实就可以立刻释放fd了。如何知道谁在引用这个文件呢? 想必大家都用过lsof -f列出系统中进程打开的文件列表,这个工具通过扫描每一个进程的/proc/PID/fd/目录下的所有文件描述符,通过readlink就可以查看这个描述符对应的文件路径,例如下面这个例子:

tianqian-zyf@ubuntu:~$ sudo ls -al /proc/22686/fd
total 0
dr-x------ 2 tianqian-zyf tianqian-zyf  0 May 27 12:25 .
dr-xr-xr-x 9 tianqian-zyf tianqian-zyf  0 May 27 12:25 ..
lrwx------ 1 tianqian-zyf tianqian-zyf 64 May 27 12:25 0 -> /dev/pts/19
lrwx------ 1 tianqian-zyf tianqian-zyf 64 May 27 12:25 1 -> /dev/pts/19
lrwx------ 1 tianqian-zyf tianqian-zyf 64 May 27 12:25 2 -> /dev/pts/19
lrwx------ 1 tianqian-zyf tianqian-zyf 64 May 27 12:25 4 -> /home/tianqian-zyf/.post.lua.swp

22686这个进程就打开了一个文件,fd是4,对应的文件路径是/home/tianqian-zyf/.post.lua.swp。通过这个方法可以查询到文件的引用计数,如果引用计数是1,也就是只有当前进程引用,那么基本上可以做到安全的释放fd,不会造成数据丢失,但是带来的问题就是开销有点大,需要遍历所有的进程查看它们的打开文件表逐一的比较,复杂度是O(n),如果能做到O(1)这个问题才算完美解决。通过搜索相关的资料我发现这个在用户态来做几乎是没有办法做到的,Linux内核没有暴露相关的API。只能通过Kernel的方式来解决,比如添加一个API通过fd来获取文件的引用计数。这在内核中还是比较容易做到的,每一个进程都保存了打开的文件,在内核中就是struct file结构,通过这个结构就可以找到这个文件对应的struct inode对象,这个对象内部就维护了引用计数值。期待后续Linux内核能够提供相关的API来完美解决这个问题吧。

p-fd.png

总结

到此为此,一个基于文件的采集Agen涉及到的核心技术点都已经介绍完毕了,这其中涉及到很多文件系统、Linux相关的知识,只有掌握好这些知识才能更好的驾驭日志采集。想要编写一个可靠的日志采集Agent确保数据不丢失,这其中的复杂度和挑战不容忽视。希望通过本文能让读者对日志采集有一个较为全面的认知。

基于 Apache Flink 的实时监控告警系统关于数据中台的深度思考与总结(干干货)日志收集Agent,阴暗潮湿的地底世界
2020 继续踏踏实实的做好自己公众号(zhisheng)里回复 面经、ClickHouse、ES、Flink、 Spring、Java、Kafka、监控 等关键字可以查看更多关键字对应的文章。点个赞+在看,少个 bug ????

这篇关于阿里三面:你的日志采集系统是怎么做的?用了那些高大上的技术呢?的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/953788

相关文章

AI绘图怎么变现?想做点副业的小白必看!

在科技飞速发展的今天,AI绘图作为一种新兴技术,不仅改变了艺术创作的方式,也为创作者提供了多种变现途径。本文将详细探讨几种常见的AI绘图变现方式,帮助创作者更好地利用这一技术实现经济收益。 更多实操教程和AI绘画工具,可以扫描下方,免费获取 定制服务:个性化的创意商机 个性化定制 AI绘图技术能够根据用户需求生成个性化的头像、壁纸、插画等作品。例如,姓氏头像在电商平台上非常受欢迎,

不懂推荐算法也能设计推荐系统

本文以商业化应用推荐为例,告诉我们不懂推荐算法的产品,也能从产品侧出发, 设计出一款不错的推荐系统。 相信很多新手产品,看到算法二字,多是懵圈的。 什么排序算法、最短路径等都是相对传统的算法(注:传统是指科班出身的产品都会接触过)。但对于推荐算法,多数产品对着网上搜到的资源,都会无从下手。特别当某些推荐算法 和 “AI”扯上关系后,更是加大了理解的难度。 但,不了解推荐算法,就无法做推荐系

W外链微信推广短连接怎么做?

制作微信推广链接的难点分析 一、内容创作难度 制作微信推广链接时,首先需要创作有吸引力的内容。这不仅要求内容本身有趣、有价值,还要能够激起人们的分享欲望。对于许多企业和个人来说,尤其是那些缺乏创意和写作能力的人来说,这是制作微信推广链接的一大难点。 二、精准定位难度 微信用户群体庞大,不同用户的需求和兴趣各异。因此,制作推广链接时需要精准定位目标受众,以便更有效地吸引他们点击并分享链接

基于人工智能的图像分类系统

目录 引言项目背景环境准备 硬件要求软件安装与配置系统设计 系统架构关键技术代码示例 数据预处理模型训练模型预测应用场景结论 1. 引言 图像分类是计算机视觉中的一个重要任务,目标是自动识别图像中的对象类别。通过卷积神经网络(CNN)等深度学习技术,我们可以构建高效的图像分类系统,广泛应用于自动驾驶、医疗影像诊断、监控分析等领域。本文将介绍如何构建一个基于人工智能的图像分类系统,包括环境

水位雨量在线监测系统概述及应用介绍

在当今社会,随着科技的飞速发展,各种智能监测系统已成为保障公共安全、促进资源管理和环境保护的重要工具。其中,水位雨量在线监测系统作为自然灾害预警、水资源管理及水利工程运行的关键技术,其重要性不言而喻。 一、水位雨量在线监测系统的基本原理 水位雨量在线监测系统主要由数据采集单元、数据传输网络、数据处理中心及用户终端四大部分构成,形成了一个完整的闭环系统。 数据采集单元:这是系统的“眼睛”,

电脑桌面文件删除了怎么找回来?别急,快速恢复攻略在此

在日常使用电脑的过程中,我们经常会遇到这样的情况:一不小心,桌面上的某个重要文件被删除了。这时,大多数人可能会感到惊慌失措,不知所措。 其实,不必过于担心,因为有很多方法可以帮助我们找回被删除的桌面文件。下面,就让我们一起来了解一下这些恢复桌面文件的方法吧。 一、使用撤销操作 如果我们刚刚删除了桌面上的文件,并且还没有进行其他操作,那么可以尝试使用撤销操作来恢复文件。在键盘上同时按下“C

嵌入式QT开发:构建高效智能的嵌入式系统

摘要: 本文深入探讨了嵌入式 QT 相关的各个方面。从 QT 框架的基础架构和核心概念出发,详细阐述了其在嵌入式环境中的优势与特点。文中分析了嵌入式 QT 的开发环境搭建过程,包括交叉编译工具链的配置等关键步骤。进一步探讨了嵌入式 QT 的界面设计与开发,涵盖了从基本控件的使用到复杂界面布局的构建。同时也深入研究了信号与槽机制在嵌入式系统中的应用,以及嵌入式 QT 与硬件设备的交互,包括输入输出设

JAVA智听未来一站式有声阅读平台听书系统小程序源码

智听未来,一站式有声阅读平台听书系统 🌟 开篇:遇见未来,从“智听”开始 在这个快节奏的时代,你是否渴望在忙碌的间隙,找到一片属于自己的宁静角落?是否梦想着能随时随地,沉浸在知识的海洋,或是故事的奇幻世界里?今天,就让我带你一起探索“智听未来”——这一站式有声阅读平台听书系统,它正悄悄改变着我们的阅读方式,让未来触手可及! 📚 第一站:海量资源,应有尽有 走进“智听

阿里开源语音识别SenseVoiceWindows环境部署

SenseVoice介绍 SenseVoice 专注于高精度多语言语音识别、情感辨识和音频事件检测多语言识别: 采用超过 40 万小时数据训练,支持超过 50 种语言,识别效果上优于 Whisper 模型。富文本识别:具备优秀的情感识别,能够在测试数据上达到和超过目前最佳情感识别模型的效果。支持声音事件检测能力,支持音乐、掌声、笑声、哭声、咳嗽、喷嚏等多种常见人机交互事件进行检测。高效推

【专题】2024飞行汽车技术全景报告合集PDF分享(附原数据表)

原文链接: https://tecdat.cn/?p=37628 6月16日,小鹏汇天旅航者X2在北京大兴国际机场临空经济区完成首飞,这也是小鹏汇天的产品在京津冀地区进行的首次飞行。小鹏汇天方面还表示,公司准备量产,并计划今年四季度开启预售小鹏汇天分体式飞行汽车,探索分体式飞行汽车城际通勤。阅读原文,获取专题报告合集全文,解锁文末271份飞行汽车相关行业研究报告。 据悉,业内人士对飞行汽车行业