I have some request timeout when using the manual async commit: Received an error event: server1:9092/1: 6521 request(s) timed out: disconnect(Local: Message timed out)
My application requires to commit transaction manually in order to ensure that the current transaction is successful before doing a commit. So the consumer currently takes the responsibility to do a async commit once the transaction is processed: consumer->commitAsync(message);
My scenario is the following:
Kafka consumer configuration:
The issue:
My application is able to consume around 300k messages at a good rate and the the following happens:
This result in a delay of 1 minute: no messages were consumed between 11:51:37 and 11:52:38. This problem happens again after another ~300k messages consumed. I also noticed the first timeout there is elapse time of ~5-10s where not messages are processed but no error is logged and no rebalance are triggered.
This error doesn't happen if I turn the auto commit to true and remove the commitAsync (no timeout, not rebalance), so this issue seems to be linked to the async commit.
Note that the issue happens each time I run the above scenario
See my scenario above
Please provide the following information:
debug=.. as necessary) from librdkafkaThat looks nasty, can you try reproducing this issue with debug=broker,protocol enabled?
I just reproduced the issue with debug logs. I can see a lot of those lines:
17:52:23.686339468 [2311] INFO - KafkaEventCallback: Received a log event: server1:9092/1: OffsetCommitRequest failed: Local: Timed out: explicit actions 0x0(7, REQERR)
Please see the attached file for the full logs.
kafkalog.txt
If you are asynchronously committing offsets for each processed message, and the OffsetCommit request-response times are non-negligent, you will quite quickly build up a queue of OffsetCommitRequests waiting in-queue or in-flight to be processed and responded to by the broker.
When this queue grows large enough the latency to make it through is higher than the request timeout (socket.timeout.ms, def 60s) and these requests will start failing with "Local: Timed out", as you are seeing.
When more than socket.max.fails requests have timed out the broker connection is torn down and re-established and all this starts over.
The underlying problem is that your consumtion and processing rate is higher than the commit rate, which inevitably leads to these queue build ups.
...:
enable.auto.offset.store=false to disable automatic offset store (which is typically done prior to your processing).Thanks for your answer.
I actually quite like the third solution using offset_store(). However according to the documentation this method should only be used with the old consumer. I am currently using the CPP api with the high-level consumer: KafkaConsumer. Is there a way of using it with the new consumer?
Note that I am also using virtual ErrorCode subscribe (const std::vector<std::string> &topics) = 0; and virtual ErrorCode assign (const std::vector<TopicPartition*> &partitions) = 0 so I do not have any Topic handles.
I do not need to commit on every message, I just don't want the following scenario to happen:
The idea was to commit once we are sure the message was processed correctly.
Is it the call to consume(1000) that will trigger an auto commit of previous processed offsets? Or, does the auto commit is handled by a different thread and can be triggered anytime?
Ah yeah, offset_store() should be exposed on the KafkaConsumer class as well, without the Topic object requirement.. I'll fix that.
If enable.auto.commit is enabled the automatic commit is done every auto.commit.interval.ms by one of librdkafka's internal threads. The commit will commit the last stored offset for each partition.
Can you give the offsets_store_826 branch a try, it has the new offsets_store() API that takes a list of partitions to store.
I just tried it and it worked. Thanks for this! Is this feature will be added to the future 0.9.2 release?
It would be good to pass directly the message to the store method (like it is done for commit methods). I think that most user will call the function after processing a RdKafka::Message
For now I am doing an ugly workaround:
RdKafka::TopicPartition * topar = RdKafka::TopicPartition::create(message->topic_name(), message->partition());
topar->set_offset(message->offset());
std::vector<RdKafka::TopicPartition *> topars = {topar};
RdKafka::ErrorCode err = m_consumer->offsets_store(topars);
Hi,
I see that the issue is mark as closed. Is there any plan to merge this enhancement with the master branch?
Thanks.
You are right, seems like I missed to merge this.
@edenhill Would it be possible to merge this branch in order to have the feature in the 0.9.4 release of librdkafka?
Argh, missed it twice!
I'm sorry but it is too late to merge this for 0.9.4 now :(
I screwed up.
Merge it
@edenhill I see that the fix is on Master but I don't see it in the RC2 of 0.9.5. Would it be possible to add it in the final release? Thanks
Most helpful comment
If you are asynchronously committing offsets for each processed message, and the OffsetCommit request-response times are non-negligent, you will quite quickly build up a queue of OffsetCommitRequests waiting in-queue or in-flight to be processed and responded to by the broker.
When this queue grows large enough the latency to make it through is higher than the request timeout (socket.timeout.ms, def 60s) and these requests will start failing with "Local: Timed out", as you are seeing.
When more than socket.max.fails requests have timed out the broker connection is torn down and re-established and all this starts over.
The underlying problem is that your consumtion and processing rate is higher than the commit rate, which inevitably leads to these queue build ups.
...:
enable.auto.offset.store=falseto disable automatic offset store (which is typically done prior to your processing).