节点kafka使用者按顺序处理消息

时间:2017-04-19 19:41:19

标签: node.js apache-kafka

我想要使用节点应用程序使用kafka主题。节点应用程序必须按顺序逐个处理主题中的消息,而不是同时处理多个消息。

我试过这种代码,但这并不是我想要的。当主题中的消息等待处理并且此代码启动时,将立即触发所有消息的on“message”事件。第一条消息首先获取互斥锁,但其余消息按随机顺序处理。

var mutex = require( 'node-mutex' )();
var crypto = require('crypto');
var mutexToken = crypto.randomBytes(64).toString('hex');
var kafka = require('kafka-node');
var Consumer = kafka.Consumer;
var client = new kafka.Client('localhost:2181');
var consumer = new Consumer(
        client,
        [
                { topic: 'my_topic' }
        ]
);
consumer.on('message', function(message) {
        console.log("new message")
        mutex
                .lock( mutexToken )
                .then( function( unlock ) {
                        console.log(message);
                        unlock();
                } );
});

是否可以同步消耗消息?也许还有其他一些图书馆?

1 个答案:

答案 0 :(得分:0)

我相信您可以通过明确禁用autoCommit功能直接控制消息偏移。

以下是消费者文档的链接:

以下是autoCommit设置示例的链接:

我从来不需要禁用autoCommit功能,所以我不能说实现。

从测试代码看起来它应该是这些内容:

var Offset = kafka.Offset;
var offset = new Offset(client);
var topics = [ { topic: EXISTS_TOPIC_2 } ];
      var options = { autoCommit: false, groupId: '_groupId_1_test' };
      var consumer = new Consumer(client, topics, options);
      var count = 0;
      consumer.on('error', noop);
      consumer.on('offsetOutOfRange', function (topic) {
        offsetOutOfRange(topic, this);
      });
      consumer.on('message', function (message) {
        message.topic.should.equal(EXISTS_TOPIC_2);
        message.value.should.equal('hello kafka');
        message.partition.should.equal(0);
        offset.commit('_groupId_1_test', [message], function (err) {
          if (count++ === 0) done(err);
        });
      });

好的,我再看了一下API,并认为这可能是一个值得为你调查的角度:

Consumer.prototype.pauseTopics = function (topics) {
  if (!this.pausedPayloads) this.pausedPayloads = [];
  pauseOrResume(this.payloads, this.pausedPayloads, topics);
};

Consumer.prototype.resumeTopics = function (topics) {
  if (!this.pausedPayloads) this.pausedPayloads = [];
  var reFetch = !this.payloads.length;
  pauseOrResume(this.pausedPayloads, this.payloads, topics);
  reFetch = reFetch && this.payloads.length;
  if (reFetch) this.fetch();
};

来自文档:

  

暂停()

     

暂停消费者。呼叫暂停不会自动停止消息   从被释放。这是因为暂停只是停止了卡夫卡   消费者获取循环。获取循环的每次迭代都可以获得a   批量消息(受fetchMaxBytes限制)。

因此,如果您只获取一条消息(可能您的字节足够小,最大提取只有1),那么暂停将停止下一次提取发生。但是,如果您获取了多条消息,则暂停不会阻止发出多条消息。

我认为100%肯定你需要编写逻辑来同步处理消息。也许可以将消息发送到队列中,然后处理队列?