Kafka有更高效的存储格式。平均而言,Kafka每条消息有9字节的开销,而ActiveMQ有144字节。其原因是JMS所需的沉重消息头,以及维护各种索引结构的开销。LinkedIn注意到ActiveMQ一个最忙的线程大部分时间都在存取B-Tree以维护消息元数据和状态。
消费者测试为了做消费者测试,LinkedIn使用一个消费者获取总共1000万条消息。LinkedIn让所有系统每次拉请求都预获取大约相同数量的数据,最多1000条消息或者200KB。对ActiveMQ和RabbitMQ,LinkedIn设置消费者确认模型为自动。结果如图7所示。
图7:LinkedIn的消费者性能实验结果
Kafka性能要好很多的主要原因包括:
Kafka有更高效的存储格式;在Kafka中,从代理传输到消费者的字节更少。
ActiveMQ和RabbitMQ两个容器中的代理必须维护每个消息的传输状态。LinkedIn团队注意到其中一个ActiveMQ线程在测试过程中,一直在将KahaDB页写入磁盘。与此相反,Kafka代理没有磁盘写入动作。最后,Kafka通过使用sendfile API降低了传输开销。
目前,我正在工作的一个项目提供实时服务,从消息中快速并准确地提取场外交易市场(OTC)定价内容。这是一个非常重要的项目,处理近25种资产类别的财务信息,包括债券、贷款和ABS(资产担保证券)。项目的原始信息来源涵盖了欧洲、北美、加拿大和拉丁美洲的主要金融市场领域。下面是这个项目的一些统计,说明了解决方案中包括高效的分布式消息服务是多么重要:
每天处理的消息数量超过1,300,000;
每天解析的OTC价格数量超过12,000,000;
支持超过25种资产类别;
每天解析的独立票据超过70,000。
消息包含PDF、Word文档、Excel及其它格式。OTC定价也可能要从附件中提取。
由于传统消息服务器的性能限制,当处理大附件时,消息队列变得非常大,我们的项目面临严重的问题,JMSqueue一天需要启动2-3次。重启JMS队列可能丢失队列中的全部消息。项目需要一个框架,不论解析器(消费者)的行为如何,都能够保住消息。Kafka的特性非常适用于我们项目的需求。
当前项目具备的特性:
使用Fetchmail获取远程邮件消息,然后由Procmail过滤并处理,例如单独分发基于附件的消息。
每条消息从单独的文件获取,该文件被处理(读取和删除)为一条消息插入到消息服务器中。
消息内容从消息服务队列中获取,用于解析和提取信息。
示例应用这个示例应用是基于我在项目中使用的原始应用修改后的版本。我已经删除日志的使用和多线程特性,使示例应用的工件尽量简单。示例应用的目的是展示如何使用Kafka生产者和消费者的API。应用包括一个生产者示例(简单的生产者代码,演示Kafka生产者API用法并发布特定话题的消息),消费者示例(简单的消费者代码,用于演示Kafka消费者API的用法)以及消息内容生成API(在特定路径下生成消息内容到文件的API)。下图展示了各组件以及它们与系统中其它组件间的关系。
图8:示例应用组件架构
示例应用的结构与Kafka源代码中的例子程序相似。应用的源代码包含Java源程序文件夹‘src’和'config'文件夹,后者包括几个配置文件和一些Shell脚本,用于执行示例应用。要运行示例应用,请参照ReadMe.md文件或GitHub网站Wiki页面的说明。
程序构建可以使用Apache Maven,定制也很容易。如果有人想修改或定制示例应用的代码,有几个Kafka构建脚本已经过修改,可用于重新构建示例应用代码。关于如何定制示例应用的详细描述已经放在项目GitHub的Wiki页面。
现在,让我们看看示例应用的核心工件。