Quarkus REST Client与@ClientExceptionMapper的错误处理问询
Kafka Sink HTTP连接器:按HTTP状态码控制重试与DLQ流程
针对你的需求,核心问题是要让重试机制识别并跳过40x类错误的重试,直接触发DLQ。你之前的ClientExceptionMapper返回null的方式无法阻止重试,因为框架会把这种情况视为未抛出可触发终止的异常,依然会执行重试逻辑。下面是可行的解决方案:
步骤1:定义不可重试的自定义异常
创建一个专属异常类,用来标记不需要重试的40x错误:
public class NonRetryableClientErrorException extends RuntimeException { public NonRetryableClientErrorException(String message) { super(message); } }
步骤2:修改ClientExceptionMapper抛出异常
在自定义异常映射器中,遇到40x状态码时抛出上述异常,而不是返回null:
@ClientExceptionMapper static RuntimeException toException(Response response) { switch (response.getStatusInfo().getFamily()) { case CLIENT_ERROR: String errorDetail = "40x客户端错误,将消息发送至DLQ: " + response.readEntity(String.class); CremHttpClient.log.error(errorDetail); // 抛出不可重试异常,告知框架终止重试 return new NonRetryableClientErrorException(errorDetail); case SERVER_ERROR: // 50x错误抛出普通RuntimeException,触发重试 return new RuntimeException("50x服务端错误: " + response.readEntity(String.class)); default: return null; } }
步骤3:配置@Retry注解排除不可重试异常
在你的消费者方法上,通过@Retry的exclude属性指定刚才定义的异常,让重试机制遇到该异常时直接跳过重试,进入DLQ流程:
@Retry( attempts = "3", // 自定义重试次数 delay = "1000", // 自定义重试间隔 exclude = NonRetryableClientErrorException.class ) @DLQ(name = "your-dlq-topic-name") // 替换为你的死信队列主题名 public void consumeMessage(YourMessageType message) { // 调用HTTP接口的业务逻辑 }
原理说明
@Retry注解的exclude属性会过滤掉指定的异常,当该异常抛出时,重试机制不会触发,直接将消息路由到DLQ。- 通过自定义异常标记40x错误,能精准区分需要重试的50x错误和直接入DLQ的40x错误,避免无效重试。
内容的提问来源于stack exchange,提问作者Romain Wilbert
相关产品推荐
相关产品推荐

