skoo's notes

努力记录一些自己觉得有趣的东西...
02 April 2014
by skoo

一年以前我们在着手为阿里集团内部实现一个日志运维平台的时候,mozilla开源了Heka这个工具,当时由于我们的理念和Heka不太一致,也就没有过多的参考它、甚至是使用它。(当然,我们的日志运维平台最终并没有做太成功;现在来看,当初没借鉴Heka是一个不太正确的选择)。今天我在从事CDN调度系统开发的过程中,发现我们的一个子系统以及一些工具好像挺适合用Heka来做。于是我再次深入研究了一下Heka和阅读了其5,6K行的核心源码。

Heka 是一个高可扩展的数据收集和处理工具。它的可扩展性不仅仅是体现在程序本身可以进行插件开发、更可以方便的通过添加机器进行水平扩展。Heka是一个使用Go语言开发的工具,大量使用了Go的goroutine并发和channel通信,通过我们做日志平台的经验来看,一般情况下性能问题不需要太多的顾虑。

Heka程序的可扩展性体现在它的插件开发上。Heka核心是Go语言开发,其插件理所当然的可以采用Go语言开发,当然你还可以通过lua来开发插件,如果你更喜欢写lua的话;lua开发的插件具备热更新的能力,也就是修改了lua插件的代码,并不需要重启Heka进程,在某些应用场景下,热更新具备很强的竞争力。根据实际的应用需求,可以为Heka开发4种类型的插件,这4种插件就构成了Heka的整体结构和功能,所以Heka的核心代码量(非插件)只有5,6K行。可开发的4种插件分别是:Input、Decoder、Filter、Output。

Input插件就是Heka的数据输入源。假设需要从一个日志文件读入数据,那就只需要开发一个从日志文件读取日志数据的Input插件即可。值得开心的事情是,Heka已经默认自带了多个Input插件,可以满足大部分数据来源的需求。自带的LogstreamerInput插件就是用来从日志文件实时读入数据用的,它支持读取各种rotate规则的日志文件路径;HttpInput插件可以间断式的通过访问一个URL地址来获取数据,比如:Web服务器的7层健康检查场景就可以使用HttpInput插件来探测。HttpListenInput插件会启动一个Http服务器接收外部访问来获取数据,比如:通过curl等命令直接将数据post到Heka;还有两个比较重要的Input插件:分别是TcpInputUdpInput,有这两个插件外部程序就可以通过TCP/UDP将数据发送给Heka。http://hekad.readthedocs.org/en/latest/config/inputs/index.html, 这里可以看到Heka提供的全部Input插件和详细使用方法,大部分情况都不需要自己开发Input插件了。

Decoder插件,各种Input插件负责将原始数据送入到Heka内部,这些数据一般来说都是具备一定的格式,比如:Nginx access日志、Syslog协议数据、自定义的数据格式等等,Decoder插件干的事情就是将Input插件输入的一个个的原始数据消息给解析一遍,最终得到一个结构化好的消息,不再是一个非结构化的原始数据消息。结构化的消息更利于编程进行处理。http://hekad.readthedocs.org/en/latest/config/decoders/index.html,这里例举了Heka自带的所有Decoder插件,我最关注的插件是:Nginx Access Log DecoderSyslog Decoder,这两个插件都是Lua开发的。注意,每个Input插件得有一个Decoder插件负责对输入的数据进行解析到结构化的程度

Filter插件干的事情就是负责具体的数据分析、计算任务。Heka默认也带了好几个Filter插件,但都不是我的菜,绝大多数时候,可能都需要我们自己根据应用需求开发自己的Filter插件来完成数据分析、计算工作。

OutPut插件负责将Heka内部的一个个消息输出到外部环境,比如:文件、数据库、消息队列等;注意,也可以通过TcpOutput将消息输出到下一个Heka继续处理,这样就可以部署成多机分布式结构,只要有必要。

通过4种类型的插件,基本可以了解到Heka是基于Pipeline方式对数据进行实时处理。除了可以开发4种插件以外,Heka还提供了一个很高端的机制——message matcher,message matcher是应用在Filter和Output两种插件身上,它主要是用来指定哪些消息由哪些插件(Filter/Output)处理。有了message matcher机制就可以通过配置文件实现不同的数据由不同的Filter进行计算、不同的Output输出到不同的外部环境。没有message_matcher,Heka的价值就会大打折扣了。

#####Heka’s Agent/Aggregator架构

Heka可以通过配置文件部署成为不同的角色,实际上它们都是同一个二进制程序。上图中的圆形组件Heka担任的是Agent角色,而矩形组件Heka担任的是Aggregator角色。假设每个Agent部署在不同的主机上,使用LogstreamerInput插件负责监控、采集Nginx Access日志,然后将日志数据通过Nginx Access Decoder插件进行解析,最后通过特定的Filter插件做一些分析、计算工作,最终的计算结果再通过TcpOutput插件发送到扮演Aggregator角色的Heka进行聚合、汇总计算从而得到所有主机的日志计算结果。Heka具备这样的一个扩展架构,可以非常方便的将计算任务分摊到多机,从而实现类MapReduce,当然Heka仅仅只是一个轻量级的小工具,不是一个分布式计算平台。

#####Heka’s Agent/Router架构

除了Agent/Aggregator架构外,还可以把Heka当做一个Router来使用,图中圆形组件Heka还是Agent,每个Agent负责采集不同的数据发送给矩形组件Heka,也就是Router。Heka Router可以通过message matcher机制将不同的数据输出到不同的外部存储等,从而实现一个Router的功能。当然,上面的两种架构也是可以混合到一起使用的,Heka的系统级扩展性还是足够灵活的。Agent/Router架构其实非常像淘宝开源的DataX工具(DataX是由淘宝 @泽远 同学领导开发的一款各种存储间数据交换的瑞士军刀。DataX也是支持各种插件开发,可以通过插件实现MySql数据同步到Oracle、Oracle同步到MySql、Mysql同步HDFS等等),在没有DataX以前,就是各种存储间同步的独立工具,由不同的人开发,使用方式也完全不一致,零散的小工具极其不友好。在一个灵活、可扩展的工具上面,进行扩展开发实现各种业务需求,可以让系统的运维更加的友好,部署、使用方式也更加的一致。

Heka能够自定义Input/Output插件,再配合message matcher机制,我认为这才是最具想象力的部分。输入输出是直接和外部交互,有了扩展外部交互的能力,我就可以将一切零散的小工具(各种脚本等)整合起来,统一维护,从而实现出一整套完整的应用逻辑;就好比Nginx一样,各种Http相关需求都可以通过开发模块来实现,最后将多个模块组合起来就构成一个完整的应用解决方案。

最后,还是轻量,足够轻量运维成本才足够低。