最近在测试kafka性能的时候特别对kafka的producer端进行了一些扩展,本想着针对多个业务开发多个producer进行并行的生产数据,并通过统一的线程池进行管理,结果在用jconsole进行观察的时候,发现线程数一路飙升。
本以为一个简单的发送端程序却花了不少精力。造成线程上涨的主要原因是有两个线程对象不断的被创建,并且暂时无法销毁。一个叫sendThread,另一个叫eventThread。并且由于这两类线程驻留在线程池内,也无法回收线程资源。
在google中很容易找到这两个线程的来源,zookeeper。ZkClient去连接zookeeper的server时候都会创建sendThread和eventThread两个线程,其中sendThread主要用于client与server端之间的网络连接,真正的处理线程由eventThread来执行。Zookeeper是一个分布式的协调框架,而分布式应用中经常会出现动态的增加或删除节点的操作,所以为了实时了解分布式整个节点的数量和基本信息,就有必要维护一个长连接的线程与服务端保持连接。另外zookeeper连接时占用的时间也比较长,如果每次生产数据时都连接发起一次连接势必造成了大量时间的耗费。
所以推荐将producer端改写成单例模式,有助于减少zookeeper端占用的资源。Producer自身是线程安全的类,只要封装得当就能最恰当的发挥好producer的作用。
另外producer分同步producer和异步producer两种发送方式,基本代码都相似,只需要在创建对象的时候new不同的对象即可。如果需要较高的实时性,则推荐使用同步方式发送数据,如果对实时性要求并不高则可采用异步方式发送数据,降低系统的开销。