flume日志收集系统架构设计

大数据 Jenner 7131℃ 0评论
    flume是当下最为流行的日志收集工具,还有很多同类型的产品原理大多与flume相同,具体可参考:http://www.ttlsa.com/log-system/scribe-chukwa-kafka-flume-log-system-contrast/。本文会假设你已经了解了flume的原理、组件、配置及使用方法。如果对flume还不是很了解,建议先阅读官方文档:http://flume.apache.org/。我们在广告系统日志收集中大量的使用了flume,并逐渐替换了原来的日志收集脚本。本文分为两部分向大家介绍flume日志收集架构及运维与监控。

架构设计

首先讲一下我们的业务场景,前端agent大概几十台机器,负责线上服务,产生各种类型的日志。这些日志异构、流量差异较大、重要度不同。我们希望设计一套简单、可复用的日志收集系统架构。
我们的flume日志收集系统架构如下:
flume架构

flume架构

agent

前端负载机,nginx或java server产生日志,由本地flume采集。这里的业务日志,我们采用直接落盘再由flume spooling dir source采集的方式,虽然flume提供了其他socket的采集方式,但我们觉得这种方式的侵入性最小,比较符合我们的要求。这里我们使用了load_banlance的机制,避免由collector故障引起的本地日志堆积问题。
这里可能产生的问题就是source无故停止工作,造成日志堆积。解决办法:
  • 通过metrics接口监控source stop时间(没办法监控到所有情况,有时source只是不断在处理异常,并没有stop)
  • 监控source目录下文件数量,文件总大小,文件最后修改时间(最靠谱的办法)

collector A

日志收集中异地机房备份。这里做异地机房备份主要考虑如果collector B集群(所有机器都在一个机房)网络故障无法提供服务,collector A能够继续为agents提供服务,待collector B集群恢复之后,collector A再将数据传递给collector B。这时,你需要分配足够的channel空间和event数量给colletor A做故障缓冲,我们设定的是20G,你可以根据实际情况设定,保证collector A能够给你保留足够的故障处理时间。这里可能遇到的问题就是channel的性能瓶颈,由于所有日志都会传到这个节点,且这个节点仅仅是用来做故障备份不宜花费太多成本(尽量不加机器),那么方向只能是尽量提高单机IO吞吐能力了,增加硬盘,不同channel写不同硬盘,或磁盘做raid提高写能力等。

collector B

日志收集中心主集群,这个集群负责最终的日志收集、格式化、持久化等任务,首先collect B会将数据写入kafka,同时会写一份本地备份,再将数据传递给hive collect进行hdfs 持久化。需要注意的是,我们的kafka sink是使用1.6.0版本内置的,期间发现在collector节点CPU利用率非常高,使用jprofiler分析发现kafka sink占用了大多数的CPU,DEBUG发现存在死循环,有用到的童鞋要注意了。由于官网的flume版本一直没有更新,所以这个bug也会一直存在直到1.6.1或1.7发布。collector B还做了一些扩展,例如:
  • NginxSerializer,自动对nginx日志进行格式化,结果使用\t分隔
  • ChannelSelector,由于我们的日志种类非常多,如果每种日志都有单独的source,对于运维管理非常不方便。所以我们开发了ChannelSelector,原理是根据basename header(spooling dir source自动注入)将event路由到不同的channel,最终由不同的sink处理
  • TopicInterceptor,我们知道event写入kafka时,如果没有topic header,会写入默认topic,我们种类繁多的日志需要写入不同的topic,我们使用TopicInterceptor结合业务场景,对不同日志进行不同配置

在collector B集群,我们使用二次开发的safe-rolling-file-sink替代了官方的rolling-file-sink,该sink支持原子的文件移动、文件复制等功能。

hive collector

    hive数据接收器,负责向hdfs写入数据。这里没有使用collector B直接向hdfs写入数据的理由是,我们不希望由于某一个sink个故障导致整个collector B集群阻塞;例如hdfs集群故障,暂时无法写入数据,collector B就会把要写入hdfs的数据缓存在channel中,当这个channel满了之后,由于同一份日志要写三个channel(kafka channel、local storage channel、hive channel),其他channel也无法写入数据了,导致整个collector B阻塞。实践证明,hdfs节点出问题的概率较高,这种架构能够保证kafka、local storage不受影响。
同时,我们为了做到hdfs的准实时,将轮转时间调整为3分钟,这样我们可以使用hive查询准实时的数据;虽然kafka中有实时的数据,但对汇总等任务来说,并不合适。
这里我们遇到了诸多问题,列举如下:
  • 整个进程的reload、restart过程长到难以忍受,有时只能kill -9
  • 当日志量暴涨时,hdfs sink容易挂掉停止工作
  • 1.5.2的hdfs sink不稳定,升级到1.6.0后问题明显减少,但依然存在
根据以上描述,我们的架构能够保证agent的日志不会在本地堆积,collector集群高可用异地容灾,hdfs、kafka解耦,互不影响,架构高可用、可复用。

运维与监控

与之前我们自己编写的日志收集系统相比,flume虽然具有诸多方面具有优势,但同样也带来了一些蛋疼的问题。如:
  • 怎样才能知道flume是否在正常工作?
  • 怎样才能知道日志是否有延迟?
我们采用了如下的监控方案:
  • metrics监控,监控source、sink的stop time以及失败任务数等
  • flume log4j日志监控,对日志中的Exception、ERROR进行监控,这样我们才能真正的对flume运行情况有了解
  • 对其任务输入、输出进行监控,如spooling dir source目录文件、hdfs日志延迟时间等
由于在前期刚刚搭建flume集群时,我们对flume配置文件的修改比较频繁,人工发布再restart的方式太不方便;我们采用定时任务定时拉去配置文件的方式覆盖flume配置文件,flume会定时扫描配置文件,如果发生变更(文件最后修改时间),则reload所有线程。这里遇到了一个问题,如果修改的配置文件删掉了某一个source或sink,在metrics信息中,这个source或sink依然会存在,并且显示为stop状态,监控就会报红,只能restart进程解决;希望后续的flume版本能够解决这个问题。

结束语

大多使用flume的场景,稳定性往往比性能更重要,好的日志收集架构不一定性能有多突出,但一定可以做到很好的数据可靠性。完善的日志收集系统需要不但演化,需要有完善的监控体系等等。

原创文章,转载请注明: 转载自始终不够

本文链接地址: flume日志收集系统架构设计

转载请注明:始终不够 » flume日志收集系统架构设计

喜欢 (2)