@Slf4j
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class, DataSourceTransactionManagerAutoConfiguration.class})
@ComponentScan(basePackages = {
"com.tplink.nbu.demo.basicspringboot",
"com.tplink.smb.eventcenter.port.kafka.deadletter",
"com.tplink.smb.eventcenter.api.config"
})
public class DLQGenericValidationApp implements CommandLineRunner {
@Autowired
private KafkaEventCenter eventCenter;
@Autowired
private DLQConfig deadLetterConfig; // 假设DLQConfig已配置maxRetries=3,retryStrategy为固定延时
public static void main(String[] args) {
SpringApplication.run(DLQGenericValidationApp.class, args);
}
@Override
public void run(String... args) throws Exception {
// 步骤1:注册带DLQ的泛型消费者(使用重载方法)
registerDLQGenericConsumer();
// 步骤2:注册死信队列监听(验证死信是否发送)
registerDLQListener();
// 步骤3:发送3类测试事件触发验证
sendTestEvents();
}
/**
* 注册带DLQ的泛型消费者(使用重载的registerUnicastGenerically)
*/
private void registerDLQGenericConsumer() {
// 定义一个会抛异常的泛型处理器(模拟消费失败)
GenericEventHandler<Object> failingHandler = event -> {
log.info("尝试处理事件: {}", event);
throw new RuntimeException("模拟泛型业务处理失败"); // 主动抛异常触发重试
};
// 使用重载方法注册(带DLQConfig参数)
eventCenter.registerUnicastGenerically(
"test-generic-topic", // 主Topic
"generic-demo-group", // 消费者组ID
failingHandler, // 会失败的处理器
ForkJoinPool.commonPool(), // 线程池
PartitionAssignorMode.COOPERATIVE_STICKY, // 分区分配策略
Object.class, // 泛型类型(这里用Object兼容所有测试事件)
deadLetterConfig // DLQ配置(自动注入)
);
}
/**
* 注册死信队列监听(验证死信是否发送)
*/
private void registerDLQListener() {
String dlqTopic = "test-generic-topic_dlq_topic"; // 根据DLQGenericEventHandlerWrapper逻辑拼接
eventCenter.registerUnicast(
dlqTopic, // 死信Topic
"dlq-generic-group", // 死信消费者组
event -> log.info("收到死信消息: {}", event.getMessage()), // 死信处理器
ForkJoinPool.commonPool()
);
}
/**
* 发送3类测试事件(Event、EventV2、CustomEvent)
*/
private void sendTestEvents() {
// 1. 发送基础Event对象(应走JSON序列化)
Event event = new Event("key1", "Hello Event!");
eventCenter.sendGenerically("test-generic-topic", event, buildTestFuture("Event"));
// 2. 发送EventV2对象(应走Kryo序列化)
EventV2<String> eventV2 = new EventV2<>("key2", "Hello EventV2!");
eventCenter.send("test-generic-topic", eventV2, buildTestFuture("EventV2"), SerializeEnum.KRYO);
// 3. 发送其他类型对象(如自定义CustomEvent,应触发"暂不支持"日志)
CustomEvent customEvent = new CustomEvent("key3", "Hello CustomEvent!");
eventCenter.sendGenerically("test-generic-topic", customEvent, buildTestFuture("CustomEvent"));
}
/**
* 构建测试用的GenericEventFuture(仅记录发送结果)
*/
private <U> GenericEventFuture<U> buildTestFuture(String eventType) {
return new GenericEventFuture<U>() {
@Override
public void onSuccess(GenericEventCenterSendResult<U> result) {
log.info("[{}] 发送成功 | 主题: {}, 分区: {}", eventType, result.getTopic(), result.getPartition());
}
@Override
public void onFailure(Throwable throwable) {
log.error("[{}] 发送失败 | 原因: {}", eventType, throwable.getMessage());
}
};
}
/**
* 自定义测试事件类型(非Event/EventV2)
*/
@Data
@AllArgsConstructor
public static class CustomEvent {
private String key;
private String content;
}
}
2025-10-10 14:55:07.770 INFO 8440 --- [ main] o.a.kafka.common.utils.AppInfoParser : Kafka version: 2.8.0
2025-10-10 14:55:07.770 INFO 8440 --- [ main] o.a.kafka.common.utils.AppInfoParser : Kafka commitId: ebb1d6e21cc92130
2025-10-10 14:55:07.770 INFO 8440 --- [ main] o.a.kafka.common.utils.AppInfoParser : Kafka startTimeMs: 1760079307769
2025-10-10 14:55:07.781 INFO 8440 --- [eric-demo-group] o.a.kafka.common.utils.AppInfoParser : Kafka version: 2.8.0
2025-10-10 14:55:07.781 INFO 8440 --- [eric-demo-group] o.a.kafka.common.utils.AppInfoParser : Kafka commitId: ebb1d6e21cc92130
2025-10-10 14:55:07.781 INFO 8440 --- [eric-demo-group] o.a.kafka.common.utils.AppInfoParser : Kafka startTimeMs: 1760079307781
2025-10-10 14:55:07.781 INFO 8440 --- [q-generic-group] o.a.kafka.common.utils.AppInfoParser : Kafka version: 2.8.0
2025-10-10 14:55:07.781 INFO 8440 --- [q-generic-group] o.a.kafka.common.utils.AppInfoParser : Kafka commitId: ebb1d6e21cc92130
2025-10-10 14:55:07.781 INFO 8440 --- [q-generic-group] o.a.kafka.common.utils.AppInfoParser : Kafka startTimeMs: 1760079307781
2025-10-10 14:55:07.781 INFO 8440 --- [q-generic-group] c.t.s.e.p.k.consumer.KafkaConsumerTask : start to consumer kafka topic: test-generic-topic_dlq_topic
2025-10-10 14:55:07.781 INFO 8440 --- [eric-demo-group] c.t.s.e.p.k.c.GenericKafkaConsumerTask : start to consumer kafka topic: test-generic-topic
2025-10-10 14:55:07.781 INFO 8440 --- [q-generic-group] c.t.s.e.p.k.c.AbstractTaskService : KafkaConsumerTask is running! topic:test-generic-topic_dlq_topic
2025-10-10 14:55:07.781 INFO 8440 --- [eric-demo-group] c.t.s.e.p.k.c.AbstractTaskService : KafkaConsumerTask is running! topic:test-generic-topic
2025-10-10 14:55:07.782 INFO 8440 --- [q-generic-group] o.a.k.clients.consumer.KafkaConsumer : [Consumer clientId=consumer_10.13.35.30_3810c305-f1f5-4bde-ad46-07f4e49da60c, groupId=dlq-generic-group] Subscribed to topic(s): test-generic-topic_dlq_topic
2025-10-10 14:55:07.782 INFO 8440 --- [eric-demo-group] o.a.k.clients.consumer.KafkaConsumer : [Consumer clientId=consumer_10.13.35.30_a3702082-156d-4427-9a46-64d97c370b37, groupId=generic-demo-group] Subscribed to topic(s): test-generic-topic
2025-10-10 14:55:07.937 INFO 8440 --- [ad | producer-1] org.apache.kafka.clients.Metadata : [Producer clientId=producer-1] Cluster ID: Cp8MopI8TC6QJ8pHpIkP9A
2025-10-10 14:55:07.937 INFO 8440 --- [q-generic-group] org.apache.kafka.clients.Metadata : [Consumer clientId=consumer_10.13.35.30_3810c305-f1f5-4bde-ad46-07f4e49da60c, groupId=dlq-generic-group] Cluster ID: Cp8MopI8TC6QJ8pHpIkP9A
2025-10-10 14:55:07.937 INFO 8440 --- [eric-demo-group] org.apache.kafka.clients.Metadata : [Consumer clientId=consumer_10.13.35.30_a3702082-156d-4427-9a46-64d97c370b37, groupId=generic-demo-group] Cluster ID: Cp8MopI8TC6QJ8pHpIkP9A
2025-10-10 14:55:07.937 INFO 8440 --- [eric-demo-group] o.a.k.c.c.internals.AbstractCoordinator : [Consumer clientId=consumer_10.13.35.30_a3702082-156d-4427-9a46-64d97c370b37, groupId=generic-demo-group] Discovered group coordinator admin1-virtual-machine:9092 (id: 2147483647 rack: null)
2025-10-10 14:55:07.937 INFO 8440 --- [q-generic-group] o.a.k.c.c.internals.AbstractCoordinator : [Consumer clientId=consumer_10.13.35.30_3810c305-f1f5-4bde-ad46-07f4e49da60c, groupId=dlq-generic-group] Discovered group coordinator admin1-virtual-machine:9092 (id: 2147483647 rack: null)
2025-10-10 14:55:08.366 INFO 8440 --- [eric-demo-group] o.a.k.c.c.internals.AbstractCoordinator : [Consumer clientId=consumer_10.13.35.30_a3702082-156d-4427-9a46-64d97c370b37, groupId=generic-demo-group] (Re-)joining group
2025-10-10 14:55:08.366 INFO 8440 --- [q-generic-group] o.a.k.c.c.internals.AbstractCoordinator : [Consumer clientId=consumer_10.13.35.30_3810c305-f1f5-4bde-ad46-07f4e49da60c, groupId=dlq-generic-group] (Re-)joining group
2025-10-10 14:55:08.379 INFO 8440 --- [eric-demo-group] o.a.k.c.c.internals.AbstractCoordinator : [Consumer clientId=consumer_10.13.35.30_a3702082-156d-4427-9a46-64d97c370b37, groupId=generic-demo-group] (Re-)joining group
2025-10-10 14:55:08.379 INFO 8440 --- [q-generic-group] o.a.k.c.c.internals.AbstractCoordinator : [Consumer clientId=consumer_10.13.35.30_3810c305-f1f5-4bde-ad46-07f4e49da60c, groupId=dlq-generic-group] (Re-)joining group
2025-10-10 14:55:08.380 INFO 8440 --- [eric-demo-group] o.a.k.c.c.internals.AbstractCoordinator : [Consumer clientId=consumer_10.13.35.30_a3702082-156d-4427-9a46-64d97c370b37, groupId=generic-demo-group] Successfully joined group with generation Generation{generationId=3, memberId='consumer_10.13.35.30_a3702082-156d-4427-9a46-64d97c370b37-fc7354c6-88ad-44f6-b5ef-b53edc844343', protocol='cooperative-sticky'}
2025-10-10 14:55:08.381 INFO 8440 --- [q-generic-group] o.a.k.c.c.internals.AbstractCoordinator : [Consumer clientId=consumer_10.13.35.30_3810c305-f1f5-4bde-ad46-07f4e49da60c, groupId=dlq-generic-group] Successfully joined group with generation Generation{generationId=3, memberId='consumer_10.13.35.30_3810c305-f1f5-4bde-ad46-07f4e49da60c-5a10e471-a645-478f-bacf-7fbabf62cea0', protocol='cooperative-sticky'}
2025-10-10 14:55:08.381 INFO 8440 --- [eric-demo-group] o.a.k.c.c.internals.ConsumerCoordinator : [Consumer clientId=consumer_10.13.35.30_a3702082-156d-4427-9a46-64d97c370b37, groupId=generic-demo-group] Finished assignment for group at generation 3: {consumer_10.13.35.30_a3702082-156d-4427-9a46-64d97c370b37-fc7354c6-88ad-44f6-b5ef-b53edc844343=Assignment(partitions=[test-generic-topic-0])}
2025-10-10 14:55:08.381 INFO 8440 --- [q-generic-group] o.a.k.c.c.internals.ConsumerCoordinator : [Consumer clientId=consumer_10.13.35.30_3810c305-f1f5-4bde-ad46-07f4e49da60c, groupId=dlq-generic-group] Finished assignment for group at generation 3: {consumer_10.13.35.30_3810c305-f1f5-4bde-ad46-07f4e49da60c-5a10e471-a645-478f-bacf-7fbabf62cea0=Assignment(partitions=[test-generic-topic_dlq_topic-0])}
2025-10-10 14:55:08.384 INFO 8440 --- [eric-demo-group] o.a.k.c.c.internals.AbstractCoordinator : [Consumer clientId=consumer_10.13.35.30_a3702082-156d-4427-9a46-64d97c370b37, groupId=generic-demo-group] Successfully synced group in generation Generation{generationId=3, memberId='consumer_10.13.35.30_a3702082-156d-4427-9a46-64d97c370b37-fc7354c6-88ad-44f6-b5ef-b53edc844343', protocol='cooperative-sticky'}
2025-10-10 14:55:08.384 INFO 8440 --- [ad | producer-1] c.t.n.d.b.DLQGenericValidationApp : [Event] 发送成功 | 主题: test-generic-topic, 分区: 0
2025-10-10 14:55:08.384 INFO 8440 --- [eric-demo-group] o.a.k.c.c.internals.ConsumerCoordinator : [Consumer clientId=consumer_10.13.35.30_a3702082-156d-4427-9a46-64d97c370b37, groupId=generic-demo-group] Updating assignment with
Assigned partitions: [test-generic-topic-0]
Current owned partitions: []
Added partitions (assigned - owned): [test-generic-topic-0]
Revoked partitions (owned - assigned): []
2025-10-10 14:55:08.384 INFO 8440 --- [eric-demo-group] o.a.k.c.c.internals.ConsumerCoordinator : [Consumer clientId=consumer_10.13.35.30_a3702082-156d-4427-9a46-64d97c370b37, groupId=generic-demo-group] Notifying assignor about the new Assignment(partitions=[test-generic-topic-0])
2025-10-10 14:55:08.384 INFO 8440 --- [q-generic-group] o.a.k.c.c.internals.AbstractCoordinator : [Consumer clientId=consumer_10.13.35.30_3810c305-f1f5-4bde-ad46-07f4e49da60c, groupId=dlq-generic-group] Successfully synced group in generation Generation{generationId=3, memberId='consumer_10.13.35.30_3810c305-f1f5-4bde-ad46-07f4e49da60c-5a10e471-a645-478f-bacf-7fbabf62cea0', protocol='cooperative-sticky'}
2025-10-10 14:55:08.384 INFO 8440 --- [ad | producer-1] c.t.n.d.b.DLQGenericValidationApp : [EventV2] 发送成功 | 主题: test-generic-topic, 分区: 0
2025-10-10 14:55:08.384 INFO 8440 --- [q-generic-group] o.a.k.c.c.internals.ConsumerCoordinator : [Consumer clientId=consumer_10.13.35.30_3810c305-f1f5-4bde-ad46-07f4e49da60c, groupId=dlq-generic-group] Updating assignment with
Assigned partitions: [test-generic-topic_dlq_topic-0]
Current owned partitions: []
Added partitions (assigned - owned): [test-generic-topic_dlq_topic-0]
Revoked partitions (owned - assigned): []
2025-10-10 14:55:08.384 INFO 8440 --- [ad | producer-1] c.t.n.d.b.DLQGenericValidationApp : [CustomEvent] 发送成功 | 主题: test-generic-topic, 分区: 0
2025-10-10 14:55:08.384 INFO 8440 --- [q-generic-group] o.a.k.c.c.internals.ConsumerCoordinator : [Consumer clientId=consumer_10.13.35.30_3810c305-f1f5-4bde-ad46-07f4e49da60c, groupId=dlq-generic-group] Notifying assignor about the new Assignment(partitions=[test-generic-topic_dlq_topic-0])
2025-10-10 14:55:08.385 INFO 8440 --- [eric-demo-group] o.a.k.c.c.internals.ConsumerCoordinator : [Consumer clientId=consumer_10.13.35.30_a3702082-156d-4427-9a46-64d97c370b37, groupId=generic-demo-group] Adding newly assigned partitions: test-generic-topic-0
2025-10-10 14:55:08.385 INFO 8440 --- [q-generic-group] o.a.k.c.c.internals.ConsumerCoordinator : [Consumer clientId=consumer_10.13.35.30_3810c305-f1f5-4bde-ad46-07f4e49da60c, groupId=dlq-generic-group] Adding newly assigned partitions: test-generic-topic_dlq_topic-0
2025-10-10 14:55:08.385 INFO 8440 --- [q-generic-group] com.tplink.smb.eventcenter.api.Handler : ending rebalance!
2025-10-10 14:55:08.385 INFO 8440 --- [eric-demo-group] com.tplink.smb.eventcenter.api.Handler : ending rebalance!
2025-10-10 14:55:08.390 INFO 8440 --- [q-generic-group] o.a.k.c.c.internals.ConsumerCoordinator : [Consumer clientId=consumer_10.13.35.30_3810c305-f1f5-4bde-ad46-07f4e49da60c, groupId=dlq-generic-group] Setting offset for partition test-generic-topic_dlq_topic-0 to the committed offset FetchPosition{offset=0, offsetEpoch=Optional.empty, currentLeader=LeaderAndEpoch{leader=Optional[admin1-virtual-machine:9092 (id: 0 rack: null)], epoch=absent}}
2025-10-10 14:55:08.390 INFO 8440 --- [eric-demo-group] o.a.k.c.c.internals.ConsumerCoordinator : [Consumer clientId=consumer_10.13.35.30_a3702082-156d-4427-9a46-64d97c370b37, groupId=generic-demo-group] Setting offset for partition test-generic-topic-0 to the committed offset FetchPosition{offset=3, offsetEpoch=Optional.empty, currentLeader=LeaderAndEpoch{leader=Optional[admin1-virtual-machine:9092 (id: 0 rack: null)], epoch=absent}}
2025-10-10 14:55:08.423 INFO 8440 --- [onPool-worker-8] c.t.n.d.b.DLQGenericValidationApp : 尝试处理事件: {messageId=416f51ee-ba18-4215-ac0a-d8c9581942c8, totalSize=59, size=59, totalIndex=1, index=1, compressionType=null, compressionLevel=-1, enableSlice=false, payload={"filterKey":"key1","timeStamp":0,"message":"Hello Event!"}}
2025-10-10 14:55:08.423 WARN 8440 --- [onPool-worker-8] .s.e.p.k.d.DLQGenericEventHandlerWrapper : 泛型事件处理失败 (重试 1/3): 模拟泛型业务处理失败
2025-10-10 14:55:08.423 INFO 8440 --- [onPool-worker-8] .s.e.p.k.d.DLQGenericEventHandlerWrapper : 事件延时 1000ms 后重试
2025-10-10 14:55:08.423 INFO 8440 --- [onPool-worker-8] c.t.n.d.b.DLQGenericValidationApp : 尝试处理事件: {messageId=416f51ee-ba18-4215-ac0a-d8c9581942c8, totalSize=59, size=59, totalIndex=1, index=1, compressionType=null, compressionLevel=-1, enableSlice=false, payload={"filterKey":"key1","timeStamp":0,"message":"Hello Event!"}}
2025-10-10 14:55:08.423 WARN 8440 --- [onPool-worker-8] .s.e.p.k.d.DLQGenericEventHandlerWrapper : 泛型事件处理失败 (重试 2/3): 模拟泛型业务处理失败
2025-10-10 14:55:08.424 INFO 8440 --- [onPool-worker-8] .s.e.p.k.d.DLQGenericEventHandlerWrapper : 事件延时 5000ms 后重试
2025-10-10 14:55:08.424 INFO 8440 --- [onPool-worker-8] c.t.n.d.b.DLQGenericValidationApp : 尝试处理事件: {messageId=416f51ee-ba18-4215-ac0a-d8c9581942c8, totalSize=59, size=59, totalIndex=1, index=1, compressionType=null, compressionLevel=-1, enableSlice=false, payload={"filterKey":"key1","timeStamp":0,"message":"Hello Event!"}}
2025-10-10 14:55:08.424 WARN 8440 --- [onPool-worker-8] .s.e.p.k.d.DLQGenericEventHandlerWrapper : 泛型事件处理失败 (重试 3/3): 模拟泛型业务处理失败
2025-10-10 14:55:08.424 WARN 8440 --- [onPool-worker-8] .s.e.p.k.d.DLQGenericEventHandlerWrapper : 暂不支持的类型 | 类型: java.util.LinkedHashMap, 重试次数: 3
2025-10-10 14:55:08.424 ERROR 8440 --- [onPool-worker-8] .s.e.p.k.d.DLQGenericEventHandlerWrapper : 泛型事件重试3次后失败,已发送至死信队列
2025-10-10 14:55:08.426 ERROR 8440 --- [eric-demo-group] .t.s.e.p.k.c.AbstractGenericConsumerTask : Exception happened while handling generic message:[0, 69, -125, -128, 1, 107, 101, 121, -78, 3, 72, 101, 108, 108, 111, 32, 69, 118, 101, 110, 116, 86, 50, -95, -48, -110, -73, -50, -71, 102]
2025-10-10 14:55:08.427 INFO 8440 --- [onPool-worker-8] c.t.n.d.b.DLQGenericValidationApp : 尝试处理事件: {messageId=87aa4c4b-bd90-4b2b-abfd-b3bf6571bfc6, totalSize=45, size=45, totalIndex=1, index=1, compressionType=null, compressionLevel=-1, enableSlice=false, payload={"key":"key3","content":"Hello CustomEvent!"}}
2025-10-10 14:55:08.427 WARN 8440 --- [onPool-worker-8] .s.e.p.k.d.DLQGenericEventHandlerWrapper : 泛型事件处理失败 (重试 1/3): 模拟泛型业务处理失败
2025-10-10 14:55:08.427 INFO 8440 --- [onPool-worker-8] .s.e.p.k.d.DLQGenericEventHandlerWrapper : 事件延时 1000ms 后重试
2025-10-10 14:55:08.427 INFO 8440 --- [onPool-worker-8] c.t.n.d.b.DLQGenericValidationApp : 尝试处理事件: {messageId=87aa4c4b-bd90-4b2b-abfd-b3bf6571bfc6, totalSize=45, size=45, totalIndex=1, index=1, compressionType=null, compressionLevel=-1, enableSlice=false, payload={"key":"key3","content":"Hello CustomEvent!"}}
2025-10-10 14:55:08.427 WARN 8440 --- [onPool-worker-8] .s.e.p.k.d.DLQGenericEventHandlerWrapper : 泛型事件处理失败 (重试 2/3): 模拟泛型业务处理失败
2025-10-10 14:55:08.427 INFO 8440 --- [onPool-worker-8] .s.e.p.k.d.DLQGenericEventHandlerWrapper : 事件延时 5000ms 后重试
2025-10-10 14:55:08.427 INFO 8440 --- [onPool-worker-8] c.t.n.d.b.DLQGenericValidationApp : 尝试处理事件: {messageId=87aa4c4b-bd90-4b2b-abfd-b3bf6571bfc6, totalSize=45, size=45, totalIndex=1, index=1, compressionType=null, compressionLevel=-1, enableSlice=false, payload={"key":"key3","content":"Hello CustomEvent!"}}
2025-10-10 14:55:08.427 WARN 8440 --- [onPool-worker-8] .s.e.p.k.d.DLQGenericEventHandlerWrapper : 泛型事件处理失败 (重试 3/3): 模拟泛型业务处理失败
2025-10-10 14:55:08.427 WARN 8440 --- [onPool-worker-8] .s.e.p.k.d.DLQGenericEventHandlerWrapper : 暂不支持的类型 | 类型: java.util.LinkedHashMap, 重试次数: 3
2025-10-10 14:55:08.427 ERROR 8440 --- [onPool-worker-8] .s.e.p.k.d.DLQGenericEventHandlerWrapper : 泛型事件重试3次后失败,已发送至死信队列,请分析处理器处理的对象是什么类型,并尝试修改以下类@Slf4j
@RequiredArgsConstructor
public class DLQGenericEventHandlerWrapper<T> implements GenericEventHandler<T> {
// 原泛型事件处理器
private final GenericEventHandler<T> delegate;
// DLQ配置
private final DLQConfig dlqConfig;
// 原始主题名称
private final String mainTopic;
// 事件中心引用(用于发送死信)
private final KafkaEventCenter eventCenter;
// 记录最后一次异常信息
private String lastException;
@Override
public void handleEvent(T event) {
if (!dlqConfig.isEnabled()) {
delegate.handleEvent(event);
// 未启用DLQ直接处理
return;
}
int retryCount = 0;
boolean success = false;
// 重试机制
while (retryCount < dlqConfig.getMaxRetries()) {
try {
delegate.handleEvent(event);
success = true;
break;
} catch (Exception e) {
retryCount++;
log.warn("泛型事件处理失败 (重试 {}/{}): {}",
retryCount, dlqConfig.getMaxRetries(), e.getMessage());
lastException = e.getMessage();
if (retryCount >= dlqConfig.getMaxRetries()) {
break;
}
long delay = dlqConfig.getRetryStrategy().getNextDelay(retryCount);
sendDelay(event, delay);
}
}
// 最终失败时发送死信
if (!success) {
String dlqTopic = mainTopic + "_dlq_topic";
sendToDLQ(event, retryCount, lastException, dlqTopic);
log.error("泛型事件重试{}次后失败,已发送至死信队列", dlqConfig.getMaxRetries());
}
}
/**
* 发送事件到死信队列(泛型版本)
*/
private void sendToDLQ(T event, int retryCount, String exceptionMsg, String dlqTopic) {
try {
if (event instanceof Event) {
doEvent((Event) event, retryCount, exceptionMsg, dlqTopic);
}
else if (event instanceof EventV2<?>) {
doEventV2((EventV2<?>) event, retryCount, exceptionMsg, dlqTopic);
}
// 3. 其他类型暂不处理
else {
log.warn("暂不支持的类型 | 类型: {}, 重试次数: {}", event.getClass().getName(), retryCount);
}
} catch (Exception e) {
log.error("死信发送方法异常 | 重试次数: {}", retryCount, e);
}
}
/**
* 处理基础Event对象(JSON序列化发送)
*/
private void doEvent(Event event, int retryCount, String exceptionMsg, String dlqTopic) {
try {
// 构建泛型Future(匹配Event类型)
GenericEventFuture<Event> eventFuture = buildEventFuture(retryCount, exceptionMsg);
// 调用JSON序列化的发送方法(复用原有sendGenerically逻辑)
eventCenter.sendGenerically(dlqTopic, event, eventFuture);
} catch (Exception e) {
log.error("处理Event类型事件失败 | 重试次数: {}, 异常信息: {}",
retryCount, exceptionMsg, e);
}
}
/**
* 处理EventV2对象(Kryo序列化发送)
*/
private void doEventV2(EventV2<?> eventV2, int retryCount, String exceptionMsg, String dlqTopic) {
try {
// 构建泛型Future(匹配EventV2类型)
GenericEventFuture<EventV2<?>> eventFuture = buildEventFuture(retryCount, exceptionMsg);
// 调用Kryo序列化的发送方法(指定序列化方式)
eventCenter.send(dlqTopic, eventV2, eventFuture, SerializeEnum.KRYO);
} catch (Exception e) {
log.error("处理EventV2类型事件失败 | 重试次数: {}, 异常信息: {}",
retryCount, exceptionMsg, e);
}
}
/**
* 通用Future构建逻辑(保持泛型匹配,无修改)
*/
private <U> GenericEventFuture<U> buildEventFuture(int retryCount, String exceptionMsg) {
return new GenericEventFuture<U>() {
@Override
public void onSuccess(GenericEventCenterSendResult<U> result) {
log.info("死信发送成功 | 主题: {}, 分区: {}, 重试次数: {}, 异常信息: {}",
result.getTopic(), result.getPartition(), retryCount, exceptionMsg);
}
@Override
public void onFailure(Throwable throwable) {
log.error("死信发送失败 | 重试次数: {}, 异常信息: {}, 失败原因: {}",
retryCount, exceptionMsg, throwable.getMessage());
}
};
}
/**
* 延时重试机制(占位实现)
*/
private void sendDelay(T event, long delay) {
log.info("事件延时 {}ms 后重试", delay);
// TODO: 实际延时队列实现
}
}