提出问题
如果一个服务需要提供将数据推送至 kafka 的功能,不得不考虑并发的因素。在消费kafka时我们会选择使用更多的消费者以达到更高的消费效率,我们是否也需要在生产者上也需要采用这种方式呢?
初步调研
我看到了看似截然相反的两种观点:
前者认为应该只有一个实例,后者认为kafka具有无缝处理多个生产者的能力,那么当我们需要将数据推送至相同的kakfa中时,我们究竟应该使用哪种方式呢?
实践验证
验证一:多个生产者是否可以显著的提高生产效率
我们通过实现一个生产者池让服务可以更好的处理推送请求。
type ProducerPool struct {
pool sync.Pool
}
func (p *ProducerPool) Acquire() Producer {
if v := p.pool.Get(); v != nil {
return v.(Producer)
} else {
return nil
}
}
func (p *ProducerPool) Release(r Producer) {
p.pool.Put(r)
}
分别实现基于单例模式的生产者发送消息和基于生产者池的发送消息功能。
接下来利用Postman对该接口传输大量数据,在服务上层对数据进行切分,并启动新协程发送数据。
在切分的粒度上,需要尽量粗一些,防止kafka发送消息耗时远小于数据切分耗时,影响效果。
这里同时设置了一组单例模式串行不分批的发送消息,当然在这种情况下很容易因为数据量的原因导致背kafka服务器拒绝,因此需要配置相关字段的值。(这些字段基本集中在server.properties 和 producer.properties 中,都是一些关于推送量,消息体大小限制的字段)。 考虑到kakka批处理的大小影响,实验里也设置了不同的切分粒度。
根据代码运行结果,基于单例模式的生产者发送消息和基于生产者池的发送消息的总体耗时区别不大,但均低于不切分的情况。
验证二:单个生产者是否不足以满足高QPS的请求
这里使用Postman分别对两个接口以如下配置发送了少量数据
发现并没有超时的现象发生。
结论
从结果上来说,至少在相同topic时,使用一个生产者是满足需求的,对于“kafka具有无缝处理多个生产者的能力”,并没有在实验中得到验证,只能说确实可以多个生产者往相同topic推送(至于是否会乱序,这是另一个问题),但是并没有因为生产者数量的增加而导致效率有任何提高。