实时统一日志采集Flume平台化
针对原生Flume在生产环境中暴露的问题,在开源Flume1.6.0版本上做了深度定制和部门内部统一推广:
1. 与开源版本区别
模块 |
Flume1.6 |
Flumex-Agent |
功能 |
1.低侵入性: 会对业务方日志文件重命名 |
1.无侵入性 |
2.休眠轮询: 占用线程&&限制采集文件的并行度 |
2.轻量级:基于Linux的inotify机制采集 |
|
3.数据不完整性:基于file的full-name采集 |
3.数据完整性:基于inode的日志采集 |
|
4.不支持目录递归 |
4.支持目录递归 |
|
性能(单文件吞吐) |
2M/s: 按行或byte采集,效率低 |
10M/s: 根据采集进度按byte或block动态采集 |
运营 |
1.状态被动收集:自身基于server端服务的定向请求 |
1.状态主动推送:基于client端的状态心跳推送 |
2.无采集元数据备份 |
2.采集日志元数据备份: 可以记录和查询历史任一时间段内采集的文件列表、 文件数及采集文件的size、offset信息 |
2. 功能扩展
2.1. 支持file-channel可靠性采集模式
目前由于file-channel采集性能瓶颈, 所以采用memory-channel模式,两者采集能力对比如下:但memory-channel是会在服务异常中断或宕机场景时存在着日志丢失的风险。产品线上计划数据可靠性优先,所以会采用file-channel模式,其次对采集效率进行优化。
channel方式 |
readByByte |
memory-channel |
1800 |
file-channel |
1400 |
2.2. 支持单实例多目录多topic采集方式
目前支持单topic的日志采集,待支持类似向上多topic多目录的并行采集,配置初步设计如下:
agent.sources.s1.topicGroups
= t1 t2 agent.sources.s1.topicGroups.t2.topic = topic2 |
2.3 支持采集消息的定制字段追加,如host、appid等
由于上游agent采集的业务应用方较多,为了方便下游离线或实时地对消息进行分类统计分析,对采集消息的内容,agent具有进行有约束的制定字段增加功能。 增加的定制字段有:a既定的变量, 如appid、t、host。
a. 配置样例如下:
%{appid}%{t}%{host}%{data}
b. 相应消息样例如下:
appid= test- product` t=1479089921875`host=localhost`deviceId=VSMjTvvy9CgDAE`messageId=`action=register_dt`logTime=1477911600905`msgCount=1`
3. 性能改善
3.1. 目的
a. 采用可靠性file-channel采集模式,保证采集数据的稳定性、日志可靠性(不丢失);
b. 提升file-channel采集模式日志采集效率,提升5倍。 目前测试单日志文件memory模式采集能力1800行/S;
c. 支持异步memory-channel性能采集模式,提升20倍采集效率。
3.2. 目前现状
采集的方式与flume原生的tail-log采集方式类似,按Byte逐行读取的采集模式; 当 file-offset ≈ file-size时,即日志文件的消费速率与其内容的生产效率相当时,这样可以保证log采集的实时性; 实测其性能 1500Events/s。
3.3. 存在问题
但其存在性能瓶颈:假设机械磁盘的一次顺序读时间0.01ms,每行消息内容100个Bytes,则其IOPS性能上限:100000个Bytes/s = 1000Events/s; 所以当file-offset << file-size时,特别是在采集业务高峰时nginx运营日志情景时,会出现日志文件的消费速率会远小于其内容的生产效率,导致采集消息严重滞后。
3.4. 修改策略
采用实时动态调整采集方式的策略:
a. 当file-offset ≈
file-size时,采用readByByte采集模式;
b. 当file-offset
<< file-size时,采用readByBlock采集模式,提高采集吞吐量。
3.5. 优化后结果对比
channel方式 |
readByByte |
readByBlock |
memory-channel |
1800 |
20000 |
file-channel |
1400 |
15000 |
3.6. 支持同步/异步两种采集模式
另外,采集每批消息耗时主要由三部分组成: read-log(1ms) + write-channel(1ms) + write-metaDB(4ms)。为了保证数据可靠性:每一批读取日志数据后的游标元信息会sync同步到sqlite中,其耗时占比达60%,所以每批消息的大头在write-metaDB操作上。
为了支持不同的业务场景需求,服务支持”性能模式”,支持write-metaDB的异步写模式,同时会在异常关机情况时的数据丢失。下面是两种采集模式的采集效率对比:
采集模式 |
采集效率 |
吞吐能力 |
可靠模式(同步) |
15000行/s |
1.5M/s |
性能模式(异步) |
100000行/s |
10M/s |
3.7. 消息大小与采集能力关系图
线上服务已“可靠性”优先,所以会采用可靠模式。下面实验可靠模式下:不同消息字节大小与服务采集能力的关系图:
4. 产品服务化
4.1. 监控模块
支持source输入与sink输出两维度信息的状态内容汇报,采集agent周期性地汇报采集状态给dashboard服务中心, 上传字段内容以Json格式上报。心跳周期:1min;传输协议:http-post。上报字段说明如下:
a. 汇报状态字段说明
字段 |
说明 |
host |
采集点的机器名或ip名 |
appId |
采集日志的业务标示 |
receivedEventCount |
探测接收到的事件数 |
acceptedEventCount |
成功录入的事件数 |
receivedBatchCount |
探测接收到的事件批次数 |
acceptedBatchCount |
成功录入的事件批次数 |
attemptSendEventCount |
尝试下游发送的事件数 |
successSendEventCount |
成功下游发送的事件数 |
acceptedWindowEventCount |
一个时间窗口接收到的事件数 |
sendWindowEventCount |
一个时间窗口发送出的事件数 |
b. 汇报状态字段样例
{ "host":"uaerouter5-vm01", "appId":"test-new-product", "receivedEventCount":"137136", "acceptedEventCount":"137136", "receivedBatchCount":"4073", "acceptedBatchCount":"4073", "attemptSendEventCount":"137136", "successSendEventCount":"137136",
"acceptedWindowEventCount": "11000", "sendWindowEventCount": "10000“ }
4.2. 配置与部署
a. 支持本地配置的参数变化&动态监听&程序模块级别重启
b. 支持配置中心的统一程序包分发与部署