一、简要介绍
log_pipe是一个高性能的日志收集分析系统,从13年11月第一版上线以来,已经在阿里内部有了广泛的使用,目前在日志最为繁忙的CDN节点内部已经部署超过20个节点,用于对CDN的访问日志以及其他日志做接收和实时分析。它能够接收从各个服务器发过来的日志,并且支持对日志做实时分析和内存压缩,然后按照配置存放到磁盘的不同路径下。
在我设计和开发log_pipe之前,面临着各种选型,最开始使用的是syslog-ng,但随着去年开始推全量日志以后,很快就发现syslog-ng存在严重的性能瓶颈,已经满足不了CDN日志的需求,另外因为syslog-ng不能对日志做实时分析,我们需要把写到磁盘的日志又重新读出来,这对磁盘IO造成了严重的浪费,所以很快就放弃了syslog-ng的方案。在boss的鼓励下,我开始了解集团内外的各种日志系统,也对我们自己的CDN有了更新的认识。目前每天CDN的日志超过70TB,这几乎比集团内所有其他日志系统接收的日志加起来还多一倍,并且这些日志分布在全国各地。所以几乎没有人欢迎我们接入,因为这对谁的系统都是大大的负担。后来我开始了解facebook的scribe,不过我很快就放弃了,因为scribe的安装要依赖一堆的包,简直是反人类,当时我就想如果要把这玩意推到我们的CDN节点,我需要跟运维打多少嘴仗啊。。。哈哈,而且scribe同样没有实施分析的功能。后来boss问我,我们要不要自己搞一个日志服务器,我觉得也好,然后7月份就正式立项了。
二、log_pipe的主要特点
1、支持对接收的日志做实时分析。实时分析部分的编写是模块化的,只需要按照模块编写说明实现相应的接口调用,然后会编译成静态so文件,在配置中做个简单的配置log_pipe就可以在启动的时候把实时分析模块加载进来对新的日志做实时分析。
2、支持对日志数据压缩写磁盘。采用的是块压缩算法lzo,并且在内部支持多线程压缩,压缩速度上单线程可以到150MB/s
3、高性能。如果log_pipe还满足不了你对日志server性能的要求,估计没有server可以满足了,这个真不是自吹自擂。log_pipe的底层是基于libev,我在线上实际压力测试的时候,一分钟接收、分析和压缩了36GB的日志。当然这个我们的日志机器性能比较好也有关。目前40Gbps的CDN带宽下,log_pipe所占的CPU不超过10%。
4、有一套实时控制接口。可以支持对日志做实时过滤,非常方便管理员排查错误,比如下面这行命令:
1 sudo /home/cdn/log_pipe/log_pipe -s "type=add_task;source=tengine_cdn;condition={col3 like img01.taobaocdn.com; col4 > 400; col13 like {Windows NT 6.1};}; stat_interval = 600; output_name = http_err.log;"
表示对数据源名称是tengine_cdn的日志源做过滤,把httpcode大于400,url包含img01.taobaocdn.com并且UserAgent的日志过滤出来一份存好到http_err.log文件中。
三、架构
如上图所示,在log_pipe用多种功能的线程,分别包括
1、日志接收线程组:主要负责日志接收任务,支持多种协议(TCP/UDP/管道/TCP带日志协议)
2、日志压缩存磁盘线程组:这部分线程主要负责压缩日志并且把压缩日志写到磁盘(当然也可以配置趁不压缩写磁盘)
3、实时分析线程组:对于需要分析的日志,会这这部分线程中被已经挂载的各个分析模块做实时分析,同时实时过滤部分也在这部分线程中完成
4、日志轮转管理线程:管理各个日志文件fd,log_pipe本身支持对日志文件做定期或者按大小等多种轮转方式,这部分管理都有这个线程操作,对压缩和分析线程是透明的
5、实时指令和实时过滤线程:这部分主要来处理管理员实时发过来的过滤日志指令。
6、其它的一些管理线程
四、安装部署
log_pipe的安装部署非常简单,只依赖libeasy-devel包,装上libeasy-devel后,直接rpm安装就能自己跑起来
五、配置
配置部分也非常简单,比如下面这是一份完整的配置
1 access_log = "/tmp/log_pipe.log"; 2 data_dir = "/home/cdn/log_pipe/data"; 3 log_level = info; 4 5 #-----------------日志接收源 home_log--------------------- 6 log{ 7 source_name = "home_log"; #唯一标识这个数据源,用于运行时外部控制 8 log_proto = "tcp";#日志接收协议 9 port = 1305;#端口 10 log_path = "/opt/squidlog/cdn_access.log";#日志要存放到哪个目录 11 rotate_size = 1000MB;#日志轮转临界条件 12 } 13 14 #----------------------cdn access log-------------- 15 log{ 16 source_name = "cdn_log"; #唯一标识这个数据源,用于运行时外部控制 17 app_id = 1;#对于有日志协议的日志,需要指定业务id 18 log_proto = "scroll"; #tcp带日志协议 19 port = 1302; 20 log_path = "/opt/squidlog/cdn.log"; #日志输出路径 21 rotate_interval = 28800; #日志轮转周期 跟下面的rotate_size和rotate_code共同起作用 22 rotate_size = 1000MB; #日志文件大小轮转条件 23 rotate_code = "OR"; 24 rotate_name = "comp_mode";#轮转后的日志文件命名方式 25 log_type = "unify"; #对于rotate_name = comp_mode的情况需要指定log_type前缀 26 lzo = "on"; #日志是否开启实时压缩 27 28 analyze_module{ 29 module_name = "mod_cdn_common"; #要加载的分析模块 30 } 31 32 analyze_module{ 33 module_name = "mod_cdn_access"; 34 result_interval = 300; #分析统计周期,每个周期系统会调用相关的output函数输出统计结果 35 result_path = "kunlun"; #统计结果输出子路径,跟全局配置data_path 共同起作用 36 } 37 }
这个配置一共定义了两个数据源,1~3行是全局的配置, log块括住的是一个数据源的配置,5~12定义了一个完整的日志接收源,非常简单我就不做解释了。
15~37行定义了另一个数据源,稍微复杂一些,其中21~25配置了更加复杂的轮转方式,28~37定义了2个实时分析模块,分别对数据做相关的分析,总体来说配置非常简单。