技本功丨骚操作:教你如何用一支烟的时间来写个日志采集工具

2024-06-14 20:18

本文主要是介绍技本功丨骚操作:教你如何用一支烟的时间来写个日志采集工具,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

作者:良辰
袋鼠云日志团队
后端开发工程师

 

我放下了手中的键盘,陷入沉思,

作为一个优秀的程序猿最重要的就是

气~势~

泰山崩于前的镇~定~

 

我用最快的速度扫描了一遍现行的

filebeat、fluentd、flume、

scribe等解决方案,

发现,没有机会,

难道就这样放弃了吗?

 

不,没有什么可以难倒我良辰!

 

我从口袋里掏出一根烟,

在烟雾缭绕中我缓缓看向小马哥

如何唯一标识一个文件

从需求角度来讲,用户往往需要采集指定目录指定格式下的文件,常用方式是配置路径通配符,例如这样: /path/*/*.log,意思就是收集/path/a/web.log、/path/b/web_2018-12-11.log等日志。但是,用文件名来标识文件是不准确的,移动一个文件mv a.log b.log,虽然名称是变成了b.log,但实际日志依旧是a.log的日志,把b.log当做新文件处理就会出现采集到重复日志的问题。

那换成inode作为文件唯一标识怎么样?答案是,会好点。为啥是好一点而已呢,原因有2个,一是不同文件系统间的不同文件inode可以一样,二是同个文件系统下,不同时刻存在的文件inode可以一样。这2个问题都可以导致读取日志时的偏移量错乱问题,最终导致数据丢失或者数据重复。

 

那换成内容前缀的方式唯一标识怎么样?内容前缀指的是使用文件前N个字节作校验。很显然,这也是一个缓解的操作,因为不同日志依旧有出现相同校验码的情况。这里的校验码算法可以使用crc32或者adler32,后者相比前者可靠性弱一点,性能则是前者的2~3倍。

目前最靠谱的方式是通过inode+内容前缀的方式唯一标识文件,虽然没办法完全解决唯一标识文件的问题,但鉴于同个文件系统不同时刻产生的文件刚好内容前缀有相同的情况概率比较低,所以该方案已经符合业务使用了。

 

如何监听文件变化

当新增、删除、修改文件时,如果获知快速获知变化?一种方式是使用linux的inotify机制,文件发生变化会立马通知服务,这优点是实时性高,但缺点是相同通知过于频繁反而提高了开销,另外不是所有系统都含有inotify机制。另一种方式是用轮询,轮询的实时性会差点,因为考虑性能,一般轮训间隔在1s~5s,但好在简单且通用。

 

如何合并日志

有时用户有合并日志的需求,比较常见的就是异常堆栈信息,一行日志被换行符分割成了多行。因为日志都是有规范的,会按时间、日志等级、方法名、代码行号等信息顺序打印,那这里一个简单的处理方式就是使用正则匹配的方式来解决,按照匹配行作split划分日志。

但一些偏业务的日志,就不能简单地通过正则匹配了,这类日志的内容是存在着关联关系的,像订单信息,日志需要通过订单id进行关联的,但由于多线程并行写日志等原因,逻辑上存在关联的日志在物理上未必连续,所以要求合并逻辑具有"跳"行关联的能力,这时候可以利用可命名的正则捕获功能来处理,把捕获的字段作为上下文在上下游日志传递,把匹配的日志存到缓存统一输出即可。

 

如何实现高吞吐

批量化处理,一是日志读取批量化,虽然读取日志已经是顺序读了,但如果在读取时通过预读取提前把待读取的日志都读取出来放进buffer,这方式可以进一步提升性能。二是发送批量化,发送批量化的好处主要体现在2方面,一方面是提高压缩比,像日志这类存在大量重复内容的数据,数据越多压缩比越高,另一方面,降低了请求头部的大小占比,减少带宽的浪费。

异步化处理,文件监听、日志处理、日志发送3个模块解耦并异步化,数据及通知通过队列传递。

非阻塞发送,发送端要处理的常规操作包括参数校验、序列化、压缩、协议包装、ack、重试、负载均衡、心跳、校验和、失败回调、数据收发、连接管理。如果这系列操作都是由一个nio线程处理掉,发送效率肯定很低,但考虑到通常数据接收端数量不会太多(小于1000),所以这里使用reactor的多线程模型完全足够了,netty支持reactor多线程模型的,所以可以直接基于netty开发。这里只需要注意io线程除了连接管理,其余事情都交由工作线程处理就行。

 

如何实现资源控制

采集工具往往需要和待采集日志的系统放在同一个机器上,不少系统还对性能敏感的,这就要求采集工具必须有控制资源使用的能力。

如何控制句柄使用?句柄使用往往是被严格受限的,但如果机器需要监听上万上十万的文件时,如何使用句柄?这时候就需要采取惰性持有策略,即文件生成的时候不会持有句柄,只有尝试读取时再持有句柄,由于同时读取的文件往往不多,从而只会占用少量文件句柄。

另外,存在句柄引用的文件即便被删掉,空间是不会被释放掉的,导致长时间持有句柄是不是会有磁盘被打爆的风险?这就需要加上相应的定时释放句柄的机制,被删除的文件会加上一个时钟,时钟倒计时为0时把句柄释放掉。 

如何控制内存使用?无论是日志的合并还是批量化操作,都需要使用较大的缓存,一旦缓存过大,就有oom的风险,所以需要机制控制内存占用。这里可以简单实现一个内存分配器,分配器内部维护一个计数器,用于记录当前分配内存大小。线程分配关键内存或者释放内存都需要请求内存分配器,内存超限则挂起请求的线程,并用等待/通知机制让线程协同起来。把分配内存的大户控制住,就可以控制住整体内存大小了。

如何控制流量及cpu? 流量过大不仅占用多高带宽,而且流量与cpu占用也呈正比关系,所以控制流量的同时也就实现了cpu的控制。在固定窗口、滑动窗口、令牌桶、漏桶几个流控算法中,令牌桶和漏桶算法都可以令流速较为平滑,而且guava实现了令牌桶算法。这里直接使用guava的RateLimiter即可。

 

我看了一眼手上烧完的烟,

时间刚刚好。

良辰说

在实际应用中,仍旧会遇到各种各样的问题,一方面是来自于业务的扩展性需要,另一方面是随着集群的扩大,在数据热点、实时性、弹性负载均衡方面会遇到诸多复杂的挑战。本文仅提供开发采集工具常见问题的解决思路,更深入的细节需要读者实际去探索了。

这篇关于技本功丨骚操作:教你如何用一支烟的时间来写个日志采集工具的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

服务器集群同步时间手记

1.时间服务器配置(必须root用户) (1)检查ntp是否安装 [root@node1 桌面]# rpm -qa|grep ntpntp-4.2.6p5-10.el6.centos.x86_64fontpackages-filesystem-1.41-1.1.el6.noarchntpdate-4.2.6p5-10.el6.centos.x86_64 (2)修改ntp配置文件 [r

高效录音转文字:2024年四大工具精选!

在快节奏的工作生活中,能够快速将录音转换成文字是一项非常实用的能力。特别是在需要记录会议纪要、讲座内容或者是采访素材的时候,一款优秀的在线录音转文字工具能派上大用场。以下推荐几个好用的录音转文字工具! 365在线转文字 直达链接:https://www.pdf365.cn/ 365在线转文字是一款提供在线录音转文字服务的工具,它以其高效、便捷的特点受到用户的青睐。用户无需下载安装任何软件,只

【Linux 从基础到进阶】Ansible自动化运维工具使用

Ansible自动化运维工具使用 Ansible 是一款开源的自动化运维工具,采用无代理架构(agentless),基于 SSH 连接进行管理,具有简单易用、灵活强大、可扩展性高等特点。它广泛用于服务器管理、应用部署、配置管理等任务。本文将介绍 Ansible 的安装、基本使用方法及一些实际运维场景中的应用,旨在帮助运维人员快速上手并熟练运用 Ansible。 1. Ansible的核心概念

flume系列之:查看flume系统日志、查看统计flume日志类型、查看flume日志

遍历指定目录下多个文件查找指定内容 服务器系统日志会记录flume相关日志 cat /var/log/messages |grep -i oom 查找系统日志中关于flume的指定日志 import osdef search_string_in_files(directory, search_string):count = 0

我在移动打工的日志

客户:给我搞一下录音 我:不会。不在服务范围。 客户:是不想吧 我:笑嘻嘻(气笑) 客户:小姑娘明明会,却欺负老人 我:笑嘻嘻 客户:那我交话费 我:手机号 客户:给我搞录音 我:不会。不懂。没搞过。 客户:那我交话费 我:手机号。这是电信的啊!!我这是中国移动!! 客户:我不管,我要充话费,充话费是你们的 我:可是这是移动!!中国移动!! 客户:我这是手机号 我:那又如何,这是移动!你是电信!!

超强的截图工具:PixPin

你是否还在为寻找一款功能强大、操作简便的截图工具而烦恼?市面上那么多工具,常常让人无从选择。今天,想给大家安利一款神器——PixPin,一款真正解放双手的截图工具。 想象一下,你只需要按下快捷键就能轻松完成多种截图任务,还能快速编辑、标注甚至保存多种格式的图片。这款工具能满足这些需求吗? PixPin不仅支持全屏、窗口、区域截图等基础功能,它还可以进行延时截图,让你捕捉到每个关键画面。不仅如此

MiniGPT-3D, 首个高效的3D点云大语言模型,仅需一张RTX3090显卡,训练一天时间,已开源

项目主页:https://tangyuan96.github.io/minigpt_3d_project_page/ 代码:https://github.com/TangYuan96/MiniGPT-3D 论文:https://arxiv.org/pdf/2405.01413 MiniGPT-3D在多个任务上取得了SoTA,被ACM MM2024接收,只拥有47.8M的可训练参数,在一张RTX

批处理以当前时间为文件名创建文件

批处理以当前时间为文件名创建文件 批处理创建空文件 有时候,需要创建以当前时间命名的文件,手动输入当然可以,但是有更省心的方法吗? 假设我是 windows 操作系统,打开命令行。 输入以下命令试试: echo %date:~0,4%_%date:~5,2%_%date:~8,2%_%time:~0,2%_%time:~3,2%_%time:~6,2% 输出类似: 2019_06

动手学深度学习【数据操作+数据预处理】

import osos.makedirs(os.path.join('.', 'data'), exist_ok=True)data_file = os.path.join('.', 'data', 'house_tiny.csv')with open(data_file, 'w') as f:f.write('NumRooms,Alley,Price\n') # 列名f.write('NA

线程的四种操作

所属专栏:Java学习        1. 线程的开启 start和run的区别: run:描述了线程要执行的任务,也可以称为线程的入口 start:调用系统函数,真正的在系统内核中创建线程(创建PCB,加入到链表中),此处的start会根据不同的系统,分别调用不同的api,创建好之后的线程,再单独去执行run(所以说,start的本质是调用系统api,系统的api