在.NET环境下使用KAFKA
近日基于项目的解耦与削峰需求,决定在项目中引入消息队列。因为同时项目部分业务已经迁移到Java上,所以消息队列组件又要兼顾Java环境下的使用,选来选去对比了RabbitMQ、RocketMQ和Kafka,最后还是决定使用Kafka。Kafka原是Linkin的日志收集组件,慢慢的已经发展成为了一个具有消息队列/存储/流处理功能的的高效组件,需基于Zookeeper使用。我们项目因Dubbox已经有现成的Zookeeper可供使用,同时又有日志收集的需求,所以就选它了。
选定了组件后,Java是亲生儿子,组件的支持当然不在话下,而.Net环境下就有那么一点尴尬,没有官方客户端支持,只有几个在github上的开源项目可供使用。如果你在几个开源项目中一眼就看见了金光闪闪的Maintainer: Microsoft,那么十有八九你也入坑了。
CSHARPCLIENT-FOR-KAFKA
Microsoft提供的客户端,这个开源项目文档缺失、源代码复杂且注释少得可怜,连最基本的Producer和Consumer都不得不去把整个项目clone下来去看项目的Demo是怎么实现的。项目依赖.Net Framework 4.5,依赖ZookeeperNet,而ZookeeperNet组件依赖log4net,但是因为ZookeeperNet很久未更新,他依赖的log4net是使用oldkey的版本(<=1.2.10),而项目中原有的项目中有组件(Log4mongo)依赖的log4net版本是newkey的版本(>1.2.10)。编译时会报这个错 Could not load file or assembly 'log4net, Version=1.2.10.0, Culture=neutral, PublicKeyToken=692fbea5521e1304'
光折腾这个log4net的问题就花了大半天,最后还是把log4mongo的源码作为项目引用,然后把整个项目的newkey的log4net引用全部改成了同版本号的oldkey的引用才可以编译通过。 然而一切才刚刚开始,我这边的情况是Zookeeper部属在内网的一台测试机上ip地址192.168.1.123,而Producer和Consumer布在我的开发机上(ip:192.168.1.124)。 我跑Demo时按照下面这种写法,居然报了一个UnableToConnectToHostException
,最后导入源码才发现这货将ip解析为机器名,然后通过机器名加端口去连……WTF! 当然,知道是什么原因后,改下host就解决了。
var brokerConfig = new BrokerConfiguration() { BrokerId = 0, Host = "192.168.1.123", Port = 9092 };
好不容易终于可以生产和消费了,但是我们是有集群需求的,看到布多台Consumer的实例代码我又懵逼了。我就不贴出来了,有兴趣的可以去感受下。
总之后来我跑起来了BalanceConsumer的示例。但是发现有时Producer产生的消息Consumer偶尔会接收不到,不知道我自己代码写错了还是partition什么的没配置好还是这个破Microsoft客户端本来就有这个问题。总之我已然崩溃……手头上又有别的事,决定先把这货丢到一旁。
事情过了大半个月,再次准备死磕的时候发现有个issue有更新,说有用NodeJS客户端封装的解决方案,以及推荐了另外一个.Net客户端rdkafka-dotnet。
RDKAFKA-DOTNET
rdkafka-dotnet是一个基于C++客户端librdkafka的.Net客户端,官方对librdkafka的介绍是
Robust high performance C/C++ library with full protocol support
总之就是健壮/高性能/全协议/全版本支持,可想而知基于librdkafka衍生的.Net客户端也不会差。 笔者使用rdkafka-dotnet后,发现也会需要修改host文件,其他的Producer/Consumer的代码都非常简洁易懂,消费集群也非常容易配置,而且使用这个后根本就没碰到过Consumer接收不到消息的情况。
想说的
其实Apache有和CSharpClient-for-Kafka一起列出rdkafka-dotnet,只是我被耀眼的Microsoft迷惑了,别的项目看都没看,也是自己对kafka不了解才走这么多冤枉路,就当时间买个教训了。以后多试多看多学吧!