💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。
本人主要分享计算机核心技术:系统维护、数据库、网络安全、自动化运维、容器技术、云计算、人工智能、运维开发、算法结构、物联网、JAVA 、Python、PHP、C、C++等。
不同类型针对性训练,提升逻辑思维,剑指大厂,非常期待和您一起在这个小小的网络世界里共同探索、学习和成长。
1、简介
Fluentd 是一个开源的数据收集器,致力于为用户搭建统一的日志收集层,它可以让你统一日志的收集和消费,以便更好地使用和理解日志,统一的日志记录层可让你和你的团队更好地利用数据并更快地迭代你的应用。2、事件的基本结构
时间戳(time)
时间戳表示事件发生的时间,用于记录日志的精确时间点。时间戳的格式通常为 UNIX 时间戳,即自1970年1月1日(UTC)以来的秒数。
-
例子:在这个例子中,1692409200表示事件发生的具体时间。
"time": 1692409200 标签(tag)
标签是用于标识和路由事件的字符串,通常由多个部分组成,用点号(.
)分隔。标签帮助 Fluentd 将事件路由到合适的处理和输出路径。
-
例子:在这个例子中,nginx.access标签表示该事件可能与 Nginx 的访问日志相关。
"tag": "nginx.access"
记录(record)
记录部分包含了实际的日志数据,是一个键值对的结构。每个键表示一个字段,值是对应的日志信息。记录部分可以包含任意数量的字段,具体取决于日志源的类型和内容。
-
例子:在这个例子中,nginx.access标签表示该事件可能与 Nginx 的访问日志相关。
"record": { "host": "192.168.1.1", "user": "john", "method": "GET", "path": "/index.html", "code": "200", "size": "5120" }
3、事件的完整结构示例
完整的 Fluentd 事件
#在这个结构中,`time` 记录了事件的发生时间,`tag` 指示了事件的来源或类别,而 `record` 则包含了事件的实际内容。 { "time": 1692409200, "tag": "nginx.access", "record": { "host": "192.168.0.1", "user": "john", "method": "GET", "path": "/index.html", "code": "200", "size": "5120" } }
原始日志
192.168.0.1 - - [28/Feb/2024:12:00:00 +0900] "GET / HTTP/1.1" 200 777
经过fluentd 引擎处理完后
2024-07-16 08:40:35 +0000 apache.access: {"user":"-","method":"GET","code":200,"size":777,"host":"192.168.0.1","path":"/index.html"}
4、fluentd的buffer事件缓冲模型
Input -> filter 1 -> ... -> filter N -> Buffer -> Output因为每个事件数据量通常很小,考虑数据传输效率、稳定性等方面的原因,所以基本不会每条事件处理完后都会立马写入到output端,因此fluentd建立了缓冲模型,模型中主要有两个概念:
-
buffer_chunk:事件缓冲块,用来存储本地已经处理完待发送至目的端的事件,可以设置每个块的大小。
-
buffer_queue:存储chunk的队列,可以设置长度
可以设置的参数,主要有:
-
buffer_type,缓冲类型,可以设置file或者memory
-
buffer_chunk_limit,每个chunk块的大小,默认8MB
-
buffer_queue_limit ,chunk块队列的最大长度,默认256
-
flush_interval ,flush一个chunk的时间间隔
-
retry_limit ,chunk块发送失败重试次数,默认17次,之后就丢弃该chunk数据
-
retry_wait ,重试发送chunk数据的时间间隔,默认1s,第2次失败再发送的话,间隔2s,下次4秒,以此类推
大致的过程为:
随着fluentd事件的不断生成并写入chunk,缓存块持变大,当缓存块满足buffer_chunk_limit大小或者新的缓存块诞生超过flush_interval时间间隔后,会推入缓存queue队列尾部,该队列大小由buffer_queue_limit决定。
每次有新的chunk入列,位于队列最前部的chunk块会立即写入配置的存储后端,比如配置的是kafka,则立即把数据推入kafka中。
比较理想的情况是每次有新的缓存块进入缓存队列,则立马会被写入到后端,同时,新缓存块也持续入列,但是入列的速度不会快于出列的速度,这样基本上缓存队列处于空的状态,队列中最多只有一个缓存块。
但是实际情况考虑网络等因素,往往缓存块被写入后端存储的时候会出现延迟或者写入失败的情况,当缓存块写入后端失败时,该缓存块还会留在队列中,等retry_wait时间后重试发送,当retry的次数达到retry_limit后,该缓存块被销毁(数据被丢弃)。
此时缓存队列持续有新的缓存块进来,如果队列中存在很多未及时写入到后端存储的缓存块的话,当队列长度达到buffer_queue_limit大小,则新的事件被拒绝,fluentd报错,error_class=Fluent::Plugin::Buffer::BufferOverflowError error="buffer space has too many data"。
还有一种情况是网络传输缓慢的情况,若每3秒钟会产生一个新块,但是写入到后端时间却达到了30s钟,队列长度为100,那么每个块出列的时间内,又有新的10个块进来,那么队列很快就会被占满,导致异常出现。
5、Fluentd 事件流的生命周期
数据采集(Input)
-
事件流的生命周期从数据采集开始。Fluentd 通过各种插件(input plugins)从不同的源采集数据,比如日志文件、消息队列、数据库等。
-
每个输入插件会将采集到的数据封装成事件,该事件通常包含三部分:标签(tag)、时间戳(time)和记录(record)。
{ "tag": "my_app.access", "time": 1629808456, "record": { "message": "User login", "user_id": "1234" } }
-
标签用于标识事件的来源或类别,时间戳标记事件的发生时间,而记录则是实际的数据内容。
数据处理(Filter/Parser)
-
事件被采集后,通常需要对数据进行处理。Fluentd 支持通过 filter 和 parser 对事件进行过滤、修改、解析等操作。
-
Filter 插件可以对事件的记录进行修改,添加或删除字段,重写标签等。
<filter my_app.*> @type record_transformer <record> hostname ${hostname} </record> </filter>
-
Parser 插件则用于解析复杂格式的数据,比如 JSON、正则表达式等。
<source> @type tail path /var/log/my_app.log tag my_app.access <parse> @type json </parse> </source>
数据缓冲(Buffer)
-
在事件被处理后,Fluentd 将它们存储在内存或磁盘中进行缓冲。缓冲机制可以有效应对数据流的高峰,避免数据丢失。
-
缓冲有两种模式:
memory
和file
。内存缓冲速度快,但存在数据丢失的风险,而文件缓冲则更安全,但性能相对较低。<buffer tag> @type file path /var/log/fluentd-buffer/ flush_interval 10s chunk_limit_size 8m queue_limit_length 128 </buffer>
数据输出(Output)
-
最后,Fluentd 将处理过的事件转发到目标系统,比如 Elasticsearch、S3、数据库、甚至是另一个 Fluentd 实例。输出插件(output plugins)负责这部分工作。
-
输出插件配置可以指定目标地址、认证信息、输出格式等。
<match my_app.*> @type elasticsearch host 127.0.0.1 port 9200 logstash_format true index_name my_app_logs type_name _doc </match>
6、Fluentd 指令配置详解
Fluentd 的配置主要由指令块组成,每个指令块对应一个具体的任务,比如数据采集、过滤、缓冲或输出。常见的指令块包括:
source
-
用于定义数据输入源。可以配置采集的路径、标签、格式解析等。
<source> @type tail path /var/log/nginx/access.log pos_file /var/log/td-agent/nginx-access.pos tag nginx.access <parse> @type nginx </parse> </source>
filter
-
用于对事件进行过滤和处理。可以修改事件的记录、重写标签等。
<filter nginx.access> @type grep <regexp> key message pattern ^.*error.* </regexp> </filter>
match
-
定义数据输出目标。标签模式(tag pattern)用于匹配特定的标签,将事件发送到相应的目标。
<match nginx.access> @type s3 aws_key_id YOUR_AWS_KEY_ID aws_sec_key YOUR_AWS_SECRET_KEY s3_bucket your-bucket s3_region us-west-2 path logs/nginx/ <format> @type json </format> </match>
buffer
-
用于配置缓冲机制,控制数据在发送到目标前的存储方式。
<match nginx.access> @type file path /var/log/fluentd-buffer/ timekey 1d timekey_use_utc true </match>
7、Fluentd 事件流优化
合理配置缓冲:
-
根据实际需求,选择合适的缓冲模式和策略,确保系统在高负载下稳定运行。
标签和正则匹配优化:
-
使用高效的标签和正则表达式,减少不必要的数据处理,提升系统性能。
监控与日志:
-
配置 Fluentd 自身的监控和日志输出,及时发现问题,避免数据丢失或处理瓶颈。
插件选择:
-
根据使用场景选择合适的插件,并及时更新插件版本以利用新功能和性能改进。
8、实现业务应用日志的收集及字段解析
收集日志
#收集容器内的nginx应用的access.log日志,并解析日志字段为JSON格式,原始日志的格式。 $ tail -f access.log ... 53.49.146.149 1561620585.973 0.005 502 [27/Jun/2019:15:29:45 +0800] 178.73.215.171 33337 GET https
收集并处理成
{ "serverIp": "53.49.146.149", "timestamp": "1561620585.973", "respondTime": "0.005", "httpCode": "502", "eventTime": "27/Jun/2019:15:29:45 +0800", "clientIp": "178.73.215.171", "clientPort": "33337", "method": "GET", "protocol": "https" }
配置fluent.conf
#使用@tail插件通过监听access.log文件,用filter实现对nginx日志格式解析 [root@work01 containers]# vim /tmp/fluent.conf <source> @type tail @label @nginx_access path /fluentd/access.log pos_file /fluentd/nginx_access.posg tag nginx_access format none @log_level trace </source> <label @nginx_access> <filter nginx_access> @type parser key_name message format /(?<serverIp>[^ ]*) (?<timestamp>[^ ]*) (?<respondTime>[^ ]*) (?<httpCode>[^ ]*) \[(?<eventTime>[^\]]*)\] (?<clientIp>[^ ]*) (?<clientPort>[^ ]*) (?<method>[^ ]*) (?<protocol>[^ ]*)/ </filter> <match nginx_access> @type stdout </match> </label>
启动服务,追加文件内容
[root@work01 containers]# docker run -d --name test -u root --rm -ti -v /tmp/fluent.conf:/tmp/fluent.conf registry.cn-shanghai.aliyuncs.com/study-03/fluentd:2.5.2 sh e2d0b38bdbf17e5be3ae13aadab88d6749dab199d9732ed4ffec5d2976275e49 [root@work01 containers]# docker ps|grep test e2d0b38bdbf1 registry.cn-shanghai.aliyuncs.com/study-03/fluentd:2.5.2 "sh" 9 seconds ago Up 7 seconds 80/tcp test [root@work01 containers]# docker exec -it test sh #创建目录 / # cd /fluentd/ / # touch access.log #启动fluentd服务 / # fluentd -c /tmp/fluent.conf #手动追加内容至access.log文件 / # echo '53.49.146.149 1561620585.973 0.005 502 [27/Jun/2019:15:29:45 +0800] 178.73.215.171 33337 GET https' >>/fluentd/access.log
观察本地输出内容是否符合预期
<!--使用该网站进行正则校验:http://fluentular.herokuapp.com-->
9、总结
Fluentd 事件流的生命周期涵盖了从数据采集到最终输出的整个过程。通过合理配置各个阶段的插件和指令,能够有效地控制和优化数据流动,确保系统的稳定性和效率。在实际操作中,理解这些配置的细节和工作原理,有助于解决复杂的日志处理需求。