当kafka消费者消息处理流程耗时时,时间不可控,需要重置过期时间
import lombok.extern.slf4j.Slf4j;
import org.apache.kafka.clients.consumer.Consumer;
import org.apache.kafka.clients.consumer.internals.ConsumerCoordinator;
import org.apache.kafka.common.utils.Time;
import java.lang.reflect.Field;
/**
* @author liaozesong
*/
@Slf4j
public class KafkaUtil {
public static void resetMaxPollIntervalMs(Consumer<?, ?> consumer) {
resetMaxPollIntervalMs(consumer, 300000);
}
public static void resetMaxPollIntervalMs(Consumer<?, ?> consumer, long ts) {
try {
Field field = consumer.getClass().getDeclaredField("coordinator");
field.setAccessible(true);
Object object = field.get(consumer);
if (object != null) {
ConsumerCoordinator coordinator = (ConsumerCoordinator) object;
coordinator.poll(Time.SYSTEM.timer(ts));
}
log.info("重设消息过期时间:{}S", ts / 1000);
} catch (Exception e) {
e.printStackTrace();
log.error("重置消息过期时间异常");
}
}
}
消费者
import cn.hutool.core.lang.Assert;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.kafka.clients.consumer.Consumer;
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.springframework.kafka.annotation.KafkaListener;
import org.springframework.kafka.support.Acknowledgment;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* 一批次解析完成
*
* @author liaozesong
*/
@Slf4j
@Component
@RequiredArgsConstructor
public class ParserComputeConsumer {
/**
* 接受硬盘文件上传成功通知
*/
@KafkaListener(topics = "${ai.topic.parse-finish}")
public void listen(ConsumerRecord<String, String> record, Acknowledgment ack, Consumer<?, ?> consumer) {
long offset = record.offset();
String json = record.value();
String topic = record.topic();
try {
log.info("listen msg:offset:{},topic:{},json:{}", offset, topic, json);
for (AiResponsePo po : pos) {
//耗时业务操作
KafkaUtil.resetMaxPollIntervalMs(consumer);
}
} catch (Exception e) {
log.warn(e.toString(), e);
log.warn("listen msg:offset:{},topic:{},json:{}", offset, topic, json);
} finally {
ack.acknowledge();
}
}
}