【发布时间】:2021-08-01 21:29:14
【问题描述】:
同事们好。我正在使用 Spring Kafka 2.2.5 我有一个听众:
@KafkaListener(topics = "${kafka.execution-task-topic}", containerFactory = "executionTaskObjectContainerFactory")
public void protocolEventsHandle(ExecutionTask executionTask,
Acknowledgment acknowledgment,
@Header(KafkaHeaders.RECEIVED_PARTITION_ID) int partition,
@Header(KafkaHeaders.RECEIVED_TOPIC) String topic,
@Header(KafkaHeaders.OFFSET) long offset) {
ResponseEntity < String > stringResponseEntity = airflowRestRunner.startDag(executionTask);
JSONObject body = new JSONObject(stringResponseEntity.getBody());
String message = body.getString("message");
String runId = messageParser.getRunId(message);
ExecutionTaskMessageInfo messageInfo = new ExecutionTaskMessageInfo(offset, partition, false, acknowledgment);
kafkaAcknowledgeObject.putMessageInfo(messageInfo, partition);
this.executorService.submit(kafkaAlertProducer.produceMessageAfterTaskSuccess(runId, executionTask, messageInfo));
}
我做了一些操作,如果它们成功了,我使用 Acknowledge 接口来提交偏移量。
我有问题。 在创建的线程中进行计算时,侦听器再次从相同的偏移量读取消息。因此,当我尝试确认偏移量时,应用程序崩溃了。
以并发方式使用 Kafka 的最佳实践是什么? 我最多可以并行收到 10 条消息,并且我只需要在计算后提交它们。
更新1
我将所有来自 kafka 的消息存储在: 键 - 分区号 value - 包含对所需确认的引用的特殊模型类
@Data
@NoArgsConstructor
@AllArgsConstructor
public abstract class KafkaAcknowledgeObject < T extends Comparable > {
protected ConcurrentHashMap < Integer,
TreeSet < T >> hashMap = new ConcurrentHashMap < > ();
public abstract void doAck();
public void putMessageInfo(T message, int partition) {
if (hashMap.containsKey(partition)) {
hashMap.get(partition).add(message);
} else {
TreeSet < T > messageInfos = new TreeSet < > ();
messageInfos.add(message);
hashMap.put(partition, messageInfos);
}
}
}
计算后我打电话给doAck(),例如
@Override
public void doAck() {
for (TreeSet < ExecutionTaskMessageInfo > messageInfoTreeSet: super.hashMap.values()) {
checkHandledOffsets(messageInfoTreeSet);
}
}
private void checkHandledOffsets(TreeSet < ExecutionTaskMessageInfo > messageInfoTreeSet) {
ExecutionTaskMessageInfo first = getFirstMessageInfo(messageInfoTreeSet);
if (first.isCompleted()) {
first.getAcknowledgment().acknowledge();
messageInfoTreeSet.remove(first);
checkHandledOffsets(messageInfoTreeSet);
}
return;
}
private ExecutionTaskMessageInfo getFirstMessageInfo(TreeSet < ExecutionTaskMessageInfo > messageInfoTreeSet) {
Iterator < ExecutionTaskMessageInfo > iterator = messageInfoTreeSet.iterator();
return iterator.next();
}
【问题讨论】:
-
“崩溃”信息不足;添加实际错误、堆栈跟踪等。还显示实际调用
acknowledge()的代码。除非发生重新平衡,否则不应重新传递记录, -
@GaryRussell,谢谢您的回答。我添加了一些信息。我无法捕捉到异常,但我正在努力做对。使用KafkaListener在自己的线程方法中开始计算后的主要问题再次得到类似的消息。
标签: java concurrency apache-kafka spring-kafka