RabbitMQ 可靠性投递:持久化、确认机制与死信队列
在分布式系统中,消息队列的可靠性投递是保证数据一致性的核心环节。本文将深入剖析 RabbitMQ 的三大可靠性保障机制:持久化、确认机制与死信队列,并结合源码分析、实战案例与最佳实践,助你构建高可用的消息系统。
目录
- [RabbitMQ 可靠性投递概述](#RabbitMQ 可靠性投递概述)
- 消息持久化:数据不丢失的第一道防线
- 消息确认机制:可靠投递的核心保障
- 死信队列:异常处理的最后一道防线
- 可靠性投递完整方案设计
- 性能优化与权衡
- 最佳实践总结
1. RabbitMQ 可靠性投递概述
1.1 什么是可靠性投递?
消息队列的可靠性投递指的是:从消息发送方到消息接收方,确保消息至少被成功处理一次,且在异常情况下能够进行补偿或重试。
在 RabbitMQ 中,可靠性投递涉及三个核心环节:
graph LR
A[生产者] -->|1. 发送消息| B[RabbitMQ Broker]
B -->|2. 存储消息| C[队列]
C -->|3. 投递消息| D[消费者]
style A fill:#e1f5ff
style B fill:#fff4e1
style C fill:#ffe1f5
style D fill:#e1ffe1
1.2 可靠性投递的三大挑战
| 挑战 | 描述 | 后果 |
|---|---|---|
| 消息丢失 | 消息在传输或存储过程中丢失 | 数据不一致,业务逻辑错误 |
| 消息重复 | 消息被多次投递或消费 | 资源浪费,可能导致数据重复 |
| 消息乱序 | 消息到达顺序与发送顺序不一致 | 状态机混乱,并发控制失效 |
1.3 RabbitMQ 的可靠性保障体系
RabbitMQ 通过多层机制构建可靠性保障:
graph TD
A[RabbitMQ 可靠性体系] --> B[持久化层]
A --> C[确认机制层]
A --> D[异常处理层]
B --> B1[交换机持久化]
B --> B2[队列持久化]
B --> B3[消息持久化]
C --> C1[生产者确认]
C --> C2[消费者手动 ACK]
D --> D1[死信队列]
D --> D2[重试策略]
D --> D3[补偿机制]
style A fill:#f9f9f9
style B fill:#e3f2fd
style C fill:#fff3e0
style D fill:#f3e5f5
2. 消息持久化:数据不丢失的第一道防线
2.1 持久化的三层架构
RabbitMQ 的持久化需要同时满足三个条件,缺一不可:
graph TB
A[消息持久化三要素] --> B[交换机持久化]
A --> C[队列持久化]
A --> D[消息持久化]
B --> B1[durable=true]
C --> C1[durable=true]
D --> D1[delivery_mode=2]
style A fill:#fff4e1
style B fill:#e1f5ff
style C fill:#e1f5ff
style D fill:#e1f5ff
2.2 源码分析:持久化的实现原理
2.2.1 消息存储格式(RabbitMQ 3.12.x)
在 RabbitMQ 源码中,消息的持久化通过 delivery_mode 字段控制:
#%% rabbit_amqqueue.erl (Line 245-256)
%% 持久化消息的存储逻辑
-define(RABBIT_MSG_HEADER_VSN, 1).
-record('basic.message', {
content_type, %% 内容类型
content_encoding, %% 内容编码
headers, %% 自定义头信息
delivery_mode, %% 1=非持久化, 2=持久化
priority, %% 优先级
correlation_id, %% 关联ID
reply_to, %% 回复队列
expiration, %% 过期时间
message_id, %% 消息ID
timestamp, %% 时间戳
type, %% 消息类型
user_id, %% 用户ID
app_id, %% 应用ID
cluster_id %% 集群ID
}).%% rabbit_amqqueue.erl (Line 245-256)
#%% rabbit_amqqueue.erl (Line 245-256)
%% 持久化消息的存储逻辑
-define(RABBIT_MSG_HEADER_VSN, 1).
-record('basic.message', {
content_type, %% 内容类型
content_encoding, %% 内容编码
headers, %% 自定义头信息
delivery_mode, %% 1=非持久化, 2=持久化
priority, %% 优先级
correlation_id, %% 关联ID
reply_to, %% 回复队列
expiration, %% 过期时间
message_id, %% 消息ID
timestamp, %% 时间戳
type, %% 消息类型
user_id, %% 用户ID
app_id, %% 应用ID
cluster_id %% 集群ID
}).%% 持久化消息的存储逻辑
#%% rabbit_amqqueue.erl (Line 245-256)
%% 持久化消息的存储逻辑
-define(RABBIT_MSG_HEADER_VSN, 1).
-record('basic.message', {
content_type, %% 内容类型
content_encoding, %% 内容编码
headers, %% 自定义头信息
delivery_mode, %% 1=非持久化, 2=持久化
priority, %% 优先级
correlation_id, %% 关联ID
reply_to, %% 回复队列
expiration, %% 过期时间
message_id, %% 消息ID
timestamp, %% 时间戳
type, %% 消息类型
user_id, %% 用户ID
app_id, %% 应用ID
cluster_id %% 集群ID
}).-define(RABBIT_MSG_HEADER_VSN, 1).
#%% rabbit_amqqueue.erl (Line 245-256)
%% 持久化消息的存储逻辑
-define(RABBIT_MSG_HEADER_VSN, 1).
-record('basic.message', {
content_type, %% 内容类型
content_encoding, %% 内容编码
headers, %% 自定义头信息
delivery_mode, %% 1=非持久化, 2=持久化
priority, %% 优先级
correlation_id, %% 关联ID
reply_to, %% 回复队列
expiration, %% 过期时间
message_id, %% 消息ID
timestamp, %% 时间戳
type, %% 消息类型
user_id, %% 用户ID
app_id, %% 应用ID
cluster_id %% 集群ID
}).
#%% rabbit_amqqueue.erl (Line 245-256)
%% 持久化消息的存储逻辑
-define(RABBIT_MSG_HEADER_VSN, 1).
-record('basic.message', {
content_type, %% 内容类型
content_encoding, %% 内容编码
headers, %% 自定义头信息
delivery_mode, %% 1=非持久化, 2=持久化
priority, %% 优先级
correlation_id, %% 关联ID
reply_to, %% 回复队列
expiration, %% 过期时间
message_id, %% 消息ID
timestamp, %% 时间戳
type, %% 消息类型
user_id, %% 用户ID
app_id, %% 应用ID
cluster_id %% 集群ID
}).-record('basic.message', {
#%% rabbit_amqqueue.erl (Line 245-256)
%% 持久化消息的存储逻辑
-define(RABBIT_MSG_HEADER_VSN, 1).
-record('basic.message', {
content_type, %% 内容类型
content_encoding, %% 内容编码
headers, %% 自定义头信息
delivery_mode, %% 1=非持久化, 2=持久化
priority, %% 优先级
correlation_id, %% 关联ID
reply_to, %% 回复队列
expiration, %% 过期时间
message_id, %% 消息ID
timestamp, %% 时间戳
type, %% 消息类型
user_id, %% 用户ID
app_id, %% 应用ID
cluster_id %% 集群ID
}). content_type, %% 内容类型
#%% rabbit_amqqueue.erl (Line 245-256)
%% 持久化消息的存储逻辑
-define(RABBIT_MSG_HEADER_VSN, 1).
-record('basic.message', {
content_type, %% 内容类型
content_encoding, %% 内容编码
headers, %% 自定义头信息
delivery_mode, %% 1=非持久化, 2=持久化
priority, %% 优先级
correlation_id, %% 关联ID
reply_to, %% 回复队列
expiration, %% 过期时间
message_id, %% 消息ID
timestamp, %% 时间戳
type, %% 消息类型
user_id, %% 用户ID
app_id, %% 应用ID
cluster_id %% 集群ID
}). content_encoding, %% 内容编码
#%% rabbit_amqqueue.erl (Line 245-256)
%% 持久化消息的存储逻辑
-define(RABBIT_MSG_HEADER_VSN, 1).
-record('basic.message', {
content_type, %% 内容类型
content_encoding, %% 内容编码
headers, %% 自定义头信息
delivery_mode, %% 1=非持久化, 2=持久化
priority, %% 优先级
correlation_id, %% 关联ID
reply_to, %% 回复队列
expiration, %% 过期时间
message_id, %% 消息ID
timestamp, %% 时间戳
type, %% 消息类型
user_id, %% 用户ID
app_id, %% 应用ID
cluster_id %% 集群ID
}). headers, %% 自定义头信息
#%% rabbit_amqqueue.erl (Line 245-256)
%% 持久化消息的存储逻辑
-define(RABBIT_MSG_HEADER_VSN, 1).
-record('basic.message', {
content_type, %% 内容类型
content_encoding, %% 内容编码
headers, %% 自定义头信息
delivery_mode, %% 1=非持久化, 2=持久化
priority, %% 优先级
correlation_id, %% 关联ID
reply_to, %% 回复队列
expiration, %% 过期时间
message_id, %% 消息ID
timestamp, %% 时间戳
type, %% 消息类型
user_id, %% 用户ID
app_id, %% 应用ID
cluster_id %% 集群ID
}). delivery_mode, %% 1=非持久化, 2=持久化
#%% rabbit_amqqueue.erl (Line 245-256)
%% 持久化消息的存储逻辑
-define(RABBIT_MSG_HEADER_VSN, 1).
-record('basic.message', {
content_type, %% 内容类型
content_encoding, %% 内容编码
headers, %% 自定义头信息
delivery_mode, %% 1=非持久化, 2=持久化
priority, %% 优先级
correlation_id, %% 关联ID
reply_to, %% 回复队列
expiration, %% 过期时间
message_id, %% 消息ID
timestamp, %% 时间戳
type, %% 消息类型
user_id, %% 用户ID
app_id, %% 应用ID
cluster_id %% 集群ID
}). priority, %% 优先级
#%% rabbit_amqqueue.erl (Line 245-256)
%% 持久化消息的存储逻辑
-define(RABBIT_MSG_HEADER_VSN, 1).
-record('basic.message', {
content_type, %% 内容类型
content_encoding, %% 内容编码
headers, %% 自定义头信息
delivery_mode, %% 1=非持久化, 2=持久化
priority, %% 优先级
correlation_id, %% 关联ID
reply_to, %% 回复队列
expiration, %% 过期时间
message_id, %% 消息ID
timestamp, %% 时间戳
type, %% 消息类型
user_id, %% 用户ID
app_id, %% 应用ID
cluster_id %% 集群ID
}). correlation_id, %% 关联ID
#%% rabbit_amqqueue.erl (Line 245-256)
%% 持久化消息的存储逻辑
-define(RABBIT_MSG_HEADER_VSN, 1).
-record('basic.message', {
content_type, %% 内容类型
content_encoding, %% 内容编码
headers, %% 自定义头信息
delivery_mode, %% 1=非持久化, 2=持久化
priority, %% 优先级
correlation_id, %% 关联ID
reply_to, %% 回复队列
expiration, %% 过期时间
message_id, %% 消息ID
timestamp, %% 时间戳
type, %% 消息类型
user_id, %% 用户ID
app_id, %% 应用ID
cluster_id %% 集群ID
}). reply_to, %% 回复队列
#%% rabbit_amqqueue.erl (Line 245-256)
%% 持久化消息的存储逻辑
-define(RABBIT_MSG_HEADER_VSN, 1).
-record('basic.message', {
content_type, %% 内容类型
content_encoding, %% 内容编码
headers, %% 自定义头信息
delivery_mode, %% 1=非持久化, 2=持久化
priority, %% 优先级
correlation_id, %% 关联ID
reply_to, %% 回复队列
expiration, %% 过期时间
message_id, %% 消息ID
timestamp, %% 时间戳
type, %% 消息类型
user_id, %% 用户ID
app_id, %% 应用ID
cluster_id %% 集群ID
}). expiration, %% 过期时间
#%% rabbit_amqqueue.erl (Line 245-256)
%% 持久化消息的存储逻辑
-define(RABBIT_MSG_HEADER_VSN, 1).
-record('basic.message', {
content_type, %% 内容类型
content_encoding, %% 内容编码
headers, %% 自定义头信息
delivery_mode, %% 1=非持久化, 2=持久化
priority, %% 优先级
correlation_id, %% 关联ID
reply_to, %% 回复队列
expiration, %% 过期时间
message_id, %% 消息ID
timestamp, %% 时间戳
type, %% 消息类型
user_id, %% 用户ID
app_id, %% 应用ID
cluster_id %% 集群ID
}). message_id, %% 消息ID
#%% rabbit_amqqueue.erl (Line 245-256)
%% 持久化消息的存储逻辑
-define(RABBIT_MSG_HEADER_VSN, 1).
-record('basic.message', {
content_type, %% 内容类型
content_encoding, %% 内容编码
headers, %% 自定义头信息
delivery_mode, %% 1=非持久化, 2=持久化
priority, %% 优先级
correlation_id, %% 关联ID
reply_to, %% 回复队列
expiration, %% 过期时间
message_id, %% 消息ID
timestamp, %% 时间戳
type, %% 消息类型
user_id, %% 用户ID
app_id, %% 应用ID
cluster_id %% 集群ID
}). timestamp, %% 时间戳
#%% rabbit_amqqueue.erl (Line 245-256)
%% 持久化消息的存储逻辑
-define(RABBIT_MSG_HEADER_VSN, 1).
-record('basic.message', {
content_type, %% 内容类型
content_encoding, %% 内容编码
headers, %% 自定义头信息
delivery_mode, %% 1=非持久化, 2=持久化
priority, %% 优先级
correlation_id, %% 关联ID
reply_to, %% 回复队列
expiration, %% 过期时间
message_id, %% 消息ID
timestamp, %% 时间戳
type, %% 消息类型
user_id, %% 用户ID
app_id, %% 应用ID
cluster_id %% 集群ID
}). type, %% 消息类型
#%% rabbit_amqqueue.erl (Line 245-256)
%% 持久化消息的存储逻辑
-define(RABBIT_MSG_HEADER_VSN, 1).
-record('basic.message', {
content_type, %% 内容类型
content_encoding, %% 内容编码
headers, %% 自定义头信息
delivery_mode, %% 1=非持久化, 2=持久化
priority, %% 优先级
correlation_id, %% 关联ID
reply_to, %% 回复队列
expiration, %% 过期时间
message_id, %% 消息ID
timestamp, %% 时间戳
type, %% 消息类型
user_id, %% 用户ID
app_id, %% 应用ID
cluster_id %% 集群ID
}). user_id, %% 用户ID
#%% rabbit_amqqueue.erl (Line 245-256)
%% 持久化消息的存储逻辑
-define(RABBIT_MSG_HEADER_VSN, 1).
-record('basic.message', {
content_type, %% 内容类型
content_encoding, %% 内容编码
headers, %% 自定义头信息
delivery_mode, %% 1=非持久化, 2=持久化
priority, %% 优先级
correlation_id, %% 关联ID
reply_to, %% 回复队列
expiration, %% 过期时间
message_id, %% 消息ID
timestamp, %% 时间戳
type, %% 消息类型
user_id, %% 用户ID
app_id, %% 应用ID
cluster_id %% 集群ID
}). app_id, %% 应用ID
#%% rabbit_amqqueue.erl (Line 245-256)
%% 持久化消息的存储逻辑
-define(RABBIT_MSG_HEADER_VSN, 1).
-record('basic.message', {
content_type, %% 内容类型
content_encoding, %% 内容编码
headers, %% 自定义头信息
delivery_mode, %% 1=非持久化, 2=持久化
priority, %% 优先级
correlation_id, %% 关联ID
reply_to, %% 回复队列
expiration, %% 过期时间
message_id, %% 消息ID
timestamp, %% 时间戳
type, %% 消息类型
user_id, %% 用户ID
app_id, %% 应用ID
cluster_id %% 集群ID
}). cluster_id %% 集群ID
#%% rabbit_amqqueue.erl (Line 245-256)
%% 持久化消息的存储逻辑
-define(RABBIT_MSG_HEADER_VSN, 1).
-record('basic.message', {
content_type, %% 内容类型
content_encoding, %% 内容编码
headers, %% 自定义头信息
delivery_mode, %% 1=非持久化, 2=持久化
priority, %% 优先级
correlation_id, %% 关联ID
reply_to, %% 回复队列
expiration, %% 过期时间
message_id, %% 消息ID
timestamp, %% 时间戳
type, %% 消息类型
user_id, %% 用户ID
app_id, %% 应用ID
cluster_id %% 集群ID
}).}).
2.2.2 消息写入磁盘的流程
#basic_message{delivery_mode = 2}) ->
%% 1. 序列化消息
Binary = rabbit_binary_generator:serialize_message(Msg),
%% 2. 计算校验和
Checksum = erlang:adler32(Binary),
%% 3. 写入消息存储文件
case file:write_file(MsgFile, <<Checksum:32, Binary/binary>>, [raw, append]) of
ok ->
%% 4. 更新内存索引
update_index(MsgId, MsgFile),
{ok, MsgId};
{error, Reason} ->
{error, Reason}
end.%% rabbit_msg_store.erl (Line 412-435)
#basic_message{delivery_mode = 2}) ->
%% 1. 序列化消息
Binary = rabbit_binary_generator:serialize_message(Msg),
%% 2. 计算校验和
Checksum = erlang:adler32(Binary),
%% 3. 写入消息存储文件
case file:write_file(MsgFile, <<Checksum:32, Binary/binary>>, [raw, append]) of
ok ->
%% 4. 更新内存索引
update_index(MsgId, MsgFile),
{ok, MsgId};
{error, Reason} ->
{error, Reason}
end.%% 消息持久化到磁盘的核心函数
#basic_message{delivery_mode = 2}) ->
%% 1. 序列化消息
Binary = rabbit_binary_generator:serialize_message(Msg),
%% 2. 计算校验和
Checksum = erlang:adler32(Binary),
%% 3. 写入消息存储文件
case file:write_file(MsgFile, <<Checksum:32, Binary/binary>>, [raw, append]) of
ok ->
%% 4. 更新内存索引
update_index(MsgId, MsgFile),
{ok, MsgId};
{error, Reason} ->
{error, Reason}
end.write_message(Msg = #basic_message{delivery_mode = 2}) ->
#basic_message{delivery_mode = 2}) ->
%% 1. 序列化消息
Binary = rabbit_binary_generator:serialize_message(Msg),
%% 2. 计算校验和
Checksum = erlang:adler32(Binary),
%% 3. 写入消息存储文件
case file:write_file(MsgFile, <<Checksum:32, Binary/binary>>, [raw, append]) of
ok ->
%% 4. 更新内存索引
update_index(MsgId, MsgFile),
{ok, MsgId};
{error, Reason} ->
{error, Reason}
end. %% 1. 序列化消息
#basic_message{delivery_mode = 2}) ->
%% 1. 序列化消息
Binary = rabbit_binary_generator:serialize_message(Msg),
%% 2. 计算校验和
Checksum = erlang:adler32(Binary),
%% 3. 写入消息存储文件
case file:write_file(MsgFile, <<Checksum:32, Binary/binary>>, [raw, append]) of
ok ->
%% 4. 更新内存索引
update_index(MsgId, MsgFile),
{ok, MsgId};
{error, Reason} ->
{error, Reason}
end. Binary = rabbit_binary_generator:serialize_message(Msg),
#basic_message{delivery_mode = 2}) ->
%% 1. 序列化消息
Binary = rabbit_binary_generator:serialize_message(Msg),
%% 2. 计算校验和
Checksum = erlang:adler32(Binary),
%% 3. 写入消息存储文件
case file:write_file(MsgFile, <<Checksum:32, Binary/binary>>, [raw, append]) of
ok ->
%% 4. 更新内存索引
update_index(MsgId, MsgFile),
{ok, MsgId};
{error, Reason} ->
{error, Reason}
end.
#basic_message{delivery_mode = 2}) ->
%% 1. 序列化消息
Binary = rabbit_binary_generator:serialize_message(Msg),
%% 2. 计算校验和
Checksum = erlang:adler32(Binary),
%% 3. 写入消息存储文件
case file:write_file(MsgFile, <<Checksum:32, Binary/binary>>, [raw, append]) of
ok ->
%% 4. 更新内存索引
update_index(MsgId, MsgFile),
{ok, MsgId};
{error, Reason} ->
{error, Reason}
end. %% 2. 计算校验和
#basic_message{delivery_mode = 2}) ->
%% 1. 序列化消息
Binary = rabbit_binary_generator:serialize_message(Msg),
%% 2. 计算校验和
Checksum = erlang:adler32(Binary),
%% 3. 写入消息存储文件
case file:write_file(MsgFile, <<Checksum:32, Binary/binary>>, [raw, append]) of
ok ->
%% 4. 更新内存索引
update_index(MsgId, MsgFile),
{ok, MsgId};
{error, Reason} ->
{error, Reason}
end. Checksum = erlang:adler32(Binary),
#basic_message{delivery_mode = 2}) ->
%% 1. 序列化消息
Binary = rabbit_binary_generator:serialize_message(Msg),
%% 2. 计算校验和
Checksum = erlang:adler32(Binary),
%% 3. 写入消息存储文件
case file:write_file(MsgFile, <<Checksum:32, Binary/binary>>, [raw, append]) of
ok ->
%% 4. 更新内存索引
update_index(MsgId, MsgFile),
{ok, MsgId};
{error, Reason} ->
{error, Reason}
end.
#basic_message{delivery_mode = 2}) ->
%% 1. 序列化消息
Binary = rabbit_binary_generator:serialize_message(Msg),
%% 2. 计算校验和
Checksum = erlang:adler32(Binary),
%% 3. 写入消息存储文件
case file:write_file(MsgFile, <<Checksum:32, Binary/binary>>, [raw, append]) of
ok ->
%% 4. 更新内存索引
update_index(MsgId, MsgFile),
{ok, MsgId};
{error, Reason} ->
{error, Reason}
end. %% 3. 写入消息存储文件
#basic_message{delivery_mode = 2}) ->
%% 1. 序列化消息
Binary = rabbit_binary_generator:serialize_message(Msg),
%% 2. 计算校验和
Checksum = erlang:adler32(Binary),
%% 3. 写入消息存储文件
case file:write_file(MsgFile, <<Checksum:32, Binary/binary>>, [raw, append]) of
ok ->
%% 4. 更新内存索引
update_index(MsgId, MsgFile),
{ok, MsgId};
{error, Reason} ->
{error, Reason}
end. case file:write_file(MsgFile, <<Checksum:32, Binary/binary>>, [raw, append]) of
#basic_message{delivery_mode = 2}) ->
%% 1. 序列化消息
Binary = rabbit_binary_generator:serialize_message(Msg),
%% 2. 计算校验和
Checksum = erlang:adler32(Binary),
%% 3. 写入消息存储文件
case file:write_file(MsgFile, <<Checksum:32, Binary/binary>>, [raw, append]) of
ok ->
%% 4. 更新内存索引
update_index(MsgId, MsgFile),
{ok, MsgId};
{error, Reason} ->
{error, Reason}
end. ok ->
#basic_message{delivery_mode = 2}) ->
%% 1. 序列化消息
Binary = rabbit_binary_generator:serialize_message(Msg),
%% 2. 计算校验和
Checksum = erlang:adler32(Binary),
%% 3. 写入消息存储文件
case file:write_file(MsgFile, <<Checksum:32, Binary/binary>>, [raw, append]) of
ok ->
%% 4. 更新内存索引
update_index(MsgId, MsgFile),
{ok, MsgId};
{error, Reason} ->
{error, Reason}
end. %% 4. 更新内存索引
#basic_message{delivery_mode = 2}) ->
%% 1. 序列化消息
Binary = rabbit_binary_generator:serialize_message(Msg),
%% 2. 计算校验和
Checksum = erlang:adler32(Binary),
%% 3. 写入消息存储文件
case file:write_file(MsgFile, <<Checksum:32, Binary/binary>>, [raw, append]) of
ok ->
%% 4. 更新内存索引
update_index(MsgId, MsgFile),
{ok, MsgId};
{error, Reason} ->
{error, Reason}
end. update_index(MsgId, MsgFile),
#basic_message{delivery_mode = 2}) ->
%% 1. 序列化消息
Binary = rabbit_binary_generator:serialize_message(Msg),
%% 2. 计算校验和
Checksum = erlang:adler32(Binary),
%% 3. 写入消息存储文件
case file:write_file(MsgFile, <<Checksum:32, Binary/binary>>, [raw, append]) of
ok ->
%% 4. 更新内存索引
update_index(MsgId, MsgFile),
{ok, MsgId};
{error, Reason} ->
{error, Reason}
end. {ok, MsgId};
#basic_message{delivery_mode = 2}) ->
%% 1. 序列化消息
Binary = rabbit_binary_generator:serialize_message(Msg),
%% 2. 计算校验和
Checksum = erlang:adler32(Binary),
%% 3. 写入消息存储文件
case file:write_file(MsgFile, <<Checksum:32, Binary/binary>>, [raw, append]) of
ok ->
%% 4. 更新内存索引
update_index(MsgId, MsgFile),
{ok, MsgId};
{error, Reason} ->
{error, Reason}
end. {error, Reason} ->
#basic_message{delivery_mode = 2}) ->
%% 1. 序列化消息
Binary = rabbit_binary_generator:serialize_message(Msg),
%% 2. 计算校验和
Checksum = erlang:adler32(Binary),
%% 3. 写入消息存储文件
case file:write_file(MsgFile, <<Checksum:32, Binary/binary>>, [raw, append]) of
ok ->
%% 4. 更新内存索引
update_index(MsgId, MsgFile),
{ok, MsgId};
{error, Reason} ->
{error, Reason}
end. {error, Reason}
#basic_message{delivery_mode = 2}) ->
%% 1. 序列化消息
Binary = rabbit_binary_generator:serialize_message(Msg),
%% 2. 计算校验和
Checksum = erlang:adler32(Binary),
%% 3. 写入消息存储文件
case file:write_file(MsgFile, <<Checksum:32, Binary/binary>>, [raw, append]) of
ok ->
%% 4. 更新内存索引
update_index(MsgId, MsgFile),
{ok, MsgId};
{error, Reason} ->
{error, Reason}
end. end.
2.3 持久化配置实战
2.3.1 Spring Boot 完整配置示例
java
#/**
* RabbitMQ 持久化配置类
*
* 核心要点:
* 1. 交换机必须设置 durable = true
* 2. 队列必须设置 durable = true
* 3. 发送消息时必须设置 deliveryMode = 2
*/
@Configuration
public class RabbitMQDurableConfig {
// 1. 声明持久化交换机
@Bean
public DirectExchange durableExchange() {
return new DirectExchange(
"durable.exchange", // 交换机名称
true, // durable: 持久化到磁盘
false // autoDelete: 不自动删除
);
}
// 2. 声明持久化队列
@Bean
public Queue durableQueue() {
return QueueBuilder
.durable("durable.queue") // 队列持久化
.withArgument("x-max-length", 10000) // 队列最大长度
.withArgument("x-max-length-bytes", 1073741824) // 队列最大大小(1GB)
.build();
}
// 3. 绑定交换机和队列
@Bean
public Binding binding(Queue durableQueue, DirectExchange durableExchange) {
return BindingBuilder
.bind(durableQueue)
.to(durableExchange)
.with("routing.key");
}
}/**`
`#/**
* RabbitMQ 持久化配置类
*
* 核心要点:
* 1. 交换机必须设置 durable = true
* 2. 队列必须设置 durable = true
* 3. 发送消息时必须设置 deliveryMode = 2
*/
@Configuration
public class RabbitMQDurableConfig {
// 1. 声明持久化交换机
@Bean
public DirectExchange durableExchange() {
return new DirectExchange(
"durable.exchange", // 交换机名称
true, // durable: 持久化到磁盘
false // autoDelete: 不自动删除
);
}
// 2. 声明持久化队列
@Bean
public Queue durableQueue() {
return QueueBuilder
.durable("durable.queue") // 队列持久化
.withArgument("x-max-length", 10000) // 队列最大长度
.withArgument("x-max-length-bytes", 1073741824) // 队列最大大小(1GB)
.build();
}
// 3. 绑定交换机和队列
@Bean
public Binding binding(Queue durableQueue, DirectExchange durableExchange) {
return BindingBuilder
.bind(durableQueue)
.to(durableExchange)
.with("routing.key");
}
} * RabbitMQ 持久化配置类`
`#/**
* RabbitMQ 持久化配置类
*
* 核心要点:
* 1. 交换机必须设置 durable = true
* 2. 队列必须设置 durable = true
* 3. 发送消息时必须设置 deliveryMode = 2
*/
@Configuration
public class RabbitMQDurableConfig {
// 1. 声明持久化交换机
@Bean
public DirectExchange durableExchange() {
return new DirectExchange(
"durable.exchange", // 交换机名称
true, // durable: 持久化到磁盘
false // autoDelete: 不自动删除
);
}
// 2. 声明持久化队列
@Bean
public Queue durableQueue() {
return QueueBuilder
.durable("durable.queue") // 队列持久化
.withArgument("x-max-length", 10000) // 队列最大长度
.withArgument("x-max-length-bytes", 1073741824) // 队列最大大小(1GB)
.build();
}
// 3. 绑定交换机和队列
@Bean
public Binding binding(Queue durableQueue, DirectExchange durableExchange) {
return BindingBuilder
.bind(durableQueue)
.to(durableExchange)
.with("routing.key");
}
} * `
`#/**
* RabbitMQ 持久化配置类
*
* 核心要点:
* 1. 交换机必须设置 durable = true
* 2. 队列必须设置 durable = true
* 3. 发送消息时必须设置 deliveryMode = 2
*/
@Configuration
public class RabbitMQDurableConfig {
// 1. 声明持久化交换机
@Bean
public DirectExchange durableExchange() {
return new DirectExchange(
"durable.exchange", // 交换机名称
true, // durable: 持久化到磁盘
false // autoDelete: 不自动删除
);
}
// 2. 声明持久化队列
@Bean
public Queue durableQueue() {
return QueueBuilder
.durable("durable.queue") // 队列持久化
.withArgument("x-max-length", 10000) // 队列最大长度
.withArgument("x-max-length-bytes", 1073741824) // 队列最大大小(1GB)
.build();
}
// 3. 绑定交换机和队列
@Bean
public Binding binding(Queue durableQueue, DirectExchange durableExchange) {
return BindingBuilder
.bind(durableQueue)
.to(durableExchange)
.with("routing.key");
}
} * 核心要点:`
`#/**
* RabbitMQ 持久化配置类
*
* 核心要点:
* 1. 交换机必须设置 durable = true
* 2. 队列必须设置 durable = true
* 3. 发送消息时必须设置 deliveryMode = 2
*/
@Configuration
public class RabbitMQDurableConfig {
// 1. 声明持久化交换机
@Bean
public DirectExchange durableExchange() {
return new DirectExchange(
"durable.exchange", // 交换机名称
true, // durable: 持久化到磁盘
false // autoDelete: 不自动删除
);
}
// 2. 声明持久化队列
@Bean
public Queue durableQueue() {
return QueueBuilder
.durable("durable.queue") // 队列持久化
.withArgument("x-max-length", 10000) // 队列最大长度
.withArgument("x-max-length-bytes", 1073741824) // 队列最大大小(1GB)
.build();
}
// 3. 绑定交换机和队列
@Bean
public Binding binding(Queue durableQueue, DirectExchange durableExchange) {
return BindingBuilder
.bind(durableQueue)
.to(durableExchange)
.with("routing.key");
}
} * 1. 交换机必须设置 durable = true`
`#/**
* RabbitMQ 持久化配置类
*
* 核心要点:
* 1. 交换机必须设置 durable = true
* 2. 队列必须设置 durable = true
* 3. 发送消息时必须设置 deliveryMode = 2
*/
@Configuration
public class RabbitMQDurableConfig {
// 1. 声明持久化交换机
@Bean
public DirectExchange durableExchange() {
return new DirectExchange(
"durable.exchange", // 交换机名称
true, // durable: 持久化到磁盘
false // autoDelete: 不自动删除
);
}
// 2. 声明持久化队列
@Bean
public Queue durableQueue() {
return QueueBuilder
.durable("durable.queue") // 队列持久化
.withArgument("x-max-length", 10000) // 队列最大长度
.withArgument("x-max-length-bytes", 1073741824) // 队列最大大小(1GB)
.build();
}
// 3. 绑定交换机和队列
@Bean
public Binding binding(Queue durableQueue, DirectExchange durableExchange) {
return BindingBuilder
.bind(durableQueue)
.to(durableExchange)
.with("routing.key");
}
} * 2. 队列必须设置 durable = true`
`#/**
* RabbitMQ 持久化配置类
*
* 核心要点:
* 1. 交换机必须设置 durable = true
* 2. 队列必须设置 durable = true
* 3. 发送消息时必须设置 deliveryMode = 2
*/
@Configuration
public class RabbitMQDurableConfig {
// 1. 声明持久化交换机
@Bean
public DirectExchange durableExchange() {
return new DirectExchange(
"durable.exchange", // 交换机名称
true, // durable: 持久化到磁盘
false // autoDelete: 不自动删除
);
}
// 2. 声明持久化队列
@Bean
public Queue durableQueue() {
return QueueBuilder
.durable("durable.queue") // 队列持久化
.withArgument("x-max-length", 10000) // 队列最大长度
.withArgument("x-max-length-bytes", 1073741824) // 队列最大大小(1GB)
.build();
}
// 3. 绑定交换机和队列
@Bean
public Binding binding(Queue durableQueue, DirectExchange durableExchange) {
return BindingBuilder
.bind(durableQueue)
.to(durableExchange)
.with("routing.key");
}
} * 3. 发送消息时必须设置 deliveryMode = 2`
`#/**
* RabbitMQ 持久化配置类
*
* 核心要点:
* 1. 交换机必须设置 durable = true
* 2. 队列必须设置 durable = true
* 3. 发送消息时必须设置 deliveryMode = 2
*/
@Configuration
public class RabbitMQDurableConfig {
// 1. 声明持久化交换机
@Bean
public DirectExchange durableExchange() {
return new DirectExchange(
"durable.exchange", // 交换机名称
true, // durable: 持久化到磁盘
false // autoDelete: 不自动删除
);
}
// 2. 声明持久化队列
@Bean
public Queue durableQueue() {
return QueueBuilder
.durable("durable.queue") // 队列持久化
.withArgument("x-max-length", 10000) // 队列最大长度
.withArgument("x-max-length-bytes", 1073741824) // 队列最大大小(1GB)
.build();
}
// 3. 绑定交换机和队列
@Bean
public Binding binding(Queue durableQueue, DirectExchange durableExchange) {
return BindingBuilder
.bind(durableQueue)
.to(durableExchange)
.with("routing.key");
}
} */`
`#/**
* RabbitMQ 持久化配置类
*
* 核心要点:
* 1. 交换机必须设置 durable = true
* 2. 队列必须设置 durable = true
* 3. 发送消息时必须设置 deliveryMode = 2
*/
@Configuration
public class RabbitMQDurableConfig {
// 1. 声明持久化交换机
@Bean
public DirectExchange durableExchange() {
return new DirectExchange(
"durable.exchange", // 交换机名称
true, // durable: 持久化到磁盘
false // autoDelete: 不自动删除
);
}
// 2. 声明持久化队列
@Bean
public Queue durableQueue() {
return QueueBuilder
.durable("durable.queue") // 队列持久化
.withArgument("x-max-length", 10000) // 队列最大长度
.withArgument("x-max-length-bytes", 1073741824) // 队列最大大小(1GB)
.build();
}
// 3. 绑定交换机和队列
@Bean
public Binding binding(Queue durableQueue, DirectExchange durableExchange) {
return BindingBuilder
.bind(durableQueue)
.to(durableExchange)
.with("routing.key");
}
}@Configuration`
`#/**
* RabbitMQ 持久化配置类
*
* 核心要点:
* 1. 交换机必须设置 durable = true
* 2. 队列必须设置 durable = true
* 3. 发送消息时必须设置 deliveryMode = 2
*/
@Configuration
public class RabbitMQDurableConfig {
// 1. 声明持久化交换机
@Bean
public DirectExchange durableExchange() {
return new DirectExchange(
"durable.exchange", // 交换机名称
true, // durable: 持久化到磁盘
false // autoDelete: 不自动删除
);
}
// 2. 声明持久化队列
@Bean
public Queue durableQueue() {
return QueueBuilder
.durable("durable.queue") // 队列持久化
.withArgument("x-max-length", 10000) // 队列最大长度
.withArgument("x-max-length-bytes", 1073741824) // 队列最大大小(1GB)
.build();
}
// 3. 绑定交换机和队列
@Bean
public Binding binding(Queue durableQueue, DirectExchange durableExchange) {
return BindingBuilder
.bind(durableQueue)
.to(durableExchange)
.with("routing.key");
}
}public class RabbitMQDurableConfig {`
`#/**
* RabbitMQ 持久化配置类
*
* 核心要点:
* 1. 交换机必须设置 durable = true
* 2. 队列必须设置 durable = true
* 3. 发送消息时必须设置 deliveryMode = 2
*/
@Configuration
public class RabbitMQDurableConfig {
// 1. 声明持久化交换机
@Bean
public DirectExchange durableExchange() {
return new DirectExchange(
"durable.exchange", // 交换机名称
true, // durable: 持久化到磁盘
false // autoDelete: 不自动删除
);
}
// 2. 声明持久化队列
@Bean
public Queue durableQueue() {
return QueueBuilder
.durable("durable.queue") // 队列持久化
.withArgument("x-max-length", 10000) // 队列最大长度
.withArgument("x-max-length-bytes", 1073741824) // 队列最大大小(1GB)
.build();
}
// 3. 绑定交换机和队列
@Bean
public Binding binding(Queue durableQueue, DirectExchange durableExchange) {
return BindingBuilder
.bind(durableQueue)
.to(durableExchange)
.with("routing.key");
}
}`
`#/**
* RabbitMQ 持久化配置类
*
* 核心要点:
* 1. 交换机必须设置 durable = true
* 2. 队列必须设置 durable = true
* 3. 发送消息时必须设置 deliveryMode = 2
*/
@Configuration
public class RabbitMQDurableConfig {
// 1. 声明持久化交换机
@Bean
public DirectExchange durableExchange() {
return new DirectExchange(
"durable.exchange", // 交换机名称
true, // durable: 持久化到磁盘
false // autoDelete: 不自动删除
);
}
// 2. 声明持久化队列
@Bean
public Queue durableQueue() {
return QueueBuilder
.durable("durable.queue") // 队列持久化
.withArgument("x-max-length", 10000) // 队列最大长度
.withArgument("x-max-length-bytes", 1073741824) // 队列最大大小(1GB)
.build();
}
// 3. 绑定交换机和队列
@Bean
public Binding binding(Queue durableQueue, DirectExchange durableExchange) {
return BindingBuilder
.bind(durableQueue)
.to(durableExchange)
.with("routing.key");
}
} // 1. 声明持久化交换机`
`#/**
* RabbitMQ 持久化配置类
*
* 核心要点:
* 1. 交换机必须设置 durable = true
* 2. 队列必须设置 durable = true
* 3. 发送消息时必须设置 deliveryMode = 2
*/
@Configuration
public class RabbitMQDurableConfig {
// 1. 声明持久化交换机
@Bean
public DirectExchange durableExchange() {
return new DirectExchange(
"durable.exchange", // 交换机名称
true, // durable: 持久化到磁盘
false // autoDelete: 不自动删除
);
}
// 2. 声明持久化队列
@Bean
public Queue durableQueue() {
return QueueBuilder
.durable("durable.queue") // 队列持久化
.withArgument("x-max-length", 10000) // 队列最大长度
.withArgument("x-max-length-bytes", 1073741824) // 队列最大大小(1GB)
.build();
}
// 3. 绑定交换机和队列
@Bean
public Binding binding(Queue durableQueue, DirectExchange durableExchange) {
return BindingBuilder
.bind(durableQueue)
.to(durableExchange)
.with("routing.key");
}
} @Bean`
`#/**
* RabbitMQ 持久化配置类
*
* 核心要点:
* 1. 交换机必须设置 durable = true
* 2. 队列必须设置 durable = true
* 3. 发送消息时必须设置 deliveryMode = 2
*/
@Configuration
public class RabbitMQDurableConfig {
// 1. 声明持久化交换机
@Bean
public DirectExchange durableExchange() {
return new DirectExchange(
"durable.exchange", // 交换机名称
true, // durable: 持久化到磁盘
false // autoDelete: 不自动删除
);
}
// 2. 声明持久化队列
@Bean
public Queue durableQueue() {
return QueueBuilder
.durable("durable.queue") // 队列持久化
.withArgument("x-max-length", 10000) // 队列最大长度
.withArgument("x-max-length-bytes", 1073741824) // 队列最大大小(1GB)
.build();
}
// 3. 绑定交换机和队列
@Bean
public Binding binding(Queue durableQueue, DirectExchange durableExchange) {
return BindingBuilder
.bind(durableQueue)
.to(durableExchange)
.with("routing.key");
}
} public DirectExchange durableExchange() {`
`#/**
* RabbitMQ 持久化配置类
*
* 核心要点:
* 1. 交换机必须设置 durable = true
* 2. 队列必须设置 durable = true
* 3. 发送消息时必须设置 deliveryMode = 2
*/
@Configuration
public class RabbitMQDurableConfig {
// 1. 声明持久化交换机
@Bean
public DirectExchange durableExchange() {
return new DirectExchange(
"durable.exchange", // 交换机名称
true, // durable: 持久化到磁盘
false // autoDelete: 不自动删除
);
}
// 2. 声明持久化队列
@Bean
public Queue durableQueue() {
return QueueBuilder
.durable("durable.queue") // 队列持久化
.withArgument("x-max-length", 10000) // 队列最大长度
.withArgument("x-max-length-bytes", 1073741824) // 队列最大大小(1GB)
.build();
}
// 3. 绑定交换机和队列
@Bean
public Binding binding(Queue durableQueue, DirectExchange durableExchange) {
return BindingBuilder
.bind(durableQueue)
.to(durableExchange)
.with("routing.key");
}
} return new DirectExchange(`
`#/**
* RabbitMQ 持久化配置类
*
* 核心要点:
* 1. 交换机必须设置 durable = true
* 2. 队列必须设置 durable = true
* 3. 发送消息时必须设置 deliveryMode = 2
*/
@Configuration
public class RabbitMQDurableConfig {
// 1. 声明持久化交换机
@Bean
public DirectExchange durableExchange() {
return new DirectExchange(
"durable.exchange", // 交换机名称
true, // durable: 持久化到磁盘
false // autoDelete: 不自动删除
);
}
// 2. 声明持久化队列
@Bean
public Queue durableQueue() {
return QueueBuilder
.durable("durable.queue") // 队列持久化
.withArgument("x-max-length", 10000) // 队列最大长度
.withArgument("x-max-length-bytes", 1073741824) // 队列最大大小(1GB)
.build();
}
// 3. 绑定交换机和队列
@Bean
public Binding binding(Queue durableQueue, DirectExchange durableExchange) {
return BindingBuilder
.bind(durableQueue)
.to(durableExchange)
.with("routing.key");
}
} "durable.exchange", // 交换机名称`
`#/**
* RabbitMQ 持久化配置类
*
* 核心要点:
* 1. 交换机必须设置 durable = true
* 2. 队列必须设置 durable = true
* 3. 发送消息时必须设置 deliveryMode = 2
*/
@Configuration
public class RabbitMQDurableConfig {
// 1. 声明持久化交换机
@Bean
public DirectExchange durableExchange() {
return new DirectExchange(
"durable.exchange", // 交换机名称
true, // durable: 持久化到磁盘
false // autoDelete: 不自动删除
);
}
// 2. 声明持久化队列
@Bean
public Queue durableQueue() {
return QueueBuilder
.durable("durable.queue") // 队列持久化
.withArgument("x-max-length", 10000) // 队列最大长度
.withArgument("x-max-length-bytes", 1073741824) // 队列最大大小(1GB)
.build();
}
// 3. 绑定交换机和队列
@Bean
public Binding binding(Queue durableQueue, DirectExchange durableExchange) {
return BindingBuilder
.bind(durableQueue)
.to(durableExchange)
.with("routing.key");
}
} true, // durable: 持久化到磁盘`
`#/**
* RabbitMQ 持久化配置类
*
* 核心要点:
* 1. 交换机必须设置 durable = true
* 2. 队列必须设置 durable = true
* 3. 发送消息时必须设置 deliveryMode = 2
*/
@Configuration
public class RabbitMQDurableConfig {
// 1. 声明持久化交换机
@Bean
public DirectExchange durableExchange() {
return new DirectExchange(
"durable.exchange", // 交换机名称
true, // durable: 持久化到磁盘
false // autoDelete: 不自动删除
);
}
// 2. 声明持久化队列
@Bean
public Queue durableQueue() {
return QueueBuilder
.durable("durable.queue") // 队列持久化
.withArgument("x-max-length", 10000) // 队列最大长度
.withArgument("x-max-length-bytes", 1073741824) // 队列最大大小(1GB)
.build();
}
// 3. 绑定交换机和队列
@Bean
public Binding binding(Queue durableQueue, DirectExchange durableExchange) {
return BindingBuilder
.bind(durableQueue)
.to(durableExchange)
.with("routing.key");
}
} false // autoDelete: 不自动删除`
`#/**
* RabbitMQ 持久化配置类
*
* 核心要点:
* 1. 交换机必须设置 durable = true
* 2. 队列必须设置 durable = true
* 3. 发送消息时必须设置 deliveryMode = 2
*/
@Configuration
public class RabbitMQDurableConfig {
// 1. 声明持久化交换机
@Bean
public DirectExchange durableExchange() {
return new DirectExchange(
"durable.exchange", // 交换机名称
true, // durable: 持久化到磁盘
false // autoDelete: 不自动删除
);
}
// 2. 声明持久化队列
@Bean
public Queue durableQueue() {
return QueueBuilder
.durable("durable.queue") // 队列持久化
.withArgument("x-max-length", 10000) // 队列最大长度
.withArgument("x-max-length-bytes", 1073741824) // 队列最大大小(1GB)
.build();
}
// 3. 绑定交换机和队列
@Bean
public Binding binding(Queue durableQueue, DirectExchange durableExchange) {
return BindingBuilder
.bind(durableQueue)
.to(durableExchange)
.with("routing.key");
}
} );`
`#/**
* RabbitMQ 持久化配置类
*
* 核心要点:
* 1. 交换机必须设置 durable = true
* 2. 队列必须设置 durable = true
* 3. 发送消息时必须设置 deliveryMode = 2
*/
@Configuration
public class RabbitMQDurableConfig {
// 1. 声明持久化交换机
@Bean
public DirectExchange durableExchange() {
return new DirectExchange(
"durable.exchange", // 交换机名称
true, // durable: 持久化到磁盘
false // autoDelete: 不自动删除
);
}
// 2. 声明持久化队列
@Bean
public Queue durableQueue() {
return QueueBuilder
.durable("durable.queue") // 队列持久化
.withArgument("x-max-length", 10000) // 队列最大长度
.withArgument("x-max-length-bytes", 1073741824) // 队列最大大小(1GB)
.build();
}
// 3. 绑定交换机和队列
@Bean
public Binding binding(Queue durableQueue, DirectExchange durableExchange) {
return BindingBuilder
.bind(durableQueue)
.to(durableExchange)
.with("routing.key");
}
} }`
`#/**
* RabbitMQ 持久化配置类
*
* 核心要点:
* 1. 交换机必须设置 durable = true
* 2. 队列必须设置 durable = true
* 3. 发送消息时必须设置 deliveryMode = 2
*/
@Configuration
public class RabbitMQDurableConfig {
// 1. 声明持久化交换机
@Bean
public DirectExchange durableExchange() {
return new DirectExchange(
"durable.exchange", // 交换机名称
true, // durable: 持久化到磁盘
false // autoDelete: 不自动删除
);
}
// 2. 声明持久化队列
@Bean
public Queue durableQueue() {
return QueueBuilder
.durable("durable.queue") // 队列持久化
.withArgument("x-max-length", 10000) // 队列最大长度
.withArgument("x-max-length-bytes", 1073741824) // 队列最大大小(1GB)
.build();
}
// 3. 绑定交换机和队列
@Bean
public Binding binding(Queue durableQueue, DirectExchange durableExchange) {
return BindingBuilder
.bind(durableQueue)
.to(durableExchange)
.with("routing.key");
}
}`
`#/**
* RabbitMQ 持久化配置类
*
* 核心要点:
* 1. 交换机必须设置 durable = true
* 2. 队列必须设置 durable = true
* 3. 发送消息时必须设置 deliveryMode = 2
*/
@Configuration
public class RabbitMQDurableConfig {
// 1. 声明持久化交换机
@Bean
public DirectExchange durableExchange() {
return new DirectExchange(
"durable.exchange", // 交换机名称
true, // durable: 持久化到磁盘
false // autoDelete: 不自动删除
);
}
// 2. 声明持久化队列
@Bean
public Queue durableQueue() {
return QueueBuilder
.durable("durable.queue") // 队列持久化
.withArgument("x-max-length", 10000) // 队列最大长度
.withArgument("x-max-length-bytes", 1073741824) // 队列最大大小(1GB)
.build();
}
// 3. 绑定交换机和队列
@Bean
public Binding binding(Queue durableQueue, DirectExchange durableExchange) {
return BindingBuilder
.bind(durableQueue)
.to(durableExchange)
.with("routing.key");
}
} // 2. 声明持久化队列`
`#/**
* RabbitMQ 持久化配置类
*
* 核心要点:
* 1. 交换机必须设置 durable = true
* 2. 队列必须设置 durable = true
* 3. 发送消息时必须设置 deliveryMode = 2
*/
@Configuration
public class RabbitMQDurableConfig {
// 1. 声明持久化交换机
@Bean
public DirectExchange durableExchange() {
return new DirectExchange(
"durable.exchange", // 交换机名称
true, // durable: 持久化到磁盘
false // autoDelete: 不自动删除
);
}
// 2. 声明持久化队列
@Bean
public Queue durableQueue() {
return QueueBuilder
.durable("durable.queue") // 队列持久化
.withArgument("x-max-length", 10000) // 队列最大长度
.withArgument("x-max-length-bytes", 1073741824) // 队列最大大小(1GB)
.build();
}
// 3. 绑定交换机和队列
@Bean
public Binding binding(Queue durableQueue, DirectExchange durableExchange) {
return BindingBuilder
.bind(durableQueue)
.to(durableExchange)
.with("routing.key");
}
} @Bean`
`#/**
* RabbitMQ 持久化配置类
*
* 核心要点:
* 1. 交换机必须设置 durable = true
* 2. 队列必须设置 durable = true
* 3. 发送消息时必须设置 deliveryMode = 2
*/
@Configuration
public class RabbitMQDurableConfig {
// 1. 声明持久化交换机
@Bean
public DirectExchange durableExchange() {
return new DirectExchange(
"durable.exchange", // 交换机名称
true, // durable: 持久化到磁盘
false // autoDelete: 不自动删除
);
}
// 2. 声明持久化队列
@Bean
public Queue durableQueue() {
return QueueBuilder
.durable("durable.queue") // 队列持久化
.withArgument("x-max-length", 10000) // 队列最大长度
.withArgument("x-max-length-bytes", 1073741824) // 队列最大大小(1GB)
.build();
}
// 3. 绑定交换机和队列
@Bean
public Binding binding(Queue durableQueue, DirectExchange durableExchange) {
return BindingBuilder
.bind(durableQueue)
.to(durableExchange)
.with("routing.key");
}
} public Queue durableQueue() {`
`#/**
* RabbitMQ 持久化配置类
*
* 核心要点:
* 1. 交换机必须设置 durable = true
* 2. 队列必须设置 durable = true
* 3. 发送消息时必须设置 deliveryMode = 2
*/
@Configuration
public class RabbitMQDurableConfig {
// 1. 声明持久化交换机
@Bean
public DirectExchange durableExchange() {
return new DirectExchange(
"durable.exchange", // 交换机名称
true, // durable: 持久化到磁盘
false // autoDelete: 不自动删除
);
}
// 2. 声明持久化队列
@Bean
public Queue durableQueue() {
return QueueBuilder
.durable("durable.queue") // 队列持久化
.withArgument("x-max-length", 10000) // 队列最大长度
.withArgument("x-max-length-bytes", 1073741824) // 队列最大大小(1GB)
.build();
}
// 3. 绑定交换机和队列
@Bean
public Binding binding(Queue durableQueue, DirectExchange durableExchange) {
return BindingBuilder
.bind(durableQueue)
.to(durableExchange)
.with("routing.key");
}
} return QueueBuilder`
`#/**
* RabbitMQ 持久化配置类
*
* 核心要点:
* 1. 交换机必须设置 durable = true
* 2. 队列必须设置 durable = true
* 3. 发送消息时必须设置 deliveryMode = 2
*/
@Configuration
public class RabbitMQDurableConfig {
// 1. 声明持久化交换机
@Bean
public DirectExchange durableExchange() {
return new DirectExchange(
"durable.exchange", // 交换机名称
true, // durable: 持久化到磁盘
false // autoDelete: 不自动删除
);
}
// 2. 声明持久化队列
@Bean
public Queue durableQueue() {
return QueueBuilder
.durable("durable.queue") // 队列持久化
.withArgument("x-max-length", 10000) // 队列最大长度
.withArgument("x-max-length-bytes", 1073741824) // 队列最大大小(1GB)
.build();
}
// 3. 绑定交换机和队列
@Bean
public Binding binding(Queue durableQueue, DirectExchange durableExchange) {
return BindingBuilder
.bind(durableQueue)
.to(durableExchange)
.with("routing.key");
}
} .durable("durable.queue") // 队列持久化`
`#/**
* RabbitMQ 持久化配置类
*
* 核心要点:
* 1. 交换机必须设置 durable = true
* 2. 队列必须设置 durable = true
* 3. 发送消息时必须设置 deliveryMode = 2
*/
@Configuration
public class RabbitMQDurableConfig {
// 1. 声明持久化交换机
@Bean
public DirectExchange durableExchange() {
return new DirectExchange(
"durable.exchange", // 交换机名称
true, // durable: 持久化到磁盘
false // autoDelete: 不自动删除
);
}
// 2. 声明持久化队列
@Bean
public Queue durableQueue() {
return QueueBuilder
.durable("durable.queue") // 队列持久化
.withArgument("x-max-length", 10000) // 队列最大长度
.withArgument("x-max-length-bytes", 1073741824) // 队列最大大小(1GB)
.build();
}
// 3. 绑定交换机和队列
@Bean
public Binding binding(Queue durableQueue, DirectExchange durableExchange) {
return BindingBuilder
.bind(durableQueue)
.to(durableExchange)
.with("routing.key");
}
} .withArgument("x-max-length", 10000) // 队列最大长度`
`#/**
* RabbitMQ 持久化配置类
*
* 核心要点:
* 1. 交换机必须设置 durable = true
* 2. 队列必须设置 durable = true
* 3. 发送消息时必须设置 deliveryMode = 2
*/
@Configuration
public class RabbitMQDurableConfig {
// 1. 声明持久化交换机
@Bean
public DirectExchange durableExchange() {
return new DirectExchange(
"durable.exchange", // 交换机名称
true, // durable: 持久化到磁盘
false // autoDelete: 不自动删除
);
}
// 2. 声明持久化队列
@Bean
public Queue durableQueue() {
return QueueBuilder
.durable("durable.queue") // 队列持久化
.withArgument("x-max-length", 10000) // 队列最大长度
.withArgument("x-max-length-bytes", 1073741824) // 队列最大大小(1GB)
.build();
}
// 3. 绑定交换机和队列
@Bean
public Binding binding(Queue durableQueue, DirectExchange durableExchange) {
return BindingBuilder
.bind(durableQueue)
.to(durableExchange)
.with("routing.key");
}
} .withArgument("x-max-length-bytes", 1073741824) // 队列最大大小(1GB)`
`#/**
* RabbitMQ 持久化配置类
*
* 核心要点:
* 1. 交换机必须设置 durable = true
* 2. 队列必须设置 durable = true
* 3. 发送消息时必须设置 deliveryMode = 2
*/
@Configuration
public class RabbitMQDurableConfig {
// 1. 声明持久化交换机
@Bean
public DirectExchange durableExchange() {
return new DirectExchange(
"durable.exchange", // 交换机名称
true, // durable: 持久化到磁盘
false // autoDelete: 不自动删除
);
}
// 2. 声明持久化队列
@Bean
public Queue durableQueue() {
return QueueBuilder
.durable("durable.queue") // 队列持久化
.withArgument("x-max-length", 10000) // 队列最大长度
.withArgument("x-max-length-bytes", 1073741824) // 队列最大大小(1GB)
.build();
}
// 3. 绑定交换机和队列
@Bean
public Binding binding(Queue durableQueue, DirectExchange durableExchange) {
return BindingBuilder
.bind(durableQueue)
.to(durableExchange)
.with("routing.key");
}
} .build();`
`#/**
* RabbitMQ 持久化配置类
*
* 核心要点:
* 1. 交换机必须设置 durable = true
* 2. 队列必须设置 durable = true
* 3. 发送消息时必须设置 deliveryMode = 2
*/
@Configuration
public class RabbitMQDurableConfig {
// 1. 声明持久化交换机
@Bean
public DirectExchange durableExchange() {
return new DirectExchange(
"durable.exchange", // 交换机名称
true, // durable: 持久化到磁盘
false // autoDelete: 不自动删除
);
}
// 2. 声明持久化队列
@Bean
public Queue durableQueue() {
return QueueBuilder
.durable("durable.queue") // 队列持久化
.withArgument("x-max-length", 10000) // 队列最大长度
.withArgument("x-max-length-bytes", 1073741824) // 队列最大大小(1GB)
.build();
}
// 3. 绑定交换机和队列
@Bean
public Binding binding(Queue durableQueue, DirectExchange durableExchange) {
return BindingBuilder
.bind(durableQueue)
.to(durableExchange)
.with("routing.key");
}
} }`
`#/**
* RabbitMQ 持久化配置类
*
* 核心要点:
* 1. 交换机必须设置 durable = true
* 2. 队列必须设置 durable = true
* 3. 发送消息时必须设置 deliveryMode = 2
*/
@Configuration
public class RabbitMQDurableConfig {
// 1. 声明持久化交换机
@Bean
public DirectExchange durableExchange() {
return new DirectExchange(
"durable.exchange", // 交换机名称
true, // durable: 持久化到磁盘
false // autoDelete: 不自动删除
);
}
// 2. 声明持久化队列
@Bean
public Queue durableQueue() {
return QueueBuilder
.durable("durable.queue") // 队列持久化
.withArgument("x-max-length", 10000) // 队列最大长度
.withArgument("x-max-length-bytes", 1073741824) // 队列最大大小(1GB)
.build();
}
// 3. 绑定交换机和队列
@Bean
public Binding binding(Queue durableQueue, DirectExchange durableExchange) {
return BindingBuilder
.bind(durableQueue)
.to(durableExchange)
.with("routing.key");
}
}`
`#/**
* RabbitMQ 持久化配置类
*
* 核心要点:
* 1. 交换机必须设置 durable = true
* 2. 队列必须设置 durable = true
* 3. 发送消息时必须设置 deliveryMode = 2
*/
@Configuration
public class RabbitMQDurableConfig {
// 1. 声明持久化交换机
@Bean
public DirectExchange durableExchange() {
return new DirectExchange(
"durable.exchange", // 交换机名称
true, // durable: 持久化到磁盘
false // autoDelete: 不自动删除
);
}
// 2. 声明持久化队列
@Bean
public Queue durableQueue() {
return QueueBuilder
.durable("durable.queue") // 队列持久化
.withArgument("x-max-length", 10000) // 队列最大长度
.withArgument("x-max-length-bytes", 1073741824) // 队列最大大小(1GB)
.build();
}
// 3. 绑定交换机和队列
@Bean
public Binding binding(Queue durableQueue, DirectExchange durableExchange) {
return BindingBuilder
.bind(durableQueue)
.to(durableExchange)
.with("routing.key");
}
} // 3. 绑定交换机和队列`
`#/**
* RabbitMQ 持久化配置类
*
* 核心要点:
* 1. 交换机必须设置 durable = true
* 2. 队列必须设置 durable = true
* 3. 发送消息时必须设置 deliveryMode = 2
*/
@Configuration
public class RabbitMQDurableConfig {
// 1. 声明持久化交换机
@Bean
public DirectExchange durableExchange() {
return new DirectExchange(
"durable.exchange", // 交换机名称
true, // durable: 持久化到磁盘
false // autoDelete: 不自动删除
);
}
// 2. 声明持久化队列
@Bean
public Queue durableQueue() {
return QueueBuilder
.durable("durable.queue") // 队列持久化
.withArgument("x-max-length", 10000) // 队列最大长度
.withArgument("x-max-length-bytes", 1073741824) // 队列最大大小(1GB)
.build();
}
// 3. 绑定交换机和队列
@Bean
public Binding binding(Queue durableQueue, DirectExchange durableExchange) {
return BindingBuilder
.bind(durableQueue)
.to(durableExchange)
.with("routing.key");
}
} @Bean`
`#/**
* RabbitMQ 持久化配置类
*
* 核心要点:
* 1. 交换机必须设置 durable = true
* 2. 队列必须设置 durable = true
* 3. 发送消息时必须设置 deliveryMode = 2
*/
@Configuration
public class RabbitMQDurableConfig {
// 1. 声明持久化交换机
@Bean
public DirectExchange durableExchange() {
return new DirectExchange(
"durable.exchange", // 交换机名称
true, // durable: 持久化到磁盘
false // autoDelete: 不自动删除
);
}
// 2. 声明持久化队列
@Bean
public Queue durableQueue() {
return QueueBuilder
.durable("durable.queue") // 队列持久化
.withArgument("x-max-length", 10000) // 队列最大长度
.withArgument("x-max-length-bytes", 1073741824) // 队列最大大小(1GB)
.build();
}
// 3. 绑定交换机和队列
@Bean
public Binding binding(Queue durableQueue, DirectExchange durableExchange) {
return BindingBuilder
.bind(durableQueue)
.to(durableExchange)
.with("routing.key");
}
} public Binding binding(Queue durableQueue, DirectExchange durableExchange) {`
`#/**
* RabbitMQ 持久化配置类
*
* 核心要点:
* 1. 交换机必须设置 durable = true
* 2. 队列必须设置 durable = true
* 3. 发送消息时必须设置 deliveryMode = 2
*/
@Configuration
public class RabbitMQDurableConfig {
// 1. 声明持久化交换机
@Bean
public DirectExchange durableExchange() {
return new DirectExchange(
"durable.exchange", // 交换机名称
true, // durable: 持久化到磁盘
false // autoDelete: 不自动删除
);
}
// 2. 声明持久化队列
@Bean
public Queue durableQueue() {
return QueueBuilder
.durable("durable.queue") // 队列持久化
.withArgument("x-max-length", 10000) // 队列最大长度
.withArgument("x-max-length-bytes", 1073741824) // 队列最大大小(1GB)
.build();
}
// 3. 绑定交换机和队列
@Bean
public Binding binding(Queue durableQueue, DirectExchange durableExchange) {
return BindingBuilder
.bind(durableQueue)
.to(durableExchange)
.with("routing.key");
}
} return BindingBuilder`
`#/**
* RabbitMQ 持久化配置类
*
* 核心要点:
* 1. 交换机必须设置 durable = true
* 2. 队列必须设置 durable = true
* 3. 发送消息时必须设置 deliveryMode = 2
*/
@Configuration
public class RabbitMQDurableConfig {
// 1. 声明持久化交换机
@Bean
public DirectExchange durableExchange() {
return new DirectExchange(
"durable.exchange", // 交换机名称
true, // durable: 持久化到磁盘
false // autoDelete: 不自动删除
);
}
// 2. 声明持久化队列
@Bean
public Queue durableQueue() {
return QueueBuilder
.durable("durable.queue") // 队列持久化
.withArgument("x-max-length", 10000) // 队列最大长度
.withArgument("x-max-length-bytes", 1073741824) // 队列最大大小(1GB)
.build();
}
// 3. 绑定交换机和队列
@Bean
public Binding binding(Queue durableQueue, DirectExchange durableExchange) {
return BindingBuilder
.bind(durableQueue)
.to(durableExchange)
.with("routing.key");
}
} .bind(durableQueue)`
`#/**
* RabbitMQ 持久化配置类
*
* 核心要点:
* 1. 交换机必须设置 durable = true
* 2. 队列必须设置 durable = true
* 3. 发送消息时必须设置 deliveryMode = 2
*/
@Configuration
public class RabbitMQDurableConfig {
// 1. 声明持久化交换机
@Bean
public DirectExchange durableExchange() {
return new DirectExchange(
"durable.exchange", // 交换机名称
true, // durable: 持久化到磁盘
false // autoDelete: 不自动删除
);
}
// 2. 声明持久化队列
@Bean
public Queue durableQueue() {
return QueueBuilder
.durable("durable.queue") // 队列持久化
.withArgument("x-max-length", 10000) // 队列最大长度
.withArgument("x-max-length-bytes", 1073741824) // 队列最大大小(1GB)
.build();
}
// 3. 绑定交换机和队列
@Bean
public Binding binding(Queue durableQueue, DirectExchange durableExchange) {
return BindingBuilder
.bind(durableQueue)
.to(durableExchange)
.with("routing.key");
}
} .to(durableExchange)`
`#/**
* RabbitMQ 持久化配置类
*
* 核心要点:
* 1. 交换机必须设置 durable = true
* 2. 队列必须设置 durable = true
* 3. 发送消息时必须设置 deliveryMode = 2
*/
@Configuration
public class RabbitMQDurableConfig {
// 1. 声明持久化交换机
@Bean
public DirectExchange durableExchange() {
return new DirectExchange(
"durable.exchange", // 交换机名称
true, // durable: 持久化到磁盘
false // autoDelete: 不自动删除
);
}
// 2. 声明持久化队列
@Bean
public Queue durableQueue() {
return QueueBuilder
.durable("durable.queue") // 队列持久化
.withArgument("x-max-length", 10000) // 队列最大长度
.withArgument("x-max-length-bytes", 1073741824) // 队列最大大小(1GB)
.build();
}
// 3. 绑定交换机和队列
@Bean
public Binding binding(Queue durableQueue, DirectExchange durableExchange) {
return BindingBuilder
.bind(durableQueue)
.to(durableExchange)
.with("routing.key");
}
} .with("routing.key");`
`#/**
* RabbitMQ 持久化配置类
*
* 核心要点:
* 1. 交换机必须设置 durable = true
* 2. 队列必须设置 durable = true
* 3. 发送消息时必须设置 deliveryMode = 2
*/
@Configuration
public class RabbitMQDurableConfig {
// 1. 声明持久化交换机
@Bean
public DirectExchange durableExchange() {
return new DirectExchange(
"durable.exchange", // 交换机名称
true, // durable: 持久化到磁盘
false // autoDelete: 不自动删除
);
}
// 2. 声明持久化队列
@Bean
public Queue durableQueue() {
return QueueBuilder
.durable("durable.queue") // 队列持久化
.withArgument("x-max-length", 10000) // 队列最大长度
.withArgument("x-max-length-bytes", 1073741824) // 队列最大大小(1GB)
.build();
}
// 3. 绑定交换机和队列
@Bean
public Binding binding(Queue durableQueue, DirectExchange durableExchange) {
return BindingBuilder
.bind(durableQueue)
.to(durableExchange)
.with("routing.key");
}
} }`
`#/**
* RabbitMQ 持久化配置类
*
* 核心要点:
* 1. 交换机必须设置 durable = true
* 2. 队列必须设置 durable = true
* 3. 发送消息时必须设置 deliveryMode = 2
*/
@Configuration
public class RabbitMQDurableConfig {
// 1. 声明持久化交换机
@Bean
public DirectExchange durableExchange() {
return new DirectExchange(
"durable.exchange", // 交换机名称
true, // durable: 持久化到磁盘
false // autoDelete: 不自动删除
);
}
// 2. 声明持久化队列
@Bean
public Queue durableQueue() {
return QueueBuilder
.durable("durable.queue") // 队列持久化
.withArgument("x-max-length", 10000) // 队列最大长度
.withArgument("x-max-length-bytes", 1073741824) // 队列最大大小(1GB)
.build();
}
// 3. 绑定交换机和队列
@Bean
public Binding binding(Queue durableQueue, DirectExchange durableExchange) {
return BindingBuilder
.bind(durableQueue)
.to(durableExchange)
.with("routing.key");
}
}}
2.3.2 发送持久化消息
java
#/**
* 发送持久化消息
*
* 关键点:
* 1. MessagePostProcessor 设置 deliveryMode
* 2. 确保交换机和队列都已持久化
*/
@Service
public class MessageProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
public void sendDurableMessage(String messageContent) {
// 使用 MessagePostProcessor 设置消息属性
rabbitTemplate.convertAndSend(
"durable.exchange",
"routing.key",
messageContent,
new MessagePostProcessor() {
@Override
public Message postProcessMessage(Message message) throws AmqpException {
// 设置消息持久化(deliveryMode = 2)
message.getMessageProperties()
.setDeliveryMode(MessageDeliveryMode.PERSISTENT);
// 设置消息ID(用于去重)
message.getMessageProperties()
.setMessageId(UUID.randomUUID().toString());
return message;
}
}
);
}
}/**`
`#/**
* 发送持久化消息
*
* 关键点:
* 1. MessagePostProcessor 设置 deliveryMode
* 2. 确保交换机和队列都已持久化
*/
@Service
public class MessageProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
public void sendDurableMessage(String messageContent) {
// 使用 MessagePostProcessor 设置消息属性
rabbitTemplate.convertAndSend(
"durable.exchange",
"routing.key",
messageContent,
new MessagePostProcessor() {
@Override
public Message postProcessMessage(Message message) throws AmqpException {
// 设置消息持久化(deliveryMode = 2)
message.getMessageProperties()
.setDeliveryMode(MessageDeliveryMode.PERSISTENT);
// 设置消息ID(用于去重)
message.getMessageProperties()
.setMessageId(UUID.randomUUID().toString());
return message;
}
}
);
}
} * 发送持久化消息`
`#/**
* 发送持久化消息
*
* 关键点:
* 1. MessagePostProcessor 设置 deliveryMode
* 2. 确保交换机和队列都已持久化
*/
@Service
public class MessageProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
public void sendDurableMessage(String messageContent) {
// 使用 MessagePostProcessor 设置消息属性
rabbitTemplate.convertAndSend(
"durable.exchange",
"routing.key",
messageContent,
new MessagePostProcessor() {
@Override
public Message postProcessMessage(Message message) throws AmqpException {
// 设置消息持久化(deliveryMode = 2)
message.getMessageProperties()
.setDeliveryMode(MessageDeliveryMode.PERSISTENT);
// 设置消息ID(用于去重)
message.getMessageProperties()
.setMessageId(UUID.randomUUID().toString());
return message;
}
}
);
}
} * `
`#/**
* 发送持久化消息
*
* 关键点:
* 1. MessagePostProcessor 设置 deliveryMode
* 2. 确保交换机和队列都已持久化
*/
@Service
public class MessageProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
public void sendDurableMessage(String messageContent) {
// 使用 MessagePostProcessor 设置消息属性
rabbitTemplate.convertAndSend(
"durable.exchange",
"routing.key",
messageContent,
new MessagePostProcessor() {
@Override
public Message postProcessMessage(Message message) throws AmqpException {
// 设置消息持久化(deliveryMode = 2)
message.getMessageProperties()
.setDeliveryMode(MessageDeliveryMode.PERSISTENT);
// 设置消息ID(用于去重)
message.getMessageProperties()
.setMessageId(UUID.randomUUID().toString());
return message;
}
}
);
}
} * 关键点:`
`#/**
* 发送持久化消息
*
* 关键点:
* 1. MessagePostProcessor 设置 deliveryMode
* 2. 确保交换机和队列都已持久化
*/
@Service
public class MessageProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
public void sendDurableMessage(String messageContent) {
// 使用 MessagePostProcessor 设置消息属性
rabbitTemplate.convertAndSend(
"durable.exchange",
"routing.key",
messageContent,
new MessagePostProcessor() {
@Override
public Message postProcessMessage(Message message) throws AmqpException {
// 设置消息持久化(deliveryMode = 2)
message.getMessageProperties()
.setDeliveryMode(MessageDeliveryMode.PERSISTENT);
// 设置消息ID(用于去重)
message.getMessageProperties()
.setMessageId(UUID.randomUUID().toString());
return message;
}
}
);
}
} * 1. MessagePostProcessor 设置 deliveryMode`
`#/**
* 发送持久化消息
*
* 关键点:
* 1. MessagePostProcessor 设置 deliveryMode
* 2. 确保交换机和队列都已持久化
*/
@Service
public class MessageProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
public void sendDurableMessage(String messageContent) {
// 使用 MessagePostProcessor 设置消息属性
rabbitTemplate.convertAndSend(
"durable.exchange",
"routing.key",
messageContent,
new MessagePostProcessor() {
@Override
public Message postProcessMessage(Message message) throws AmqpException {
// 设置消息持久化(deliveryMode = 2)
message.getMessageProperties()
.setDeliveryMode(MessageDeliveryMode.PERSISTENT);
// 设置消息ID(用于去重)
message.getMessageProperties()
.setMessageId(UUID.randomUUID().toString());
return message;
}
}
);
}
} * 2. 确保交换机和队列都已持久化`
`#/**
* 发送持久化消息
*
* 关键点:
* 1. MessagePostProcessor 设置 deliveryMode
* 2. 确保交换机和队列都已持久化
*/
@Service
public class MessageProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
public void sendDurableMessage(String messageContent) {
// 使用 MessagePostProcessor 设置消息属性
rabbitTemplate.convertAndSend(
"durable.exchange",
"routing.key",
messageContent,
new MessagePostProcessor() {
@Override
public Message postProcessMessage(Message message) throws AmqpException {
// 设置消息持久化(deliveryMode = 2)
message.getMessageProperties()
.setDeliveryMode(MessageDeliveryMode.PERSISTENT);
// 设置消息ID(用于去重)
message.getMessageProperties()
.setMessageId(UUID.randomUUID().toString());
return message;
}
}
);
}
} */`
`#/**
* 发送持久化消息
*
* 关键点:
* 1. MessagePostProcessor 设置 deliveryMode
* 2. 确保交换机和队列都已持久化
*/
@Service
public class MessageProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
public void sendDurableMessage(String messageContent) {
// 使用 MessagePostProcessor 设置消息属性
rabbitTemplate.convertAndSend(
"durable.exchange",
"routing.key",
messageContent,
new MessagePostProcessor() {
@Override
public Message postProcessMessage(Message message) throws AmqpException {
// 设置消息持久化(deliveryMode = 2)
message.getMessageProperties()
.setDeliveryMode(MessageDeliveryMode.PERSISTENT);
// 设置消息ID(用于去重)
message.getMessageProperties()
.setMessageId(UUID.randomUUID().toString());
return message;
}
}
);
}
}@Service`
`#/**
* 发送持久化消息
*
* 关键点:
* 1. MessagePostProcessor 设置 deliveryMode
* 2. 确保交换机和队列都已持久化
*/
@Service
public class MessageProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
public void sendDurableMessage(String messageContent) {
// 使用 MessagePostProcessor 设置消息属性
rabbitTemplate.convertAndSend(
"durable.exchange",
"routing.key",
messageContent,
new MessagePostProcessor() {
@Override
public Message postProcessMessage(Message message) throws AmqpException {
// 设置消息持久化(deliveryMode = 2)
message.getMessageProperties()
.setDeliveryMode(MessageDeliveryMode.PERSISTENT);
// 设置消息ID(用于去重)
message.getMessageProperties()
.setMessageId(UUID.randomUUID().toString());
return message;
}
}
);
}
}public class MessageProducer {`
`#/**
* 发送持久化消息
*
* 关键点:
* 1. MessagePostProcessor 设置 deliveryMode
* 2. 确保交换机和队列都已持久化
*/
@Service
public class MessageProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
public void sendDurableMessage(String messageContent) {
// 使用 MessagePostProcessor 设置消息属性
rabbitTemplate.convertAndSend(
"durable.exchange",
"routing.key",
messageContent,
new MessagePostProcessor() {
@Override
public Message postProcessMessage(Message message) throws AmqpException {
// 设置消息持久化(deliveryMode = 2)
message.getMessageProperties()
.setDeliveryMode(MessageDeliveryMode.PERSISTENT);
// 设置消息ID(用于去重)
message.getMessageProperties()
.setMessageId(UUID.randomUUID().toString());
return message;
}
}
);
}
}`
`#/**
* 发送持久化消息
*
* 关键点:
* 1. MessagePostProcessor 设置 deliveryMode
* 2. 确保交换机和队列都已持久化
*/
@Service
public class MessageProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
public void sendDurableMessage(String messageContent) {
// 使用 MessagePostProcessor 设置消息属性
rabbitTemplate.convertAndSend(
"durable.exchange",
"routing.key",
messageContent,
new MessagePostProcessor() {
@Override
public Message postProcessMessage(Message message) throws AmqpException {
// 设置消息持久化(deliveryMode = 2)
message.getMessageProperties()
.setDeliveryMode(MessageDeliveryMode.PERSISTENT);
// 设置消息ID(用于去重)
message.getMessageProperties()
.setMessageId(UUID.randomUUID().toString());
return message;
}
}
);
}
} @Autowired`
`#/**
* 发送持久化消息
*
* 关键点:
* 1. MessagePostProcessor 设置 deliveryMode
* 2. 确保交换机和队列都已持久化
*/
@Service
public class MessageProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
public void sendDurableMessage(String messageContent) {
// 使用 MessagePostProcessor 设置消息属性
rabbitTemplate.convertAndSend(
"durable.exchange",
"routing.key",
messageContent,
new MessagePostProcessor() {
@Override
public Message postProcessMessage(Message message) throws AmqpException {
// 设置消息持久化(deliveryMode = 2)
message.getMessageProperties()
.setDeliveryMode(MessageDeliveryMode.PERSISTENT);
// 设置消息ID(用于去重)
message.getMessageProperties()
.setMessageId(UUID.randomUUID().toString());
return message;
}
}
);
}
} private RabbitTemplate rabbitTemplate;`
`#/**
* 发送持久化消息
*
* 关键点:
* 1. MessagePostProcessor 设置 deliveryMode
* 2. 确保交换机和队列都已持久化
*/
@Service
public class MessageProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
public void sendDurableMessage(String messageContent) {
// 使用 MessagePostProcessor 设置消息属性
rabbitTemplate.convertAndSend(
"durable.exchange",
"routing.key",
messageContent,
new MessagePostProcessor() {
@Override
public Message postProcessMessage(Message message) throws AmqpException {
// 设置消息持久化(deliveryMode = 2)
message.getMessageProperties()
.setDeliveryMode(MessageDeliveryMode.PERSISTENT);
// 设置消息ID(用于去重)
message.getMessageProperties()
.setMessageId(UUID.randomUUID().toString());
return message;
}
}
);
}
}`
`#/**
* 发送持久化消息
*
* 关键点:
* 1. MessagePostProcessor 设置 deliveryMode
* 2. 确保交换机和队列都已持久化
*/
@Service
public class MessageProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
public void sendDurableMessage(String messageContent) {
// 使用 MessagePostProcessor 设置消息属性
rabbitTemplate.convertAndSend(
"durable.exchange",
"routing.key",
messageContent,
new MessagePostProcessor() {
@Override
public Message postProcessMessage(Message message) throws AmqpException {
// 设置消息持久化(deliveryMode = 2)
message.getMessageProperties()
.setDeliveryMode(MessageDeliveryMode.PERSISTENT);
// 设置消息ID(用于去重)
message.getMessageProperties()
.setMessageId(UUID.randomUUID().toString());
return message;
}
}
);
}
} public void sendDurableMessage(String messageContent) {`
`#/**
* 发送持久化消息
*
* 关键点:
* 1. MessagePostProcessor 设置 deliveryMode
* 2. 确保交换机和队列都已持久化
*/
@Service
public class MessageProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
public void sendDurableMessage(String messageContent) {
// 使用 MessagePostProcessor 设置消息属性
rabbitTemplate.convertAndSend(
"durable.exchange",
"routing.key",
messageContent,
new MessagePostProcessor() {
@Override
public Message postProcessMessage(Message message) throws AmqpException {
// 设置消息持久化(deliveryMode = 2)
message.getMessageProperties()
.setDeliveryMode(MessageDeliveryMode.PERSISTENT);
// 设置消息ID(用于去重)
message.getMessageProperties()
.setMessageId(UUID.randomUUID().toString());
return message;
}
}
);
}
} // 使用 MessagePostProcessor 设置消息属性`
`#/**
* 发送持久化消息
*
* 关键点:
* 1. MessagePostProcessor 设置 deliveryMode
* 2. 确保交换机和队列都已持久化
*/
@Service
public class MessageProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
public void sendDurableMessage(String messageContent) {
// 使用 MessagePostProcessor 设置消息属性
rabbitTemplate.convertAndSend(
"durable.exchange",
"routing.key",
messageContent,
new MessagePostProcessor() {
@Override
public Message postProcessMessage(Message message) throws AmqpException {
// 设置消息持久化(deliveryMode = 2)
message.getMessageProperties()
.setDeliveryMode(MessageDeliveryMode.PERSISTENT);
// 设置消息ID(用于去重)
message.getMessageProperties()
.setMessageId(UUID.randomUUID().toString());
return message;
}
}
);
}
} rabbitTemplate.convertAndSend(`
`#/**
* 发送持久化消息
*
* 关键点:
* 1. MessagePostProcessor 设置 deliveryMode
* 2. 确保交换机和队列都已持久化
*/
@Service
public class MessageProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
public void sendDurableMessage(String messageContent) {
// 使用 MessagePostProcessor 设置消息属性
rabbitTemplate.convertAndSend(
"durable.exchange",
"routing.key",
messageContent,
new MessagePostProcessor() {
@Override
public Message postProcessMessage(Message message) throws AmqpException {
// 设置消息持久化(deliveryMode = 2)
message.getMessageProperties()
.setDeliveryMode(MessageDeliveryMode.PERSISTENT);
// 设置消息ID(用于去重)
message.getMessageProperties()
.setMessageId(UUID.randomUUID().toString());
return message;
}
}
);
}
} "durable.exchange",`
`#/**
* 发送持久化消息
*
* 关键点:
* 1. MessagePostProcessor 设置 deliveryMode
* 2. 确保交换机和队列都已持久化
*/
@Service
public class MessageProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
public void sendDurableMessage(String messageContent) {
// 使用 MessagePostProcessor 设置消息属性
rabbitTemplate.convertAndSend(
"durable.exchange",
"routing.key",
messageContent,
new MessagePostProcessor() {
@Override
public Message postProcessMessage(Message message) throws AmqpException {
// 设置消息持久化(deliveryMode = 2)
message.getMessageProperties()
.setDeliveryMode(MessageDeliveryMode.PERSISTENT);
// 设置消息ID(用于去重)
message.getMessageProperties()
.setMessageId(UUID.randomUUID().toString());
return message;
}
}
);
}
} "routing.key",`
`#/**
* 发送持久化消息
*
* 关键点:
* 1. MessagePostProcessor 设置 deliveryMode
* 2. 确保交换机和队列都已持久化
*/
@Service
public class MessageProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
public void sendDurableMessage(String messageContent) {
// 使用 MessagePostProcessor 设置消息属性
rabbitTemplate.convertAndSend(
"durable.exchange",
"routing.key",
messageContent,
new MessagePostProcessor() {
@Override
public Message postProcessMessage(Message message) throws AmqpException {
// 设置消息持久化(deliveryMode = 2)
message.getMessageProperties()
.setDeliveryMode(MessageDeliveryMode.PERSISTENT);
// 设置消息ID(用于去重)
message.getMessageProperties()
.setMessageId(UUID.randomUUID().toString());
return message;
}
}
);
}
} messageContent,`
`#/**
* 发送持久化消息
*
* 关键点:
* 1. MessagePostProcessor 设置 deliveryMode
* 2. 确保交换机和队列都已持久化
*/
@Service
public class MessageProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
public void sendDurableMessage(String messageContent) {
// 使用 MessagePostProcessor 设置消息属性
rabbitTemplate.convertAndSend(
"durable.exchange",
"routing.key",
messageContent,
new MessagePostProcessor() {
@Override
public Message postProcessMessage(Message message) throws AmqpException {
// 设置消息持久化(deliveryMode = 2)
message.getMessageProperties()
.setDeliveryMode(MessageDeliveryMode.PERSISTENT);
// 设置消息ID(用于去重)
message.getMessageProperties()
.setMessageId(UUID.randomUUID().toString());
return message;
}
}
);
}
} new MessagePostProcessor() {`
`#/**
* 发送持久化消息
*
* 关键点:
* 1. MessagePostProcessor 设置 deliveryMode
* 2. 确保交换机和队列都已持久化
*/
@Service
public class MessageProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
public void sendDurableMessage(String messageContent) {
// 使用 MessagePostProcessor 设置消息属性
rabbitTemplate.convertAndSend(
"durable.exchange",
"routing.key",
messageContent,
new MessagePostProcessor() {
@Override
public Message postProcessMessage(Message message) throws AmqpException {
// 设置消息持久化(deliveryMode = 2)
message.getMessageProperties()
.setDeliveryMode(MessageDeliveryMode.PERSISTENT);
// 设置消息ID(用于去重)
message.getMessageProperties()
.setMessageId(UUID.randomUUID().toString());
return message;
}
}
);
}
} @Override`
`#/**
* 发送持久化消息
*
* 关键点:
* 1. MessagePostProcessor 设置 deliveryMode
* 2. 确保交换机和队列都已持久化
*/
@Service
public class MessageProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
public void sendDurableMessage(String messageContent) {
// 使用 MessagePostProcessor 设置消息属性
rabbitTemplate.convertAndSend(
"durable.exchange",
"routing.key",
messageContent,
new MessagePostProcessor() {
@Override
public Message postProcessMessage(Message message) throws AmqpException {
// 设置消息持久化(deliveryMode = 2)
message.getMessageProperties()
.setDeliveryMode(MessageDeliveryMode.PERSISTENT);
// 设置消息ID(用于去重)
message.getMessageProperties()
.setMessageId(UUID.randomUUID().toString());
return message;
}
}
);
}
} public Message postProcessMessage(Message message) throws AmqpException {`
`#/**
* 发送持久化消息
*
* 关键点:
* 1. MessagePostProcessor 设置 deliveryMode
* 2. 确保交换机和队列都已持久化
*/
@Service
public class MessageProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
public void sendDurableMessage(String messageContent) {
// 使用 MessagePostProcessor 设置消息属性
rabbitTemplate.convertAndSend(
"durable.exchange",
"routing.key",
messageContent,
new MessagePostProcessor() {
@Override
public Message postProcessMessage(Message message) throws AmqpException {
// 设置消息持久化(deliveryMode = 2)
message.getMessageProperties()
.setDeliveryMode(MessageDeliveryMode.PERSISTENT);
// 设置消息ID(用于去重)
message.getMessageProperties()
.setMessageId(UUID.randomUUID().toString());
return message;
}
}
);
}
} // 设置消息持久化(deliveryMode = 2)`
`#/**
* 发送持久化消息
*
* 关键点:
* 1. MessagePostProcessor 设置 deliveryMode
* 2. 确保交换机和队列都已持久化
*/
@Service
public class MessageProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
public void sendDurableMessage(String messageContent) {
// 使用 MessagePostProcessor 设置消息属性
rabbitTemplate.convertAndSend(
"durable.exchange",
"routing.key",
messageContent,
new MessagePostProcessor() {
@Override
public Message postProcessMessage(Message message) throws AmqpException {
// 设置消息持久化(deliveryMode = 2)
message.getMessageProperties()
.setDeliveryMode(MessageDeliveryMode.PERSISTENT);
// 设置消息ID(用于去重)
message.getMessageProperties()
.setMessageId(UUID.randomUUID().toString());
return message;
}
}
);
}
} message.getMessageProperties()`
`#/**
* 发送持久化消息
*
* 关键点:
* 1. MessagePostProcessor 设置 deliveryMode
* 2. 确保交换机和队列都已持久化
*/
@Service
public class MessageProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
public void sendDurableMessage(String messageContent) {
// 使用 MessagePostProcessor 设置消息属性
rabbitTemplate.convertAndSend(
"durable.exchange",
"routing.key",
messageContent,
new MessagePostProcessor() {
@Override
public Message postProcessMessage(Message message) throws AmqpException {
// 设置消息持久化(deliveryMode = 2)
message.getMessageProperties()
.setDeliveryMode(MessageDeliveryMode.PERSISTENT);
// 设置消息ID(用于去重)
message.getMessageProperties()
.setMessageId(UUID.randomUUID().toString());
return message;
}
}
);
}
} .setDeliveryMode(MessageDeliveryMode.PERSISTENT);`
`#/**
* 发送持久化消息
*
* 关键点:
* 1. MessagePostProcessor 设置 deliveryMode
* 2. 确保交换机和队列都已持久化
*/
@Service
public class MessageProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
public void sendDurableMessage(String messageContent) {
// 使用 MessagePostProcessor 设置消息属性
rabbitTemplate.convertAndSend(
"durable.exchange",
"routing.key",
messageContent,
new MessagePostProcessor() {
@Override
public Message postProcessMessage(Message message) throws AmqpException {
// 设置消息持久化(deliveryMode = 2)
message.getMessageProperties()
.setDeliveryMode(MessageDeliveryMode.PERSISTENT);
// 设置消息ID(用于去重)
message.getMessageProperties()
.setMessageId(UUID.randomUUID().toString());
return message;
}
}
);
}
} `
`#/**
* 发送持久化消息
*
* 关键点:
* 1. MessagePostProcessor 设置 deliveryMode
* 2. 确保交换机和队列都已持久化
*/
@Service
public class MessageProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
public void sendDurableMessage(String messageContent) {
// 使用 MessagePostProcessor 设置消息属性
rabbitTemplate.convertAndSend(
"durable.exchange",
"routing.key",
messageContent,
new MessagePostProcessor() {
@Override
public Message postProcessMessage(Message message) throws AmqpException {
// 设置消息持久化(deliveryMode = 2)
message.getMessageProperties()
.setDeliveryMode(MessageDeliveryMode.PERSISTENT);
// 设置消息ID(用于去重)
message.getMessageProperties()
.setMessageId(UUID.randomUUID().toString());
return message;
}
}
);
}
} // 设置消息ID(用于去重)`
`#/**
* 发送持久化消息
*
* 关键点:
* 1. MessagePostProcessor 设置 deliveryMode
* 2. 确保交换机和队列都已持久化
*/
@Service
public class MessageProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
public void sendDurableMessage(String messageContent) {
// 使用 MessagePostProcessor 设置消息属性
rabbitTemplate.convertAndSend(
"durable.exchange",
"routing.key",
messageContent,
new MessagePostProcessor() {
@Override
public Message postProcessMessage(Message message) throws AmqpException {
// 设置消息持久化(deliveryMode = 2)
message.getMessageProperties()
.setDeliveryMode(MessageDeliveryMode.PERSISTENT);
// 设置消息ID(用于去重)
message.getMessageProperties()
.setMessageId(UUID.randomUUID().toString());
return message;
}
}
);
}
} message.getMessageProperties()`
`#/**
* 发送持久化消息
*
* 关键点:
* 1. MessagePostProcessor 设置 deliveryMode
* 2. 确保交换机和队列都已持久化
*/
@Service
public class MessageProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
public void sendDurableMessage(String messageContent) {
// 使用 MessagePostProcessor 设置消息属性
rabbitTemplate.convertAndSend(
"durable.exchange",
"routing.key",
messageContent,
new MessagePostProcessor() {
@Override
public Message postProcessMessage(Message message) throws AmqpException {
// 设置消息持久化(deliveryMode = 2)
message.getMessageProperties()
.setDeliveryMode(MessageDeliveryMode.PERSISTENT);
// 设置消息ID(用于去重)
message.getMessageProperties()
.setMessageId(UUID.randomUUID().toString());
return message;
}
}
);
}
} .setMessageId(UUID.randomUUID().toString());`
`#/**
* 发送持久化消息
*
* 关键点:
* 1. MessagePostProcessor 设置 deliveryMode
* 2. 确保交换机和队列都已持久化
*/
@Service
public class MessageProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
public void sendDurableMessage(String messageContent) {
// 使用 MessagePostProcessor 设置消息属性
rabbitTemplate.convertAndSend(
"durable.exchange",
"routing.key",
messageContent,
new MessagePostProcessor() {
@Override
public Message postProcessMessage(Message message) throws AmqpException {
// 设置消息持久化(deliveryMode = 2)
message.getMessageProperties()
.setDeliveryMode(MessageDeliveryMode.PERSISTENT);
// 设置消息ID(用于去重)
message.getMessageProperties()
.setMessageId(UUID.randomUUID().toString());
return message;
}
}
);
}
} `
`#/**
* 发送持久化消息
*
* 关键点:
* 1. MessagePostProcessor 设置 deliveryMode
* 2. 确保交换机和队列都已持久化
*/
@Service
public class MessageProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
public void sendDurableMessage(String messageContent) {
// 使用 MessagePostProcessor 设置消息属性
rabbitTemplate.convertAndSend(
"durable.exchange",
"routing.key",
messageContent,
new MessagePostProcessor() {
@Override
public Message postProcessMessage(Message message) throws AmqpException {
// 设置消息持久化(deliveryMode = 2)
message.getMessageProperties()
.setDeliveryMode(MessageDeliveryMode.PERSISTENT);
// 设置消息ID(用于去重)
message.getMessageProperties()
.setMessageId(UUID.randomUUID().toString());
return message;
}
}
);
}
} return message;`
`#/**
* 发送持久化消息
*
* 关键点:
* 1. MessagePostProcessor 设置 deliveryMode
* 2. 确保交换机和队列都已持久化
*/
@Service
public class MessageProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
public void sendDurableMessage(String messageContent) {
// 使用 MessagePostProcessor 设置消息属性
rabbitTemplate.convertAndSend(
"durable.exchange",
"routing.key",
messageContent,
new MessagePostProcessor() {
@Override
public Message postProcessMessage(Message message) throws AmqpException {
// 设置消息持久化(deliveryMode = 2)
message.getMessageProperties()
.setDeliveryMode(MessageDeliveryMode.PERSISTENT);
// 设置消息ID(用于去重)
message.getMessageProperties()
.setMessageId(UUID.randomUUID().toString());
return message;
}
}
);
}
} }`
`#/**
* 发送持久化消息
*
* 关键点:
* 1. MessagePostProcessor 设置 deliveryMode
* 2. 确保交换机和队列都已持久化
*/
@Service
public class MessageProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
public void sendDurableMessage(String messageContent) {
// 使用 MessagePostProcessor 设置消息属性
rabbitTemplate.convertAndSend(
"durable.exchange",
"routing.key",
messageContent,
new MessagePostProcessor() {
@Override
public Message postProcessMessage(Message message) throws AmqpException {
// 设置消息持久化(deliveryMode = 2)
message.getMessageProperties()
.setDeliveryMode(MessageDeliveryMode.PERSISTENT);
// 设置消息ID(用于去重)
message.getMessageProperties()
.setMessageId(UUID.randomUUID().toString());
return message;
}
}
);
}
} }`
`#/**
* 发送持久化消息
*
* 关键点:
* 1. MessagePostProcessor 设置 deliveryMode
* 2. 确保交换机和队列都已持久化
*/
@Service
public class MessageProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
public void sendDurableMessage(String messageContent) {
// 使用 MessagePostProcessor 设置消息属性
rabbitTemplate.convertAndSend(
"durable.exchange",
"routing.key",
messageContent,
new MessagePostProcessor() {
@Override
public Message postProcessMessage(Message message) throws AmqpException {
// 设置消息持久化(deliveryMode = 2)
message.getMessageProperties()
.setDeliveryMode(MessageDeliveryMode.PERSISTENT);
// 设置消息ID(用于去重)
message.getMessageProperties()
.setMessageId(UUID.randomUUID().toString());
return message;
}
}
);
}
} );`
`#/**
* 发送持久化消息
*
* 关键点:
* 1. MessagePostProcessor 设置 deliveryMode
* 2. 确保交换机和队列都已持久化
*/
@Service
public class MessageProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
public void sendDurableMessage(String messageContent) {
// 使用 MessagePostProcessor 设置消息属性
rabbitTemplate.convertAndSend(
"durable.exchange",
"routing.key",
messageContent,
new MessagePostProcessor() {
@Override
public Message postProcessMessage(Message message) throws AmqpException {
// 设置消息持久化(deliveryMode = 2)
message.getMessageProperties()
.setDeliveryMode(MessageDeliveryMode.PERSISTENT);
// 设置消息ID(用于去重)
message.getMessageProperties()
.setMessageId(UUID.randomUUID().toString());
return message;
}
}
);
}
} }`
`#/**
* 发送持久化消息
*
* 关键点:
* 1. MessagePostProcessor 设置 deliveryMode
* 2. 确保交换机和队列都已持久化
*/
@Service
public class MessageProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
public void sendDurableMessage(String messageContent) {
// 使用 MessagePostProcessor 设置消息属性
rabbitTemplate.convertAndSend(
"durable.exchange",
"routing.key",
messageContent,
new MessagePostProcessor() {
@Override
public Message postProcessMessage(Message message) throws AmqpException {
// 设置消息持久化(deliveryMode = 2)
message.getMessageProperties()
.setDeliveryMode(MessageDeliveryMode.PERSISTENT);
// 设置消息ID(用于去重)
message.getMessageProperties()
.setMessageId(UUID.randomUUID().toString());
return message;
}
}
);
}
}}
2.4 持久化的性能影响与优化
| 持久化级别 | 写入速度 | 可靠性 | 适用场景 |
|---|---|---|---|
| 纯内存 | 最快(基准) | 最低(宕机丢失) | 临时数据、测试环境 |
| 异步持久化 | 快(约80%基准) | 中等(可能丢失少量数据) | 日志、监控数据 |
| 同步持久化 | 慢(约30%基准) | 最高(数据零丢失) | 金融交易、订单数据 |
性能优化技巧:
java
#/**
* 性能优化配置
*
* 通过调整队列和消息属性,在可靠性和性能之间取得平衡
*/
@Bean
public Queue optimizedQueue() {
return QueueBuilder
.durable("optimized.queue")
// 批量优化:减少磁盘IO次数
.withArgument("x-max-length", 50000)
// 惰性分发:消费者未连接时不预加载
.lazy()
// 主节点定位:锁定队列到主节点,减少集群同步开销
.withArgument("x-queue-master-locator", "client-local")
.build();
}/**`
`#/**
* 性能优化配置
*
* 通过调整队列和消息属性,在可靠性和性能之间取得平衡
*/
@Bean
public Queue optimizedQueue() {
return QueueBuilder
.durable("optimized.queue")
// 批量优化:减少磁盘IO次数
.withArgument("x-max-length", 50000)
// 惰性分发:消费者未连接时不预加载
.lazy()
// 主节点定位:锁定队列到主节点,减少集群同步开销
.withArgument("x-queue-master-locator", "client-local")
.build();
} * 性能优化配置`
`#/**
* 性能优化配置
*
* 通过调整队列和消息属性,在可靠性和性能之间取得平衡
*/
@Bean
public Queue optimizedQueue() {
return QueueBuilder
.durable("optimized.queue")
// 批量优化:减少磁盘IO次数
.withArgument("x-max-length", 50000)
// 惰性分发:消费者未连接时不预加载
.lazy()
// 主节点定位:锁定队列到主节点,减少集群同步开销
.withArgument("x-queue-master-locator", "client-local")
.build();
} * `
`#/**
* 性能优化配置
*
* 通过调整队列和消息属性,在可靠性和性能之间取得平衡
*/
@Bean
public Queue optimizedQueue() {
return QueueBuilder
.durable("optimized.queue")
// 批量优化:减少磁盘IO次数
.withArgument("x-max-length", 50000)
// 惰性分发:消费者未连接时不预加载
.lazy()
// 主节点定位:锁定队列到主节点,减少集群同步开销
.withArgument("x-queue-master-locator", "client-local")
.build();
} * 通过调整队列和消息属性,在可靠性和性能之间取得平衡`
`#/**
* 性能优化配置
*
* 通过调整队列和消息属性,在可靠性和性能之间取得平衡
*/
@Bean
public Queue optimizedQueue() {
return QueueBuilder
.durable("optimized.queue")
// 批量优化:减少磁盘IO次数
.withArgument("x-max-length", 50000)
// 惰性分发:消费者未连接时不预加载
.lazy()
// 主节点定位:锁定队列到主节点,减少集群同步开销
.withArgument("x-queue-master-locator", "client-local")
.build();
} */`
`#/**
* 性能优化配置
*
* 通过调整队列和消息属性,在可靠性和性能之间取得平衡
*/
@Bean
public Queue optimizedQueue() {
return QueueBuilder
.durable("optimized.queue")
// 批量优化:减少磁盘IO次数
.withArgument("x-max-length", 50000)
// 惰性分发:消费者未连接时不预加载
.lazy()
// 主节点定位:锁定队列到主节点,减少集群同步开销
.withArgument("x-queue-master-locator", "client-local")
.build();
}@Bean`
`#/**
* 性能优化配置
*
* 通过调整队列和消息属性,在可靠性和性能之间取得平衡
*/
@Bean
public Queue optimizedQueue() {
return QueueBuilder
.durable("optimized.queue")
// 批量优化:减少磁盘IO次数
.withArgument("x-max-length", 50000)
// 惰性分发:消费者未连接时不预加载
.lazy()
// 主节点定位:锁定队列到主节点,减少集群同步开销
.withArgument("x-queue-master-locator", "client-local")
.build();
}public Queue optimizedQueue() {`
`#/**
* 性能优化配置
*
* 通过调整队列和消息属性,在可靠性和性能之间取得平衡
*/
@Bean
public Queue optimizedQueue() {
return QueueBuilder
.durable("optimized.queue")
// 批量优化:减少磁盘IO次数
.withArgument("x-max-length", 50000)
// 惰性分发:消费者未连接时不预加载
.lazy()
// 主节点定位:锁定队列到主节点,减少集群同步开销
.withArgument("x-queue-master-locator", "client-local")
.build();
} return QueueBuilder`
`#/**
* 性能优化配置
*
* 通过调整队列和消息属性,在可靠性和性能之间取得平衡
*/
@Bean
public Queue optimizedQueue() {
return QueueBuilder
.durable("optimized.queue")
// 批量优化:减少磁盘IO次数
.withArgument("x-max-length", 50000)
// 惰性分发:消费者未连接时不预加载
.lazy()
// 主节点定位:锁定队列到主节点,减少集群同步开销
.withArgument("x-queue-master-locator", "client-local")
.build();
} .durable("optimized.queue")`
`#/**
* 性能优化配置
*
* 通过调整队列和消息属性,在可靠性和性能之间取得平衡
*/
@Bean
public Queue optimizedQueue() {
return QueueBuilder
.durable("optimized.queue")
// 批量优化:减少磁盘IO次数
.withArgument("x-max-length", 50000)
// 惰性分发:消费者未连接时不预加载
.lazy()
// 主节点定位:锁定队列到主节点,减少集群同步开销
.withArgument("x-queue-master-locator", "client-local")
.build();
} // 批量优化:减少磁盘IO次数`
`#/**
* 性能优化配置
*
* 通过调整队列和消息属性,在可靠性和性能之间取得平衡
*/
@Bean
public Queue optimizedQueue() {
return QueueBuilder
.durable("optimized.queue")
// 批量优化:减少磁盘IO次数
.withArgument("x-max-length", 50000)
// 惰性分发:消费者未连接时不预加载
.lazy()
// 主节点定位:锁定队列到主节点,减少集群同步开销
.withArgument("x-queue-master-locator", "client-local")
.build();
} .withArgument("x-max-length", 50000)`
`#/**
* 性能优化配置
*
* 通过调整队列和消息属性,在可靠性和性能之间取得平衡
*/
@Bean
public Queue optimizedQueue() {
return QueueBuilder
.durable("optimized.queue")
// 批量优化:减少磁盘IO次数
.withArgument("x-max-length", 50000)
// 惰性分发:消费者未连接时不预加载
.lazy()
// 主节点定位:锁定队列到主节点,减少集群同步开销
.withArgument("x-queue-master-locator", "client-local")
.build();
} // 惰性分发:消费者未连接时不预加载`
`#/**
* 性能优化配置
*
* 通过调整队列和消息属性,在可靠性和性能之间取得平衡
*/
@Bean
public Queue optimizedQueue() {
return QueueBuilder
.durable("optimized.queue")
// 批量优化:减少磁盘IO次数
.withArgument("x-max-length", 50000)
// 惰性分发:消费者未连接时不预加载
.lazy()
// 主节点定位:锁定队列到主节点,减少集群同步开销
.withArgument("x-queue-master-locator", "client-local")
.build();
} .lazy() `
`#/**
* 性能优化配置
*
* 通过调整队列和消息属性,在可靠性和性能之间取得平衡
*/
@Bean
public Queue optimizedQueue() {
return QueueBuilder
.durable("optimized.queue")
// 批量优化:减少磁盘IO次数
.withArgument("x-max-length", 50000)
// 惰性分发:消费者未连接时不预加载
.lazy()
// 主节点定位:锁定队列到主节点,减少集群同步开销
.withArgument("x-queue-master-locator", "client-local")
.build();
} // 主节点定位:锁定队列到主节点,减少集群同步开销`
`#/**
* 性能优化配置
*
* 通过调整队列和消息属性,在可靠性和性能之间取得平衡
*/
@Bean
public Queue optimizedQueue() {
return QueueBuilder
.durable("optimized.queue")
// 批量优化:减少磁盘IO次数
.withArgument("x-max-length", 50000)
// 惰性分发:消费者未连接时不预加载
.lazy()
// 主节点定位:锁定队列到主节点,减少集群同步开销
.withArgument("x-queue-master-locator", "client-local")
.build();
} .withArgument("x-queue-master-locator", "client-local")`
`#/**
* 性能优化配置
*
* 通过调整队列和消息属性,在可靠性和性能之间取得平衡
*/
@Bean
public Queue optimizedQueue() {
return QueueBuilder
.durable("optimized.queue")
// 批量优化:减少磁盘IO次数
.withArgument("x-max-length", 50000)
// 惰性分发:消费者未连接时不预加载
.lazy()
// 主节点定位:锁定队列到主节点,减少集群同步开销
.withArgument("x-queue-master-locator", "client-local")
.build();
} .build();`
`#/**
* 性能优化配置
*
* 通过调整队列和消息属性,在可靠性和性能之间取得平衡
*/
@Bean
public Queue optimizedQueue() {
return QueueBuilder
.durable("optimized.queue")
// 批量优化:减少磁盘IO次数
.withArgument("x-max-length", 50000)
// 惰性分发:消费者未连接时不预加载
.lazy()
// 主节点定位:锁定队列到主节点,减少集群同步开销
.withArgument("x-queue-master-locator", "client-local")
.build();
}}
3. 消息确认机制:可靠投递的核心保障
3.1 确认机制的双向模型
RabbitMQ 的确认机制是双向的,确保消息从生产者到消费者的完整链路可靠:
sequenceDiagram
participant P as 生产者
participant B as RabbitMQ Broker
participant C as 消费者
P->>B: 1. 发送消息
B->>P: 2. Publisher Confirm (确认接收)
B->>C: 3. 投递消息
C->>B: 4. Consumer Ack (确认处理完成)
Note over P,B: 如果步骤2失败,生产者重发
Note over B,C: 如果步骤4失败,Broker重新投递
3.2 生产者确认机制(Publisher Confirm)
3.2.1 Confirm 的三种模式对比
| 模式 | 实现方式 | 性能 | 可靠性 | 适用场景 |
|---|---|---|---|---|
| 普通 Confirm | waitForConfirms() |
低(串行) | 高 | 低吞吐量场景 |
| 批量 Confirm | waitForConfirmsOrDie() |
中 | 中 | 中等吞吐量场景 |
| 异步 Confirm | addConfirmListener() |
高 | 高 | 高吞吐量场景(推荐) |
3.2.2 源码分析:异步 Confirm 的实现
java
#/**
* RabbitMQ 异步 Confirm 机制源码分析
* 基于 rabbitmq-java-client 5.16.0
*
* 核心流程:
* 1. 生产者发送消息时分配内部序列号
* 2. Broker 收到消息后返回确认(带序列号)
* 3. 生产者通过回调函数处理确认结果
*/
public class AsyncConfirmExample {
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
public void setupConfirmChannel(Channel channel) throws IOException {
// 启用发布确认模式
channel.confirmSelect();
// 添加异步确认监听器
channel.addConfirmListener(new ConfirmListener() {
/**
* 消息成功确认回调
* @param deliveryTag 消息序列号
* @param multiple 是否批量确认
*/
@Override
public void handleAck(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量确认:移除所有 <= deliveryTag 的消息
unconfirmedSet.headSet(deliveryTag + 1).clear();
} else {
// 单条确认:移除指定消息
unconfirmedSet.remove(deliveryTag);
}
System.out.println("消息确认成功,序列号: " + deliveryTag);
}
/**
* 消息失败回调(未确认)
* @param deliveryTag 消息序列号
* @param multiple 是否批量未确认
*/
@Override
public void handleNack(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量未确认:重试所有 <= deliveryTag 的消息
SortedSet<Long> headSet = unconfirmedSet.headSet(deliveryTag + 1);
for (Long seq : headSet) {
retryMessage(seq);
}
headSet.clear();
} else {
// 单条未确认:重试指定消息
retryMessage(deliveryTag);
unconfirmedSet.remove(deliveryTag);
}
System.err.println("消息确认失败,序列号: " + deliveryTag);
}
});
}
/**
* 发送消息(带序列号跟踪)
*/
public void sendMessageWithTracking(Channel channel, String message)
throws IOException {
// 获取下一个序列号
long sequenceNumber = channel.getNextPublishSeqNo();
// 记录未确认的消息
unconfirmedSet.add(sequenceNumber);
// 发送消息
channel.basicPublish(
"durable.exchange",
"routing.key",
null,
message.getBytes()
);
}
/**
* 重试失败的消息
*/
private void retryMessage(long sequenceNumber) {
// 实现重试逻辑:从缓存中取出消息重新发送
// 注意:这里需要维护消息内容与序列号的映射
}
}/**`
`#/**
* RabbitMQ 异步 Confirm 机制源码分析
* 基于 rabbitmq-java-client 5.16.0
*
* 核心流程:
* 1. 生产者发送消息时分配内部序列号
* 2. Broker 收到消息后返回确认(带序列号)
* 3. 生产者通过回调函数处理确认结果
*/
public class AsyncConfirmExample {
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
public void setupConfirmChannel(Channel channel) throws IOException {
// 启用发布确认模式
channel.confirmSelect();
// 添加异步确认监听器
channel.addConfirmListener(new ConfirmListener() {
/**
* 消息成功确认回调
* @param deliveryTag 消息序列号
* @param multiple 是否批量确认
*/
@Override
public void handleAck(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量确认:移除所有 <= deliveryTag 的消息
unconfirmedSet.headSet(deliveryTag + 1).clear();
} else {
// 单条确认:移除指定消息
unconfirmedSet.remove(deliveryTag);
}
System.out.println("消息确认成功,序列号: " + deliveryTag);
}
/**
* 消息失败回调(未确认)
* @param deliveryTag 消息序列号
* @param multiple 是否批量未确认
*/
@Override
public void handleNack(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量未确认:重试所有 <= deliveryTag 的消息
SortedSet<Long> headSet = unconfirmedSet.headSet(deliveryTag + 1);
for (Long seq : headSet) {
retryMessage(seq);
}
headSet.clear();
} else {
// 单条未确认:重试指定消息
retryMessage(deliveryTag);
unconfirmedSet.remove(deliveryTag);
}
System.err.println("消息确认失败,序列号: " + deliveryTag);
}
});
}
/**
* 发送消息(带序列号跟踪)
*/
public void sendMessageWithTracking(Channel channel, String message)
throws IOException {
// 获取下一个序列号
long sequenceNumber = channel.getNextPublishSeqNo();
// 记录未确认的消息
unconfirmedSet.add(sequenceNumber);
// 发送消息
channel.basicPublish(
"durable.exchange",
"routing.key",
null,
message.getBytes()
);
}
/**
* 重试失败的消息
*/
private void retryMessage(long sequenceNumber) {
// 实现重试逻辑:从缓存中取出消息重新发送
// 注意:这里需要维护消息内容与序列号的映射
}
} * RabbitMQ 异步 Confirm 机制源码分析`
`#/**
* RabbitMQ 异步 Confirm 机制源码分析
* 基于 rabbitmq-java-client 5.16.0
*
* 核心流程:
* 1. 生产者发送消息时分配内部序列号
* 2. Broker 收到消息后返回确认(带序列号)
* 3. 生产者通过回调函数处理确认结果
*/
public class AsyncConfirmExample {
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
public void setupConfirmChannel(Channel channel) throws IOException {
// 启用发布确认模式
channel.confirmSelect();
// 添加异步确认监听器
channel.addConfirmListener(new ConfirmListener() {
/**
* 消息成功确认回调
* @param deliveryTag 消息序列号
* @param multiple 是否批量确认
*/
@Override
public void handleAck(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量确认:移除所有 <= deliveryTag 的消息
unconfirmedSet.headSet(deliveryTag + 1).clear();
} else {
// 单条确认:移除指定消息
unconfirmedSet.remove(deliveryTag);
}
System.out.println("消息确认成功,序列号: " + deliveryTag);
}
/**
* 消息失败回调(未确认)
* @param deliveryTag 消息序列号
* @param multiple 是否批量未确认
*/
@Override
public void handleNack(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量未确认:重试所有 <= deliveryTag 的消息
SortedSet<Long> headSet = unconfirmedSet.headSet(deliveryTag + 1);
for (Long seq : headSet) {
retryMessage(seq);
}
headSet.clear();
} else {
// 单条未确认:重试指定消息
retryMessage(deliveryTag);
unconfirmedSet.remove(deliveryTag);
}
System.err.println("消息确认失败,序列号: " + deliveryTag);
}
});
}
/**
* 发送消息(带序列号跟踪)
*/
public void sendMessageWithTracking(Channel channel, String message)
throws IOException {
// 获取下一个序列号
long sequenceNumber = channel.getNextPublishSeqNo();
// 记录未确认的消息
unconfirmedSet.add(sequenceNumber);
// 发送消息
channel.basicPublish(
"durable.exchange",
"routing.key",
null,
message.getBytes()
);
}
/**
* 重试失败的消息
*/
private void retryMessage(long sequenceNumber) {
// 实现重试逻辑:从缓存中取出消息重新发送
// 注意:这里需要维护消息内容与序列号的映射
}
} * 基于 rabbitmq-java-client 5.16.0`
`#/**
* RabbitMQ 异步 Confirm 机制源码分析
* 基于 rabbitmq-java-client 5.16.0
*
* 核心流程:
* 1. 生产者发送消息时分配内部序列号
* 2. Broker 收到消息后返回确认(带序列号)
* 3. 生产者通过回调函数处理确认结果
*/
public class AsyncConfirmExample {
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
public void setupConfirmChannel(Channel channel) throws IOException {
// 启用发布确认模式
channel.confirmSelect();
// 添加异步确认监听器
channel.addConfirmListener(new ConfirmListener() {
/**
* 消息成功确认回调
* @param deliveryTag 消息序列号
* @param multiple 是否批量确认
*/
@Override
public void handleAck(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量确认:移除所有 <= deliveryTag 的消息
unconfirmedSet.headSet(deliveryTag + 1).clear();
} else {
// 单条确认:移除指定消息
unconfirmedSet.remove(deliveryTag);
}
System.out.println("消息确认成功,序列号: " + deliveryTag);
}
/**
* 消息失败回调(未确认)
* @param deliveryTag 消息序列号
* @param multiple 是否批量未确认
*/
@Override
public void handleNack(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量未确认:重试所有 <= deliveryTag 的消息
SortedSet<Long> headSet = unconfirmedSet.headSet(deliveryTag + 1);
for (Long seq : headSet) {
retryMessage(seq);
}
headSet.clear();
} else {
// 单条未确认:重试指定消息
retryMessage(deliveryTag);
unconfirmedSet.remove(deliveryTag);
}
System.err.println("消息确认失败,序列号: " + deliveryTag);
}
});
}
/**
* 发送消息(带序列号跟踪)
*/
public void sendMessageWithTracking(Channel channel, String message)
throws IOException {
// 获取下一个序列号
long sequenceNumber = channel.getNextPublishSeqNo();
// 记录未确认的消息
unconfirmedSet.add(sequenceNumber);
// 发送消息
channel.basicPublish(
"durable.exchange",
"routing.key",
null,
message.getBytes()
);
}
/**
* 重试失败的消息
*/
private void retryMessage(long sequenceNumber) {
// 实现重试逻辑:从缓存中取出消息重新发送
// 注意:这里需要维护消息内容与序列号的映射
}
} * `
`#/**
* RabbitMQ 异步 Confirm 机制源码分析
* 基于 rabbitmq-java-client 5.16.0
*
* 核心流程:
* 1. 生产者发送消息时分配内部序列号
* 2. Broker 收到消息后返回确认(带序列号)
* 3. 生产者通过回调函数处理确认结果
*/
public class AsyncConfirmExample {
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
public void setupConfirmChannel(Channel channel) throws IOException {
// 启用发布确认模式
channel.confirmSelect();
// 添加异步确认监听器
channel.addConfirmListener(new ConfirmListener() {
/**
* 消息成功确认回调
* @param deliveryTag 消息序列号
* @param multiple 是否批量确认
*/
@Override
public void handleAck(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量确认:移除所有 <= deliveryTag 的消息
unconfirmedSet.headSet(deliveryTag + 1).clear();
} else {
// 单条确认:移除指定消息
unconfirmedSet.remove(deliveryTag);
}
System.out.println("消息确认成功,序列号: " + deliveryTag);
}
/**
* 消息失败回调(未确认)
* @param deliveryTag 消息序列号
* @param multiple 是否批量未确认
*/
@Override
public void handleNack(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量未确认:重试所有 <= deliveryTag 的消息
SortedSet<Long> headSet = unconfirmedSet.headSet(deliveryTag + 1);
for (Long seq : headSet) {
retryMessage(seq);
}
headSet.clear();
} else {
// 单条未确认:重试指定消息
retryMessage(deliveryTag);
unconfirmedSet.remove(deliveryTag);
}
System.err.println("消息确认失败,序列号: " + deliveryTag);
}
});
}
/**
* 发送消息(带序列号跟踪)
*/
public void sendMessageWithTracking(Channel channel, String message)
throws IOException {
// 获取下一个序列号
long sequenceNumber = channel.getNextPublishSeqNo();
// 记录未确认的消息
unconfirmedSet.add(sequenceNumber);
// 发送消息
channel.basicPublish(
"durable.exchange",
"routing.key",
null,
message.getBytes()
);
}
/**
* 重试失败的消息
*/
private void retryMessage(long sequenceNumber) {
// 实现重试逻辑:从缓存中取出消息重新发送
// 注意:这里需要维护消息内容与序列号的映射
}
} * 核心流程:`
`#/**
* RabbitMQ 异步 Confirm 机制源码分析
* 基于 rabbitmq-java-client 5.16.0
*
* 核心流程:
* 1. 生产者发送消息时分配内部序列号
* 2. Broker 收到消息后返回确认(带序列号)
* 3. 生产者通过回调函数处理确认结果
*/
public class AsyncConfirmExample {
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
public void setupConfirmChannel(Channel channel) throws IOException {
// 启用发布确认模式
channel.confirmSelect();
// 添加异步确认监听器
channel.addConfirmListener(new ConfirmListener() {
/**
* 消息成功确认回调
* @param deliveryTag 消息序列号
* @param multiple 是否批量确认
*/
@Override
public void handleAck(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量确认:移除所有 <= deliveryTag 的消息
unconfirmedSet.headSet(deliveryTag + 1).clear();
} else {
// 单条确认:移除指定消息
unconfirmedSet.remove(deliveryTag);
}
System.out.println("消息确认成功,序列号: " + deliveryTag);
}
/**
* 消息失败回调(未确认)
* @param deliveryTag 消息序列号
* @param multiple 是否批量未确认
*/
@Override
public void handleNack(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量未确认:重试所有 <= deliveryTag 的消息
SortedSet<Long> headSet = unconfirmedSet.headSet(deliveryTag + 1);
for (Long seq : headSet) {
retryMessage(seq);
}
headSet.clear();
} else {
// 单条未确认:重试指定消息
retryMessage(deliveryTag);
unconfirmedSet.remove(deliveryTag);
}
System.err.println("消息确认失败,序列号: " + deliveryTag);
}
});
}
/**
* 发送消息(带序列号跟踪)
*/
public void sendMessageWithTracking(Channel channel, String message)
throws IOException {
// 获取下一个序列号
long sequenceNumber = channel.getNextPublishSeqNo();
// 记录未确认的消息
unconfirmedSet.add(sequenceNumber);
// 发送消息
channel.basicPublish(
"durable.exchange",
"routing.key",
null,
message.getBytes()
);
}
/**
* 重试失败的消息
*/
private void retryMessage(long sequenceNumber) {
// 实现重试逻辑:从缓存中取出消息重新发送
// 注意:这里需要维护消息内容与序列号的映射
}
} * 1. 生产者发送消息时分配内部序列号`
`#/**
* RabbitMQ 异步 Confirm 机制源码分析
* 基于 rabbitmq-java-client 5.16.0
*
* 核心流程:
* 1. 生产者发送消息时分配内部序列号
* 2. Broker 收到消息后返回确认(带序列号)
* 3. 生产者通过回调函数处理确认结果
*/
public class AsyncConfirmExample {
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
public void setupConfirmChannel(Channel channel) throws IOException {
// 启用发布确认模式
channel.confirmSelect();
// 添加异步确认监听器
channel.addConfirmListener(new ConfirmListener() {
/**
* 消息成功确认回调
* @param deliveryTag 消息序列号
* @param multiple 是否批量确认
*/
@Override
public void handleAck(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量确认:移除所有 <= deliveryTag 的消息
unconfirmedSet.headSet(deliveryTag + 1).clear();
} else {
// 单条确认:移除指定消息
unconfirmedSet.remove(deliveryTag);
}
System.out.println("消息确认成功,序列号: " + deliveryTag);
}
/**
* 消息失败回调(未确认)
* @param deliveryTag 消息序列号
* @param multiple 是否批量未确认
*/
@Override
public void handleNack(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量未确认:重试所有 <= deliveryTag 的消息
SortedSet<Long> headSet = unconfirmedSet.headSet(deliveryTag + 1);
for (Long seq : headSet) {
retryMessage(seq);
}
headSet.clear();
} else {
// 单条未确认:重试指定消息
retryMessage(deliveryTag);
unconfirmedSet.remove(deliveryTag);
}
System.err.println("消息确认失败,序列号: " + deliveryTag);
}
});
}
/**
* 发送消息(带序列号跟踪)
*/
public void sendMessageWithTracking(Channel channel, String message)
throws IOException {
// 获取下一个序列号
long sequenceNumber = channel.getNextPublishSeqNo();
// 记录未确认的消息
unconfirmedSet.add(sequenceNumber);
// 发送消息
channel.basicPublish(
"durable.exchange",
"routing.key",
null,
message.getBytes()
);
}
/**
* 重试失败的消息
*/
private void retryMessage(long sequenceNumber) {
// 实现重试逻辑:从缓存中取出消息重新发送
// 注意:这里需要维护消息内容与序列号的映射
}
} * 2. Broker 收到消息后返回确认(带序列号)`
`#/**
* RabbitMQ 异步 Confirm 机制源码分析
* 基于 rabbitmq-java-client 5.16.0
*
* 核心流程:
* 1. 生产者发送消息时分配内部序列号
* 2. Broker 收到消息后返回确认(带序列号)
* 3. 生产者通过回调函数处理确认结果
*/
public class AsyncConfirmExample {
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
public void setupConfirmChannel(Channel channel) throws IOException {
// 启用发布确认模式
channel.confirmSelect();
// 添加异步确认监听器
channel.addConfirmListener(new ConfirmListener() {
/**
* 消息成功确认回调
* @param deliveryTag 消息序列号
* @param multiple 是否批量确认
*/
@Override
public void handleAck(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量确认:移除所有 <= deliveryTag 的消息
unconfirmedSet.headSet(deliveryTag + 1).clear();
} else {
// 单条确认:移除指定消息
unconfirmedSet.remove(deliveryTag);
}
System.out.println("消息确认成功,序列号: " + deliveryTag);
}
/**
* 消息失败回调(未确认)
* @param deliveryTag 消息序列号
* @param multiple 是否批量未确认
*/
@Override
public void handleNack(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量未确认:重试所有 <= deliveryTag 的消息
SortedSet<Long> headSet = unconfirmedSet.headSet(deliveryTag + 1);
for (Long seq : headSet) {
retryMessage(seq);
}
headSet.clear();
} else {
// 单条未确认:重试指定消息
retryMessage(deliveryTag);
unconfirmedSet.remove(deliveryTag);
}
System.err.println("消息确认失败,序列号: " + deliveryTag);
}
});
}
/**
* 发送消息(带序列号跟踪)
*/
public void sendMessageWithTracking(Channel channel, String message)
throws IOException {
// 获取下一个序列号
long sequenceNumber = channel.getNextPublishSeqNo();
// 记录未确认的消息
unconfirmedSet.add(sequenceNumber);
// 发送消息
channel.basicPublish(
"durable.exchange",
"routing.key",
null,
message.getBytes()
);
}
/**
* 重试失败的消息
*/
private void retryMessage(long sequenceNumber) {
// 实现重试逻辑:从缓存中取出消息重新发送
// 注意:这里需要维护消息内容与序列号的映射
}
} * 3. 生产者通过回调函数处理确认结果`
`#/**
* RabbitMQ 异步 Confirm 机制源码分析
* 基于 rabbitmq-java-client 5.16.0
*
* 核心流程:
* 1. 生产者发送消息时分配内部序列号
* 2. Broker 收到消息后返回确认(带序列号)
* 3. 生产者通过回调函数处理确认结果
*/
public class AsyncConfirmExample {
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
public void setupConfirmChannel(Channel channel) throws IOException {
// 启用发布确认模式
channel.confirmSelect();
// 添加异步确认监听器
channel.addConfirmListener(new ConfirmListener() {
/**
* 消息成功确认回调
* @param deliveryTag 消息序列号
* @param multiple 是否批量确认
*/
@Override
public void handleAck(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量确认:移除所有 <= deliveryTag 的消息
unconfirmedSet.headSet(deliveryTag + 1).clear();
} else {
// 单条确认:移除指定消息
unconfirmedSet.remove(deliveryTag);
}
System.out.println("消息确认成功,序列号: " + deliveryTag);
}
/**
* 消息失败回调(未确认)
* @param deliveryTag 消息序列号
* @param multiple 是否批量未确认
*/
@Override
public void handleNack(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量未确认:重试所有 <= deliveryTag 的消息
SortedSet<Long> headSet = unconfirmedSet.headSet(deliveryTag + 1);
for (Long seq : headSet) {
retryMessage(seq);
}
headSet.clear();
} else {
// 单条未确认:重试指定消息
retryMessage(deliveryTag);
unconfirmedSet.remove(deliveryTag);
}
System.err.println("消息确认失败,序列号: " + deliveryTag);
}
});
}
/**
* 发送消息(带序列号跟踪)
*/
public void sendMessageWithTracking(Channel channel, String message)
throws IOException {
// 获取下一个序列号
long sequenceNumber = channel.getNextPublishSeqNo();
// 记录未确认的消息
unconfirmedSet.add(sequenceNumber);
// 发送消息
channel.basicPublish(
"durable.exchange",
"routing.key",
null,
message.getBytes()
);
}
/**
* 重试失败的消息
*/
private void retryMessage(long sequenceNumber) {
// 实现重试逻辑:从缓存中取出消息重新发送
// 注意:这里需要维护消息内容与序列号的映射
}
} */`
`#/**
* RabbitMQ 异步 Confirm 机制源码分析
* 基于 rabbitmq-java-client 5.16.0
*
* 核心流程:
* 1. 生产者发送消息时分配内部序列号
* 2. Broker 收到消息后返回确认(带序列号)
* 3. 生产者通过回调函数处理确认结果
*/
public class AsyncConfirmExample {
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
public void setupConfirmChannel(Channel channel) throws IOException {
// 启用发布确认模式
channel.confirmSelect();
// 添加异步确认监听器
channel.addConfirmListener(new ConfirmListener() {
/**
* 消息成功确认回调
* @param deliveryTag 消息序列号
* @param multiple 是否批量确认
*/
@Override
public void handleAck(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量确认:移除所有 <= deliveryTag 的消息
unconfirmedSet.headSet(deliveryTag + 1).clear();
} else {
// 单条确认:移除指定消息
unconfirmedSet.remove(deliveryTag);
}
System.out.println("消息确认成功,序列号: " + deliveryTag);
}
/**
* 消息失败回调(未确认)
* @param deliveryTag 消息序列号
* @param multiple 是否批量未确认
*/
@Override
public void handleNack(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量未确认:重试所有 <= deliveryTag 的消息
SortedSet<Long> headSet = unconfirmedSet.headSet(deliveryTag + 1);
for (Long seq : headSet) {
retryMessage(seq);
}
headSet.clear();
} else {
// 单条未确认:重试指定消息
retryMessage(deliveryTag);
unconfirmedSet.remove(deliveryTag);
}
System.err.println("消息确认失败,序列号: " + deliveryTag);
}
});
}
/**
* 发送消息(带序列号跟踪)
*/
public void sendMessageWithTracking(Channel channel, String message)
throws IOException {
// 获取下一个序列号
long sequenceNumber = channel.getNextPublishSeqNo();
// 记录未确认的消息
unconfirmedSet.add(sequenceNumber);
// 发送消息
channel.basicPublish(
"durable.exchange",
"routing.key",
null,
message.getBytes()
);
}
/**
* 重试失败的消息
*/
private void retryMessage(long sequenceNumber) {
// 实现重试逻辑:从缓存中取出消息重新发送
// 注意:这里需要维护消息内容与序列号的映射
}
}public class AsyncConfirmExample {`
`#/**
* RabbitMQ 异步 Confirm 机制源码分析
* 基于 rabbitmq-java-client 5.16.0
*
* 核心流程:
* 1. 生产者发送消息时分配内部序列号
* 2. Broker 收到消息后返回确认(带序列号)
* 3. 生产者通过回调函数处理确认结果
*/
public class AsyncConfirmExample {
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
public void setupConfirmChannel(Channel channel) throws IOException {
// 启用发布确认模式
channel.confirmSelect();
// 添加异步确认监听器
channel.addConfirmListener(new ConfirmListener() {
/**
* 消息成功确认回调
* @param deliveryTag 消息序列号
* @param multiple 是否批量确认
*/
@Override
public void handleAck(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量确认:移除所有 <= deliveryTag 的消息
unconfirmedSet.headSet(deliveryTag + 1).clear();
} else {
// 单条确认:移除指定消息
unconfirmedSet.remove(deliveryTag);
}
System.out.println("消息确认成功,序列号: " + deliveryTag);
}
/**
* 消息失败回调(未确认)
* @param deliveryTag 消息序列号
* @param multiple 是否批量未确认
*/
@Override
public void handleNack(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量未确认:重试所有 <= deliveryTag 的消息
SortedSet<Long> headSet = unconfirmedSet.headSet(deliveryTag + 1);
for (Long seq : headSet) {
retryMessage(seq);
}
headSet.clear();
} else {
// 单条未确认:重试指定消息
retryMessage(deliveryTag);
unconfirmedSet.remove(deliveryTag);
}
System.err.println("消息确认失败,序列号: " + deliveryTag);
}
});
}
/**
* 发送消息(带序列号跟踪)
*/
public void sendMessageWithTracking(Channel channel, String message)
throws IOException {
// 获取下一个序列号
long sequenceNumber = channel.getNextPublishSeqNo();
// 记录未确认的消息
unconfirmedSet.add(sequenceNumber);
// 发送消息
channel.basicPublish(
"durable.exchange",
"routing.key",
null,
message.getBytes()
);
}
/**
* 重试失败的消息
*/
private void retryMessage(long sequenceNumber) {
// 实现重试逻辑:从缓存中取出消息重新发送
// 注意:这里需要维护消息内容与序列号的映射
}
}`
`#/**
* RabbitMQ 异步 Confirm 机制源码分析
* 基于 rabbitmq-java-client 5.16.0
*
* 核心流程:
* 1. 生产者发送消息时分配内部序列号
* 2. Broker 收到消息后返回确认(带序列号)
* 3. 生产者通过回调函数处理确认结果
*/
public class AsyncConfirmExample {
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
public void setupConfirmChannel(Channel channel) throws IOException {
// 启用发布确认模式
channel.confirmSelect();
// 添加异步确认监听器
channel.addConfirmListener(new ConfirmListener() {
/**
* 消息成功确认回调
* @param deliveryTag 消息序列号
* @param multiple 是否批量确认
*/
@Override
public void handleAck(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量确认:移除所有 <= deliveryTag 的消息
unconfirmedSet.headSet(deliveryTag + 1).clear();
} else {
// 单条确认:移除指定消息
unconfirmedSet.remove(deliveryTag);
}
System.out.println("消息确认成功,序列号: " + deliveryTag);
}
/**
* 消息失败回调(未确认)
* @param deliveryTag 消息序列号
* @param multiple 是否批量未确认
*/
@Override
public void handleNack(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量未确认:重试所有 <= deliveryTag 的消息
SortedSet<Long> headSet = unconfirmedSet.headSet(deliveryTag + 1);
for (Long seq : headSet) {
retryMessage(seq);
}
headSet.clear();
} else {
// 单条未确认:重试指定消息
retryMessage(deliveryTag);
unconfirmedSet.remove(deliveryTag);
}
System.err.println("消息确认失败,序列号: " + deliveryTag);
}
});
}
/**
* 发送消息(带序列号跟踪)
*/
public void sendMessageWithTracking(Channel channel, String message)
throws IOException {
// 获取下一个序列号
long sequenceNumber = channel.getNextPublishSeqNo();
// 记录未确认的消息
unconfirmedSet.add(sequenceNumber);
// 发送消息
channel.basicPublish(
"durable.exchange",
"routing.key",
null,
message.getBytes()
);
}
/**
* 重试失败的消息
*/
private void retryMessage(long sequenceNumber) {
// 实现重试逻辑:从缓存中取出消息重新发送
// 注意:这里需要维护消息内容与序列号的映射
}
} private final SortedSet<Long> unconfirmedSet = `
`#/**
* RabbitMQ 异步 Confirm 机制源码分析
* 基于 rabbitmq-java-client 5.16.0
*
* 核心流程:
* 1. 生产者发送消息时分配内部序列号
* 2. Broker 收到消息后返回确认(带序列号)
* 3. 生产者通过回调函数处理确认结果
*/
public class AsyncConfirmExample {
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
public void setupConfirmChannel(Channel channel) throws IOException {
// 启用发布确认模式
channel.confirmSelect();
// 添加异步确认监听器
channel.addConfirmListener(new ConfirmListener() {
/**
* 消息成功确认回调
* @param deliveryTag 消息序列号
* @param multiple 是否批量确认
*/
@Override
public void handleAck(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量确认:移除所有 <= deliveryTag 的消息
unconfirmedSet.headSet(deliveryTag + 1).clear();
} else {
// 单条确认:移除指定消息
unconfirmedSet.remove(deliveryTag);
}
System.out.println("消息确认成功,序列号: " + deliveryTag);
}
/**
* 消息失败回调(未确认)
* @param deliveryTag 消息序列号
* @param multiple 是否批量未确认
*/
@Override
public void handleNack(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量未确认:重试所有 <= deliveryTag 的消息
SortedSet<Long> headSet = unconfirmedSet.headSet(deliveryTag + 1);
for (Long seq : headSet) {
retryMessage(seq);
}
headSet.clear();
} else {
// 单条未确认:重试指定消息
retryMessage(deliveryTag);
unconfirmedSet.remove(deliveryTag);
}
System.err.println("消息确认失败,序列号: " + deliveryTag);
}
});
}
/**
* 发送消息(带序列号跟踪)
*/
public void sendMessageWithTracking(Channel channel, String message)
throws IOException {
// 获取下一个序列号
long sequenceNumber = channel.getNextPublishSeqNo();
// 记录未确认的消息
unconfirmedSet.add(sequenceNumber);
// 发送消息
channel.basicPublish(
"durable.exchange",
"routing.key",
null,
message.getBytes()
);
}
/**
* 重试失败的消息
*/
private void retryMessage(long sequenceNumber) {
// 实现重试逻辑:从缓存中取出消息重新发送
// 注意:这里需要维护消息内容与序列号的映射
}
} Collections.synchronizedSortedSet(new TreeSet<>());`
`#/**
* RabbitMQ 异步 Confirm 机制源码分析
* 基于 rabbitmq-java-client 5.16.0
*
* 核心流程:
* 1. 生产者发送消息时分配内部序列号
* 2. Broker 收到消息后返回确认(带序列号)
* 3. 生产者通过回调函数处理确认结果
*/
public class AsyncConfirmExample {
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
public void setupConfirmChannel(Channel channel) throws IOException {
// 启用发布确认模式
channel.confirmSelect();
// 添加异步确认监听器
channel.addConfirmListener(new ConfirmListener() {
/**
* 消息成功确认回调
* @param deliveryTag 消息序列号
* @param multiple 是否批量确认
*/
@Override
public void handleAck(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量确认:移除所有 <= deliveryTag 的消息
unconfirmedSet.headSet(deliveryTag + 1).clear();
} else {
// 单条确认:移除指定消息
unconfirmedSet.remove(deliveryTag);
}
System.out.println("消息确认成功,序列号: " + deliveryTag);
}
/**
* 消息失败回调(未确认)
* @param deliveryTag 消息序列号
* @param multiple 是否批量未确认
*/
@Override
public void handleNack(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量未确认:重试所有 <= deliveryTag 的消息
SortedSet<Long> headSet = unconfirmedSet.headSet(deliveryTag + 1);
for (Long seq : headSet) {
retryMessage(seq);
}
headSet.clear();
} else {
// 单条未确认:重试指定消息
retryMessage(deliveryTag);
unconfirmedSet.remove(deliveryTag);
}
System.err.println("消息确认失败,序列号: " + deliveryTag);
}
});
}
/**
* 发送消息(带序列号跟踪)
*/
public void sendMessageWithTracking(Channel channel, String message)
throws IOException {
// 获取下一个序列号
long sequenceNumber = channel.getNextPublishSeqNo();
// 记录未确认的消息
unconfirmedSet.add(sequenceNumber);
// 发送消息
channel.basicPublish(
"durable.exchange",
"routing.key",
null,
message.getBytes()
);
}
/**
* 重试失败的消息
*/
private void retryMessage(long sequenceNumber) {
// 实现重试逻辑:从缓存中取出消息重新发送
// 注意:这里需要维护消息内容与序列号的映射
}
}`
`#/**
* RabbitMQ 异步 Confirm 机制源码分析
* 基于 rabbitmq-java-client 5.16.0
*
* 核心流程:
* 1. 生产者发送消息时分配内部序列号
* 2. Broker 收到消息后返回确认(带序列号)
* 3. 生产者通过回调函数处理确认结果
*/
public class AsyncConfirmExample {
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
public void setupConfirmChannel(Channel channel) throws IOException {
// 启用发布确认模式
channel.confirmSelect();
// 添加异步确认监听器
channel.addConfirmListener(new ConfirmListener() {
/**
* 消息成功确认回调
* @param deliveryTag 消息序列号
* @param multiple 是否批量确认
*/
@Override
public void handleAck(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量确认:移除所有 <= deliveryTag 的消息
unconfirmedSet.headSet(deliveryTag + 1).clear();
} else {
// 单条确认:移除指定消息
unconfirmedSet.remove(deliveryTag);
}
System.out.println("消息确认成功,序列号: " + deliveryTag);
}
/**
* 消息失败回调(未确认)
* @param deliveryTag 消息序列号
* @param multiple 是否批量未确认
*/
@Override
public void handleNack(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量未确认:重试所有 <= deliveryTag 的消息
SortedSet<Long> headSet = unconfirmedSet.headSet(deliveryTag + 1);
for (Long seq : headSet) {
retryMessage(seq);
}
headSet.clear();
} else {
// 单条未确认:重试指定消息
retryMessage(deliveryTag);
unconfirmedSet.remove(deliveryTag);
}
System.err.println("消息确认失败,序列号: " + deliveryTag);
}
});
}
/**
* 发送消息(带序列号跟踪)
*/
public void sendMessageWithTracking(Channel channel, String message)
throws IOException {
// 获取下一个序列号
long sequenceNumber = channel.getNextPublishSeqNo();
// 记录未确认的消息
unconfirmedSet.add(sequenceNumber);
// 发送消息
channel.basicPublish(
"durable.exchange",
"routing.key",
null,
message.getBytes()
);
}
/**
* 重试失败的消息
*/
private void retryMessage(long sequenceNumber) {
// 实现重试逻辑:从缓存中取出消息重新发送
// 注意:这里需要维护消息内容与序列号的映射
}
} public void setupConfirmChannel(Channel channel) throws IOException {`
`#/**
* RabbitMQ 异步 Confirm 机制源码分析
* 基于 rabbitmq-java-client 5.16.0
*
* 核心流程:
* 1. 生产者发送消息时分配内部序列号
* 2. Broker 收到消息后返回确认(带序列号)
* 3. 生产者通过回调函数处理确认结果
*/
public class AsyncConfirmExample {
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
public void setupConfirmChannel(Channel channel) throws IOException {
// 启用发布确认模式
channel.confirmSelect();
// 添加异步确认监听器
channel.addConfirmListener(new ConfirmListener() {
/**
* 消息成功确认回调
* @param deliveryTag 消息序列号
* @param multiple 是否批量确认
*/
@Override
public void handleAck(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量确认:移除所有 <= deliveryTag 的消息
unconfirmedSet.headSet(deliveryTag + 1).clear();
} else {
// 单条确认:移除指定消息
unconfirmedSet.remove(deliveryTag);
}
System.out.println("消息确认成功,序列号: " + deliveryTag);
}
/**
* 消息失败回调(未确认)
* @param deliveryTag 消息序列号
* @param multiple 是否批量未确认
*/
@Override
public void handleNack(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量未确认:重试所有 <= deliveryTag 的消息
SortedSet<Long> headSet = unconfirmedSet.headSet(deliveryTag + 1);
for (Long seq : headSet) {
retryMessage(seq);
}
headSet.clear();
} else {
// 单条未确认:重试指定消息
retryMessage(deliveryTag);
unconfirmedSet.remove(deliveryTag);
}
System.err.println("消息确认失败,序列号: " + deliveryTag);
}
});
}
/**
* 发送消息(带序列号跟踪)
*/
public void sendMessageWithTracking(Channel channel, String message)
throws IOException {
// 获取下一个序列号
long sequenceNumber = channel.getNextPublishSeqNo();
// 记录未确认的消息
unconfirmedSet.add(sequenceNumber);
// 发送消息
channel.basicPublish(
"durable.exchange",
"routing.key",
null,
message.getBytes()
);
}
/**
* 重试失败的消息
*/
private void retryMessage(long sequenceNumber) {
// 实现重试逻辑:从缓存中取出消息重新发送
// 注意:这里需要维护消息内容与序列号的映射
}
} // 启用发布确认模式`
`#/**
* RabbitMQ 异步 Confirm 机制源码分析
* 基于 rabbitmq-java-client 5.16.0
*
* 核心流程:
* 1. 生产者发送消息时分配内部序列号
* 2. Broker 收到消息后返回确认(带序列号)
* 3. 生产者通过回调函数处理确认结果
*/
public class AsyncConfirmExample {
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
public void setupConfirmChannel(Channel channel) throws IOException {
// 启用发布确认模式
channel.confirmSelect();
// 添加异步确认监听器
channel.addConfirmListener(new ConfirmListener() {
/**
* 消息成功确认回调
* @param deliveryTag 消息序列号
* @param multiple 是否批量确认
*/
@Override
public void handleAck(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量确认:移除所有 <= deliveryTag 的消息
unconfirmedSet.headSet(deliveryTag + 1).clear();
} else {
// 单条确认:移除指定消息
unconfirmedSet.remove(deliveryTag);
}
System.out.println("消息确认成功,序列号: " + deliveryTag);
}
/**
* 消息失败回调(未确认)
* @param deliveryTag 消息序列号
* @param multiple 是否批量未确认
*/
@Override
public void handleNack(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量未确认:重试所有 <= deliveryTag 的消息
SortedSet<Long> headSet = unconfirmedSet.headSet(deliveryTag + 1);
for (Long seq : headSet) {
retryMessage(seq);
}
headSet.clear();
} else {
// 单条未确认:重试指定消息
retryMessage(deliveryTag);
unconfirmedSet.remove(deliveryTag);
}
System.err.println("消息确认失败,序列号: " + deliveryTag);
}
});
}
/**
* 发送消息(带序列号跟踪)
*/
public void sendMessageWithTracking(Channel channel, String message)
throws IOException {
// 获取下一个序列号
long sequenceNumber = channel.getNextPublishSeqNo();
// 记录未确认的消息
unconfirmedSet.add(sequenceNumber);
// 发送消息
channel.basicPublish(
"durable.exchange",
"routing.key",
null,
message.getBytes()
);
}
/**
* 重试失败的消息
*/
private void retryMessage(long sequenceNumber) {
// 实现重试逻辑:从缓存中取出消息重新发送
// 注意:这里需要维护消息内容与序列号的映射
}
} channel.confirmSelect();`
`#/**
* RabbitMQ 异步 Confirm 机制源码分析
* 基于 rabbitmq-java-client 5.16.0
*
* 核心流程:
* 1. 生产者发送消息时分配内部序列号
* 2. Broker 收到消息后返回确认(带序列号)
* 3. 生产者通过回调函数处理确认结果
*/
public class AsyncConfirmExample {
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
public void setupConfirmChannel(Channel channel) throws IOException {
// 启用发布确认模式
channel.confirmSelect();
// 添加异步确认监听器
channel.addConfirmListener(new ConfirmListener() {
/**
* 消息成功确认回调
* @param deliveryTag 消息序列号
* @param multiple 是否批量确认
*/
@Override
public void handleAck(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量确认:移除所有 <= deliveryTag 的消息
unconfirmedSet.headSet(deliveryTag + 1).clear();
} else {
// 单条确认:移除指定消息
unconfirmedSet.remove(deliveryTag);
}
System.out.println("消息确认成功,序列号: " + deliveryTag);
}
/**
* 消息失败回调(未确认)
* @param deliveryTag 消息序列号
* @param multiple 是否批量未确认
*/
@Override
public void handleNack(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量未确认:重试所有 <= deliveryTag 的消息
SortedSet<Long> headSet = unconfirmedSet.headSet(deliveryTag + 1);
for (Long seq : headSet) {
retryMessage(seq);
}
headSet.clear();
} else {
// 单条未确认:重试指定消息
retryMessage(deliveryTag);
unconfirmedSet.remove(deliveryTag);
}
System.err.println("消息确认失败,序列号: " + deliveryTag);
}
});
}
/**
* 发送消息(带序列号跟踪)
*/
public void sendMessageWithTracking(Channel channel, String message)
throws IOException {
// 获取下一个序列号
long sequenceNumber = channel.getNextPublishSeqNo();
// 记录未确认的消息
unconfirmedSet.add(sequenceNumber);
// 发送消息
channel.basicPublish(
"durable.exchange",
"routing.key",
null,
message.getBytes()
);
}
/**
* 重试失败的消息
*/
private void retryMessage(long sequenceNumber) {
// 实现重试逻辑:从缓存中取出消息重新发送
// 注意:这里需要维护消息内容与序列号的映射
}
}`
`#/**
* RabbitMQ 异步 Confirm 机制源码分析
* 基于 rabbitmq-java-client 5.16.0
*
* 核心流程:
* 1. 生产者发送消息时分配内部序列号
* 2. Broker 收到消息后返回确认(带序列号)
* 3. 生产者通过回调函数处理确认结果
*/
public class AsyncConfirmExample {
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
public void setupConfirmChannel(Channel channel) throws IOException {
// 启用发布确认模式
channel.confirmSelect();
// 添加异步确认监听器
channel.addConfirmListener(new ConfirmListener() {
/**
* 消息成功确认回调
* @param deliveryTag 消息序列号
* @param multiple 是否批量确认
*/
@Override
public void handleAck(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量确认:移除所有 <= deliveryTag 的消息
unconfirmedSet.headSet(deliveryTag + 1).clear();
} else {
// 单条确认:移除指定消息
unconfirmedSet.remove(deliveryTag);
}
System.out.println("消息确认成功,序列号: " + deliveryTag);
}
/**
* 消息失败回调(未确认)
* @param deliveryTag 消息序列号
* @param multiple 是否批量未确认
*/
@Override
public void handleNack(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量未确认:重试所有 <= deliveryTag 的消息
SortedSet<Long> headSet = unconfirmedSet.headSet(deliveryTag + 1);
for (Long seq : headSet) {
retryMessage(seq);
}
headSet.clear();
} else {
// 单条未确认:重试指定消息
retryMessage(deliveryTag);
unconfirmedSet.remove(deliveryTag);
}
System.err.println("消息确认失败,序列号: " + deliveryTag);
}
});
}
/**
* 发送消息(带序列号跟踪)
*/
public void sendMessageWithTracking(Channel channel, String message)
throws IOException {
// 获取下一个序列号
long sequenceNumber = channel.getNextPublishSeqNo();
// 记录未确认的消息
unconfirmedSet.add(sequenceNumber);
// 发送消息
channel.basicPublish(
"durable.exchange",
"routing.key",
null,
message.getBytes()
);
}
/**
* 重试失败的消息
*/
private void retryMessage(long sequenceNumber) {
// 实现重试逻辑:从缓存中取出消息重新发送
// 注意:这里需要维护消息内容与序列号的映射
}
} // 添加异步确认监听器`
`#/**
* RabbitMQ 异步 Confirm 机制源码分析
* 基于 rabbitmq-java-client 5.16.0
*
* 核心流程:
* 1. 生产者发送消息时分配内部序列号
* 2. Broker 收到消息后返回确认(带序列号)
* 3. 生产者通过回调函数处理确认结果
*/
public class AsyncConfirmExample {
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
public void setupConfirmChannel(Channel channel) throws IOException {
// 启用发布确认模式
channel.confirmSelect();
// 添加异步确认监听器
channel.addConfirmListener(new ConfirmListener() {
/**
* 消息成功确认回调
* @param deliveryTag 消息序列号
* @param multiple 是否批量确认
*/
@Override
public void handleAck(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量确认:移除所有 <= deliveryTag 的消息
unconfirmedSet.headSet(deliveryTag + 1).clear();
} else {
// 单条确认:移除指定消息
unconfirmedSet.remove(deliveryTag);
}
System.out.println("消息确认成功,序列号: " + deliveryTag);
}
/**
* 消息失败回调(未确认)
* @param deliveryTag 消息序列号
* @param multiple 是否批量未确认
*/
@Override
public void handleNack(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量未确认:重试所有 <= deliveryTag 的消息
SortedSet<Long> headSet = unconfirmedSet.headSet(deliveryTag + 1);
for (Long seq : headSet) {
retryMessage(seq);
}
headSet.clear();
} else {
// 单条未确认:重试指定消息
retryMessage(deliveryTag);
unconfirmedSet.remove(deliveryTag);
}
System.err.println("消息确认失败,序列号: " + deliveryTag);
}
});
}
/**
* 发送消息(带序列号跟踪)
*/
public void sendMessageWithTracking(Channel channel, String message)
throws IOException {
// 获取下一个序列号
long sequenceNumber = channel.getNextPublishSeqNo();
// 记录未确认的消息
unconfirmedSet.add(sequenceNumber);
// 发送消息
channel.basicPublish(
"durable.exchange",
"routing.key",
null,
message.getBytes()
);
}
/**
* 重试失败的消息
*/
private void retryMessage(long sequenceNumber) {
// 实现重试逻辑:从缓存中取出消息重新发送
// 注意:这里需要维护消息内容与序列号的映射
}
} channel.addConfirmListener(new ConfirmListener() {`
`#/**
* RabbitMQ 异步 Confirm 机制源码分析
* 基于 rabbitmq-java-client 5.16.0
*
* 核心流程:
* 1. 生产者发送消息时分配内部序列号
* 2. Broker 收到消息后返回确认(带序列号)
* 3. 生产者通过回调函数处理确认结果
*/
public class AsyncConfirmExample {
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
public void setupConfirmChannel(Channel channel) throws IOException {
// 启用发布确认模式
channel.confirmSelect();
// 添加异步确认监听器
channel.addConfirmListener(new ConfirmListener() {
/**
* 消息成功确认回调
* @param deliveryTag 消息序列号
* @param multiple 是否批量确认
*/
@Override
public void handleAck(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量确认:移除所有 <= deliveryTag 的消息
unconfirmedSet.headSet(deliveryTag + 1).clear();
} else {
// 单条确认:移除指定消息
unconfirmedSet.remove(deliveryTag);
}
System.out.println("消息确认成功,序列号: " + deliveryTag);
}
/**
* 消息失败回调(未确认)
* @param deliveryTag 消息序列号
* @param multiple 是否批量未确认
*/
@Override
public void handleNack(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量未确认:重试所有 <= deliveryTag 的消息
SortedSet<Long> headSet = unconfirmedSet.headSet(deliveryTag + 1);
for (Long seq : headSet) {
retryMessage(seq);
}
headSet.clear();
} else {
// 单条未确认:重试指定消息
retryMessage(deliveryTag);
unconfirmedSet.remove(deliveryTag);
}
System.err.println("消息确认失败,序列号: " + deliveryTag);
}
});
}
/**
* 发送消息(带序列号跟踪)
*/
public void sendMessageWithTracking(Channel channel, String message)
throws IOException {
// 获取下一个序列号
long sequenceNumber = channel.getNextPublishSeqNo();
// 记录未确认的消息
unconfirmedSet.add(sequenceNumber);
// 发送消息
channel.basicPublish(
"durable.exchange",
"routing.key",
null,
message.getBytes()
);
}
/**
* 重试失败的消息
*/
private void retryMessage(long sequenceNumber) {
// 实现重试逻辑:从缓存中取出消息重新发送
// 注意:这里需要维护消息内容与序列号的映射
}
} `
`#/**
* RabbitMQ 异步 Confirm 机制源码分析
* 基于 rabbitmq-java-client 5.16.0
*
* 核心流程:
* 1. 生产者发送消息时分配内部序列号
* 2. Broker 收到消息后返回确认(带序列号)
* 3. 生产者通过回调函数处理确认结果
*/
public class AsyncConfirmExample {
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
public void setupConfirmChannel(Channel channel) throws IOException {
// 启用发布确认模式
channel.confirmSelect();
// 添加异步确认监听器
channel.addConfirmListener(new ConfirmListener() {
/**
* 消息成功确认回调
* @param deliveryTag 消息序列号
* @param multiple 是否批量确认
*/
@Override
public void handleAck(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量确认:移除所有 <= deliveryTag 的消息
unconfirmedSet.headSet(deliveryTag + 1).clear();
} else {
// 单条确认:移除指定消息
unconfirmedSet.remove(deliveryTag);
}
System.out.println("消息确认成功,序列号: " + deliveryTag);
}
/**
* 消息失败回调(未确认)
* @param deliveryTag 消息序列号
* @param multiple 是否批量未确认
*/
@Override
public void handleNack(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量未确认:重试所有 <= deliveryTag 的消息
SortedSet<Long> headSet = unconfirmedSet.headSet(deliveryTag + 1);
for (Long seq : headSet) {
retryMessage(seq);
}
headSet.clear();
} else {
// 单条未确认:重试指定消息
retryMessage(deliveryTag);
unconfirmedSet.remove(deliveryTag);
}
System.err.println("消息确认失败,序列号: " + deliveryTag);
}
});
}
/**
* 发送消息(带序列号跟踪)
*/
public void sendMessageWithTracking(Channel channel, String message)
throws IOException {
// 获取下一个序列号
long sequenceNumber = channel.getNextPublishSeqNo();
// 记录未确认的消息
unconfirmedSet.add(sequenceNumber);
// 发送消息
channel.basicPublish(
"durable.exchange",
"routing.key",
null,
message.getBytes()
);
}
/**
* 重试失败的消息
*/
private void retryMessage(long sequenceNumber) {
// 实现重试逻辑:从缓存中取出消息重新发送
// 注意:这里需要维护消息内容与序列号的映射
}
} /**`
`#/**
* RabbitMQ 异步 Confirm 机制源码分析
* 基于 rabbitmq-java-client 5.16.0
*
* 核心流程:
* 1. 生产者发送消息时分配内部序列号
* 2. Broker 收到消息后返回确认(带序列号)
* 3. 生产者通过回调函数处理确认结果
*/
public class AsyncConfirmExample {
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
public void setupConfirmChannel(Channel channel) throws IOException {
// 启用发布确认模式
channel.confirmSelect();
// 添加异步确认监听器
channel.addConfirmListener(new ConfirmListener() {
/**
* 消息成功确认回调
* @param deliveryTag 消息序列号
* @param multiple 是否批量确认
*/
@Override
public void handleAck(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量确认:移除所有 <= deliveryTag 的消息
unconfirmedSet.headSet(deliveryTag + 1).clear();
} else {
// 单条确认:移除指定消息
unconfirmedSet.remove(deliveryTag);
}
System.out.println("消息确认成功,序列号: " + deliveryTag);
}
/**
* 消息失败回调(未确认)
* @param deliveryTag 消息序列号
* @param multiple 是否批量未确认
*/
@Override
public void handleNack(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量未确认:重试所有 <= deliveryTag 的消息
SortedSet<Long> headSet = unconfirmedSet.headSet(deliveryTag + 1);
for (Long seq : headSet) {
retryMessage(seq);
}
headSet.clear();
} else {
// 单条未确认:重试指定消息
retryMessage(deliveryTag);
unconfirmedSet.remove(deliveryTag);
}
System.err.println("消息确认失败,序列号: " + deliveryTag);
}
});
}
/**
* 发送消息(带序列号跟踪)
*/
public void sendMessageWithTracking(Channel channel, String message)
throws IOException {
// 获取下一个序列号
long sequenceNumber = channel.getNextPublishSeqNo();
// 记录未确认的消息
unconfirmedSet.add(sequenceNumber);
// 发送消息
channel.basicPublish(
"durable.exchange",
"routing.key",
null,
message.getBytes()
);
}
/**
* 重试失败的消息
*/
private void retryMessage(long sequenceNumber) {
// 实现重试逻辑:从缓存中取出消息重新发送
// 注意:这里需要维护消息内容与序列号的映射
}
} * 消息成功确认回调`
`#/**
* RabbitMQ 异步 Confirm 机制源码分析
* 基于 rabbitmq-java-client 5.16.0
*
* 核心流程:
* 1. 生产者发送消息时分配内部序列号
* 2. Broker 收到消息后返回确认(带序列号)
* 3. 生产者通过回调函数处理确认结果
*/
public class AsyncConfirmExample {
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
public void setupConfirmChannel(Channel channel) throws IOException {
// 启用发布确认模式
channel.confirmSelect();
// 添加异步确认监听器
channel.addConfirmListener(new ConfirmListener() {
/**
* 消息成功确认回调
* @param deliveryTag 消息序列号
* @param multiple 是否批量确认
*/
@Override
public void handleAck(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量确认:移除所有 <= deliveryTag 的消息
unconfirmedSet.headSet(deliveryTag + 1).clear();
} else {
// 单条确认:移除指定消息
unconfirmedSet.remove(deliveryTag);
}
System.out.println("消息确认成功,序列号: " + deliveryTag);
}
/**
* 消息失败回调(未确认)
* @param deliveryTag 消息序列号
* @param multiple 是否批量未确认
*/
@Override
public void handleNack(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量未确认:重试所有 <= deliveryTag 的消息
SortedSet<Long> headSet = unconfirmedSet.headSet(deliveryTag + 1);
for (Long seq : headSet) {
retryMessage(seq);
}
headSet.clear();
} else {
// 单条未确认:重试指定消息
retryMessage(deliveryTag);
unconfirmedSet.remove(deliveryTag);
}
System.err.println("消息确认失败,序列号: " + deliveryTag);
}
});
}
/**
* 发送消息(带序列号跟踪)
*/
public void sendMessageWithTracking(Channel channel, String message)
throws IOException {
// 获取下一个序列号
long sequenceNumber = channel.getNextPublishSeqNo();
// 记录未确认的消息
unconfirmedSet.add(sequenceNumber);
// 发送消息
channel.basicPublish(
"durable.exchange",
"routing.key",
null,
message.getBytes()
);
}
/**
* 重试失败的消息
*/
private void retryMessage(long sequenceNumber) {
// 实现重试逻辑:从缓存中取出消息重新发送
// 注意:这里需要维护消息内容与序列号的映射
}
} * @param deliveryTag 消息序列号`
`#/**
* RabbitMQ 异步 Confirm 机制源码分析
* 基于 rabbitmq-java-client 5.16.0
*
* 核心流程:
* 1. 生产者发送消息时分配内部序列号
* 2. Broker 收到消息后返回确认(带序列号)
* 3. 生产者通过回调函数处理确认结果
*/
public class AsyncConfirmExample {
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
public void setupConfirmChannel(Channel channel) throws IOException {
// 启用发布确认模式
channel.confirmSelect();
// 添加异步确认监听器
channel.addConfirmListener(new ConfirmListener() {
/**
* 消息成功确认回调
* @param deliveryTag 消息序列号
* @param multiple 是否批量确认
*/
@Override
public void handleAck(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量确认:移除所有 <= deliveryTag 的消息
unconfirmedSet.headSet(deliveryTag + 1).clear();
} else {
// 单条确认:移除指定消息
unconfirmedSet.remove(deliveryTag);
}
System.out.println("消息确认成功,序列号: " + deliveryTag);
}
/**
* 消息失败回调(未确认)
* @param deliveryTag 消息序列号
* @param multiple 是否批量未确认
*/
@Override
public void handleNack(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量未确认:重试所有 <= deliveryTag 的消息
SortedSet<Long> headSet = unconfirmedSet.headSet(deliveryTag + 1);
for (Long seq : headSet) {
retryMessage(seq);
}
headSet.clear();
} else {
// 单条未确认:重试指定消息
retryMessage(deliveryTag);
unconfirmedSet.remove(deliveryTag);
}
System.err.println("消息确认失败,序列号: " + deliveryTag);
}
});
}
/**
* 发送消息(带序列号跟踪)
*/
public void sendMessageWithTracking(Channel channel, String message)
throws IOException {
// 获取下一个序列号
long sequenceNumber = channel.getNextPublishSeqNo();
// 记录未确认的消息
unconfirmedSet.add(sequenceNumber);
// 发送消息
channel.basicPublish(
"durable.exchange",
"routing.key",
null,
message.getBytes()
);
}
/**
* 重试失败的消息
*/
private void retryMessage(long sequenceNumber) {
// 实现重试逻辑:从缓存中取出消息重新发送
// 注意:这里需要维护消息内容与序列号的映射
}
} * @param multiple 是否批量确认`
`#/**
* RabbitMQ 异步 Confirm 机制源码分析
* 基于 rabbitmq-java-client 5.16.0
*
* 核心流程:
* 1. 生产者发送消息时分配内部序列号
* 2. Broker 收到消息后返回确认(带序列号)
* 3. 生产者通过回调函数处理确认结果
*/
public class AsyncConfirmExample {
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
public void setupConfirmChannel(Channel channel) throws IOException {
// 启用发布确认模式
channel.confirmSelect();
// 添加异步确认监听器
channel.addConfirmListener(new ConfirmListener() {
/**
* 消息成功确认回调
* @param deliveryTag 消息序列号
* @param multiple 是否批量确认
*/
@Override
public void handleAck(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量确认:移除所有 <= deliveryTag 的消息
unconfirmedSet.headSet(deliveryTag + 1).clear();
} else {
// 单条确认:移除指定消息
unconfirmedSet.remove(deliveryTag);
}
System.out.println("消息确认成功,序列号: " + deliveryTag);
}
/**
* 消息失败回调(未确认)
* @param deliveryTag 消息序列号
* @param multiple 是否批量未确认
*/
@Override
public void handleNack(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量未确认:重试所有 <= deliveryTag 的消息
SortedSet<Long> headSet = unconfirmedSet.headSet(deliveryTag + 1);
for (Long seq : headSet) {
retryMessage(seq);
}
headSet.clear();
} else {
// 单条未确认:重试指定消息
retryMessage(deliveryTag);
unconfirmedSet.remove(deliveryTag);
}
System.err.println("消息确认失败,序列号: " + deliveryTag);
}
});
}
/**
* 发送消息(带序列号跟踪)
*/
public void sendMessageWithTracking(Channel channel, String message)
throws IOException {
// 获取下一个序列号
long sequenceNumber = channel.getNextPublishSeqNo();
// 记录未确认的消息
unconfirmedSet.add(sequenceNumber);
// 发送消息
channel.basicPublish(
"durable.exchange",
"routing.key",
null,
message.getBytes()
);
}
/**
* 重试失败的消息
*/
private void retryMessage(long sequenceNumber) {
// 实现重试逻辑:从缓存中取出消息重新发送
// 注意:这里需要维护消息内容与序列号的映射
}
} */`
`#/**
* RabbitMQ 异步 Confirm 机制源码分析
* 基于 rabbitmq-java-client 5.16.0
*
* 核心流程:
* 1. 生产者发送消息时分配内部序列号
* 2. Broker 收到消息后返回确认(带序列号)
* 3. 生产者通过回调函数处理确认结果
*/
public class AsyncConfirmExample {
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
public void setupConfirmChannel(Channel channel) throws IOException {
// 启用发布确认模式
channel.confirmSelect();
// 添加异步确认监听器
channel.addConfirmListener(new ConfirmListener() {
/**
* 消息成功确认回调
* @param deliveryTag 消息序列号
* @param multiple 是否批量确认
*/
@Override
public void handleAck(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量确认:移除所有 <= deliveryTag 的消息
unconfirmedSet.headSet(deliveryTag + 1).clear();
} else {
// 单条确认:移除指定消息
unconfirmedSet.remove(deliveryTag);
}
System.out.println("消息确认成功,序列号: " + deliveryTag);
}
/**
* 消息失败回调(未确认)
* @param deliveryTag 消息序列号
* @param multiple 是否批量未确认
*/
@Override
public void handleNack(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量未确认:重试所有 <= deliveryTag 的消息
SortedSet<Long> headSet = unconfirmedSet.headSet(deliveryTag + 1);
for (Long seq : headSet) {
retryMessage(seq);
}
headSet.clear();
} else {
// 单条未确认:重试指定消息
retryMessage(deliveryTag);
unconfirmedSet.remove(deliveryTag);
}
System.err.println("消息确认失败,序列号: " + deliveryTag);
}
});
}
/**
* 发送消息(带序列号跟踪)
*/
public void sendMessageWithTracking(Channel channel, String message)
throws IOException {
// 获取下一个序列号
long sequenceNumber = channel.getNextPublishSeqNo();
// 记录未确认的消息
unconfirmedSet.add(sequenceNumber);
// 发送消息
channel.basicPublish(
"durable.exchange",
"routing.key",
null,
message.getBytes()
);
}
/**
* 重试失败的消息
*/
private void retryMessage(long sequenceNumber) {
// 实现重试逻辑:从缓存中取出消息重新发送
// 注意:这里需要维护消息内容与序列号的映射
}
} @Override`
`#/**
* RabbitMQ 异步 Confirm 机制源码分析
* 基于 rabbitmq-java-client 5.16.0
*
* 核心流程:
* 1. 生产者发送消息时分配内部序列号
* 2. Broker 收到消息后返回确认(带序列号)
* 3. 生产者通过回调函数处理确认结果
*/
public class AsyncConfirmExample {
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
public void setupConfirmChannel(Channel channel) throws IOException {
// 启用发布确认模式
channel.confirmSelect();
// 添加异步确认监听器
channel.addConfirmListener(new ConfirmListener() {
/**
* 消息成功确认回调
* @param deliveryTag 消息序列号
* @param multiple 是否批量确认
*/
@Override
public void handleAck(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量确认:移除所有 <= deliveryTag 的消息
unconfirmedSet.headSet(deliveryTag + 1).clear();
} else {
// 单条确认:移除指定消息
unconfirmedSet.remove(deliveryTag);
}
System.out.println("消息确认成功,序列号: " + deliveryTag);
}
/**
* 消息失败回调(未确认)
* @param deliveryTag 消息序列号
* @param multiple 是否批量未确认
*/
@Override
public void handleNack(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量未确认:重试所有 <= deliveryTag 的消息
SortedSet<Long> headSet = unconfirmedSet.headSet(deliveryTag + 1);
for (Long seq : headSet) {
retryMessage(seq);
}
headSet.clear();
} else {
// 单条未确认:重试指定消息
retryMessage(deliveryTag);
unconfirmedSet.remove(deliveryTag);
}
System.err.println("消息确认失败,序列号: " + deliveryTag);
}
});
}
/**
* 发送消息(带序列号跟踪)
*/
public void sendMessageWithTracking(Channel channel, String message)
throws IOException {
// 获取下一个序列号
long sequenceNumber = channel.getNextPublishSeqNo();
// 记录未确认的消息
unconfirmedSet.add(sequenceNumber);
// 发送消息
channel.basicPublish(
"durable.exchange",
"routing.key",
null,
message.getBytes()
);
}
/**
* 重试失败的消息
*/
private void retryMessage(long sequenceNumber) {
// 实现重试逻辑:从缓存中取出消息重新发送
// 注意:这里需要维护消息内容与序列号的映射
}
} public void handleAck(long deliveryTag, boolean multiple) {`
`#/**
* RabbitMQ 异步 Confirm 机制源码分析
* 基于 rabbitmq-java-client 5.16.0
*
* 核心流程:
* 1. 生产者发送消息时分配内部序列号
* 2. Broker 收到消息后返回确认(带序列号)
* 3. 生产者通过回调函数处理确认结果
*/
public class AsyncConfirmExample {
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
public void setupConfirmChannel(Channel channel) throws IOException {
// 启用发布确认模式
channel.confirmSelect();
// 添加异步确认监听器
channel.addConfirmListener(new ConfirmListener() {
/**
* 消息成功确认回调
* @param deliveryTag 消息序列号
* @param multiple 是否批量确认
*/
@Override
public void handleAck(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量确认:移除所有 <= deliveryTag 的消息
unconfirmedSet.headSet(deliveryTag + 1).clear();
} else {
// 单条确认:移除指定消息
unconfirmedSet.remove(deliveryTag);
}
System.out.println("消息确认成功,序列号: " + deliveryTag);
}
/**
* 消息失败回调(未确认)
* @param deliveryTag 消息序列号
* @param multiple 是否批量未确认
*/
@Override
public void handleNack(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量未确认:重试所有 <= deliveryTag 的消息
SortedSet<Long> headSet = unconfirmedSet.headSet(deliveryTag + 1);
for (Long seq : headSet) {
retryMessage(seq);
}
headSet.clear();
} else {
// 单条未确认:重试指定消息
retryMessage(deliveryTag);
unconfirmedSet.remove(deliveryTag);
}
System.err.println("消息确认失败,序列号: " + deliveryTag);
}
});
}
/**
* 发送消息(带序列号跟踪)
*/
public void sendMessageWithTracking(Channel channel, String message)
throws IOException {
// 获取下一个序列号
long sequenceNumber = channel.getNextPublishSeqNo();
// 记录未确认的消息
unconfirmedSet.add(sequenceNumber);
// 发送消息
channel.basicPublish(
"durable.exchange",
"routing.key",
null,
message.getBytes()
);
}
/**
* 重试失败的消息
*/
private void retryMessage(long sequenceNumber) {
// 实现重试逻辑:从缓存中取出消息重新发送
// 注意:这里需要维护消息内容与序列号的映射
}
} if (multiple) {`
`#/**
* RabbitMQ 异步 Confirm 机制源码分析
* 基于 rabbitmq-java-client 5.16.0
*
* 核心流程:
* 1. 生产者发送消息时分配内部序列号
* 2. Broker 收到消息后返回确认(带序列号)
* 3. 生产者通过回调函数处理确认结果
*/
public class AsyncConfirmExample {
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
public void setupConfirmChannel(Channel channel) throws IOException {
// 启用发布确认模式
channel.confirmSelect();
// 添加异步确认监听器
channel.addConfirmListener(new ConfirmListener() {
/**
* 消息成功确认回调
* @param deliveryTag 消息序列号
* @param multiple 是否批量确认
*/
@Override
public void handleAck(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量确认:移除所有 <= deliveryTag 的消息
unconfirmedSet.headSet(deliveryTag + 1).clear();
} else {
// 单条确认:移除指定消息
unconfirmedSet.remove(deliveryTag);
}
System.out.println("消息确认成功,序列号: " + deliveryTag);
}
/**
* 消息失败回调(未确认)
* @param deliveryTag 消息序列号
* @param multiple 是否批量未确认
*/
@Override
public void handleNack(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量未确认:重试所有 <= deliveryTag 的消息
SortedSet<Long> headSet = unconfirmedSet.headSet(deliveryTag + 1);
for (Long seq : headSet) {
retryMessage(seq);
}
headSet.clear();
} else {
// 单条未确认:重试指定消息
retryMessage(deliveryTag);
unconfirmedSet.remove(deliveryTag);
}
System.err.println("消息确认失败,序列号: " + deliveryTag);
}
});
}
/**
* 发送消息(带序列号跟踪)
*/
public void sendMessageWithTracking(Channel channel, String message)
throws IOException {
// 获取下一个序列号
long sequenceNumber = channel.getNextPublishSeqNo();
// 记录未确认的消息
unconfirmedSet.add(sequenceNumber);
// 发送消息
channel.basicPublish(
"durable.exchange",
"routing.key",
null,
message.getBytes()
);
}
/**
* 重试失败的消息
*/
private void retryMessage(long sequenceNumber) {
// 实现重试逻辑:从缓存中取出消息重新发送
// 注意:这里需要维护消息内容与序列号的映射
}
} // 批量确认:移除所有 <= deliveryTag 的消息`
`#/**
* RabbitMQ 异步 Confirm 机制源码分析
* 基于 rabbitmq-java-client 5.16.0
*
* 核心流程:
* 1. 生产者发送消息时分配内部序列号
* 2. Broker 收到消息后返回确认(带序列号)
* 3. 生产者通过回调函数处理确认结果
*/
public class AsyncConfirmExample {
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
public void setupConfirmChannel(Channel channel) throws IOException {
// 启用发布确认模式
channel.confirmSelect();
// 添加异步确认监听器
channel.addConfirmListener(new ConfirmListener() {
/**
* 消息成功确认回调
* @param deliveryTag 消息序列号
* @param multiple 是否批量确认
*/
@Override
public void handleAck(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量确认:移除所有 <= deliveryTag 的消息
unconfirmedSet.headSet(deliveryTag + 1).clear();
} else {
// 单条确认:移除指定消息
unconfirmedSet.remove(deliveryTag);
}
System.out.println("消息确认成功,序列号: " + deliveryTag);
}
/**
* 消息失败回调(未确认)
* @param deliveryTag 消息序列号
* @param multiple 是否批量未确认
*/
@Override
public void handleNack(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量未确认:重试所有 <= deliveryTag 的消息
SortedSet<Long> headSet = unconfirmedSet.headSet(deliveryTag + 1);
for (Long seq : headSet) {
retryMessage(seq);
}
headSet.clear();
} else {
// 单条未确认:重试指定消息
retryMessage(deliveryTag);
unconfirmedSet.remove(deliveryTag);
}
System.err.println("消息确认失败,序列号: " + deliveryTag);
}
});
}
/**
* 发送消息(带序列号跟踪)
*/
public void sendMessageWithTracking(Channel channel, String message)
throws IOException {
// 获取下一个序列号
long sequenceNumber = channel.getNextPublishSeqNo();
// 记录未确认的消息
unconfirmedSet.add(sequenceNumber);
// 发送消息
channel.basicPublish(
"durable.exchange",
"routing.key",
null,
message.getBytes()
);
}
/**
* 重试失败的消息
*/
private void retryMessage(long sequenceNumber) {
// 实现重试逻辑:从缓存中取出消息重新发送
// 注意:这里需要维护消息内容与序列号的映射
}
} unconfirmedSet.headSet(deliveryTag + 1).clear();`
`#/**
* RabbitMQ 异步 Confirm 机制源码分析
* 基于 rabbitmq-java-client 5.16.0
*
* 核心流程:
* 1. 生产者发送消息时分配内部序列号
* 2. Broker 收到消息后返回确认(带序列号)
* 3. 生产者通过回调函数处理确认结果
*/
public class AsyncConfirmExample {
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
public void setupConfirmChannel(Channel channel) throws IOException {
// 启用发布确认模式
channel.confirmSelect();
// 添加异步确认监听器
channel.addConfirmListener(new ConfirmListener() {
/**
* 消息成功确认回调
* @param deliveryTag 消息序列号
* @param multiple 是否批量确认
*/
@Override
public void handleAck(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量确认:移除所有 <= deliveryTag 的消息
unconfirmedSet.headSet(deliveryTag + 1).clear();
} else {
// 单条确认:移除指定消息
unconfirmedSet.remove(deliveryTag);
}
System.out.println("消息确认成功,序列号: " + deliveryTag);
}
/**
* 消息失败回调(未确认)
* @param deliveryTag 消息序列号
* @param multiple 是否批量未确认
*/
@Override
public void handleNack(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量未确认:重试所有 <= deliveryTag 的消息
SortedSet<Long> headSet = unconfirmedSet.headSet(deliveryTag + 1);
for (Long seq : headSet) {
retryMessage(seq);
}
headSet.clear();
} else {
// 单条未确认:重试指定消息
retryMessage(deliveryTag);
unconfirmedSet.remove(deliveryTag);
}
System.err.println("消息确认失败,序列号: " + deliveryTag);
}
});
}
/**
* 发送消息(带序列号跟踪)
*/
public void sendMessageWithTracking(Channel channel, String message)
throws IOException {
// 获取下一个序列号
long sequenceNumber = channel.getNextPublishSeqNo();
// 记录未确认的消息
unconfirmedSet.add(sequenceNumber);
// 发送消息
channel.basicPublish(
"durable.exchange",
"routing.key",
null,
message.getBytes()
);
}
/**
* 重试失败的消息
*/
private void retryMessage(long sequenceNumber) {
// 实现重试逻辑:从缓存中取出消息重新发送
// 注意:这里需要维护消息内容与序列号的映射
}
} } else {`
`#/**
* RabbitMQ 异步 Confirm 机制源码分析
* 基于 rabbitmq-java-client 5.16.0
*
* 核心流程:
* 1. 生产者发送消息时分配内部序列号
* 2. Broker 收到消息后返回确认(带序列号)
* 3. 生产者通过回调函数处理确认结果
*/
public class AsyncConfirmExample {
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
public void setupConfirmChannel(Channel channel) throws IOException {
// 启用发布确认模式
channel.confirmSelect();
// 添加异步确认监听器
channel.addConfirmListener(new ConfirmListener() {
/**
* 消息成功确认回调
* @param deliveryTag 消息序列号
* @param multiple 是否批量确认
*/
@Override
public void handleAck(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量确认:移除所有 <= deliveryTag 的消息
unconfirmedSet.headSet(deliveryTag + 1).clear();
} else {
// 单条确认:移除指定消息
unconfirmedSet.remove(deliveryTag);
}
System.out.println("消息确认成功,序列号: " + deliveryTag);
}
/**
* 消息失败回调(未确认)
* @param deliveryTag 消息序列号
* @param multiple 是否批量未确认
*/
@Override
public void handleNack(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量未确认:重试所有 <= deliveryTag 的消息
SortedSet<Long> headSet = unconfirmedSet.headSet(deliveryTag + 1);
for (Long seq : headSet) {
retryMessage(seq);
}
headSet.clear();
} else {
// 单条未确认:重试指定消息
retryMessage(deliveryTag);
unconfirmedSet.remove(deliveryTag);
}
System.err.println("消息确认失败,序列号: " + deliveryTag);
}
});
}
/**
* 发送消息(带序列号跟踪)
*/
public void sendMessageWithTracking(Channel channel, String message)
throws IOException {
// 获取下一个序列号
long sequenceNumber = channel.getNextPublishSeqNo();
// 记录未确认的消息
unconfirmedSet.add(sequenceNumber);
// 发送消息
channel.basicPublish(
"durable.exchange",
"routing.key",
null,
message.getBytes()
);
}
/**
* 重试失败的消息
*/
private void retryMessage(long sequenceNumber) {
// 实现重试逻辑:从缓存中取出消息重新发送
// 注意:这里需要维护消息内容与序列号的映射
}
} // 单条确认:移除指定消息`
`#/**
* RabbitMQ 异步 Confirm 机制源码分析
* 基于 rabbitmq-java-client 5.16.0
*
* 核心流程:
* 1. 生产者发送消息时分配内部序列号
* 2. Broker 收到消息后返回确认(带序列号)
* 3. 生产者通过回调函数处理确认结果
*/
public class AsyncConfirmExample {
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
public void setupConfirmChannel(Channel channel) throws IOException {
// 启用发布确认模式
channel.confirmSelect();
// 添加异步确认监听器
channel.addConfirmListener(new ConfirmListener() {
/**
* 消息成功确认回调
* @param deliveryTag 消息序列号
* @param multiple 是否批量确认
*/
@Override
public void handleAck(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量确认:移除所有 <= deliveryTag 的消息
unconfirmedSet.headSet(deliveryTag + 1).clear();
} else {
// 单条确认:移除指定消息
unconfirmedSet.remove(deliveryTag);
}
System.out.println("消息确认成功,序列号: " + deliveryTag);
}
/**
* 消息失败回调(未确认)
* @param deliveryTag 消息序列号
* @param multiple 是否批量未确认
*/
@Override
public void handleNack(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量未确认:重试所有 <= deliveryTag 的消息
SortedSet<Long> headSet = unconfirmedSet.headSet(deliveryTag + 1);
for (Long seq : headSet) {
retryMessage(seq);
}
headSet.clear();
} else {
// 单条未确认:重试指定消息
retryMessage(deliveryTag);
unconfirmedSet.remove(deliveryTag);
}
System.err.println("消息确认失败,序列号: " + deliveryTag);
}
});
}
/**
* 发送消息(带序列号跟踪)
*/
public void sendMessageWithTracking(Channel channel, String message)
throws IOException {
// 获取下一个序列号
long sequenceNumber = channel.getNextPublishSeqNo();
// 记录未确认的消息
unconfirmedSet.add(sequenceNumber);
// 发送消息
channel.basicPublish(
"durable.exchange",
"routing.key",
null,
message.getBytes()
);
}
/**
* 重试失败的消息
*/
private void retryMessage(long sequenceNumber) {
// 实现重试逻辑:从缓存中取出消息重新发送
// 注意:这里需要维护消息内容与序列号的映射
}
} unconfirmedSet.remove(deliveryTag);`
`#/**
* RabbitMQ 异步 Confirm 机制源码分析
* 基于 rabbitmq-java-client 5.16.0
*
* 核心流程:
* 1. 生产者发送消息时分配内部序列号
* 2. Broker 收到消息后返回确认(带序列号)
* 3. 生产者通过回调函数处理确认结果
*/
public class AsyncConfirmExample {
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
public void setupConfirmChannel(Channel channel) throws IOException {
// 启用发布确认模式
channel.confirmSelect();
// 添加异步确认监听器
channel.addConfirmListener(new ConfirmListener() {
/**
* 消息成功确认回调
* @param deliveryTag 消息序列号
* @param multiple 是否批量确认
*/
@Override
public void handleAck(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量确认:移除所有 <= deliveryTag 的消息
unconfirmedSet.headSet(deliveryTag + 1).clear();
} else {
// 单条确认:移除指定消息
unconfirmedSet.remove(deliveryTag);
}
System.out.println("消息确认成功,序列号: " + deliveryTag);
}
/**
* 消息失败回调(未确认)
* @param deliveryTag 消息序列号
* @param multiple 是否批量未确认
*/
@Override
public void handleNack(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量未确认:重试所有 <= deliveryTag 的消息
SortedSet<Long> headSet = unconfirmedSet.headSet(deliveryTag + 1);
for (Long seq : headSet) {
retryMessage(seq);
}
headSet.clear();
} else {
// 单条未确认:重试指定消息
retryMessage(deliveryTag);
unconfirmedSet.remove(deliveryTag);
}
System.err.println("消息确认失败,序列号: " + deliveryTag);
}
});
}
/**
* 发送消息(带序列号跟踪)
*/
public void sendMessageWithTracking(Channel channel, String message)
throws IOException {
// 获取下一个序列号
long sequenceNumber = channel.getNextPublishSeqNo();
// 记录未确认的消息
unconfirmedSet.add(sequenceNumber);
// 发送消息
channel.basicPublish(
"durable.exchange",
"routing.key",
null,
message.getBytes()
);
}
/**
* 重试失败的消息
*/
private void retryMessage(long sequenceNumber) {
// 实现重试逻辑:从缓存中取出消息重新发送
// 注意:这里需要维护消息内容与序列号的映射
}
} }`
`#/**
* RabbitMQ 异步 Confirm 机制源码分析
* 基于 rabbitmq-java-client 5.16.0
*
* 核心流程:
* 1. 生产者发送消息时分配内部序列号
* 2. Broker 收到消息后返回确认(带序列号)
* 3. 生产者通过回调函数处理确认结果
*/
public class AsyncConfirmExample {
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
public void setupConfirmChannel(Channel channel) throws IOException {
// 启用发布确认模式
channel.confirmSelect();
// 添加异步确认监听器
channel.addConfirmListener(new ConfirmListener() {
/**
* 消息成功确认回调
* @param deliveryTag 消息序列号
* @param multiple 是否批量确认
*/
@Override
public void handleAck(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量确认:移除所有 <= deliveryTag 的消息
unconfirmedSet.headSet(deliveryTag + 1).clear();
} else {
// 单条确认:移除指定消息
unconfirmedSet.remove(deliveryTag);
}
System.out.println("消息确认成功,序列号: " + deliveryTag);
}
/**
* 消息失败回调(未确认)
* @param deliveryTag 消息序列号
* @param multiple 是否批量未确认
*/
@Override
public void handleNack(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量未确认:重试所有 <= deliveryTag 的消息
SortedSet<Long> headSet = unconfirmedSet.headSet(deliveryTag + 1);
for (Long seq : headSet) {
retryMessage(seq);
}
headSet.clear();
} else {
// 单条未确认:重试指定消息
retryMessage(deliveryTag);
unconfirmedSet.remove(deliveryTag);
}
System.err.println("消息确认失败,序列号: " + deliveryTag);
}
});
}
/**
* 发送消息(带序列号跟踪)
*/
public void sendMessageWithTracking(Channel channel, String message)
throws IOException {
// 获取下一个序列号
long sequenceNumber = channel.getNextPublishSeqNo();
// 记录未确认的消息
unconfirmedSet.add(sequenceNumber);
// 发送消息
channel.basicPublish(
"durable.exchange",
"routing.key",
null,
message.getBytes()
);
}
/**
* 重试失败的消息
*/
private void retryMessage(long sequenceNumber) {
// 实现重试逻辑:从缓存中取出消息重新发送
// 注意:这里需要维护消息内容与序列号的映射
}
} `
`#/**
* RabbitMQ 异步 Confirm 机制源码分析
* 基于 rabbitmq-java-client 5.16.0
*
* 核心流程:
* 1. 生产者发送消息时分配内部序列号
* 2. Broker 收到消息后返回确认(带序列号)
* 3. 生产者通过回调函数处理确认结果
*/
public class AsyncConfirmExample {
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
public void setupConfirmChannel(Channel channel) throws IOException {
// 启用发布确认模式
channel.confirmSelect();
// 添加异步确认监听器
channel.addConfirmListener(new ConfirmListener() {
/**
* 消息成功确认回调
* @param deliveryTag 消息序列号
* @param multiple 是否批量确认
*/
@Override
public void handleAck(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量确认:移除所有 <= deliveryTag 的消息
unconfirmedSet.headSet(deliveryTag + 1).clear();
} else {
// 单条确认:移除指定消息
unconfirmedSet.remove(deliveryTag);
}
System.out.println("消息确认成功,序列号: " + deliveryTag);
}
/**
* 消息失败回调(未确认)
* @param deliveryTag 消息序列号
* @param multiple 是否批量未确认
*/
@Override
public void handleNack(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量未确认:重试所有 <= deliveryTag 的消息
SortedSet<Long> headSet = unconfirmedSet.headSet(deliveryTag + 1);
for (Long seq : headSet) {
retryMessage(seq);
}
headSet.clear();
} else {
// 单条未确认:重试指定消息
retryMessage(deliveryTag);
unconfirmedSet.remove(deliveryTag);
}
System.err.println("消息确认失败,序列号: " + deliveryTag);
}
});
}
/**
* 发送消息(带序列号跟踪)
*/
public void sendMessageWithTracking(Channel channel, String message)
throws IOException {
// 获取下一个序列号
long sequenceNumber = channel.getNextPublishSeqNo();
// 记录未确认的消息
unconfirmedSet.add(sequenceNumber);
// 发送消息
channel.basicPublish(
"durable.exchange",
"routing.key",
null,
message.getBytes()
);
}
/**
* 重试失败的消息
*/
private void retryMessage(long sequenceNumber) {
// 实现重试逻辑:从缓存中取出消息重新发送
// 注意:这里需要维护消息内容与序列号的映射
}
} System.out.println("消息确认成功,序列号: " + deliveryTag);`
`#/**
* RabbitMQ 异步 Confirm 机制源码分析
* 基于 rabbitmq-java-client 5.16.0
*
* 核心流程:
* 1. 生产者发送消息时分配内部序列号
* 2. Broker 收到消息后返回确认(带序列号)
* 3. 生产者通过回调函数处理确认结果
*/
public class AsyncConfirmExample {
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
public void setupConfirmChannel(Channel channel) throws IOException {
// 启用发布确认模式
channel.confirmSelect();
// 添加异步确认监听器
channel.addConfirmListener(new ConfirmListener() {
/**
* 消息成功确认回调
* @param deliveryTag 消息序列号
* @param multiple 是否批量确认
*/
@Override
public void handleAck(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量确认:移除所有 <= deliveryTag 的消息
unconfirmedSet.headSet(deliveryTag + 1).clear();
} else {
// 单条确认:移除指定消息
unconfirmedSet.remove(deliveryTag);
}
System.out.println("消息确认成功,序列号: " + deliveryTag);
}
/**
* 消息失败回调(未确认)
* @param deliveryTag 消息序列号
* @param multiple 是否批量未确认
*/
@Override
public void handleNack(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量未确认:重试所有 <= deliveryTag 的消息
SortedSet<Long> headSet = unconfirmedSet.headSet(deliveryTag + 1);
for (Long seq : headSet) {
retryMessage(seq);
}
headSet.clear();
} else {
// 单条未确认:重试指定消息
retryMessage(deliveryTag);
unconfirmedSet.remove(deliveryTag);
}
System.err.println("消息确认失败,序列号: " + deliveryTag);
}
});
}
/**
* 发送消息(带序列号跟踪)
*/
public void sendMessageWithTracking(Channel channel, String message)
throws IOException {
// 获取下一个序列号
long sequenceNumber = channel.getNextPublishSeqNo();
// 记录未确认的消息
unconfirmedSet.add(sequenceNumber);
// 发送消息
channel.basicPublish(
"durable.exchange",
"routing.key",
null,
message.getBytes()
);
}
/**
* 重试失败的消息
*/
private void retryMessage(long sequenceNumber) {
// 实现重试逻辑:从缓存中取出消息重新发送
// 注意:这里需要维护消息内容与序列号的映射
}
} }`
`#/**
* RabbitMQ 异步 Confirm 机制源码分析
* 基于 rabbitmq-java-client 5.16.0
*
* 核心流程:
* 1. 生产者发送消息时分配内部序列号
* 2. Broker 收到消息后返回确认(带序列号)
* 3. 生产者通过回调函数处理确认结果
*/
public class AsyncConfirmExample {
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
public void setupConfirmChannel(Channel channel) throws IOException {
// 启用发布确认模式
channel.confirmSelect();
// 添加异步确认监听器
channel.addConfirmListener(new ConfirmListener() {
/**
* 消息成功确认回调
* @param deliveryTag 消息序列号
* @param multiple 是否批量确认
*/
@Override
public void handleAck(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量确认:移除所有 <= deliveryTag 的消息
unconfirmedSet.headSet(deliveryTag + 1).clear();
} else {
// 单条确认:移除指定消息
unconfirmedSet.remove(deliveryTag);
}
System.out.println("消息确认成功,序列号: " + deliveryTag);
}
/**
* 消息失败回调(未确认)
* @param deliveryTag 消息序列号
* @param multiple 是否批量未确认
*/
@Override
public void handleNack(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量未确认:重试所有 <= deliveryTag 的消息
SortedSet<Long> headSet = unconfirmedSet.headSet(deliveryTag + 1);
for (Long seq : headSet) {
retryMessage(seq);
}
headSet.clear();
} else {
// 单条未确认:重试指定消息
retryMessage(deliveryTag);
unconfirmedSet.remove(deliveryTag);
}
System.err.println("消息确认失败,序列号: " + deliveryTag);
}
});
}
/**
* 发送消息(带序列号跟踪)
*/
public void sendMessageWithTracking(Channel channel, String message)
throws IOException {
// 获取下一个序列号
long sequenceNumber = channel.getNextPublishSeqNo();
// 记录未确认的消息
unconfirmedSet.add(sequenceNumber);
// 发送消息
channel.basicPublish(
"durable.exchange",
"routing.key",
null,
message.getBytes()
);
}
/**
* 重试失败的消息
*/
private void retryMessage(long sequenceNumber) {
// 实现重试逻辑:从缓存中取出消息重新发送
// 注意:这里需要维护消息内容与序列号的映射
}
}`
`#/**
* RabbitMQ 异步 Confirm 机制源码分析
* 基于 rabbitmq-java-client 5.16.0
*
* 核心流程:
* 1. 生产者发送消息时分配内部序列号
* 2. Broker 收到消息后返回确认(带序列号)
* 3. 生产者通过回调函数处理确认结果
*/
public class AsyncConfirmExample {
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
public void setupConfirmChannel(Channel channel) throws IOException {
// 启用发布确认模式
channel.confirmSelect();
// 添加异步确认监听器
channel.addConfirmListener(new ConfirmListener() {
/**
* 消息成功确认回调
* @param deliveryTag 消息序列号
* @param multiple 是否批量确认
*/
@Override
public void handleAck(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量确认:移除所有 <= deliveryTag 的消息
unconfirmedSet.headSet(deliveryTag + 1).clear();
} else {
// 单条确认:移除指定消息
unconfirmedSet.remove(deliveryTag);
}
System.out.println("消息确认成功,序列号: " + deliveryTag);
}
/**
* 消息失败回调(未确认)
* @param deliveryTag 消息序列号
* @param multiple 是否批量未确认
*/
@Override
public void handleNack(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量未确认:重试所有 <= deliveryTag 的消息
SortedSet<Long> headSet = unconfirmedSet.headSet(deliveryTag + 1);
for (Long seq : headSet) {
retryMessage(seq);
}
headSet.clear();
} else {
// 单条未确认:重试指定消息
retryMessage(deliveryTag);
unconfirmedSet.remove(deliveryTag);
}
System.err.println("消息确认失败,序列号: " + deliveryTag);
}
});
}
/**
* 发送消息(带序列号跟踪)
*/
public void sendMessageWithTracking(Channel channel, String message)
throws IOException {
// 获取下一个序列号
long sequenceNumber = channel.getNextPublishSeqNo();
// 记录未确认的消息
unconfirmedSet.add(sequenceNumber);
// 发送消息
channel.basicPublish(
"durable.exchange",
"routing.key",
null,
message.getBytes()
);
}
/**
* 重试失败的消息
*/
private void retryMessage(long sequenceNumber) {
// 实现重试逻辑:从缓存中取出消息重新发送
// 注意:这里需要维护消息内容与序列号的映射
}
} /**`
`#/**
* RabbitMQ 异步 Confirm 机制源码分析
* 基于 rabbitmq-java-client 5.16.0
*
* 核心流程:
* 1. 生产者发送消息时分配内部序列号
* 2. Broker 收到消息后返回确认(带序列号)
* 3. 生产者通过回调函数处理确认结果
*/
public class AsyncConfirmExample {
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
public void setupConfirmChannel(Channel channel) throws IOException {
// 启用发布确认模式
channel.confirmSelect();
// 添加异步确认监听器
channel.addConfirmListener(new ConfirmListener() {
/**
* 消息成功确认回调
* @param deliveryTag 消息序列号
* @param multiple 是否批量确认
*/
@Override
public void handleAck(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量确认:移除所有 <= deliveryTag 的消息
unconfirmedSet.headSet(deliveryTag + 1).clear();
} else {
// 单条确认:移除指定消息
unconfirmedSet.remove(deliveryTag);
}
System.out.println("消息确认成功,序列号: " + deliveryTag);
}
/**
* 消息失败回调(未确认)
* @param deliveryTag 消息序列号
* @param multiple 是否批量未确认
*/
@Override
public void handleNack(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量未确认:重试所有 <= deliveryTag 的消息
SortedSet<Long> headSet = unconfirmedSet.headSet(deliveryTag + 1);
for (Long seq : headSet) {
retryMessage(seq);
}
headSet.clear();
} else {
// 单条未确认:重试指定消息
retryMessage(deliveryTag);
unconfirmedSet.remove(deliveryTag);
}
System.err.println("消息确认失败,序列号: " + deliveryTag);
}
});
}
/**
* 发送消息(带序列号跟踪)
*/
public void sendMessageWithTracking(Channel channel, String message)
throws IOException {
// 获取下一个序列号
long sequenceNumber = channel.getNextPublishSeqNo();
// 记录未确认的消息
unconfirmedSet.add(sequenceNumber);
// 发送消息
channel.basicPublish(
"durable.exchange",
"routing.key",
null,
message.getBytes()
);
}
/**
* 重试失败的消息
*/
private void retryMessage(long sequenceNumber) {
// 实现重试逻辑:从缓存中取出消息重新发送
// 注意:这里需要维护消息内容与序列号的映射
}
} * 消息失败回调(未确认)`
`#/**
* RabbitMQ 异步 Confirm 机制源码分析
* 基于 rabbitmq-java-client 5.16.0
*
* 核心流程:
* 1. 生产者发送消息时分配内部序列号
* 2. Broker 收到消息后返回确认(带序列号)
* 3. 生产者通过回调函数处理确认结果
*/
public class AsyncConfirmExample {
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
public void setupConfirmChannel(Channel channel) throws IOException {
// 启用发布确认模式
channel.confirmSelect();
// 添加异步确认监听器
channel.addConfirmListener(new ConfirmListener() {
/**
* 消息成功确认回调
* @param deliveryTag 消息序列号
* @param multiple 是否批量确认
*/
@Override
public void handleAck(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量确认:移除所有 <= deliveryTag 的消息
unconfirmedSet.headSet(deliveryTag + 1).clear();
} else {
// 单条确认:移除指定消息
unconfirmedSet.remove(deliveryTag);
}
System.out.println("消息确认成功,序列号: " + deliveryTag);
}
/**
* 消息失败回调(未确认)
* @param deliveryTag 消息序列号
* @param multiple 是否批量未确认
*/
@Override
public void handleNack(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量未确认:重试所有 <= deliveryTag 的消息
SortedSet<Long> headSet = unconfirmedSet.headSet(deliveryTag + 1);
for (Long seq : headSet) {
retryMessage(seq);
}
headSet.clear();
} else {
// 单条未确认:重试指定消息
retryMessage(deliveryTag);
unconfirmedSet.remove(deliveryTag);
}
System.err.println("消息确认失败,序列号: " + deliveryTag);
}
});
}
/**
* 发送消息(带序列号跟踪)
*/
public void sendMessageWithTracking(Channel channel, String message)
throws IOException {
// 获取下一个序列号
long sequenceNumber = channel.getNextPublishSeqNo();
// 记录未确认的消息
unconfirmedSet.add(sequenceNumber);
// 发送消息
channel.basicPublish(
"durable.exchange",
"routing.key",
null,
message.getBytes()
);
}
/**
* 重试失败的消息
*/
private void retryMessage(long sequenceNumber) {
// 实现重试逻辑:从缓存中取出消息重新发送
// 注意:这里需要维护消息内容与序列号的映射
}
} * @param deliveryTag 消息序列号`
`#/**
* RabbitMQ 异步 Confirm 机制源码分析
* 基于 rabbitmq-java-client 5.16.0
*
* 核心流程:
* 1. 生产者发送消息时分配内部序列号
* 2. Broker 收到消息后返回确认(带序列号)
* 3. 生产者通过回调函数处理确认结果
*/
public class AsyncConfirmExample {
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
public void setupConfirmChannel(Channel channel) throws IOException {
// 启用发布确认模式
channel.confirmSelect();
// 添加异步确认监听器
channel.addConfirmListener(new ConfirmListener() {
/**
* 消息成功确认回调
* @param deliveryTag 消息序列号
* @param multiple 是否批量确认
*/
@Override
public void handleAck(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量确认:移除所有 <= deliveryTag 的消息
unconfirmedSet.headSet(deliveryTag + 1).clear();
} else {
// 单条确认:移除指定消息
unconfirmedSet.remove(deliveryTag);
}
System.out.println("消息确认成功,序列号: " + deliveryTag);
}
/**
* 消息失败回调(未确认)
* @param deliveryTag 消息序列号
* @param multiple 是否批量未确认
*/
@Override
public void handleNack(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量未确认:重试所有 <= deliveryTag 的消息
SortedSet<Long> headSet = unconfirmedSet.headSet(deliveryTag + 1);
for (Long seq : headSet) {
retryMessage(seq);
}
headSet.clear();
} else {
// 单条未确认:重试指定消息
retryMessage(deliveryTag);
unconfirmedSet.remove(deliveryTag);
}
System.err.println("消息确认失败,序列号: " + deliveryTag);
}
});
}
/**
* 发送消息(带序列号跟踪)
*/
public void sendMessageWithTracking(Channel channel, String message)
throws IOException {
// 获取下一个序列号
long sequenceNumber = channel.getNextPublishSeqNo();
// 记录未确认的消息
unconfirmedSet.add(sequenceNumber);
// 发送消息
channel.basicPublish(
"durable.exchange",
"routing.key",
null,
message.getBytes()
);
}
/**
* 重试失败的消息
*/
private void retryMessage(long sequenceNumber) {
// 实现重试逻辑:从缓存中取出消息重新发送
// 注意:这里需要维护消息内容与序列号的映射
}
} * @param multiple 是否批量未确认`
`#/**
* RabbitMQ 异步 Confirm 机制源码分析
* 基于 rabbitmq-java-client 5.16.0
*
* 核心流程:
* 1. 生产者发送消息时分配内部序列号
* 2. Broker 收到消息后返回确认(带序列号)
* 3. 生产者通过回调函数处理确认结果
*/
public class AsyncConfirmExample {
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
public void setupConfirmChannel(Channel channel) throws IOException {
// 启用发布确认模式
channel.confirmSelect();
// 添加异步确认监听器
channel.addConfirmListener(new ConfirmListener() {
/**
* 消息成功确认回调
* @param deliveryTag 消息序列号
* @param multiple 是否批量确认
*/
@Override
public void handleAck(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量确认:移除所有 <= deliveryTag 的消息
unconfirmedSet.headSet(deliveryTag + 1).clear();
} else {
// 单条确认:移除指定消息
unconfirmedSet.remove(deliveryTag);
}
System.out.println("消息确认成功,序列号: " + deliveryTag);
}
/**
* 消息失败回调(未确认)
* @param deliveryTag 消息序列号
* @param multiple 是否批量未确认
*/
@Override
public void handleNack(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量未确认:重试所有 <= deliveryTag 的消息
SortedSet<Long> headSet = unconfirmedSet.headSet(deliveryTag + 1);
for (Long seq : headSet) {
retryMessage(seq);
}
headSet.clear();
} else {
// 单条未确认:重试指定消息
retryMessage(deliveryTag);
unconfirmedSet.remove(deliveryTag);
}
System.err.println("消息确认失败,序列号: " + deliveryTag);
}
});
}
/**
* 发送消息(带序列号跟踪)
*/
public void sendMessageWithTracking(Channel channel, String message)
throws IOException {
// 获取下一个序列号
long sequenceNumber = channel.getNextPublishSeqNo();
// 记录未确认的消息
unconfirmedSet.add(sequenceNumber);
// 发送消息
channel.basicPublish(
"durable.exchange",
"routing.key",
null,
message.getBytes()
);
}
/**
* 重试失败的消息
*/
private void retryMessage(long sequenceNumber) {
// 实现重试逻辑:从缓存中取出消息重新发送
// 注意:这里需要维护消息内容与序列号的映射
}
} */`
`#/**
* RabbitMQ 异步 Confirm 机制源码分析
* 基于 rabbitmq-java-client 5.16.0
*
* 核心流程:
* 1. 生产者发送消息时分配内部序列号
* 2. Broker 收到消息后返回确认(带序列号)
* 3. 生产者通过回调函数处理确认结果
*/
public class AsyncConfirmExample {
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
public void setupConfirmChannel(Channel channel) throws IOException {
// 启用发布确认模式
channel.confirmSelect();
// 添加异步确认监听器
channel.addConfirmListener(new ConfirmListener() {
/**
* 消息成功确认回调
* @param deliveryTag 消息序列号
* @param multiple 是否批量确认
*/
@Override
public void handleAck(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量确认:移除所有 <= deliveryTag 的消息
unconfirmedSet.headSet(deliveryTag + 1).clear();
} else {
// 单条确认:移除指定消息
unconfirmedSet.remove(deliveryTag);
}
System.out.println("消息确认成功,序列号: " + deliveryTag);
}
/**
* 消息失败回调(未确认)
* @param deliveryTag 消息序列号
* @param multiple 是否批量未确认
*/
@Override
public void handleNack(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量未确认:重试所有 <= deliveryTag 的消息
SortedSet<Long> headSet = unconfirmedSet.headSet(deliveryTag + 1);
for (Long seq : headSet) {
retryMessage(seq);
}
headSet.clear();
} else {
// 单条未确认:重试指定消息
retryMessage(deliveryTag);
unconfirmedSet.remove(deliveryTag);
}
System.err.println("消息确认失败,序列号: " + deliveryTag);
}
});
}
/**
* 发送消息(带序列号跟踪)
*/
public void sendMessageWithTracking(Channel channel, String message)
throws IOException {
// 获取下一个序列号
long sequenceNumber = channel.getNextPublishSeqNo();
// 记录未确认的消息
unconfirmedSet.add(sequenceNumber);
// 发送消息
channel.basicPublish(
"durable.exchange",
"routing.key",
null,
message.getBytes()
);
}
/**
* 重试失败的消息
*/
private void retryMessage(long sequenceNumber) {
// 实现重试逻辑:从缓存中取出消息重新发送
// 注意:这里需要维护消息内容与序列号的映射
}
} @Override`
`#/**
* RabbitMQ 异步 Confirm 机制源码分析
* 基于 rabbitmq-java-client 5.16.0
*
* 核心流程:
* 1. 生产者发送消息时分配内部序列号
* 2. Broker 收到消息后返回确认(带序列号)
* 3. 生产者通过回调函数处理确认结果
*/
public class AsyncConfirmExample {
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
public void setupConfirmChannel(Channel channel) throws IOException {
// 启用发布确认模式
channel.confirmSelect();
// 添加异步确认监听器
channel.addConfirmListener(new ConfirmListener() {
/**
* 消息成功确认回调
* @param deliveryTag 消息序列号
* @param multiple 是否批量确认
*/
@Override
public void handleAck(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量确认:移除所有 <= deliveryTag 的消息
unconfirmedSet.headSet(deliveryTag + 1).clear();
} else {
// 单条确认:移除指定消息
unconfirmedSet.remove(deliveryTag);
}
System.out.println("消息确认成功,序列号: " + deliveryTag);
}
/**
* 消息失败回调(未确认)
* @param deliveryTag 消息序列号
* @param multiple 是否批量未确认
*/
@Override
public void handleNack(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量未确认:重试所有 <= deliveryTag 的消息
SortedSet<Long> headSet = unconfirmedSet.headSet(deliveryTag + 1);
for (Long seq : headSet) {
retryMessage(seq);
}
headSet.clear();
} else {
// 单条未确认:重试指定消息
retryMessage(deliveryTag);
unconfirmedSet.remove(deliveryTag);
}
System.err.println("消息确认失败,序列号: " + deliveryTag);
}
});
}
/**
* 发送消息(带序列号跟踪)
*/
public void sendMessageWithTracking(Channel channel, String message)
throws IOException {
// 获取下一个序列号
long sequenceNumber = channel.getNextPublishSeqNo();
// 记录未确认的消息
unconfirmedSet.add(sequenceNumber);
// 发送消息
channel.basicPublish(
"durable.exchange",
"routing.key",
null,
message.getBytes()
);
}
/**
* 重试失败的消息
*/
private void retryMessage(long sequenceNumber) {
// 实现重试逻辑:从缓存中取出消息重新发送
// 注意:这里需要维护消息内容与序列号的映射
}
} public void handleNack(long deliveryTag, boolean multiple) {`
`#/**
* RabbitMQ 异步 Confirm 机制源码分析
* 基于 rabbitmq-java-client 5.16.0
*
* 核心流程:
* 1. 生产者发送消息时分配内部序列号
* 2. Broker 收到消息后返回确认(带序列号)
* 3. 生产者通过回调函数处理确认结果
*/
public class AsyncConfirmExample {
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
public void setupConfirmChannel(Channel channel) throws IOException {
// 启用发布确认模式
channel.confirmSelect();
// 添加异步确认监听器
channel.addConfirmListener(new ConfirmListener() {
/**
* 消息成功确认回调
* @param deliveryTag 消息序列号
* @param multiple 是否批量确认
*/
@Override
public void handleAck(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量确认:移除所有 <= deliveryTag 的消息
unconfirmedSet.headSet(deliveryTag + 1).clear();
} else {
// 单条确认:移除指定消息
unconfirmedSet.remove(deliveryTag);
}
System.out.println("消息确认成功,序列号: " + deliveryTag);
}
/**
* 消息失败回调(未确认)
* @param deliveryTag 消息序列号
* @param multiple 是否批量未确认
*/
@Override
public void handleNack(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量未确认:重试所有 <= deliveryTag 的消息
SortedSet<Long> headSet = unconfirmedSet.headSet(deliveryTag + 1);
for (Long seq : headSet) {
retryMessage(seq);
}
headSet.clear();
} else {
// 单条未确认:重试指定消息
retryMessage(deliveryTag);
unconfirmedSet.remove(deliveryTag);
}
System.err.println("消息确认失败,序列号: " + deliveryTag);
}
});
}
/**
* 发送消息(带序列号跟踪)
*/
public void sendMessageWithTracking(Channel channel, String message)
throws IOException {
// 获取下一个序列号
long sequenceNumber = channel.getNextPublishSeqNo();
// 记录未确认的消息
unconfirmedSet.add(sequenceNumber);
// 发送消息
channel.basicPublish(
"durable.exchange",
"routing.key",
null,
message.getBytes()
);
}
/**
* 重试失败的消息
*/
private void retryMessage(long sequenceNumber) {
// 实现重试逻辑:从缓存中取出消息重新发送
// 注意:这里需要维护消息内容与序列号的映射
}
} if (multiple) {`
`#/**
* RabbitMQ 异步 Confirm 机制源码分析
* 基于 rabbitmq-java-client 5.16.0
*
* 核心流程:
* 1. 生产者发送消息时分配内部序列号
* 2. Broker 收到消息后返回确认(带序列号)
* 3. 生产者通过回调函数处理确认结果
*/
public class AsyncConfirmExample {
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
public void setupConfirmChannel(Channel channel) throws IOException {
// 启用发布确认模式
channel.confirmSelect();
// 添加异步确认监听器
channel.addConfirmListener(new ConfirmListener() {
/**
* 消息成功确认回调
* @param deliveryTag 消息序列号
* @param multiple 是否批量确认
*/
@Override
public void handleAck(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量确认:移除所有 <= deliveryTag 的消息
unconfirmedSet.headSet(deliveryTag + 1).clear();
} else {
// 单条确认:移除指定消息
unconfirmedSet.remove(deliveryTag);
}
System.out.println("消息确认成功,序列号: " + deliveryTag);
}
/**
* 消息失败回调(未确认)
* @param deliveryTag 消息序列号
* @param multiple 是否批量未确认
*/
@Override
public void handleNack(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量未确认:重试所有 <= deliveryTag 的消息
SortedSet<Long> headSet = unconfirmedSet.headSet(deliveryTag + 1);
for (Long seq : headSet) {
retryMessage(seq);
}
headSet.clear();
} else {
// 单条未确认:重试指定消息
retryMessage(deliveryTag);
unconfirmedSet.remove(deliveryTag);
}
System.err.println("消息确认失败,序列号: " + deliveryTag);
}
});
}
/**
* 发送消息(带序列号跟踪)
*/
public void sendMessageWithTracking(Channel channel, String message)
throws IOException {
// 获取下一个序列号
long sequenceNumber = channel.getNextPublishSeqNo();
// 记录未确认的消息
unconfirmedSet.add(sequenceNumber);
// 发送消息
channel.basicPublish(
"durable.exchange",
"routing.key",
null,
message.getBytes()
);
}
/**
* 重试失败的消息
*/
private void retryMessage(long sequenceNumber) {
// 实现重试逻辑:从缓存中取出消息重新发送
// 注意:这里需要维护消息内容与序列号的映射
}
} // 批量未确认:重试所有 <= deliveryTag 的消息`
`#/**
* RabbitMQ 异步 Confirm 机制源码分析
* 基于 rabbitmq-java-client 5.16.0
*
* 核心流程:
* 1. 生产者发送消息时分配内部序列号
* 2. Broker 收到消息后返回确认(带序列号)
* 3. 生产者通过回调函数处理确认结果
*/
public class AsyncConfirmExample {
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
public void setupConfirmChannel(Channel channel) throws IOException {
// 启用发布确认模式
channel.confirmSelect();
// 添加异步确认监听器
channel.addConfirmListener(new ConfirmListener() {
/**
* 消息成功确认回调
* @param deliveryTag 消息序列号
* @param multiple 是否批量确认
*/
@Override
public void handleAck(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量确认:移除所有 <= deliveryTag 的消息
unconfirmedSet.headSet(deliveryTag + 1).clear();
} else {
// 单条确认:移除指定消息
unconfirmedSet.remove(deliveryTag);
}
System.out.println("消息确认成功,序列号: " + deliveryTag);
}
/**
* 消息失败回调(未确认)
* @param deliveryTag 消息序列号
* @param multiple 是否批量未确认
*/
@Override
public void handleNack(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量未确认:重试所有 <= deliveryTag 的消息
SortedSet<Long> headSet = unconfirmedSet.headSet(deliveryTag + 1);
for (Long seq : headSet) {
retryMessage(seq);
}
headSet.clear();
} else {
// 单条未确认:重试指定消息
retryMessage(deliveryTag);
unconfirmedSet.remove(deliveryTag);
}
System.err.println("消息确认失败,序列号: " + deliveryTag);
}
});
}
/**
* 发送消息(带序列号跟踪)
*/
public void sendMessageWithTracking(Channel channel, String message)
throws IOException {
// 获取下一个序列号
long sequenceNumber = channel.getNextPublishSeqNo();
// 记录未确认的消息
unconfirmedSet.add(sequenceNumber);
// 发送消息
channel.basicPublish(
"durable.exchange",
"routing.key",
null,
message.getBytes()
);
}
/**
* 重试失败的消息
*/
private void retryMessage(long sequenceNumber) {
// 实现重试逻辑:从缓存中取出消息重新发送
// 注意:这里需要维护消息内容与序列号的映射
}
} SortedSet<Long> headSet = unconfirmedSet.headSet(deliveryTag + 1);`
`#/**
* RabbitMQ 异步 Confirm 机制源码分析
* 基于 rabbitmq-java-client 5.16.0
*
* 核心流程:
* 1. 生产者发送消息时分配内部序列号
* 2. Broker 收到消息后返回确认(带序列号)
* 3. 生产者通过回调函数处理确认结果
*/
public class AsyncConfirmExample {
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
public void setupConfirmChannel(Channel channel) throws IOException {
// 启用发布确认模式
channel.confirmSelect();
// 添加异步确认监听器
channel.addConfirmListener(new ConfirmListener() {
/**
* 消息成功确认回调
* @param deliveryTag 消息序列号
* @param multiple 是否批量确认
*/
@Override
public void handleAck(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量确认:移除所有 <= deliveryTag 的消息
unconfirmedSet.headSet(deliveryTag + 1).clear();
} else {
// 单条确认:移除指定消息
unconfirmedSet.remove(deliveryTag);
}
System.out.println("消息确认成功,序列号: " + deliveryTag);
}
/**
* 消息失败回调(未确认)
* @param deliveryTag 消息序列号
* @param multiple 是否批量未确认
*/
@Override
public void handleNack(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量未确认:重试所有 <= deliveryTag 的消息
SortedSet<Long> headSet = unconfirmedSet.headSet(deliveryTag + 1);
for (Long seq : headSet) {
retryMessage(seq);
}
headSet.clear();
} else {
// 单条未确认:重试指定消息
retryMessage(deliveryTag);
unconfirmedSet.remove(deliveryTag);
}
System.err.println("消息确认失败,序列号: " + deliveryTag);
}
});
}
/**
* 发送消息(带序列号跟踪)
*/
public void sendMessageWithTracking(Channel channel, String message)
throws IOException {
// 获取下一个序列号
long sequenceNumber = channel.getNextPublishSeqNo();
// 记录未确认的消息
unconfirmedSet.add(sequenceNumber);
// 发送消息
channel.basicPublish(
"durable.exchange",
"routing.key",
null,
message.getBytes()
);
}
/**
* 重试失败的消息
*/
private void retryMessage(long sequenceNumber) {
// 实现重试逻辑:从缓存中取出消息重新发送
// 注意:这里需要维护消息内容与序列号的映射
}
} for (Long seq : headSet) {`
`#/**
* RabbitMQ 异步 Confirm 机制源码分析
* 基于 rabbitmq-java-client 5.16.0
*
* 核心流程:
* 1. 生产者发送消息时分配内部序列号
* 2. Broker 收到消息后返回确认(带序列号)
* 3. 生产者通过回调函数处理确认结果
*/
public class AsyncConfirmExample {
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
public void setupConfirmChannel(Channel channel) throws IOException {
// 启用发布确认模式
channel.confirmSelect();
// 添加异步确认监听器
channel.addConfirmListener(new ConfirmListener() {
/**
* 消息成功确认回调
* @param deliveryTag 消息序列号
* @param multiple 是否批量确认
*/
@Override
public void handleAck(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量确认:移除所有 <= deliveryTag 的消息
unconfirmedSet.headSet(deliveryTag + 1).clear();
} else {
// 单条确认:移除指定消息
unconfirmedSet.remove(deliveryTag);
}
System.out.println("消息确认成功,序列号: " + deliveryTag);
}
/**
* 消息失败回调(未确认)
* @param deliveryTag 消息序列号
* @param multiple 是否批量未确认
*/
@Override
public void handleNack(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量未确认:重试所有 <= deliveryTag 的消息
SortedSet<Long> headSet = unconfirmedSet.headSet(deliveryTag + 1);
for (Long seq : headSet) {
retryMessage(seq);
}
headSet.clear();
} else {
// 单条未确认:重试指定消息
retryMessage(deliveryTag);
unconfirmedSet.remove(deliveryTag);
}
System.err.println("消息确认失败,序列号: " + deliveryTag);
}
});
}
/**
* 发送消息(带序列号跟踪)
*/
public void sendMessageWithTracking(Channel channel, String message)
throws IOException {
// 获取下一个序列号
long sequenceNumber = channel.getNextPublishSeqNo();
// 记录未确认的消息
unconfirmedSet.add(sequenceNumber);
// 发送消息
channel.basicPublish(
"durable.exchange",
"routing.key",
null,
message.getBytes()
);
}
/**
* 重试失败的消息
*/
private void retryMessage(long sequenceNumber) {
// 实现重试逻辑:从缓存中取出消息重新发送
// 注意:这里需要维护消息内容与序列号的映射
}
} retryMessage(seq);`
`#/**
* RabbitMQ 异步 Confirm 机制源码分析
* 基于 rabbitmq-java-client 5.16.0
*
* 核心流程:
* 1. 生产者发送消息时分配内部序列号
* 2. Broker 收到消息后返回确认(带序列号)
* 3. 生产者通过回调函数处理确认结果
*/
public class AsyncConfirmExample {
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
public void setupConfirmChannel(Channel channel) throws IOException {
// 启用发布确认模式
channel.confirmSelect();
// 添加异步确认监听器
channel.addConfirmListener(new ConfirmListener() {
/**
* 消息成功确认回调
* @param deliveryTag 消息序列号
* @param multiple 是否批量确认
*/
@Override
public void handleAck(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量确认:移除所有 <= deliveryTag 的消息
unconfirmedSet.headSet(deliveryTag + 1).clear();
} else {
// 单条确认:移除指定消息
unconfirmedSet.remove(deliveryTag);
}
System.out.println("消息确认成功,序列号: " + deliveryTag);
}
/**
* 消息失败回调(未确认)
* @param deliveryTag 消息序列号
* @param multiple 是否批量未确认
*/
@Override
public void handleNack(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量未确认:重试所有 <= deliveryTag 的消息
SortedSet<Long> headSet = unconfirmedSet.headSet(deliveryTag + 1);
for (Long seq : headSet) {
retryMessage(seq);
}
headSet.clear();
} else {
// 单条未确认:重试指定消息
retryMessage(deliveryTag);
unconfirmedSet.remove(deliveryTag);
}
System.err.println("消息确认失败,序列号: " + deliveryTag);
}
});
}
/**
* 发送消息(带序列号跟踪)
*/
public void sendMessageWithTracking(Channel channel, String message)
throws IOException {
// 获取下一个序列号
long sequenceNumber = channel.getNextPublishSeqNo();
// 记录未确认的消息
unconfirmedSet.add(sequenceNumber);
// 发送消息
channel.basicPublish(
"durable.exchange",
"routing.key",
null,
message.getBytes()
);
}
/**
* 重试失败的消息
*/
private void retryMessage(long sequenceNumber) {
// 实现重试逻辑:从缓存中取出消息重新发送
// 注意:这里需要维护消息内容与序列号的映射
}
} }`
`#/**
* RabbitMQ 异步 Confirm 机制源码分析
* 基于 rabbitmq-java-client 5.16.0
*
* 核心流程:
* 1. 生产者发送消息时分配内部序列号
* 2. Broker 收到消息后返回确认(带序列号)
* 3. 生产者通过回调函数处理确认结果
*/
public class AsyncConfirmExample {
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
public void setupConfirmChannel(Channel channel) throws IOException {
// 启用发布确认模式
channel.confirmSelect();
// 添加异步确认监听器
channel.addConfirmListener(new ConfirmListener() {
/**
* 消息成功确认回调
* @param deliveryTag 消息序列号
* @param multiple 是否批量确认
*/
@Override
public void handleAck(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量确认:移除所有 <= deliveryTag 的消息
unconfirmedSet.headSet(deliveryTag + 1).clear();
} else {
// 单条确认:移除指定消息
unconfirmedSet.remove(deliveryTag);
}
System.out.println("消息确认成功,序列号: " + deliveryTag);
}
/**
* 消息失败回调(未确认)
* @param deliveryTag 消息序列号
* @param multiple 是否批量未确认
*/
@Override
public void handleNack(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量未确认:重试所有 <= deliveryTag 的消息
SortedSet<Long> headSet = unconfirmedSet.headSet(deliveryTag + 1);
for (Long seq : headSet) {
retryMessage(seq);
}
headSet.clear();
} else {
// 单条未确认:重试指定消息
retryMessage(deliveryTag);
unconfirmedSet.remove(deliveryTag);
}
System.err.println("消息确认失败,序列号: " + deliveryTag);
}
});
}
/**
* 发送消息(带序列号跟踪)
*/
public void sendMessageWithTracking(Channel channel, String message)
throws IOException {
// 获取下一个序列号
long sequenceNumber = channel.getNextPublishSeqNo();
// 记录未确认的消息
unconfirmedSet.add(sequenceNumber);
// 发送消息
channel.basicPublish(
"durable.exchange",
"routing.key",
null,
message.getBytes()
);
}
/**
* 重试失败的消息
*/
private void retryMessage(long sequenceNumber) {
// 实现重试逻辑:从缓存中取出消息重新发送
// 注意:这里需要维护消息内容与序列号的映射
}
} headSet.clear();`
`#/**
* RabbitMQ 异步 Confirm 机制源码分析
* 基于 rabbitmq-java-client 5.16.0
*
* 核心流程:
* 1. 生产者发送消息时分配内部序列号
* 2. Broker 收到消息后返回确认(带序列号)
* 3. 生产者通过回调函数处理确认结果
*/
public class AsyncConfirmExample {
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
public void setupConfirmChannel(Channel channel) throws IOException {
// 启用发布确认模式
channel.confirmSelect();
// 添加异步确认监听器
channel.addConfirmListener(new ConfirmListener() {
/**
* 消息成功确认回调
* @param deliveryTag 消息序列号
* @param multiple 是否批量确认
*/
@Override
public void handleAck(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量确认:移除所有 <= deliveryTag 的消息
unconfirmedSet.headSet(deliveryTag + 1).clear();
} else {
// 单条确认:移除指定消息
unconfirmedSet.remove(deliveryTag);
}
System.out.println("消息确认成功,序列号: " + deliveryTag);
}
/**
* 消息失败回调(未确认)
* @param deliveryTag 消息序列号
* @param multiple 是否批量未确认
*/
@Override
public void handleNack(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量未确认:重试所有 <= deliveryTag 的消息
SortedSet<Long> headSet = unconfirmedSet.headSet(deliveryTag + 1);
for (Long seq : headSet) {
retryMessage(seq);
}
headSet.clear();
} else {
// 单条未确认:重试指定消息
retryMessage(deliveryTag);
unconfirmedSet.remove(deliveryTag);
}
System.err.println("消息确认失败,序列号: " + deliveryTag);
}
});
}
/**
* 发送消息(带序列号跟踪)
*/
public void sendMessageWithTracking(Channel channel, String message)
throws IOException {
// 获取下一个序列号
long sequenceNumber = channel.getNextPublishSeqNo();
// 记录未确认的消息
unconfirmedSet.add(sequenceNumber);
// 发送消息
channel.basicPublish(
"durable.exchange",
"routing.key",
null,
message.getBytes()
);
}
/**
* 重试失败的消息
*/
private void retryMessage(long sequenceNumber) {
// 实现重试逻辑:从缓存中取出消息重新发送
// 注意:这里需要维护消息内容与序列号的映射
}
} } else {`
`#/**
* RabbitMQ 异步 Confirm 机制源码分析
* 基于 rabbitmq-java-client 5.16.0
*
* 核心流程:
* 1. 生产者发送消息时分配内部序列号
* 2. Broker 收到消息后返回确认(带序列号)
* 3. 生产者通过回调函数处理确认结果
*/
public class AsyncConfirmExample {
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
public void setupConfirmChannel(Channel channel) throws IOException {
// 启用发布确认模式
channel.confirmSelect();
// 添加异步确认监听器
channel.addConfirmListener(new ConfirmListener() {
/**
* 消息成功确认回调
* @param deliveryTag 消息序列号
* @param multiple 是否批量确认
*/
@Override
public void handleAck(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量确认:移除所有 <= deliveryTag 的消息
unconfirmedSet.headSet(deliveryTag + 1).clear();
} else {
// 单条确认:移除指定消息
unconfirmedSet.remove(deliveryTag);
}
System.out.println("消息确认成功,序列号: " + deliveryTag);
}
/**
* 消息失败回调(未确认)
* @param deliveryTag 消息序列号
* @param multiple 是否批量未确认
*/
@Override
public void handleNack(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量未确认:重试所有 <= deliveryTag 的消息
SortedSet<Long> headSet = unconfirmedSet.headSet(deliveryTag + 1);
for (Long seq : headSet) {
retryMessage(seq);
}
headSet.clear();
} else {
// 单条未确认:重试指定消息
retryMessage(deliveryTag);
unconfirmedSet.remove(deliveryTag);
}
System.err.println("消息确认失败,序列号: " + deliveryTag);
}
});
}
/**
* 发送消息(带序列号跟踪)
*/
public void sendMessageWithTracking(Channel channel, String message)
throws IOException {
// 获取下一个序列号
long sequenceNumber = channel.getNextPublishSeqNo();
// 记录未确认的消息
unconfirmedSet.add(sequenceNumber);
// 发送消息
channel.basicPublish(
"durable.exchange",
"routing.key",
null,
message.getBytes()
);
}
/**
* 重试失败的消息
*/
private void retryMessage(long sequenceNumber) {
// 实现重试逻辑:从缓存中取出消息重新发送
// 注意:这里需要维护消息内容与序列号的映射
}
} // 单条未确认:重试指定消息`
`#/**
* RabbitMQ 异步 Confirm 机制源码分析
* 基于 rabbitmq-java-client 5.16.0
*
* 核心流程:
* 1. 生产者发送消息时分配内部序列号
* 2. Broker 收到消息后返回确认(带序列号)
* 3. 生产者通过回调函数处理确认结果
*/
public class AsyncConfirmExample {
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
public void setupConfirmChannel(Channel channel) throws IOException {
// 启用发布确认模式
channel.confirmSelect();
// 添加异步确认监听器
channel.addConfirmListener(new ConfirmListener() {
/**
* 消息成功确认回调
* @param deliveryTag 消息序列号
* @param multiple 是否批量确认
*/
@Override
public void handleAck(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量确认:移除所有 <= deliveryTag 的消息
unconfirmedSet.headSet(deliveryTag + 1).clear();
} else {
// 单条确认:移除指定消息
unconfirmedSet.remove(deliveryTag);
}
System.out.println("消息确认成功,序列号: " + deliveryTag);
}
/**
* 消息失败回调(未确认)
* @param deliveryTag 消息序列号
* @param multiple 是否批量未确认
*/
@Override
public void handleNack(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量未确认:重试所有 <= deliveryTag 的消息
SortedSet<Long> headSet = unconfirmedSet.headSet(deliveryTag + 1);
for (Long seq : headSet) {
retryMessage(seq);
}
headSet.clear();
} else {
// 单条未确认:重试指定消息
retryMessage(deliveryTag);
unconfirmedSet.remove(deliveryTag);
}
System.err.println("消息确认失败,序列号: " + deliveryTag);
}
});
}
/**
* 发送消息(带序列号跟踪)
*/
public void sendMessageWithTracking(Channel channel, String message)
throws IOException {
// 获取下一个序列号
long sequenceNumber = channel.getNextPublishSeqNo();
// 记录未确认的消息
unconfirmedSet.add(sequenceNumber);
// 发送消息
channel.basicPublish(
"durable.exchange",
"routing.key",
null,
message.getBytes()
);
}
/**
* 重试失败的消息
*/
private void retryMessage(long sequenceNumber) {
// 实现重试逻辑:从缓存中取出消息重新发送
// 注意:这里需要维护消息内容与序列号的映射
}
} retryMessage(deliveryTag);`
`#/**
* RabbitMQ 异步 Confirm 机制源码分析
* 基于 rabbitmq-java-client 5.16.0
*
* 核心流程:
* 1. 生产者发送消息时分配内部序列号
* 2. Broker 收到消息后返回确认(带序列号)
* 3. 生产者通过回调函数处理确认结果
*/
public class AsyncConfirmExample {
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
public void setupConfirmChannel(Channel channel) throws IOException {
// 启用发布确认模式
channel.confirmSelect();
// 添加异步确认监听器
channel.addConfirmListener(new ConfirmListener() {
/**
* 消息成功确认回调
* @param deliveryTag 消息序列号
* @param multiple 是否批量确认
*/
@Override
public void handleAck(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量确认:移除所有 <= deliveryTag 的消息
unconfirmedSet.headSet(deliveryTag + 1).clear();
} else {
// 单条确认:移除指定消息
unconfirmedSet.remove(deliveryTag);
}
System.out.println("消息确认成功,序列号: " + deliveryTag);
}
/**
* 消息失败回调(未确认)
* @param deliveryTag 消息序列号
* @param multiple 是否批量未确认
*/
@Override
public void handleNack(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量未确认:重试所有 <= deliveryTag 的消息
SortedSet<Long> headSet = unconfirmedSet.headSet(deliveryTag + 1);
for (Long seq : headSet) {
retryMessage(seq);
}
headSet.clear();
} else {
// 单条未确认:重试指定消息
retryMessage(deliveryTag);
unconfirmedSet.remove(deliveryTag);
}
System.err.println("消息确认失败,序列号: " + deliveryTag);
}
});
}
/**
* 发送消息(带序列号跟踪)
*/
public void sendMessageWithTracking(Channel channel, String message)
throws IOException {
// 获取下一个序列号
long sequenceNumber = channel.getNextPublishSeqNo();
// 记录未确认的消息
unconfirmedSet.add(sequenceNumber);
// 发送消息
channel.basicPublish(
"durable.exchange",
"routing.key",
null,
message.getBytes()
);
}
/**
* 重试失败的消息
*/
private void retryMessage(long sequenceNumber) {
// 实现重试逻辑:从缓存中取出消息重新发送
// 注意:这里需要维护消息内容与序列号的映射
}
} unconfirmedSet.remove(deliveryTag);`
`#/**
* RabbitMQ 异步 Confirm 机制源码分析
* 基于 rabbitmq-java-client 5.16.0
*
* 核心流程:
* 1. 生产者发送消息时分配内部序列号
* 2. Broker 收到消息后返回确认(带序列号)
* 3. 生产者通过回调函数处理确认结果
*/
public class AsyncConfirmExample {
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
public void setupConfirmChannel(Channel channel) throws IOException {
// 启用发布确认模式
channel.confirmSelect();
// 添加异步确认监听器
channel.addConfirmListener(new ConfirmListener() {
/**
* 消息成功确认回调
* @param deliveryTag 消息序列号
* @param multiple 是否批量确认
*/
@Override
public void handleAck(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量确认:移除所有 <= deliveryTag 的消息
unconfirmedSet.headSet(deliveryTag + 1).clear();
} else {
// 单条确认:移除指定消息
unconfirmedSet.remove(deliveryTag);
}
System.out.println("消息确认成功,序列号: " + deliveryTag);
}
/**
* 消息失败回调(未确认)
* @param deliveryTag 消息序列号
* @param multiple 是否批量未确认
*/
@Override
public void handleNack(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量未确认:重试所有 <= deliveryTag 的消息
SortedSet<Long> headSet = unconfirmedSet.headSet(deliveryTag + 1);
for (Long seq : headSet) {
retryMessage(seq);
}
headSet.clear();
} else {
// 单条未确认:重试指定消息
retryMessage(deliveryTag);
unconfirmedSet.remove(deliveryTag);
}
System.err.println("消息确认失败,序列号: " + deliveryTag);
}
});
}
/**
* 发送消息(带序列号跟踪)
*/
public void sendMessageWithTracking(Channel channel, String message)
throws IOException {
// 获取下一个序列号
long sequenceNumber = channel.getNextPublishSeqNo();
// 记录未确认的消息
unconfirmedSet.add(sequenceNumber);
// 发送消息
channel.basicPublish(
"durable.exchange",
"routing.key",
null,
message.getBytes()
);
}
/**
* 重试失败的消息
*/
private void retryMessage(long sequenceNumber) {
// 实现重试逻辑:从缓存中取出消息重新发送
// 注意:这里需要维护消息内容与序列号的映射
}
} }`
`#/**
* RabbitMQ 异步 Confirm 机制源码分析
* 基于 rabbitmq-java-client 5.16.0
*
* 核心流程:
* 1. 生产者发送消息时分配内部序列号
* 2. Broker 收到消息后返回确认(带序列号)
* 3. 生产者通过回调函数处理确认结果
*/
public class AsyncConfirmExample {
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
public void setupConfirmChannel(Channel channel) throws IOException {
// 启用发布确认模式
channel.confirmSelect();
// 添加异步确认监听器
channel.addConfirmListener(new ConfirmListener() {
/**
* 消息成功确认回调
* @param deliveryTag 消息序列号
* @param multiple 是否批量确认
*/
@Override
public void handleAck(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量确认:移除所有 <= deliveryTag 的消息
unconfirmedSet.headSet(deliveryTag + 1).clear();
} else {
// 单条确认:移除指定消息
unconfirmedSet.remove(deliveryTag);
}
System.out.println("消息确认成功,序列号: " + deliveryTag);
}
/**
* 消息失败回调(未确认)
* @param deliveryTag 消息序列号
* @param multiple 是否批量未确认
*/
@Override
public void handleNack(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量未确认:重试所有 <= deliveryTag 的消息
SortedSet<Long> headSet = unconfirmedSet.headSet(deliveryTag + 1);
for (Long seq : headSet) {
retryMessage(seq);
}
headSet.clear();
} else {
// 单条未确认:重试指定消息
retryMessage(deliveryTag);
unconfirmedSet.remove(deliveryTag);
}
System.err.println("消息确认失败,序列号: " + deliveryTag);
}
});
}
/**
* 发送消息(带序列号跟踪)
*/
public void sendMessageWithTracking(Channel channel, String message)
throws IOException {
// 获取下一个序列号
long sequenceNumber = channel.getNextPublishSeqNo();
// 记录未确认的消息
unconfirmedSet.add(sequenceNumber);
// 发送消息
channel.basicPublish(
"durable.exchange",
"routing.key",
null,
message.getBytes()
);
}
/**
* 重试失败的消息
*/
private void retryMessage(long sequenceNumber) {
// 实现重试逻辑:从缓存中取出消息重新发送
// 注意:这里需要维护消息内容与序列号的映射
}
} `
`#/**
* RabbitMQ 异步 Confirm 机制源码分析
* 基于 rabbitmq-java-client 5.16.0
*
* 核心流程:
* 1. 生产者发送消息时分配内部序列号
* 2. Broker 收到消息后返回确认(带序列号)
* 3. 生产者通过回调函数处理确认结果
*/
public class AsyncConfirmExample {
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
public void setupConfirmChannel(Channel channel) throws IOException {
// 启用发布确认模式
channel.confirmSelect();
// 添加异步确认监听器
channel.addConfirmListener(new ConfirmListener() {
/**
* 消息成功确认回调
* @param deliveryTag 消息序列号
* @param multiple 是否批量确认
*/
@Override
public void handleAck(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量确认:移除所有 <= deliveryTag 的消息
unconfirmedSet.headSet(deliveryTag + 1).clear();
} else {
// 单条确认:移除指定消息
unconfirmedSet.remove(deliveryTag);
}
System.out.println("消息确认成功,序列号: " + deliveryTag);
}
/**
* 消息失败回调(未确认)
* @param deliveryTag 消息序列号
* @param multiple 是否批量未确认
*/
@Override
public void handleNack(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量未确认:重试所有 <= deliveryTag 的消息
SortedSet<Long> headSet = unconfirmedSet.headSet(deliveryTag + 1);
for (Long seq : headSet) {
retryMessage(seq);
}
headSet.clear();
} else {
// 单条未确认:重试指定消息
retryMessage(deliveryTag);
unconfirmedSet.remove(deliveryTag);
}
System.err.println("消息确认失败,序列号: " + deliveryTag);
}
});
}
/**
* 发送消息(带序列号跟踪)
*/
public void sendMessageWithTracking(Channel channel, String message)
throws IOException {
// 获取下一个序列号
long sequenceNumber = channel.getNextPublishSeqNo();
// 记录未确认的消息
unconfirmedSet.add(sequenceNumber);
// 发送消息
channel.basicPublish(
"durable.exchange",
"routing.key",
null,
message.getBytes()
);
}
/**
* 重试失败的消息
*/
private void retryMessage(long sequenceNumber) {
// 实现重试逻辑:从缓存中取出消息重新发送
// 注意:这里需要维护消息内容与序列号的映射
}
} System.err.println("消息确认失败,序列号: " + deliveryTag);`
`#/**
* RabbitMQ 异步 Confirm 机制源码分析
* 基于 rabbitmq-java-client 5.16.0
*
* 核心流程:
* 1. 生产者发送消息时分配内部序列号
* 2. Broker 收到消息后返回确认(带序列号)
* 3. 生产者通过回调函数处理确认结果
*/
public class AsyncConfirmExample {
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
public void setupConfirmChannel(Channel channel) throws IOException {
// 启用发布确认模式
channel.confirmSelect();
// 添加异步确认监听器
channel.addConfirmListener(new ConfirmListener() {
/**
* 消息成功确认回调
* @param deliveryTag 消息序列号
* @param multiple 是否批量确认
*/
@Override
public void handleAck(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量确认:移除所有 <= deliveryTag 的消息
unconfirmedSet.headSet(deliveryTag + 1).clear();
} else {
// 单条确认:移除指定消息
unconfirmedSet.remove(deliveryTag);
}
System.out.println("消息确认成功,序列号: " + deliveryTag);
}
/**
* 消息失败回调(未确认)
* @param deliveryTag 消息序列号
* @param multiple 是否批量未确认
*/
@Override
public void handleNack(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量未确认:重试所有 <= deliveryTag 的消息
SortedSet<Long> headSet = unconfirmedSet.headSet(deliveryTag + 1);
for (Long seq : headSet) {
retryMessage(seq);
}
headSet.clear();
} else {
// 单条未确认:重试指定消息
retryMessage(deliveryTag);
unconfirmedSet.remove(deliveryTag);
}
System.err.println("消息确认失败,序列号: " + deliveryTag);
}
});
}
/**
* 发送消息(带序列号跟踪)
*/
public void sendMessageWithTracking(Channel channel, String message)
throws IOException {
// 获取下一个序列号
long sequenceNumber = channel.getNextPublishSeqNo();
// 记录未确认的消息
unconfirmedSet.add(sequenceNumber);
// 发送消息
channel.basicPublish(
"durable.exchange",
"routing.key",
null,
message.getBytes()
);
}
/**
* 重试失败的消息
*/
private void retryMessage(long sequenceNumber) {
// 实现重试逻辑:从缓存中取出消息重新发送
// 注意:这里需要维护消息内容与序列号的映射
}
} }`
`#/**
* RabbitMQ 异步 Confirm 机制源码分析
* 基于 rabbitmq-java-client 5.16.0
*
* 核心流程:
* 1. 生产者发送消息时分配内部序列号
* 2. Broker 收到消息后返回确认(带序列号)
* 3. 生产者通过回调函数处理确认结果
*/
public class AsyncConfirmExample {
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
public void setupConfirmChannel(Channel channel) throws IOException {
// 启用发布确认模式
channel.confirmSelect();
// 添加异步确认监听器
channel.addConfirmListener(new ConfirmListener() {
/**
* 消息成功确认回调
* @param deliveryTag 消息序列号
* @param multiple 是否批量确认
*/
@Override
public void handleAck(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量确认:移除所有 <= deliveryTag 的消息
unconfirmedSet.headSet(deliveryTag + 1).clear();
} else {
// 单条确认:移除指定消息
unconfirmedSet.remove(deliveryTag);
}
System.out.println("消息确认成功,序列号: " + deliveryTag);
}
/**
* 消息失败回调(未确认)
* @param deliveryTag 消息序列号
* @param multiple 是否批量未确认
*/
@Override
public void handleNack(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量未确认:重试所有 <= deliveryTag 的消息
SortedSet<Long> headSet = unconfirmedSet.headSet(deliveryTag + 1);
for (Long seq : headSet) {
retryMessage(seq);
}
headSet.clear();
} else {
// 单条未确认:重试指定消息
retryMessage(deliveryTag);
unconfirmedSet.remove(deliveryTag);
}
System.err.println("消息确认失败,序列号: " + deliveryTag);
}
});
}
/**
* 发送消息(带序列号跟踪)
*/
public void sendMessageWithTracking(Channel channel, String message)
throws IOException {
// 获取下一个序列号
long sequenceNumber = channel.getNextPublishSeqNo();
// 记录未确认的消息
unconfirmedSet.add(sequenceNumber);
// 发送消息
channel.basicPublish(
"durable.exchange",
"routing.key",
null,
message.getBytes()
);
}
/**
* 重试失败的消息
*/
private void retryMessage(long sequenceNumber) {
// 实现重试逻辑:从缓存中取出消息重新发送
// 注意:这里需要维护消息内容与序列号的映射
}
} });`
`#/**
* RabbitMQ 异步 Confirm 机制源码分析
* 基于 rabbitmq-java-client 5.16.0
*
* 核心流程:
* 1. 生产者发送消息时分配内部序列号
* 2. Broker 收到消息后返回确认(带序列号)
* 3. 生产者通过回调函数处理确认结果
*/
public class AsyncConfirmExample {
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
public void setupConfirmChannel(Channel channel) throws IOException {
// 启用发布确认模式
channel.confirmSelect();
// 添加异步确认监听器
channel.addConfirmListener(new ConfirmListener() {
/**
* 消息成功确认回调
* @param deliveryTag 消息序列号
* @param multiple 是否批量确认
*/
@Override
public void handleAck(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量确认:移除所有 <= deliveryTag 的消息
unconfirmedSet.headSet(deliveryTag + 1).clear();
} else {
// 单条确认:移除指定消息
unconfirmedSet.remove(deliveryTag);
}
System.out.println("消息确认成功,序列号: " + deliveryTag);
}
/**
* 消息失败回调(未确认)
* @param deliveryTag 消息序列号
* @param multiple 是否批量未确认
*/
@Override
public void handleNack(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量未确认:重试所有 <= deliveryTag 的消息
SortedSet<Long> headSet = unconfirmedSet.headSet(deliveryTag + 1);
for (Long seq : headSet) {
retryMessage(seq);
}
headSet.clear();
} else {
// 单条未确认:重试指定消息
retryMessage(deliveryTag);
unconfirmedSet.remove(deliveryTag);
}
System.err.println("消息确认失败,序列号: " + deliveryTag);
}
});
}
/**
* 发送消息(带序列号跟踪)
*/
public void sendMessageWithTracking(Channel channel, String message)
throws IOException {
// 获取下一个序列号
long sequenceNumber = channel.getNextPublishSeqNo();
// 记录未确认的消息
unconfirmedSet.add(sequenceNumber);
// 发送消息
channel.basicPublish(
"durable.exchange",
"routing.key",
null,
message.getBytes()
);
}
/**
* 重试失败的消息
*/
private void retryMessage(long sequenceNumber) {
// 实现重试逻辑:从缓存中取出消息重新发送
// 注意:这里需要维护消息内容与序列号的映射
}
} }`
`#/**
* RabbitMQ 异步 Confirm 机制源码分析
* 基于 rabbitmq-java-client 5.16.0
*
* 核心流程:
* 1. 生产者发送消息时分配内部序列号
* 2. Broker 收到消息后返回确认(带序列号)
* 3. 生产者通过回调函数处理确认结果
*/
public class AsyncConfirmExample {
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
public void setupConfirmChannel(Channel channel) throws IOException {
// 启用发布确认模式
channel.confirmSelect();
// 添加异步确认监听器
channel.addConfirmListener(new ConfirmListener() {
/**
* 消息成功确认回调
* @param deliveryTag 消息序列号
* @param multiple 是否批量确认
*/
@Override
public void handleAck(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量确认:移除所有 <= deliveryTag 的消息
unconfirmedSet.headSet(deliveryTag + 1).clear();
} else {
// 单条确认:移除指定消息
unconfirmedSet.remove(deliveryTag);
}
System.out.println("消息确认成功,序列号: " + deliveryTag);
}
/**
* 消息失败回调(未确认)
* @param deliveryTag 消息序列号
* @param multiple 是否批量未确认
*/
@Override
public void handleNack(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量未确认:重试所有 <= deliveryTag 的消息
SortedSet<Long> headSet = unconfirmedSet.headSet(deliveryTag + 1);
for (Long seq : headSet) {
retryMessage(seq);
}
headSet.clear();
} else {
// 单条未确认:重试指定消息
retryMessage(deliveryTag);
unconfirmedSet.remove(deliveryTag);
}
System.err.println("消息确认失败,序列号: " + deliveryTag);
}
});
}
/**
* 发送消息(带序列号跟踪)
*/
public void sendMessageWithTracking(Channel channel, String message)
throws IOException {
// 获取下一个序列号
long sequenceNumber = channel.getNextPublishSeqNo();
// 记录未确认的消息
unconfirmedSet.add(sequenceNumber);
// 发送消息
channel.basicPublish(
"durable.exchange",
"routing.key",
null,
message.getBytes()
);
}
/**
* 重试失败的消息
*/
private void retryMessage(long sequenceNumber) {
// 实现重试逻辑:从缓存中取出消息重新发送
// 注意:这里需要维护消息内容与序列号的映射
}
}`
`#/**
* RabbitMQ 异步 Confirm 机制源码分析
* 基于 rabbitmq-java-client 5.16.0
*
* 核心流程:
* 1. 生产者发送消息时分配内部序列号
* 2. Broker 收到消息后返回确认(带序列号)
* 3. 生产者通过回调函数处理确认结果
*/
public class AsyncConfirmExample {
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
public void setupConfirmChannel(Channel channel) throws IOException {
// 启用发布确认模式
channel.confirmSelect();
// 添加异步确认监听器
channel.addConfirmListener(new ConfirmListener() {
/**
* 消息成功确认回调
* @param deliveryTag 消息序列号
* @param multiple 是否批量确认
*/
@Override
public void handleAck(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量确认:移除所有 <= deliveryTag 的消息
unconfirmedSet.headSet(deliveryTag + 1).clear();
} else {
// 单条确认:移除指定消息
unconfirmedSet.remove(deliveryTag);
}
System.out.println("消息确认成功,序列号: " + deliveryTag);
}
/**
* 消息失败回调(未确认)
* @param deliveryTag 消息序列号
* @param multiple 是否批量未确认
*/
@Override
public void handleNack(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量未确认:重试所有 <= deliveryTag 的消息
SortedSet<Long> headSet = unconfirmedSet.headSet(deliveryTag + 1);
for (Long seq : headSet) {
retryMessage(seq);
}
headSet.clear();
} else {
// 单条未确认:重试指定消息
retryMessage(deliveryTag);
unconfirmedSet.remove(deliveryTag);
}
System.err.println("消息确认失败,序列号: " + deliveryTag);
}
});
}
/**
* 发送消息(带序列号跟踪)
*/
public void sendMessageWithTracking(Channel channel, String message)
throws IOException {
// 获取下一个序列号
long sequenceNumber = channel.getNextPublishSeqNo();
// 记录未确认的消息
unconfirmedSet.add(sequenceNumber);
// 发送消息
channel.basicPublish(
"durable.exchange",
"routing.key",
null,
message.getBytes()
);
}
/**
* 重试失败的消息
*/
private void retryMessage(long sequenceNumber) {
// 实现重试逻辑:从缓存中取出消息重新发送
// 注意:这里需要维护消息内容与序列号的映射
}
} /**`
`#/**
* RabbitMQ 异步 Confirm 机制源码分析
* 基于 rabbitmq-java-client 5.16.0
*
* 核心流程:
* 1. 生产者发送消息时分配内部序列号
* 2. Broker 收到消息后返回确认(带序列号)
* 3. 生产者通过回调函数处理确认结果
*/
public class AsyncConfirmExample {
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
public void setupConfirmChannel(Channel channel) throws IOException {
// 启用发布确认模式
channel.confirmSelect();
// 添加异步确认监听器
channel.addConfirmListener(new ConfirmListener() {
/**
* 消息成功确认回调
* @param deliveryTag 消息序列号
* @param multiple 是否批量确认
*/
@Override
public void handleAck(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量确认:移除所有 <= deliveryTag 的消息
unconfirmedSet.headSet(deliveryTag + 1).clear();
} else {
// 单条确认:移除指定消息
unconfirmedSet.remove(deliveryTag);
}
System.out.println("消息确认成功,序列号: " + deliveryTag);
}
/**
* 消息失败回调(未确认)
* @param deliveryTag 消息序列号
* @param multiple 是否批量未确认
*/
@Override
public void handleNack(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量未确认:重试所有 <= deliveryTag 的消息
SortedSet<Long> headSet = unconfirmedSet.headSet(deliveryTag + 1);
for (Long seq : headSet) {
retryMessage(seq);
}
headSet.clear();
} else {
// 单条未确认:重试指定消息
retryMessage(deliveryTag);
unconfirmedSet.remove(deliveryTag);
}
System.err.println("消息确认失败,序列号: " + deliveryTag);
}
});
}
/**
* 发送消息(带序列号跟踪)
*/
public void sendMessageWithTracking(Channel channel, String message)
throws IOException {
// 获取下一个序列号
long sequenceNumber = channel.getNextPublishSeqNo();
// 记录未确认的消息
unconfirmedSet.add(sequenceNumber);
// 发送消息
channel.basicPublish(
"durable.exchange",
"routing.key",
null,
message.getBytes()
);
}
/**
* 重试失败的消息
*/
private void retryMessage(long sequenceNumber) {
// 实现重试逻辑:从缓存中取出消息重新发送
// 注意:这里需要维护消息内容与序列号的映射
}
} * 发送消息(带序列号跟踪)`
`#/**
* RabbitMQ 异步 Confirm 机制源码分析
* 基于 rabbitmq-java-client 5.16.0
*
* 核心流程:
* 1. 生产者发送消息时分配内部序列号
* 2. Broker 收到消息后返回确认(带序列号)
* 3. 生产者通过回调函数处理确认结果
*/
public class AsyncConfirmExample {
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
public void setupConfirmChannel(Channel channel) throws IOException {
// 启用发布确认模式
channel.confirmSelect();
// 添加异步确认监听器
channel.addConfirmListener(new ConfirmListener() {
/**
* 消息成功确认回调
* @param deliveryTag 消息序列号
* @param multiple 是否批量确认
*/
@Override
public void handleAck(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量确认:移除所有 <= deliveryTag 的消息
unconfirmedSet.headSet(deliveryTag + 1).clear();
} else {
// 单条确认:移除指定消息
unconfirmedSet.remove(deliveryTag);
}
System.out.println("消息确认成功,序列号: " + deliveryTag);
}
/**
* 消息失败回调(未确认)
* @param deliveryTag 消息序列号
* @param multiple 是否批量未确认
*/
@Override
public void handleNack(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量未确认:重试所有 <= deliveryTag 的消息
SortedSet<Long> headSet = unconfirmedSet.headSet(deliveryTag + 1);
for (Long seq : headSet) {
retryMessage(seq);
}
headSet.clear();
} else {
// 单条未确认:重试指定消息
retryMessage(deliveryTag);
unconfirmedSet.remove(deliveryTag);
}
System.err.println("消息确认失败,序列号: " + deliveryTag);
}
});
}
/**
* 发送消息(带序列号跟踪)
*/
public void sendMessageWithTracking(Channel channel, String message)
throws IOException {
// 获取下一个序列号
long sequenceNumber = channel.getNextPublishSeqNo();
// 记录未确认的消息
unconfirmedSet.add(sequenceNumber);
// 发送消息
channel.basicPublish(
"durable.exchange",
"routing.key",
null,
message.getBytes()
);
}
/**
* 重试失败的消息
*/
private void retryMessage(long sequenceNumber) {
// 实现重试逻辑:从缓存中取出消息重新发送
// 注意:这里需要维护消息内容与序列号的映射
}
} */`
`#/**
* RabbitMQ 异步 Confirm 机制源码分析
* 基于 rabbitmq-java-client 5.16.0
*
* 核心流程:
* 1. 生产者发送消息时分配内部序列号
* 2. Broker 收到消息后返回确认(带序列号)
* 3. 生产者通过回调函数处理确认结果
*/
public class AsyncConfirmExample {
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
public void setupConfirmChannel(Channel channel) throws IOException {
// 启用发布确认模式
channel.confirmSelect();
// 添加异步确认监听器
channel.addConfirmListener(new ConfirmListener() {
/**
* 消息成功确认回调
* @param deliveryTag 消息序列号
* @param multiple 是否批量确认
*/
@Override
public void handleAck(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量确认:移除所有 <= deliveryTag 的消息
unconfirmedSet.headSet(deliveryTag + 1).clear();
} else {
// 单条确认:移除指定消息
unconfirmedSet.remove(deliveryTag);
}
System.out.println("消息确认成功,序列号: " + deliveryTag);
}
/**
* 消息失败回调(未确认)
* @param deliveryTag 消息序列号
* @param multiple 是否批量未确认
*/
@Override
public void handleNack(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量未确认:重试所有 <= deliveryTag 的消息
SortedSet<Long> headSet = unconfirmedSet.headSet(deliveryTag + 1);
for (Long seq : headSet) {
retryMessage(seq);
}
headSet.clear();
} else {
// 单条未确认:重试指定消息
retryMessage(deliveryTag);
unconfirmedSet.remove(deliveryTag);
}
System.err.println("消息确认失败,序列号: " + deliveryTag);
}
});
}
/**
* 发送消息(带序列号跟踪)
*/
public void sendMessageWithTracking(Channel channel, String message)
throws IOException {
// 获取下一个序列号
long sequenceNumber = channel.getNextPublishSeqNo();
// 记录未确认的消息
unconfirmedSet.add(sequenceNumber);
// 发送消息
channel.basicPublish(
"durable.exchange",
"routing.key",
null,
message.getBytes()
);
}
/**
* 重试失败的消息
*/
private void retryMessage(long sequenceNumber) {
// 实现重试逻辑:从缓存中取出消息重新发送
// 注意:这里需要维护消息内容与序列号的映射
}
} public void sendMessageWithTracking(Channel channel, String message) `
`#/**
* RabbitMQ 异步 Confirm 机制源码分析
* 基于 rabbitmq-java-client 5.16.0
*
* 核心流程:
* 1. 生产者发送消息时分配内部序列号
* 2. Broker 收到消息后返回确认(带序列号)
* 3. 生产者通过回调函数处理确认结果
*/
public class AsyncConfirmExample {
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
public void setupConfirmChannel(Channel channel) throws IOException {
// 启用发布确认模式
channel.confirmSelect();
// 添加异步确认监听器
channel.addConfirmListener(new ConfirmListener() {
/**
* 消息成功确认回调
* @param deliveryTag 消息序列号
* @param multiple 是否批量确认
*/
@Override
public void handleAck(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量确认:移除所有 <= deliveryTag 的消息
unconfirmedSet.headSet(deliveryTag + 1).clear();
} else {
// 单条确认:移除指定消息
unconfirmedSet.remove(deliveryTag);
}
System.out.println("消息确认成功,序列号: " + deliveryTag);
}
/**
* 消息失败回调(未确认)
* @param deliveryTag 消息序列号
* @param multiple 是否批量未确认
*/
@Override
public void handleNack(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量未确认:重试所有 <= deliveryTag 的消息
SortedSet<Long> headSet = unconfirmedSet.headSet(deliveryTag + 1);
for (Long seq : headSet) {
retryMessage(seq);
}
headSet.clear();
} else {
// 单条未确认:重试指定消息
retryMessage(deliveryTag);
unconfirmedSet.remove(deliveryTag);
}
System.err.println("消息确认失败,序列号: " + deliveryTag);
}
});
}
/**
* 发送消息(带序列号跟踪)
*/
public void sendMessageWithTracking(Channel channel, String message)
throws IOException {
// 获取下一个序列号
long sequenceNumber = channel.getNextPublishSeqNo();
// 记录未确认的消息
unconfirmedSet.add(sequenceNumber);
// 发送消息
channel.basicPublish(
"durable.exchange",
"routing.key",
null,
message.getBytes()
);
}
/**
* 重试失败的消息
*/
private void retryMessage(long sequenceNumber) {
// 实现重试逻辑:从缓存中取出消息重新发送
// 注意:这里需要维护消息内容与序列号的映射
}
} throws IOException {`
`#/**
* RabbitMQ 异步 Confirm 机制源码分析
* 基于 rabbitmq-java-client 5.16.0
*
* 核心流程:
* 1. 生产者发送消息时分配内部序列号
* 2. Broker 收到消息后返回确认(带序列号)
* 3. 生产者通过回调函数处理确认结果
*/
public class AsyncConfirmExample {
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
public void setupConfirmChannel(Channel channel) throws IOException {
// 启用发布确认模式
channel.confirmSelect();
// 添加异步确认监听器
channel.addConfirmListener(new ConfirmListener() {
/**
* 消息成功确认回调
* @param deliveryTag 消息序列号
* @param multiple 是否批量确认
*/
@Override
public void handleAck(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量确认:移除所有 <= deliveryTag 的消息
unconfirmedSet.headSet(deliveryTag + 1).clear();
} else {
// 单条确认:移除指定消息
unconfirmedSet.remove(deliveryTag);
}
System.out.println("消息确认成功,序列号: " + deliveryTag);
}
/**
* 消息失败回调(未确认)
* @param deliveryTag 消息序列号
* @param multiple 是否批量未确认
*/
@Override
public void handleNack(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量未确认:重试所有 <= deliveryTag 的消息
SortedSet<Long> headSet = unconfirmedSet.headSet(deliveryTag + 1);
for (Long seq : headSet) {
retryMessage(seq);
}
headSet.clear();
} else {
// 单条未确认:重试指定消息
retryMessage(deliveryTag);
unconfirmedSet.remove(deliveryTag);
}
System.err.println("消息确认失败,序列号: " + deliveryTag);
}
});
}
/**
* 发送消息(带序列号跟踪)
*/
public void sendMessageWithTracking(Channel channel, String message)
throws IOException {
// 获取下一个序列号
long sequenceNumber = channel.getNextPublishSeqNo();
// 记录未确认的消息
unconfirmedSet.add(sequenceNumber);
// 发送消息
channel.basicPublish(
"durable.exchange",
"routing.key",
null,
message.getBytes()
);
}
/**
* 重试失败的消息
*/
private void retryMessage(long sequenceNumber) {
// 实现重试逻辑:从缓存中取出消息重新发送
// 注意:这里需要维护消息内容与序列号的映射
}
} // 获取下一个序列号`
`#/**
* RabbitMQ 异步 Confirm 机制源码分析
* 基于 rabbitmq-java-client 5.16.0
*
* 核心流程:
* 1. 生产者发送消息时分配内部序列号
* 2. Broker 收到消息后返回确认(带序列号)
* 3. 生产者通过回调函数处理确认结果
*/
public class AsyncConfirmExample {
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
public void setupConfirmChannel(Channel channel) throws IOException {
// 启用发布确认模式
channel.confirmSelect();
// 添加异步确认监听器
channel.addConfirmListener(new ConfirmListener() {
/**
* 消息成功确认回调
* @param deliveryTag 消息序列号
* @param multiple 是否批量确认
*/
@Override
public void handleAck(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量确认:移除所有 <= deliveryTag 的消息
unconfirmedSet.headSet(deliveryTag + 1).clear();
} else {
// 单条确认:移除指定消息
unconfirmedSet.remove(deliveryTag);
}
System.out.println("消息确认成功,序列号: " + deliveryTag);
}
/**
* 消息失败回调(未确认)
* @param deliveryTag 消息序列号
* @param multiple 是否批量未确认
*/
@Override
public void handleNack(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量未确认:重试所有 <= deliveryTag 的消息
SortedSet<Long> headSet = unconfirmedSet.headSet(deliveryTag + 1);
for (Long seq : headSet) {
retryMessage(seq);
}
headSet.clear();
} else {
// 单条未确认:重试指定消息
retryMessage(deliveryTag);
unconfirmedSet.remove(deliveryTag);
}
System.err.println("消息确认失败,序列号: " + deliveryTag);
}
});
}
/**
* 发送消息(带序列号跟踪)
*/
public void sendMessageWithTracking(Channel channel, String message)
throws IOException {
// 获取下一个序列号
long sequenceNumber = channel.getNextPublishSeqNo();
// 记录未确认的消息
unconfirmedSet.add(sequenceNumber);
// 发送消息
channel.basicPublish(
"durable.exchange",
"routing.key",
null,
message.getBytes()
);
}
/**
* 重试失败的消息
*/
private void retryMessage(long sequenceNumber) {
// 实现重试逻辑:从缓存中取出消息重新发送
// 注意:这里需要维护消息内容与序列号的映射
}
} long sequenceNumber = channel.getNextPublishSeqNo();`
`#/**
* RabbitMQ 异步 Confirm 机制源码分析
* 基于 rabbitmq-java-client 5.16.0
*
* 核心流程:
* 1. 生产者发送消息时分配内部序列号
* 2. Broker 收到消息后返回确认(带序列号)
* 3. 生产者通过回调函数处理确认结果
*/
public class AsyncConfirmExample {
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
public void setupConfirmChannel(Channel channel) throws IOException {
// 启用发布确认模式
channel.confirmSelect();
// 添加异步确认监听器
channel.addConfirmListener(new ConfirmListener() {
/**
* 消息成功确认回调
* @param deliveryTag 消息序列号
* @param multiple 是否批量确认
*/
@Override
public void handleAck(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量确认:移除所有 <= deliveryTag 的消息
unconfirmedSet.headSet(deliveryTag + 1).clear();
} else {
// 单条确认:移除指定消息
unconfirmedSet.remove(deliveryTag);
}
System.out.println("消息确认成功,序列号: " + deliveryTag);
}
/**
* 消息失败回调(未确认)
* @param deliveryTag 消息序列号
* @param multiple 是否批量未确认
*/
@Override
public void handleNack(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量未确认:重试所有 <= deliveryTag 的消息
SortedSet<Long> headSet = unconfirmedSet.headSet(deliveryTag + 1);
for (Long seq : headSet) {
retryMessage(seq);
}
headSet.clear();
} else {
// 单条未确认:重试指定消息
retryMessage(deliveryTag);
unconfirmedSet.remove(deliveryTag);
}
System.err.println("消息确认失败,序列号: " + deliveryTag);
}
});
}
/**
* 发送消息(带序列号跟踪)
*/
public void sendMessageWithTracking(Channel channel, String message)
throws IOException {
// 获取下一个序列号
long sequenceNumber = channel.getNextPublishSeqNo();
// 记录未确认的消息
unconfirmedSet.add(sequenceNumber);
// 发送消息
channel.basicPublish(
"durable.exchange",
"routing.key",
null,
message.getBytes()
);
}
/**
* 重试失败的消息
*/
private void retryMessage(long sequenceNumber) {
// 实现重试逻辑:从缓存中取出消息重新发送
// 注意:这里需要维护消息内容与序列号的映射
}
} `
`#/**
* RabbitMQ 异步 Confirm 机制源码分析
* 基于 rabbitmq-java-client 5.16.0
*
* 核心流程:
* 1. 生产者发送消息时分配内部序列号
* 2. Broker 收到消息后返回确认(带序列号)
* 3. 生产者通过回调函数处理确认结果
*/
public class AsyncConfirmExample {
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
public void setupConfirmChannel(Channel channel) throws IOException {
// 启用发布确认模式
channel.confirmSelect();
// 添加异步确认监听器
channel.addConfirmListener(new ConfirmListener() {
/**
* 消息成功确认回调
* @param deliveryTag 消息序列号
* @param multiple 是否批量确认
*/
@Override
public void handleAck(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量确认:移除所有 <= deliveryTag 的消息
unconfirmedSet.headSet(deliveryTag + 1).clear();
} else {
// 单条确认:移除指定消息
unconfirmedSet.remove(deliveryTag);
}
System.out.println("消息确认成功,序列号: " + deliveryTag);
}
/**
* 消息失败回调(未确认)
* @param deliveryTag 消息序列号
* @param multiple 是否批量未确认
*/
@Override
public void handleNack(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量未确认:重试所有 <= deliveryTag 的消息
SortedSet<Long> headSet = unconfirmedSet.headSet(deliveryTag + 1);
for (Long seq : headSet) {
retryMessage(seq);
}
headSet.clear();
} else {
// 单条未确认:重试指定消息
retryMessage(deliveryTag);
unconfirmedSet.remove(deliveryTag);
}
System.err.println("消息确认失败,序列号: " + deliveryTag);
}
});
}
/**
* 发送消息(带序列号跟踪)
*/
public void sendMessageWithTracking(Channel channel, String message)
throws IOException {
// 获取下一个序列号
long sequenceNumber = channel.getNextPublishSeqNo();
// 记录未确认的消息
unconfirmedSet.add(sequenceNumber);
// 发送消息
channel.basicPublish(
"durable.exchange",
"routing.key",
null,
message.getBytes()
);
}
/**
* 重试失败的消息
*/
private void retryMessage(long sequenceNumber) {
// 实现重试逻辑:从缓存中取出消息重新发送
// 注意:这里需要维护消息内容与序列号的映射
}
} // 记录未确认的消息`
`#/**
* RabbitMQ 异步 Confirm 机制源码分析
* 基于 rabbitmq-java-client 5.16.0
*
* 核心流程:
* 1. 生产者发送消息时分配内部序列号
* 2. Broker 收到消息后返回确认(带序列号)
* 3. 生产者通过回调函数处理确认结果
*/
public class AsyncConfirmExample {
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
public void setupConfirmChannel(Channel channel) throws IOException {
// 启用发布确认模式
channel.confirmSelect();
// 添加异步确认监听器
channel.addConfirmListener(new ConfirmListener() {
/**
* 消息成功确认回调
* @param deliveryTag 消息序列号
* @param multiple 是否批量确认
*/
@Override
public void handleAck(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量确认:移除所有 <= deliveryTag 的消息
unconfirmedSet.headSet(deliveryTag + 1).clear();
} else {
// 单条确认:移除指定消息
unconfirmedSet.remove(deliveryTag);
}
System.out.println("消息确认成功,序列号: " + deliveryTag);
}
/**
* 消息失败回调(未确认)
* @param deliveryTag 消息序列号
* @param multiple 是否批量未确认
*/
@Override
public void handleNack(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量未确认:重试所有 <= deliveryTag 的消息
SortedSet<Long> headSet = unconfirmedSet.headSet(deliveryTag + 1);
for (Long seq : headSet) {
retryMessage(seq);
}
headSet.clear();
} else {
// 单条未确认:重试指定消息
retryMessage(deliveryTag);
unconfirmedSet.remove(deliveryTag);
}
System.err.println("消息确认失败,序列号: " + deliveryTag);
}
});
}
/**
* 发送消息(带序列号跟踪)
*/
public void sendMessageWithTracking(Channel channel, String message)
throws IOException {
// 获取下一个序列号
long sequenceNumber = channel.getNextPublishSeqNo();
// 记录未确认的消息
unconfirmedSet.add(sequenceNumber);
// 发送消息
channel.basicPublish(
"durable.exchange",
"routing.key",
null,
message.getBytes()
);
}
/**
* 重试失败的消息
*/
private void retryMessage(long sequenceNumber) {
// 实现重试逻辑:从缓存中取出消息重新发送
// 注意:这里需要维护消息内容与序列号的映射
}
} unconfirmedSet.add(sequenceNumber);`
`#/**
* RabbitMQ 异步 Confirm 机制源码分析
* 基于 rabbitmq-java-client 5.16.0
*
* 核心流程:
* 1. 生产者发送消息时分配内部序列号
* 2. Broker 收到消息后返回确认(带序列号)
* 3. 生产者通过回调函数处理确认结果
*/
public class AsyncConfirmExample {
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
public void setupConfirmChannel(Channel channel) throws IOException {
// 启用发布确认模式
channel.confirmSelect();
// 添加异步确认监听器
channel.addConfirmListener(new ConfirmListener() {
/**
* 消息成功确认回调
* @param deliveryTag 消息序列号
* @param multiple 是否批量确认
*/
@Override
public void handleAck(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量确认:移除所有 <= deliveryTag 的消息
unconfirmedSet.headSet(deliveryTag + 1).clear();
} else {
// 单条确认:移除指定消息
unconfirmedSet.remove(deliveryTag);
}
System.out.println("消息确认成功,序列号: " + deliveryTag);
}
/**
* 消息失败回调(未确认)
* @param deliveryTag 消息序列号
* @param multiple 是否批量未确认
*/
@Override
public void handleNack(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量未确认:重试所有 <= deliveryTag 的消息
SortedSet<Long> headSet = unconfirmedSet.headSet(deliveryTag + 1);
for (Long seq : headSet) {
retryMessage(seq);
}
headSet.clear();
} else {
// 单条未确认:重试指定消息
retryMessage(deliveryTag);
unconfirmedSet.remove(deliveryTag);
}
System.err.println("消息确认失败,序列号: " + deliveryTag);
}
});
}
/**
* 发送消息(带序列号跟踪)
*/
public void sendMessageWithTracking(Channel channel, String message)
throws IOException {
// 获取下一个序列号
long sequenceNumber = channel.getNextPublishSeqNo();
// 记录未确认的消息
unconfirmedSet.add(sequenceNumber);
// 发送消息
channel.basicPublish(
"durable.exchange",
"routing.key",
null,
message.getBytes()
);
}
/**
* 重试失败的消息
*/
private void retryMessage(long sequenceNumber) {
// 实现重试逻辑:从缓存中取出消息重新发送
// 注意:这里需要维护消息内容与序列号的映射
}
} `
`#/**
* RabbitMQ 异步 Confirm 机制源码分析
* 基于 rabbitmq-java-client 5.16.0
*
* 核心流程:
* 1. 生产者发送消息时分配内部序列号
* 2. Broker 收到消息后返回确认(带序列号)
* 3. 生产者通过回调函数处理确认结果
*/
public class AsyncConfirmExample {
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
public void setupConfirmChannel(Channel channel) throws IOException {
// 启用发布确认模式
channel.confirmSelect();
// 添加异步确认监听器
channel.addConfirmListener(new ConfirmListener() {
/**
* 消息成功确认回调
* @param deliveryTag 消息序列号
* @param multiple 是否批量确认
*/
@Override
public void handleAck(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量确认:移除所有 <= deliveryTag 的消息
unconfirmedSet.headSet(deliveryTag + 1).clear();
} else {
// 单条确认:移除指定消息
unconfirmedSet.remove(deliveryTag);
}
System.out.println("消息确认成功,序列号: " + deliveryTag);
}
/**
* 消息失败回调(未确认)
* @param deliveryTag 消息序列号
* @param multiple 是否批量未确认
*/
@Override
public void handleNack(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量未确认:重试所有 <= deliveryTag 的消息
SortedSet<Long> headSet = unconfirmedSet.headSet(deliveryTag + 1);
for (Long seq : headSet) {
retryMessage(seq);
}
headSet.clear();
} else {
// 单条未确认:重试指定消息
retryMessage(deliveryTag);
unconfirmedSet.remove(deliveryTag);
}
System.err.println("消息确认失败,序列号: " + deliveryTag);
}
});
}
/**
* 发送消息(带序列号跟踪)
*/
public void sendMessageWithTracking(Channel channel, String message)
throws IOException {
// 获取下一个序列号
long sequenceNumber = channel.getNextPublishSeqNo();
// 记录未确认的消息
unconfirmedSet.add(sequenceNumber);
// 发送消息
channel.basicPublish(
"durable.exchange",
"routing.key",
null,
message.getBytes()
);
}
/**
* 重试失败的消息
*/
private void retryMessage(long sequenceNumber) {
// 实现重试逻辑:从缓存中取出消息重新发送
// 注意:这里需要维护消息内容与序列号的映射
}
} // 发送消息`
`#/**
* RabbitMQ 异步 Confirm 机制源码分析
* 基于 rabbitmq-java-client 5.16.0
*
* 核心流程:
* 1. 生产者发送消息时分配内部序列号
* 2. Broker 收到消息后返回确认(带序列号)
* 3. 生产者通过回调函数处理确认结果
*/
public class AsyncConfirmExample {
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
public void setupConfirmChannel(Channel channel) throws IOException {
// 启用发布确认模式
channel.confirmSelect();
// 添加异步确认监听器
channel.addConfirmListener(new ConfirmListener() {
/**
* 消息成功确认回调
* @param deliveryTag 消息序列号
* @param multiple 是否批量确认
*/
@Override
public void handleAck(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量确认:移除所有 <= deliveryTag 的消息
unconfirmedSet.headSet(deliveryTag + 1).clear();
} else {
// 单条确认:移除指定消息
unconfirmedSet.remove(deliveryTag);
}
System.out.println("消息确认成功,序列号: " + deliveryTag);
}
/**
* 消息失败回调(未确认)
* @param deliveryTag 消息序列号
* @param multiple 是否批量未确认
*/
@Override
public void handleNack(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量未确认:重试所有 <= deliveryTag 的消息
SortedSet<Long> headSet = unconfirmedSet.headSet(deliveryTag + 1);
for (Long seq : headSet) {
retryMessage(seq);
}
headSet.clear();
} else {
// 单条未确认:重试指定消息
retryMessage(deliveryTag);
unconfirmedSet.remove(deliveryTag);
}
System.err.println("消息确认失败,序列号: " + deliveryTag);
}
});
}
/**
* 发送消息(带序列号跟踪)
*/
public void sendMessageWithTracking(Channel channel, String message)
throws IOException {
// 获取下一个序列号
long sequenceNumber = channel.getNextPublishSeqNo();
// 记录未确认的消息
unconfirmedSet.add(sequenceNumber);
// 发送消息
channel.basicPublish(
"durable.exchange",
"routing.key",
null,
message.getBytes()
);
}
/**
* 重试失败的消息
*/
private void retryMessage(long sequenceNumber) {
// 实现重试逻辑:从缓存中取出消息重新发送
// 注意:这里需要维护消息内容与序列号的映射
}
} channel.basicPublish(`
`#/**
* RabbitMQ 异步 Confirm 机制源码分析
* 基于 rabbitmq-java-client 5.16.0
*
* 核心流程:
* 1. 生产者发送消息时分配内部序列号
* 2. Broker 收到消息后返回确认(带序列号)
* 3. 生产者通过回调函数处理确认结果
*/
public class AsyncConfirmExample {
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
public void setupConfirmChannel(Channel channel) throws IOException {
// 启用发布确认模式
channel.confirmSelect();
// 添加异步确认监听器
channel.addConfirmListener(new ConfirmListener() {
/**
* 消息成功确认回调
* @param deliveryTag 消息序列号
* @param multiple 是否批量确认
*/
@Override
public void handleAck(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量确认:移除所有 <= deliveryTag 的消息
unconfirmedSet.headSet(deliveryTag + 1).clear();
} else {
// 单条确认:移除指定消息
unconfirmedSet.remove(deliveryTag);
}
System.out.println("消息确认成功,序列号: " + deliveryTag);
}
/**
* 消息失败回调(未确认)
* @param deliveryTag 消息序列号
* @param multiple 是否批量未确认
*/
@Override
public void handleNack(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量未确认:重试所有 <= deliveryTag 的消息
SortedSet<Long> headSet = unconfirmedSet.headSet(deliveryTag + 1);
for (Long seq : headSet) {
retryMessage(seq);
}
headSet.clear();
} else {
// 单条未确认:重试指定消息
retryMessage(deliveryTag);
unconfirmedSet.remove(deliveryTag);
}
System.err.println("消息确认失败,序列号: " + deliveryTag);
}
});
}
/**
* 发送消息(带序列号跟踪)
*/
public void sendMessageWithTracking(Channel channel, String message)
throws IOException {
// 获取下一个序列号
long sequenceNumber = channel.getNextPublishSeqNo();
// 记录未确认的消息
unconfirmedSet.add(sequenceNumber);
// 发送消息
channel.basicPublish(
"durable.exchange",
"routing.key",
null,
message.getBytes()
);
}
/**
* 重试失败的消息
*/
private void retryMessage(long sequenceNumber) {
// 实现重试逻辑:从缓存中取出消息重新发送
// 注意:这里需要维护消息内容与序列号的映射
}
} "durable.exchange",`
`#/**
* RabbitMQ 异步 Confirm 机制源码分析
* 基于 rabbitmq-java-client 5.16.0
*
* 核心流程:
* 1. 生产者发送消息时分配内部序列号
* 2. Broker 收到消息后返回确认(带序列号)
* 3. 生产者通过回调函数处理确认结果
*/
public class AsyncConfirmExample {
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
public void setupConfirmChannel(Channel channel) throws IOException {
// 启用发布确认模式
channel.confirmSelect();
// 添加异步确认监听器
channel.addConfirmListener(new ConfirmListener() {
/**
* 消息成功确认回调
* @param deliveryTag 消息序列号
* @param multiple 是否批量确认
*/
@Override
public void handleAck(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量确认:移除所有 <= deliveryTag 的消息
unconfirmedSet.headSet(deliveryTag + 1).clear();
} else {
// 单条确认:移除指定消息
unconfirmedSet.remove(deliveryTag);
}
System.out.println("消息确认成功,序列号: " + deliveryTag);
}
/**
* 消息失败回调(未确认)
* @param deliveryTag 消息序列号
* @param multiple 是否批量未确认
*/
@Override
public void handleNack(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量未确认:重试所有 <= deliveryTag 的消息
SortedSet<Long> headSet = unconfirmedSet.headSet(deliveryTag + 1);
for (Long seq : headSet) {
retryMessage(seq);
}
headSet.clear();
} else {
// 单条未确认:重试指定消息
retryMessage(deliveryTag);
unconfirmedSet.remove(deliveryTag);
}
System.err.println("消息确认失败,序列号: " + deliveryTag);
}
});
}
/**
* 发送消息(带序列号跟踪)
*/
public void sendMessageWithTracking(Channel channel, String message)
throws IOException {
// 获取下一个序列号
long sequenceNumber = channel.getNextPublishSeqNo();
// 记录未确认的消息
unconfirmedSet.add(sequenceNumber);
// 发送消息
channel.basicPublish(
"durable.exchange",
"routing.key",
null,
message.getBytes()
);
}
/**
* 重试失败的消息
*/
private void retryMessage(long sequenceNumber) {
// 实现重试逻辑:从缓存中取出消息重新发送
// 注意:这里需要维护消息内容与序列号的映射
}
} "routing.key",`
`#/**
* RabbitMQ 异步 Confirm 机制源码分析
* 基于 rabbitmq-java-client 5.16.0
*
* 核心流程:
* 1. 生产者发送消息时分配内部序列号
* 2. Broker 收到消息后返回确认(带序列号)
* 3. 生产者通过回调函数处理确认结果
*/
public class AsyncConfirmExample {
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
public void setupConfirmChannel(Channel channel) throws IOException {
// 启用发布确认模式
channel.confirmSelect();
// 添加异步确认监听器
channel.addConfirmListener(new ConfirmListener() {
/**
* 消息成功确认回调
* @param deliveryTag 消息序列号
* @param multiple 是否批量确认
*/
@Override
public void handleAck(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量确认:移除所有 <= deliveryTag 的消息
unconfirmedSet.headSet(deliveryTag + 1).clear();
} else {
// 单条确认:移除指定消息
unconfirmedSet.remove(deliveryTag);
}
System.out.println("消息确认成功,序列号: " + deliveryTag);
}
/**
* 消息失败回调(未确认)
* @param deliveryTag 消息序列号
* @param multiple 是否批量未确认
*/
@Override
public void handleNack(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量未确认:重试所有 <= deliveryTag 的消息
SortedSet<Long> headSet = unconfirmedSet.headSet(deliveryTag + 1);
for (Long seq : headSet) {
retryMessage(seq);
}
headSet.clear();
} else {
// 单条未确认:重试指定消息
retryMessage(deliveryTag);
unconfirmedSet.remove(deliveryTag);
}
System.err.println("消息确认失败,序列号: " + deliveryTag);
}
});
}
/**
* 发送消息(带序列号跟踪)
*/
public void sendMessageWithTracking(Channel channel, String message)
throws IOException {
// 获取下一个序列号
long sequenceNumber = channel.getNextPublishSeqNo();
// 记录未确认的消息
unconfirmedSet.add(sequenceNumber);
// 发送消息
channel.basicPublish(
"durable.exchange",
"routing.key",
null,
message.getBytes()
);
}
/**
* 重试失败的消息
*/
private void retryMessage(long sequenceNumber) {
// 实现重试逻辑:从缓存中取出消息重新发送
// 注意:这里需要维护消息内容与序列号的映射
}
} null,`
`#/**
* RabbitMQ 异步 Confirm 机制源码分析
* 基于 rabbitmq-java-client 5.16.0
*
* 核心流程:
* 1. 生产者发送消息时分配内部序列号
* 2. Broker 收到消息后返回确认(带序列号)
* 3. 生产者通过回调函数处理确认结果
*/
public class AsyncConfirmExample {
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
public void setupConfirmChannel(Channel channel) throws IOException {
// 启用发布确认模式
channel.confirmSelect();
// 添加异步确认监听器
channel.addConfirmListener(new ConfirmListener() {
/**
* 消息成功确认回调
* @param deliveryTag 消息序列号
* @param multiple 是否批量确认
*/
@Override
public void handleAck(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量确认:移除所有 <= deliveryTag 的消息
unconfirmedSet.headSet(deliveryTag + 1).clear();
} else {
// 单条确认:移除指定消息
unconfirmedSet.remove(deliveryTag);
}
System.out.println("消息确认成功,序列号: " + deliveryTag);
}
/**
* 消息失败回调(未确认)
* @param deliveryTag 消息序列号
* @param multiple 是否批量未确认
*/
@Override
public void handleNack(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量未确认:重试所有 <= deliveryTag 的消息
SortedSet<Long> headSet = unconfirmedSet.headSet(deliveryTag + 1);
for (Long seq : headSet) {
retryMessage(seq);
}
headSet.clear();
} else {
// 单条未确认:重试指定消息
retryMessage(deliveryTag);
unconfirmedSet.remove(deliveryTag);
}
System.err.println("消息确认失败,序列号: " + deliveryTag);
}
});
}
/**
* 发送消息(带序列号跟踪)
*/
public void sendMessageWithTracking(Channel channel, String message)
throws IOException {
// 获取下一个序列号
long sequenceNumber = channel.getNextPublishSeqNo();
// 记录未确认的消息
unconfirmedSet.add(sequenceNumber);
// 发送消息
channel.basicPublish(
"durable.exchange",
"routing.key",
null,
message.getBytes()
);
}
/**
* 重试失败的消息
*/
private void retryMessage(long sequenceNumber) {
// 实现重试逻辑:从缓存中取出消息重新发送
// 注意:这里需要维护消息内容与序列号的映射
}
} message.getBytes()`
`#/**
* RabbitMQ 异步 Confirm 机制源码分析
* 基于 rabbitmq-java-client 5.16.0
*
* 核心流程:
* 1. 生产者发送消息时分配内部序列号
* 2. Broker 收到消息后返回确认(带序列号)
* 3. 生产者通过回调函数处理确认结果
*/
public class AsyncConfirmExample {
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
public void setupConfirmChannel(Channel channel) throws IOException {
// 启用发布确认模式
channel.confirmSelect();
// 添加异步确认监听器
channel.addConfirmListener(new ConfirmListener() {
/**
* 消息成功确认回调
* @param deliveryTag 消息序列号
* @param multiple 是否批量确认
*/
@Override
public void handleAck(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量确认:移除所有 <= deliveryTag 的消息
unconfirmedSet.headSet(deliveryTag + 1).clear();
} else {
// 单条确认:移除指定消息
unconfirmedSet.remove(deliveryTag);
}
System.out.println("消息确认成功,序列号: " + deliveryTag);
}
/**
* 消息失败回调(未确认)
* @param deliveryTag 消息序列号
* @param multiple 是否批量未确认
*/
@Override
public void handleNack(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量未确认:重试所有 <= deliveryTag 的消息
SortedSet<Long> headSet = unconfirmedSet.headSet(deliveryTag + 1);
for (Long seq : headSet) {
retryMessage(seq);
}
headSet.clear();
} else {
// 单条未确认:重试指定消息
retryMessage(deliveryTag);
unconfirmedSet.remove(deliveryTag);
}
System.err.println("消息确认失败,序列号: " + deliveryTag);
}
});
}
/**
* 发送消息(带序列号跟踪)
*/
public void sendMessageWithTracking(Channel channel, String message)
throws IOException {
// 获取下一个序列号
long sequenceNumber = channel.getNextPublishSeqNo();
// 记录未确认的消息
unconfirmedSet.add(sequenceNumber);
// 发送消息
channel.basicPublish(
"durable.exchange",
"routing.key",
null,
message.getBytes()
);
}
/**
* 重试失败的消息
*/
private void retryMessage(long sequenceNumber) {
// 实现重试逻辑:从缓存中取出消息重新发送
// 注意:这里需要维护消息内容与序列号的映射
}
} );`
`#/**
* RabbitMQ 异步 Confirm 机制源码分析
* 基于 rabbitmq-java-client 5.16.0
*
* 核心流程:
* 1. 生产者发送消息时分配内部序列号
* 2. Broker 收到消息后返回确认(带序列号)
* 3. 生产者通过回调函数处理确认结果
*/
public class AsyncConfirmExample {
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
public void setupConfirmChannel(Channel channel) throws IOException {
// 启用发布确认模式
channel.confirmSelect();
// 添加异步确认监听器
channel.addConfirmListener(new ConfirmListener() {
/**
* 消息成功确认回调
* @param deliveryTag 消息序列号
* @param multiple 是否批量确认
*/
@Override
public void handleAck(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量确认:移除所有 <= deliveryTag 的消息
unconfirmedSet.headSet(deliveryTag + 1).clear();
} else {
// 单条确认:移除指定消息
unconfirmedSet.remove(deliveryTag);
}
System.out.println("消息确认成功,序列号: " + deliveryTag);
}
/**
* 消息失败回调(未确认)
* @param deliveryTag 消息序列号
* @param multiple 是否批量未确认
*/
@Override
public void handleNack(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量未确认:重试所有 <= deliveryTag 的消息
SortedSet<Long> headSet = unconfirmedSet.headSet(deliveryTag + 1);
for (Long seq : headSet) {
retryMessage(seq);
}
headSet.clear();
} else {
// 单条未确认:重试指定消息
retryMessage(deliveryTag);
unconfirmedSet.remove(deliveryTag);
}
System.err.println("消息确认失败,序列号: " + deliveryTag);
}
});
}
/**
* 发送消息(带序列号跟踪)
*/
public void sendMessageWithTracking(Channel channel, String message)
throws IOException {
// 获取下一个序列号
long sequenceNumber = channel.getNextPublishSeqNo();
// 记录未确认的消息
unconfirmedSet.add(sequenceNumber);
// 发送消息
channel.basicPublish(
"durable.exchange",
"routing.key",
null,
message.getBytes()
);
}
/**
* 重试失败的消息
*/
private void retryMessage(long sequenceNumber) {
// 实现重试逻辑:从缓存中取出消息重新发送
// 注意:这里需要维护消息内容与序列号的映射
}
} }`
`#/**
* RabbitMQ 异步 Confirm 机制源码分析
* 基于 rabbitmq-java-client 5.16.0
*
* 核心流程:
* 1. 生产者发送消息时分配内部序列号
* 2. Broker 收到消息后返回确认(带序列号)
* 3. 生产者通过回调函数处理确认结果
*/
public class AsyncConfirmExample {
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
public void setupConfirmChannel(Channel channel) throws IOException {
// 启用发布确认模式
channel.confirmSelect();
// 添加异步确认监听器
channel.addConfirmListener(new ConfirmListener() {
/**
* 消息成功确认回调
* @param deliveryTag 消息序列号
* @param multiple 是否批量确认
*/
@Override
public void handleAck(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量确认:移除所有 <= deliveryTag 的消息
unconfirmedSet.headSet(deliveryTag + 1).clear();
} else {
// 单条确认:移除指定消息
unconfirmedSet.remove(deliveryTag);
}
System.out.println("消息确认成功,序列号: " + deliveryTag);
}
/**
* 消息失败回调(未确认)
* @param deliveryTag 消息序列号
* @param multiple 是否批量未确认
*/
@Override
public void handleNack(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量未确认:重试所有 <= deliveryTag 的消息
SortedSet<Long> headSet = unconfirmedSet.headSet(deliveryTag + 1);
for (Long seq : headSet) {
retryMessage(seq);
}
headSet.clear();
} else {
// 单条未确认:重试指定消息
retryMessage(deliveryTag);
unconfirmedSet.remove(deliveryTag);
}
System.err.println("消息确认失败,序列号: " + deliveryTag);
}
});
}
/**
* 发送消息(带序列号跟踪)
*/
public void sendMessageWithTracking(Channel channel, String message)
throws IOException {
// 获取下一个序列号
long sequenceNumber = channel.getNextPublishSeqNo();
// 记录未确认的消息
unconfirmedSet.add(sequenceNumber);
// 发送消息
channel.basicPublish(
"durable.exchange",
"routing.key",
null,
message.getBytes()
);
}
/**
* 重试失败的消息
*/
private void retryMessage(long sequenceNumber) {
// 实现重试逻辑:从缓存中取出消息重新发送
// 注意:这里需要维护消息内容与序列号的映射
}
}`
`#/**
* RabbitMQ 异步 Confirm 机制源码分析
* 基于 rabbitmq-java-client 5.16.0
*
* 核心流程:
* 1. 生产者发送消息时分配内部序列号
* 2. Broker 收到消息后返回确认(带序列号)
* 3. 生产者通过回调函数处理确认结果
*/
public class AsyncConfirmExample {
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
public void setupConfirmChannel(Channel channel) throws IOException {
// 启用发布确认模式
channel.confirmSelect();
// 添加异步确认监听器
channel.addConfirmListener(new ConfirmListener() {
/**
* 消息成功确认回调
* @param deliveryTag 消息序列号
* @param multiple 是否批量确认
*/
@Override
public void handleAck(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量确认:移除所有 <= deliveryTag 的消息
unconfirmedSet.headSet(deliveryTag + 1).clear();
} else {
// 单条确认:移除指定消息
unconfirmedSet.remove(deliveryTag);
}
System.out.println("消息确认成功,序列号: " + deliveryTag);
}
/**
* 消息失败回调(未确认)
* @param deliveryTag 消息序列号
* @param multiple 是否批量未确认
*/
@Override
public void handleNack(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量未确认:重试所有 <= deliveryTag 的消息
SortedSet<Long> headSet = unconfirmedSet.headSet(deliveryTag + 1);
for (Long seq : headSet) {
retryMessage(seq);
}
headSet.clear();
} else {
// 单条未确认:重试指定消息
retryMessage(deliveryTag);
unconfirmedSet.remove(deliveryTag);
}
System.err.println("消息确认失败,序列号: " + deliveryTag);
}
});
}
/**
* 发送消息(带序列号跟踪)
*/
public void sendMessageWithTracking(Channel channel, String message)
throws IOException {
// 获取下一个序列号
long sequenceNumber = channel.getNextPublishSeqNo();
// 记录未确认的消息
unconfirmedSet.add(sequenceNumber);
// 发送消息
channel.basicPublish(
"durable.exchange",
"routing.key",
null,
message.getBytes()
);
}
/**
* 重试失败的消息
*/
private void retryMessage(long sequenceNumber) {
// 实现重试逻辑:从缓存中取出消息重新发送
// 注意:这里需要维护消息内容与序列号的映射
}
} /**`
`#/**
* RabbitMQ 异步 Confirm 机制源码分析
* 基于 rabbitmq-java-client 5.16.0
*
* 核心流程:
* 1. 生产者发送消息时分配内部序列号
* 2. Broker 收到消息后返回确认(带序列号)
* 3. 生产者通过回调函数处理确认结果
*/
public class AsyncConfirmExample {
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
public void setupConfirmChannel(Channel channel) throws IOException {
// 启用发布确认模式
channel.confirmSelect();
// 添加异步确认监听器
channel.addConfirmListener(new ConfirmListener() {
/**
* 消息成功确认回调
* @param deliveryTag 消息序列号
* @param multiple 是否批量确认
*/
@Override
public void handleAck(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量确认:移除所有 <= deliveryTag 的消息
unconfirmedSet.headSet(deliveryTag + 1).clear();
} else {
// 单条确认:移除指定消息
unconfirmedSet.remove(deliveryTag);
}
System.out.println("消息确认成功,序列号: " + deliveryTag);
}
/**
* 消息失败回调(未确认)
* @param deliveryTag 消息序列号
* @param multiple 是否批量未确认
*/
@Override
public void handleNack(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量未确认:重试所有 <= deliveryTag 的消息
SortedSet<Long> headSet = unconfirmedSet.headSet(deliveryTag + 1);
for (Long seq : headSet) {
retryMessage(seq);
}
headSet.clear();
} else {
// 单条未确认:重试指定消息
retryMessage(deliveryTag);
unconfirmedSet.remove(deliveryTag);
}
System.err.println("消息确认失败,序列号: " + deliveryTag);
}
});
}
/**
* 发送消息(带序列号跟踪)
*/
public void sendMessageWithTracking(Channel channel, String message)
throws IOException {
// 获取下一个序列号
long sequenceNumber = channel.getNextPublishSeqNo();
// 记录未确认的消息
unconfirmedSet.add(sequenceNumber);
// 发送消息
channel.basicPublish(
"durable.exchange",
"routing.key",
null,
message.getBytes()
);
}
/**
* 重试失败的消息
*/
private void retryMessage(long sequenceNumber) {
// 实现重试逻辑:从缓存中取出消息重新发送
// 注意:这里需要维护消息内容与序列号的映射
}
} * 重试失败的消息`
`#/**
* RabbitMQ 异步 Confirm 机制源码分析
* 基于 rabbitmq-java-client 5.16.0
*
* 核心流程:
* 1. 生产者发送消息时分配内部序列号
* 2. Broker 收到消息后返回确认(带序列号)
* 3. 生产者通过回调函数处理确认结果
*/
public class AsyncConfirmExample {
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
public void setupConfirmChannel(Channel channel) throws IOException {
// 启用发布确认模式
channel.confirmSelect();
// 添加异步确认监听器
channel.addConfirmListener(new ConfirmListener() {
/**
* 消息成功确认回调
* @param deliveryTag 消息序列号
* @param multiple 是否批量确认
*/
@Override
public void handleAck(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量确认:移除所有 <= deliveryTag 的消息
unconfirmedSet.headSet(deliveryTag + 1).clear();
} else {
// 单条确认:移除指定消息
unconfirmedSet.remove(deliveryTag);
}
System.out.println("消息确认成功,序列号: " + deliveryTag);
}
/**
* 消息失败回调(未确认)
* @param deliveryTag 消息序列号
* @param multiple 是否批量未确认
*/
@Override
public void handleNack(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量未确认:重试所有 <= deliveryTag 的消息
SortedSet<Long> headSet = unconfirmedSet.headSet(deliveryTag + 1);
for (Long seq : headSet) {
retryMessage(seq);
}
headSet.clear();
} else {
// 单条未确认:重试指定消息
retryMessage(deliveryTag);
unconfirmedSet.remove(deliveryTag);
}
System.err.println("消息确认失败,序列号: " + deliveryTag);
}
});
}
/**
* 发送消息(带序列号跟踪)
*/
public void sendMessageWithTracking(Channel channel, String message)
throws IOException {
// 获取下一个序列号
long sequenceNumber = channel.getNextPublishSeqNo();
// 记录未确认的消息
unconfirmedSet.add(sequenceNumber);
// 发送消息
channel.basicPublish(
"durable.exchange",
"routing.key",
null,
message.getBytes()
);
}
/**
* 重试失败的消息
*/
private void retryMessage(long sequenceNumber) {
// 实现重试逻辑:从缓存中取出消息重新发送
// 注意:这里需要维护消息内容与序列号的映射
}
} */`
`#/**
* RabbitMQ 异步 Confirm 机制源码分析
* 基于 rabbitmq-java-client 5.16.0
*
* 核心流程:
* 1. 生产者发送消息时分配内部序列号
* 2. Broker 收到消息后返回确认(带序列号)
* 3. 生产者通过回调函数处理确认结果
*/
public class AsyncConfirmExample {
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
public void setupConfirmChannel(Channel channel) throws IOException {
// 启用发布确认模式
channel.confirmSelect();
// 添加异步确认监听器
channel.addConfirmListener(new ConfirmListener() {
/**
* 消息成功确认回调
* @param deliveryTag 消息序列号
* @param multiple 是否批量确认
*/
@Override
public void handleAck(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量确认:移除所有 <= deliveryTag 的消息
unconfirmedSet.headSet(deliveryTag + 1).clear();
} else {
// 单条确认:移除指定消息
unconfirmedSet.remove(deliveryTag);
}
System.out.println("消息确认成功,序列号: " + deliveryTag);
}
/**
* 消息失败回调(未确认)
* @param deliveryTag 消息序列号
* @param multiple 是否批量未确认
*/
@Override
public void handleNack(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量未确认:重试所有 <= deliveryTag 的消息
SortedSet<Long> headSet = unconfirmedSet.headSet(deliveryTag + 1);
for (Long seq : headSet) {
retryMessage(seq);
}
headSet.clear();
} else {
// 单条未确认:重试指定消息
retryMessage(deliveryTag);
unconfirmedSet.remove(deliveryTag);
}
System.err.println("消息确认失败,序列号: " + deliveryTag);
}
});
}
/**
* 发送消息(带序列号跟踪)
*/
public void sendMessageWithTracking(Channel channel, String message)
throws IOException {
// 获取下一个序列号
long sequenceNumber = channel.getNextPublishSeqNo();
// 记录未确认的消息
unconfirmedSet.add(sequenceNumber);
// 发送消息
channel.basicPublish(
"durable.exchange",
"routing.key",
null,
message.getBytes()
);
}
/**
* 重试失败的消息
*/
private void retryMessage(long sequenceNumber) {
// 实现重试逻辑:从缓存中取出消息重新发送
// 注意:这里需要维护消息内容与序列号的映射
}
} private void retryMessage(long sequenceNumber) {`
`#/**
* RabbitMQ 异步 Confirm 机制源码分析
* 基于 rabbitmq-java-client 5.16.0
*
* 核心流程:
* 1. 生产者发送消息时分配内部序列号
* 2. Broker 收到消息后返回确认(带序列号)
* 3. 生产者通过回调函数处理确认结果
*/
public class AsyncConfirmExample {
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
public void setupConfirmChannel(Channel channel) throws IOException {
// 启用发布确认模式
channel.confirmSelect();
// 添加异步确认监听器
channel.addConfirmListener(new ConfirmListener() {
/**
* 消息成功确认回调
* @param deliveryTag 消息序列号
* @param multiple 是否批量确认
*/
@Override
public void handleAck(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量确认:移除所有 <= deliveryTag 的消息
unconfirmedSet.headSet(deliveryTag + 1).clear();
} else {
// 单条确认:移除指定消息
unconfirmedSet.remove(deliveryTag);
}
System.out.println("消息确认成功,序列号: " + deliveryTag);
}
/**
* 消息失败回调(未确认)
* @param deliveryTag 消息序列号
* @param multiple 是否批量未确认
*/
@Override
public void handleNack(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量未确认:重试所有 <= deliveryTag 的消息
SortedSet<Long> headSet = unconfirmedSet.headSet(deliveryTag + 1);
for (Long seq : headSet) {
retryMessage(seq);
}
headSet.clear();
} else {
// 单条未确认:重试指定消息
retryMessage(deliveryTag);
unconfirmedSet.remove(deliveryTag);
}
System.err.println("消息确认失败,序列号: " + deliveryTag);
}
});
}
/**
* 发送消息(带序列号跟踪)
*/
public void sendMessageWithTracking(Channel channel, String message)
throws IOException {
// 获取下一个序列号
long sequenceNumber = channel.getNextPublishSeqNo();
// 记录未确认的消息
unconfirmedSet.add(sequenceNumber);
// 发送消息
channel.basicPublish(
"durable.exchange",
"routing.key",
null,
message.getBytes()
);
}
/**
* 重试失败的消息
*/
private void retryMessage(long sequenceNumber) {
// 实现重试逻辑:从缓存中取出消息重新发送
// 注意:这里需要维护消息内容与序列号的映射
}
} // 实现重试逻辑:从缓存中取出消息重新发送`
`#/**
* RabbitMQ 异步 Confirm 机制源码分析
* 基于 rabbitmq-java-client 5.16.0
*
* 核心流程:
* 1. 生产者发送消息时分配内部序列号
* 2. Broker 收到消息后返回确认(带序列号)
* 3. 生产者通过回调函数处理确认结果
*/
public class AsyncConfirmExample {
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
public void setupConfirmChannel(Channel channel) throws IOException {
// 启用发布确认模式
channel.confirmSelect();
// 添加异步确认监听器
channel.addConfirmListener(new ConfirmListener() {
/**
* 消息成功确认回调
* @param deliveryTag 消息序列号
* @param multiple 是否批量确认
*/
@Override
public void handleAck(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量确认:移除所有 <= deliveryTag 的消息
unconfirmedSet.headSet(deliveryTag + 1).clear();
} else {
// 单条确认:移除指定消息
unconfirmedSet.remove(deliveryTag);
}
System.out.println("消息确认成功,序列号: " + deliveryTag);
}
/**
* 消息失败回调(未确认)
* @param deliveryTag 消息序列号
* @param multiple 是否批量未确认
*/
@Override
public void handleNack(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量未确认:重试所有 <= deliveryTag 的消息
SortedSet<Long> headSet = unconfirmedSet.headSet(deliveryTag + 1);
for (Long seq : headSet) {
retryMessage(seq);
}
headSet.clear();
} else {
// 单条未确认:重试指定消息
retryMessage(deliveryTag);
unconfirmedSet.remove(deliveryTag);
}
System.err.println("消息确认失败,序列号: " + deliveryTag);
}
});
}
/**
* 发送消息(带序列号跟踪)
*/
public void sendMessageWithTracking(Channel channel, String message)
throws IOException {
// 获取下一个序列号
long sequenceNumber = channel.getNextPublishSeqNo();
// 记录未确认的消息
unconfirmedSet.add(sequenceNumber);
// 发送消息
channel.basicPublish(
"durable.exchange",
"routing.key",
null,
message.getBytes()
);
}
/**
* 重试失败的消息
*/
private void retryMessage(long sequenceNumber) {
// 实现重试逻辑:从缓存中取出消息重新发送
// 注意:这里需要维护消息内容与序列号的映射
}
} // 注意:这里需要维护消息内容与序列号的映射`
`#/**
* RabbitMQ 异步 Confirm 机制源码分析
* 基于 rabbitmq-java-client 5.16.0
*
* 核心流程:
* 1. 生产者发送消息时分配内部序列号
* 2. Broker 收到消息后返回确认(带序列号)
* 3. 生产者通过回调函数处理确认结果
*/
public class AsyncConfirmExample {
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
public void setupConfirmChannel(Channel channel) throws IOException {
// 启用发布确认模式
channel.confirmSelect();
// 添加异步确认监听器
channel.addConfirmListener(new ConfirmListener() {
/**
* 消息成功确认回调
* @param deliveryTag 消息序列号
* @param multiple 是否批量确认
*/
@Override
public void handleAck(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量确认:移除所有 <= deliveryTag 的消息
unconfirmedSet.headSet(deliveryTag + 1).clear();
} else {
// 单条确认:移除指定消息
unconfirmedSet.remove(deliveryTag);
}
System.out.println("消息确认成功,序列号: " + deliveryTag);
}
/**
* 消息失败回调(未确认)
* @param deliveryTag 消息序列号
* @param multiple 是否批量未确认
*/
@Override
public void handleNack(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量未确认:重试所有 <= deliveryTag 的消息
SortedSet<Long> headSet = unconfirmedSet.headSet(deliveryTag + 1);
for (Long seq : headSet) {
retryMessage(seq);
}
headSet.clear();
} else {
// 单条未确认:重试指定消息
retryMessage(deliveryTag);
unconfirmedSet.remove(deliveryTag);
}
System.err.println("消息确认失败,序列号: " + deliveryTag);
}
});
}
/**
* 发送消息(带序列号跟踪)
*/
public void sendMessageWithTracking(Channel channel, String message)
throws IOException {
// 获取下一个序列号
long sequenceNumber = channel.getNextPublishSeqNo();
// 记录未确认的消息
unconfirmedSet.add(sequenceNumber);
// 发送消息
channel.basicPublish(
"durable.exchange",
"routing.key",
null,
message.getBytes()
);
}
/**
* 重试失败的消息
*/
private void retryMessage(long sequenceNumber) {
// 实现重试逻辑:从缓存中取出消息重新发送
// 注意:这里需要维护消息内容与序列号的映射
}
} }`
`#/**
* RabbitMQ 异步 Confirm 机制源码分析
* 基于 rabbitmq-java-client 5.16.0
*
* 核心流程:
* 1. 生产者发送消息时分配内部序列号
* 2. Broker 收到消息后返回确认(带序列号)
* 3. 生产者通过回调函数处理确认结果
*/
public class AsyncConfirmExample {
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
public void setupConfirmChannel(Channel channel) throws IOException {
// 启用发布确认模式
channel.confirmSelect();
// 添加异步确认监听器
channel.addConfirmListener(new ConfirmListener() {
/**
* 消息成功确认回调
* @param deliveryTag 消息序列号
* @param multiple 是否批量确认
*/
@Override
public void handleAck(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量确认:移除所有 <= deliveryTag 的消息
unconfirmedSet.headSet(deliveryTag + 1).clear();
} else {
// 单条确认:移除指定消息
unconfirmedSet.remove(deliveryTag);
}
System.out.println("消息确认成功,序列号: " + deliveryTag);
}
/**
* 消息失败回调(未确认)
* @param deliveryTag 消息序列号
* @param multiple 是否批量未确认
*/
@Override
public void handleNack(long deliveryTag, boolean multiple) {
if (multiple) {
// 批量未确认:重试所有 <= deliveryTag 的消息
SortedSet<Long> headSet = unconfirmedSet.headSet(deliveryTag + 1);
for (Long seq : headSet) {
retryMessage(seq);
}
headSet.clear();
} else {
// 单条未确认:重试指定消息
retryMessage(deliveryTag);
unconfirmedSet.remove(deliveryTag);
}
System.err.println("消息确认失败,序列号: " + deliveryTag);
}
});
}
/**
* 发送消息(带序列号跟踪)
*/
public void sendMessageWithTracking(Channel channel, String message)
throws IOException {
// 获取下一个序列号
long sequenceNumber = channel.getNextPublishSeqNo();
// 记录未确认的消息
unconfirmedSet.add(sequenceNumber);
// 发送消息
channel.basicPublish(
"durable.exchange",
"routing.key",
null,
message.getBytes()
);
}
/**
* 重试失败的消息
*/
private void retryMessage(long sequenceNumber) {
// 实现重试逻辑:从缓存中取出消息重新发送
// 注意:这里需要维护消息内容与序列号的映射
}
}}
3.3 消费者手动确认(Manual ACK)
3.3.1 Consumer Ack 的三种模式
graph LR
A[消息投递] --> B{消费者处理结果}
B -->|成功| C[basicAck]
B -->|失败可重试| D[basicNack + requeue=true]
B -->|失败不可重试| E[basicNack + requeue=false<br/>进入死信队列]
C --> F[消息从队列移除]
D --> G[消息重新入队]
E --> H[消息进入死信队列]
style A fill:#e1f5ff
style C fill:#e1ffe1
style D fill:#fff4e1
style E fill:#ffe1e1
3.3.2 手动 ACK 实战代码
java
#/**
* 消费者手动确认配置
*
* 关键配置:
* 1. acknowledgeMode = MANUAL(手动确认)
* 2. prefetchCount = 1(公平分发,防止消息堆积)
*/
@Configuration
public class ConsumerAckConfig {
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
// 设置手动确认模式
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 设置预取数量为1,确保公平分发
factory.setPrefetch(1);
return factory;
}
}
/**
* 消费者监听器(手动确认)
*/
@Component
public class ManualAckConsumer {
@RabbitListener(queues = "durable.queue")
public void handleMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
try {
// 1. 业务逻辑处理
processMessage(message);
// 2. 处理成功,手动确认
// multiple=false:只确认当前消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + message);
} catch (TemporaryException e) {
// 临时异常:拒绝消息并重新入队
try {
// requeue=true:消息重新入队,稍后重试
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败(临时异常),重新入队: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
} catch (PermanentException e) {
// 永久异常:拒绝消息且不重新入队(进入死信队列)
try {
// requeue=false:消息进入死信队列
channel.basicNack(deliveryTag, false, false);
System.err.println("消息处理失败(永久异常),进入死信队列: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
}
}
private void processMessage(String message) throws TemporaryException, PermanentException {
// 模拟业务逻辑
Random random = new Random();
int result = random.nextInt(100);
if (result < 5) {
throw new PermanentException("永久性异常:数据格式错误");
} else if (result < 15) {
throw new TemporaryException("临时异常:外部服务不可用");
}
// 其他情况:处理成功
}
}
/**
* 自定义异常类型
*/
class TemporaryException extends Exception {
public TemporaryException(String message) {
super(message);
}
}
class PermanentException extends Exception {
public PermanentException(String message) {
super(message);
}
}/**`
`#/**
* 消费者手动确认配置
*
* 关键配置:
* 1. acknowledgeMode = MANUAL(手动确认)
* 2. prefetchCount = 1(公平分发,防止消息堆积)
*/
@Configuration
public class ConsumerAckConfig {
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
// 设置手动确认模式
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 设置预取数量为1,确保公平分发
factory.setPrefetch(1);
return factory;
}
}
/**
* 消费者监听器(手动确认)
*/
@Component
public class ManualAckConsumer {
@RabbitListener(queues = "durable.queue")
public void handleMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
try {
// 1. 业务逻辑处理
processMessage(message);
// 2. 处理成功,手动确认
// multiple=false:只确认当前消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + message);
} catch (TemporaryException e) {
// 临时异常:拒绝消息并重新入队
try {
// requeue=true:消息重新入队,稍后重试
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败(临时异常),重新入队: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
} catch (PermanentException e) {
// 永久异常:拒绝消息且不重新入队(进入死信队列)
try {
// requeue=false:消息进入死信队列
channel.basicNack(deliveryTag, false, false);
System.err.println("消息处理失败(永久异常),进入死信队列: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
}
}
private void processMessage(String message) throws TemporaryException, PermanentException {
// 模拟业务逻辑
Random random = new Random();
int result = random.nextInt(100);
if (result < 5) {
throw new PermanentException("永久性异常:数据格式错误");
} else if (result < 15) {
throw new TemporaryException("临时异常:外部服务不可用");
}
// 其他情况:处理成功
}
}
/**
* 自定义异常类型
*/
class TemporaryException extends Exception {
public TemporaryException(String message) {
super(message);
}
}
class PermanentException extends Exception {
public PermanentException(String message) {
super(message);
}
} * 消费者手动确认配置`
`#/**
* 消费者手动确认配置
*
* 关键配置:
* 1. acknowledgeMode = MANUAL(手动确认)
* 2. prefetchCount = 1(公平分发,防止消息堆积)
*/
@Configuration
public class ConsumerAckConfig {
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
// 设置手动确认模式
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 设置预取数量为1,确保公平分发
factory.setPrefetch(1);
return factory;
}
}
/**
* 消费者监听器(手动确认)
*/
@Component
public class ManualAckConsumer {
@RabbitListener(queues = "durable.queue")
public void handleMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
try {
// 1. 业务逻辑处理
processMessage(message);
// 2. 处理成功,手动确认
// multiple=false:只确认当前消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + message);
} catch (TemporaryException e) {
// 临时异常:拒绝消息并重新入队
try {
// requeue=true:消息重新入队,稍后重试
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败(临时异常),重新入队: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
} catch (PermanentException e) {
// 永久异常:拒绝消息且不重新入队(进入死信队列)
try {
// requeue=false:消息进入死信队列
channel.basicNack(deliveryTag, false, false);
System.err.println("消息处理失败(永久异常),进入死信队列: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
}
}
private void processMessage(String message) throws TemporaryException, PermanentException {
// 模拟业务逻辑
Random random = new Random();
int result = random.nextInt(100);
if (result < 5) {
throw new PermanentException("永久性异常:数据格式错误");
} else if (result < 15) {
throw new TemporaryException("临时异常:外部服务不可用");
}
// 其他情况:处理成功
}
}
/**
* 自定义异常类型
*/
class TemporaryException extends Exception {
public TemporaryException(String message) {
super(message);
}
}
class PermanentException extends Exception {
public PermanentException(String message) {
super(message);
}
} * `
`#/**
* 消费者手动确认配置
*
* 关键配置:
* 1. acknowledgeMode = MANUAL(手动确认)
* 2. prefetchCount = 1(公平分发,防止消息堆积)
*/
@Configuration
public class ConsumerAckConfig {
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
// 设置手动确认模式
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 设置预取数量为1,确保公平分发
factory.setPrefetch(1);
return factory;
}
}
/**
* 消费者监听器(手动确认)
*/
@Component
public class ManualAckConsumer {
@RabbitListener(queues = "durable.queue")
public void handleMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
try {
// 1. 业务逻辑处理
processMessage(message);
// 2. 处理成功,手动确认
// multiple=false:只确认当前消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + message);
} catch (TemporaryException e) {
// 临时异常:拒绝消息并重新入队
try {
// requeue=true:消息重新入队,稍后重试
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败(临时异常),重新入队: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
} catch (PermanentException e) {
// 永久异常:拒绝消息且不重新入队(进入死信队列)
try {
// requeue=false:消息进入死信队列
channel.basicNack(deliveryTag, false, false);
System.err.println("消息处理失败(永久异常),进入死信队列: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
}
}
private void processMessage(String message) throws TemporaryException, PermanentException {
// 模拟业务逻辑
Random random = new Random();
int result = random.nextInt(100);
if (result < 5) {
throw new PermanentException("永久性异常:数据格式错误");
} else if (result < 15) {
throw new TemporaryException("临时异常:外部服务不可用");
}
// 其他情况:处理成功
}
}
/**
* 自定义异常类型
*/
class TemporaryException extends Exception {
public TemporaryException(String message) {
super(message);
}
}
class PermanentException extends Exception {
public PermanentException(String message) {
super(message);
}
} * 关键配置:`
`#/**
* 消费者手动确认配置
*
* 关键配置:
* 1. acknowledgeMode = MANUAL(手动确认)
* 2. prefetchCount = 1(公平分发,防止消息堆积)
*/
@Configuration
public class ConsumerAckConfig {
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
// 设置手动确认模式
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 设置预取数量为1,确保公平分发
factory.setPrefetch(1);
return factory;
}
}
/**
* 消费者监听器(手动确认)
*/
@Component
public class ManualAckConsumer {
@RabbitListener(queues = "durable.queue")
public void handleMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
try {
// 1. 业务逻辑处理
processMessage(message);
// 2. 处理成功,手动确认
// multiple=false:只确认当前消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + message);
} catch (TemporaryException e) {
// 临时异常:拒绝消息并重新入队
try {
// requeue=true:消息重新入队,稍后重试
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败(临时异常),重新入队: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
} catch (PermanentException e) {
// 永久异常:拒绝消息且不重新入队(进入死信队列)
try {
// requeue=false:消息进入死信队列
channel.basicNack(deliveryTag, false, false);
System.err.println("消息处理失败(永久异常),进入死信队列: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
}
}
private void processMessage(String message) throws TemporaryException, PermanentException {
// 模拟业务逻辑
Random random = new Random();
int result = random.nextInt(100);
if (result < 5) {
throw new PermanentException("永久性异常:数据格式错误");
} else if (result < 15) {
throw new TemporaryException("临时异常:外部服务不可用");
}
// 其他情况:处理成功
}
}
/**
* 自定义异常类型
*/
class TemporaryException extends Exception {
public TemporaryException(String message) {
super(message);
}
}
class PermanentException extends Exception {
public PermanentException(String message) {
super(message);
}
} * 1. acknowledgeMode = MANUAL(手动确认)`
`#/**
* 消费者手动确认配置
*
* 关键配置:
* 1. acknowledgeMode = MANUAL(手动确认)
* 2. prefetchCount = 1(公平分发,防止消息堆积)
*/
@Configuration
public class ConsumerAckConfig {
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
// 设置手动确认模式
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 设置预取数量为1,确保公平分发
factory.setPrefetch(1);
return factory;
}
}
/**
* 消费者监听器(手动确认)
*/
@Component
public class ManualAckConsumer {
@RabbitListener(queues = "durable.queue")
public void handleMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
try {
// 1. 业务逻辑处理
processMessage(message);
// 2. 处理成功,手动确认
// multiple=false:只确认当前消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + message);
} catch (TemporaryException e) {
// 临时异常:拒绝消息并重新入队
try {
// requeue=true:消息重新入队,稍后重试
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败(临时异常),重新入队: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
} catch (PermanentException e) {
// 永久异常:拒绝消息且不重新入队(进入死信队列)
try {
// requeue=false:消息进入死信队列
channel.basicNack(deliveryTag, false, false);
System.err.println("消息处理失败(永久异常),进入死信队列: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
}
}
private void processMessage(String message) throws TemporaryException, PermanentException {
// 模拟业务逻辑
Random random = new Random();
int result = random.nextInt(100);
if (result < 5) {
throw new PermanentException("永久性异常:数据格式错误");
} else if (result < 15) {
throw new TemporaryException("临时异常:外部服务不可用");
}
// 其他情况:处理成功
}
}
/**
* 自定义异常类型
*/
class TemporaryException extends Exception {
public TemporaryException(String message) {
super(message);
}
}
class PermanentException extends Exception {
public PermanentException(String message) {
super(message);
}
} * 2. prefetchCount = 1(公平分发,防止消息堆积)`
`#/**
* 消费者手动确认配置
*
* 关键配置:
* 1. acknowledgeMode = MANUAL(手动确认)
* 2. prefetchCount = 1(公平分发,防止消息堆积)
*/
@Configuration
public class ConsumerAckConfig {
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
// 设置手动确认模式
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 设置预取数量为1,确保公平分发
factory.setPrefetch(1);
return factory;
}
}
/**
* 消费者监听器(手动确认)
*/
@Component
public class ManualAckConsumer {
@RabbitListener(queues = "durable.queue")
public void handleMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
try {
// 1. 业务逻辑处理
processMessage(message);
// 2. 处理成功,手动确认
// multiple=false:只确认当前消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + message);
} catch (TemporaryException e) {
// 临时异常:拒绝消息并重新入队
try {
// requeue=true:消息重新入队,稍后重试
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败(临时异常),重新入队: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
} catch (PermanentException e) {
// 永久异常:拒绝消息且不重新入队(进入死信队列)
try {
// requeue=false:消息进入死信队列
channel.basicNack(deliveryTag, false, false);
System.err.println("消息处理失败(永久异常),进入死信队列: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
}
}
private void processMessage(String message) throws TemporaryException, PermanentException {
// 模拟业务逻辑
Random random = new Random();
int result = random.nextInt(100);
if (result < 5) {
throw new PermanentException("永久性异常:数据格式错误");
} else if (result < 15) {
throw new TemporaryException("临时异常:外部服务不可用");
}
// 其他情况:处理成功
}
}
/**
* 自定义异常类型
*/
class TemporaryException extends Exception {
public TemporaryException(String message) {
super(message);
}
}
class PermanentException extends Exception {
public PermanentException(String message) {
super(message);
}
} */`
`#/**
* 消费者手动确认配置
*
* 关键配置:
* 1. acknowledgeMode = MANUAL(手动确认)
* 2. prefetchCount = 1(公平分发,防止消息堆积)
*/
@Configuration
public class ConsumerAckConfig {
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
// 设置手动确认模式
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 设置预取数量为1,确保公平分发
factory.setPrefetch(1);
return factory;
}
}
/**
* 消费者监听器(手动确认)
*/
@Component
public class ManualAckConsumer {
@RabbitListener(queues = "durable.queue")
public void handleMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
try {
// 1. 业务逻辑处理
processMessage(message);
// 2. 处理成功,手动确认
// multiple=false:只确认当前消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + message);
} catch (TemporaryException e) {
// 临时异常:拒绝消息并重新入队
try {
// requeue=true:消息重新入队,稍后重试
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败(临时异常),重新入队: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
} catch (PermanentException e) {
// 永久异常:拒绝消息且不重新入队(进入死信队列)
try {
// requeue=false:消息进入死信队列
channel.basicNack(deliveryTag, false, false);
System.err.println("消息处理失败(永久异常),进入死信队列: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
}
}
private void processMessage(String message) throws TemporaryException, PermanentException {
// 模拟业务逻辑
Random random = new Random();
int result = random.nextInt(100);
if (result < 5) {
throw new PermanentException("永久性异常:数据格式错误");
} else if (result < 15) {
throw new TemporaryException("临时异常:外部服务不可用");
}
// 其他情况:处理成功
}
}
/**
* 自定义异常类型
*/
class TemporaryException extends Exception {
public TemporaryException(String message) {
super(message);
}
}
class PermanentException extends Exception {
public PermanentException(String message) {
super(message);
}
}@Configuration`
`#/**
* 消费者手动确认配置
*
* 关键配置:
* 1. acknowledgeMode = MANUAL(手动确认)
* 2. prefetchCount = 1(公平分发,防止消息堆积)
*/
@Configuration
public class ConsumerAckConfig {
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
// 设置手动确认模式
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 设置预取数量为1,确保公平分发
factory.setPrefetch(1);
return factory;
}
}
/**
* 消费者监听器(手动确认)
*/
@Component
public class ManualAckConsumer {
@RabbitListener(queues = "durable.queue")
public void handleMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
try {
// 1. 业务逻辑处理
processMessage(message);
// 2. 处理成功,手动确认
// multiple=false:只确认当前消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + message);
} catch (TemporaryException e) {
// 临时异常:拒绝消息并重新入队
try {
// requeue=true:消息重新入队,稍后重试
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败(临时异常),重新入队: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
} catch (PermanentException e) {
// 永久异常:拒绝消息且不重新入队(进入死信队列)
try {
// requeue=false:消息进入死信队列
channel.basicNack(deliveryTag, false, false);
System.err.println("消息处理失败(永久异常),进入死信队列: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
}
}
private void processMessage(String message) throws TemporaryException, PermanentException {
// 模拟业务逻辑
Random random = new Random();
int result = random.nextInt(100);
if (result < 5) {
throw new PermanentException("永久性异常:数据格式错误");
} else if (result < 15) {
throw new TemporaryException("临时异常:外部服务不可用");
}
// 其他情况:处理成功
}
}
/**
* 自定义异常类型
*/
class TemporaryException extends Exception {
public TemporaryException(String message) {
super(message);
}
}
class PermanentException extends Exception {
public PermanentException(String message) {
super(message);
}
}public class ConsumerAckConfig {`
`#/**
* 消费者手动确认配置
*
* 关键配置:
* 1. acknowledgeMode = MANUAL(手动确认)
* 2. prefetchCount = 1(公平分发,防止消息堆积)
*/
@Configuration
public class ConsumerAckConfig {
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
// 设置手动确认模式
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 设置预取数量为1,确保公平分发
factory.setPrefetch(1);
return factory;
}
}
/**
* 消费者监听器(手动确认)
*/
@Component
public class ManualAckConsumer {
@RabbitListener(queues = "durable.queue")
public void handleMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
try {
// 1. 业务逻辑处理
processMessage(message);
// 2. 处理成功,手动确认
// multiple=false:只确认当前消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + message);
} catch (TemporaryException e) {
// 临时异常:拒绝消息并重新入队
try {
// requeue=true:消息重新入队,稍后重试
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败(临时异常),重新入队: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
} catch (PermanentException e) {
// 永久异常:拒绝消息且不重新入队(进入死信队列)
try {
// requeue=false:消息进入死信队列
channel.basicNack(deliveryTag, false, false);
System.err.println("消息处理失败(永久异常),进入死信队列: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
}
}
private void processMessage(String message) throws TemporaryException, PermanentException {
// 模拟业务逻辑
Random random = new Random();
int result = random.nextInt(100);
if (result < 5) {
throw new PermanentException("永久性异常:数据格式错误");
} else if (result < 15) {
throw new TemporaryException("临时异常:外部服务不可用");
}
// 其他情况:处理成功
}
}
/**
* 自定义异常类型
*/
class TemporaryException extends Exception {
public TemporaryException(String message) {
super(message);
}
}
class PermanentException extends Exception {
public PermanentException(String message) {
super(message);
}
}`
`#/**
* 消费者手动确认配置
*
* 关键配置:
* 1. acknowledgeMode = MANUAL(手动确认)
* 2. prefetchCount = 1(公平分发,防止消息堆积)
*/
@Configuration
public class ConsumerAckConfig {
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
// 设置手动确认模式
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 设置预取数量为1,确保公平分发
factory.setPrefetch(1);
return factory;
}
}
/**
* 消费者监听器(手动确认)
*/
@Component
public class ManualAckConsumer {
@RabbitListener(queues = "durable.queue")
public void handleMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
try {
// 1. 业务逻辑处理
processMessage(message);
// 2. 处理成功,手动确认
// multiple=false:只确认当前消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + message);
} catch (TemporaryException e) {
// 临时异常:拒绝消息并重新入队
try {
// requeue=true:消息重新入队,稍后重试
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败(临时异常),重新入队: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
} catch (PermanentException e) {
// 永久异常:拒绝消息且不重新入队(进入死信队列)
try {
// requeue=false:消息进入死信队列
channel.basicNack(deliveryTag, false, false);
System.err.println("消息处理失败(永久异常),进入死信队列: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
}
}
private void processMessage(String message) throws TemporaryException, PermanentException {
// 模拟业务逻辑
Random random = new Random();
int result = random.nextInt(100);
if (result < 5) {
throw new PermanentException("永久性异常:数据格式错误");
} else if (result < 15) {
throw new TemporaryException("临时异常:外部服务不可用");
}
// 其他情况:处理成功
}
}
/**
* 自定义异常类型
*/
class TemporaryException extends Exception {
public TemporaryException(String message) {
super(message);
}
}
class PermanentException extends Exception {
public PermanentException(String message) {
super(message);
}
} @Bean`
`#/**
* 消费者手动确认配置
*
* 关键配置:
* 1. acknowledgeMode = MANUAL(手动确认)
* 2. prefetchCount = 1(公平分发,防止消息堆积)
*/
@Configuration
public class ConsumerAckConfig {
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
// 设置手动确认模式
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 设置预取数量为1,确保公平分发
factory.setPrefetch(1);
return factory;
}
}
/**
* 消费者监听器(手动确认)
*/
@Component
public class ManualAckConsumer {
@RabbitListener(queues = "durable.queue")
public void handleMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
try {
// 1. 业务逻辑处理
processMessage(message);
// 2. 处理成功,手动确认
// multiple=false:只确认当前消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + message);
} catch (TemporaryException e) {
// 临时异常:拒绝消息并重新入队
try {
// requeue=true:消息重新入队,稍后重试
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败(临时异常),重新入队: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
} catch (PermanentException e) {
// 永久异常:拒绝消息且不重新入队(进入死信队列)
try {
// requeue=false:消息进入死信队列
channel.basicNack(deliveryTag, false, false);
System.err.println("消息处理失败(永久异常),进入死信队列: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
}
}
private void processMessage(String message) throws TemporaryException, PermanentException {
// 模拟业务逻辑
Random random = new Random();
int result = random.nextInt(100);
if (result < 5) {
throw new PermanentException("永久性异常:数据格式错误");
} else if (result < 15) {
throw new TemporaryException("临时异常:外部服务不可用");
}
// 其他情况:处理成功
}
}
/**
* 自定义异常类型
*/
class TemporaryException extends Exception {
public TemporaryException(String message) {
super(message);
}
}
class PermanentException extends Exception {
public PermanentException(String message) {
super(message);
}
} public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(`
`#/**
* 消费者手动确认配置
*
* 关键配置:
* 1. acknowledgeMode = MANUAL(手动确认)
* 2. prefetchCount = 1(公平分发,防止消息堆积)
*/
@Configuration
public class ConsumerAckConfig {
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
// 设置手动确认模式
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 设置预取数量为1,确保公平分发
factory.setPrefetch(1);
return factory;
}
}
/**
* 消费者监听器(手动确认)
*/
@Component
public class ManualAckConsumer {
@RabbitListener(queues = "durable.queue")
public void handleMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
try {
// 1. 业务逻辑处理
processMessage(message);
// 2. 处理成功,手动确认
// multiple=false:只确认当前消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + message);
} catch (TemporaryException e) {
// 临时异常:拒绝消息并重新入队
try {
// requeue=true:消息重新入队,稍后重试
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败(临时异常),重新入队: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
} catch (PermanentException e) {
// 永久异常:拒绝消息且不重新入队(进入死信队列)
try {
// requeue=false:消息进入死信队列
channel.basicNack(deliveryTag, false, false);
System.err.println("消息处理失败(永久异常),进入死信队列: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
}
}
private void processMessage(String message) throws TemporaryException, PermanentException {
// 模拟业务逻辑
Random random = new Random();
int result = random.nextInt(100);
if (result < 5) {
throw new PermanentException("永久性异常:数据格式错误");
} else if (result < 15) {
throw new TemporaryException("临时异常:外部服务不可用");
}
// 其他情况:处理成功
}
}
/**
* 自定义异常类型
*/
class TemporaryException extends Exception {
public TemporaryException(String message) {
super(message);
}
}
class PermanentException extends Exception {
public PermanentException(String message) {
super(message);
}
} ConnectionFactory connectionFactory) {`
`#/**
* 消费者手动确认配置
*
* 关键配置:
* 1. acknowledgeMode = MANUAL(手动确认)
* 2. prefetchCount = 1(公平分发,防止消息堆积)
*/
@Configuration
public class ConsumerAckConfig {
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
// 设置手动确认模式
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 设置预取数量为1,确保公平分发
factory.setPrefetch(1);
return factory;
}
}
/**
* 消费者监听器(手动确认)
*/
@Component
public class ManualAckConsumer {
@RabbitListener(queues = "durable.queue")
public void handleMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
try {
// 1. 业务逻辑处理
processMessage(message);
// 2. 处理成功,手动确认
// multiple=false:只确认当前消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + message);
} catch (TemporaryException e) {
// 临时异常:拒绝消息并重新入队
try {
// requeue=true:消息重新入队,稍后重试
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败(临时异常),重新入队: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
} catch (PermanentException e) {
// 永久异常:拒绝消息且不重新入队(进入死信队列)
try {
// requeue=false:消息进入死信队列
channel.basicNack(deliveryTag, false, false);
System.err.println("消息处理失败(永久异常),进入死信队列: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
}
}
private void processMessage(String message) throws TemporaryException, PermanentException {
// 模拟业务逻辑
Random random = new Random();
int result = random.nextInt(100);
if (result < 5) {
throw new PermanentException("永久性异常:数据格式错误");
} else if (result < 15) {
throw new TemporaryException("临时异常:外部服务不可用");
}
// 其他情况:处理成功
}
}
/**
* 自定义异常类型
*/
class TemporaryException extends Exception {
public TemporaryException(String message) {
super(message);
}
}
class PermanentException extends Exception {
public PermanentException(String message) {
super(message);
}
} SimpleRabbitListenerContainerFactory factory = `
`#/**
* 消费者手动确认配置
*
* 关键配置:
* 1. acknowledgeMode = MANUAL(手动确认)
* 2. prefetchCount = 1(公平分发,防止消息堆积)
*/
@Configuration
public class ConsumerAckConfig {
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
// 设置手动确认模式
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 设置预取数量为1,确保公平分发
factory.setPrefetch(1);
return factory;
}
}
/**
* 消费者监听器(手动确认)
*/
@Component
public class ManualAckConsumer {
@RabbitListener(queues = "durable.queue")
public void handleMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
try {
// 1. 业务逻辑处理
processMessage(message);
// 2. 处理成功,手动确认
// multiple=false:只确认当前消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + message);
} catch (TemporaryException e) {
// 临时异常:拒绝消息并重新入队
try {
// requeue=true:消息重新入队,稍后重试
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败(临时异常),重新入队: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
} catch (PermanentException e) {
// 永久异常:拒绝消息且不重新入队(进入死信队列)
try {
// requeue=false:消息进入死信队列
channel.basicNack(deliveryTag, false, false);
System.err.println("消息处理失败(永久异常),进入死信队列: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
}
}
private void processMessage(String message) throws TemporaryException, PermanentException {
// 模拟业务逻辑
Random random = new Random();
int result = random.nextInt(100);
if (result < 5) {
throw new PermanentException("永久性异常:数据格式错误");
} else if (result < 15) {
throw new TemporaryException("临时异常:外部服务不可用");
}
// 其他情况:处理成功
}
}
/**
* 自定义异常类型
*/
class TemporaryException extends Exception {
public TemporaryException(String message) {
super(message);
}
}
class PermanentException extends Exception {
public PermanentException(String message) {
super(message);
}
} new SimpleRabbitListenerContainerFactory();`
`#/**
* 消费者手动确认配置
*
* 关键配置:
* 1. acknowledgeMode = MANUAL(手动确认)
* 2. prefetchCount = 1(公平分发,防止消息堆积)
*/
@Configuration
public class ConsumerAckConfig {
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
// 设置手动确认模式
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 设置预取数量为1,确保公平分发
factory.setPrefetch(1);
return factory;
}
}
/**
* 消费者监听器(手动确认)
*/
@Component
public class ManualAckConsumer {
@RabbitListener(queues = "durable.queue")
public void handleMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
try {
// 1. 业务逻辑处理
processMessage(message);
// 2. 处理成功,手动确认
// multiple=false:只确认当前消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + message);
} catch (TemporaryException e) {
// 临时异常:拒绝消息并重新入队
try {
// requeue=true:消息重新入队,稍后重试
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败(临时异常),重新入队: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
} catch (PermanentException e) {
// 永久异常:拒绝消息且不重新入队(进入死信队列)
try {
// requeue=false:消息进入死信队列
channel.basicNack(deliveryTag, false, false);
System.err.println("消息处理失败(永久异常),进入死信队列: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
}
}
private void processMessage(String message) throws TemporaryException, PermanentException {
// 模拟业务逻辑
Random random = new Random();
int result = random.nextInt(100);
if (result < 5) {
throw new PermanentException("永久性异常:数据格式错误");
} else if (result < 15) {
throw new TemporaryException("临时异常:外部服务不可用");
}
// 其他情况:处理成功
}
}
/**
* 自定义异常类型
*/
class TemporaryException extends Exception {
public TemporaryException(String message) {
super(message);
}
}
class PermanentException extends Exception {
public PermanentException(String message) {
super(message);
}
} factory.setConnectionFactory(connectionFactory);`
`#/**
* 消费者手动确认配置
*
* 关键配置:
* 1. acknowledgeMode = MANUAL(手动确认)
* 2. prefetchCount = 1(公平分发,防止消息堆积)
*/
@Configuration
public class ConsumerAckConfig {
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
// 设置手动确认模式
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 设置预取数量为1,确保公平分发
factory.setPrefetch(1);
return factory;
}
}
/**
* 消费者监听器(手动确认)
*/
@Component
public class ManualAckConsumer {
@RabbitListener(queues = "durable.queue")
public void handleMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
try {
// 1. 业务逻辑处理
processMessage(message);
// 2. 处理成功,手动确认
// multiple=false:只确认当前消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + message);
} catch (TemporaryException e) {
// 临时异常:拒绝消息并重新入队
try {
// requeue=true:消息重新入队,稍后重试
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败(临时异常),重新入队: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
} catch (PermanentException e) {
// 永久异常:拒绝消息且不重新入队(进入死信队列)
try {
// requeue=false:消息进入死信队列
channel.basicNack(deliveryTag, false, false);
System.err.println("消息处理失败(永久异常),进入死信队列: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
}
}
private void processMessage(String message) throws TemporaryException, PermanentException {
// 模拟业务逻辑
Random random = new Random();
int result = random.nextInt(100);
if (result < 5) {
throw new PermanentException("永久性异常:数据格式错误");
} else if (result < 15) {
throw new TemporaryException("临时异常:外部服务不可用");
}
// 其他情况:处理成功
}
}
/**
* 自定义异常类型
*/
class TemporaryException extends Exception {
public TemporaryException(String message) {
super(message);
}
}
class PermanentException extends Exception {
public PermanentException(String message) {
super(message);
}
} `
`#/**
* 消费者手动确认配置
*
* 关键配置:
* 1. acknowledgeMode = MANUAL(手动确认)
* 2. prefetchCount = 1(公平分发,防止消息堆积)
*/
@Configuration
public class ConsumerAckConfig {
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
// 设置手动确认模式
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 设置预取数量为1,确保公平分发
factory.setPrefetch(1);
return factory;
}
}
/**
* 消费者监听器(手动确认)
*/
@Component
public class ManualAckConsumer {
@RabbitListener(queues = "durable.queue")
public void handleMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
try {
// 1. 业务逻辑处理
processMessage(message);
// 2. 处理成功,手动确认
// multiple=false:只确认当前消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + message);
} catch (TemporaryException e) {
// 临时异常:拒绝消息并重新入队
try {
// requeue=true:消息重新入队,稍后重试
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败(临时异常),重新入队: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
} catch (PermanentException e) {
// 永久异常:拒绝消息且不重新入队(进入死信队列)
try {
// requeue=false:消息进入死信队列
channel.basicNack(deliveryTag, false, false);
System.err.println("消息处理失败(永久异常),进入死信队列: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
}
}
private void processMessage(String message) throws TemporaryException, PermanentException {
// 模拟业务逻辑
Random random = new Random();
int result = random.nextInt(100);
if (result < 5) {
throw new PermanentException("永久性异常:数据格式错误");
} else if (result < 15) {
throw new TemporaryException("临时异常:外部服务不可用");
}
// 其他情况:处理成功
}
}
/**
* 自定义异常类型
*/
class TemporaryException extends Exception {
public TemporaryException(String message) {
super(message);
}
}
class PermanentException extends Exception {
public PermanentException(String message) {
super(message);
}
} // 设置手动确认模式`
`#/**
* 消费者手动确认配置
*
* 关键配置:
* 1. acknowledgeMode = MANUAL(手动确认)
* 2. prefetchCount = 1(公平分发,防止消息堆积)
*/
@Configuration
public class ConsumerAckConfig {
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
// 设置手动确认模式
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 设置预取数量为1,确保公平分发
factory.setPrefetch(1);
return factory;
}
}
/**
* 消费者监听器(手动确认)
*/
@Component
public class ManualAckConsumer {
@RabbitListener(queues = "durable.queue")
public void handleMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
try {
// 1. 业务逻辑处理
processMessage(message);
// 2. 处理成功,手动确认
// multiple=false:只确认当前消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + message);
} catch (TemporaryException e) {
// 临时异常:拒绝消息并重新入队
try {
// requeue=true:消息重新入队,稍后重试
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败(临时异常),重新入队: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
} catch (PermanentException e) {
// 永久异常:拒绝消息且不重新入队(进入死信队列)
try {
// requeue=false:消息进入死信队列
channel.basicNack(deliveryTag, false, false);
System.err.println("消息处理失败(永久异常),进入死信队列: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
}
}
private void processMessage(String message) throws TemporaryException, PermanentException {
// 模拟业务逻辑
Random random = new Random();
int result = random.nextInt(100);
if (result < 5) {
throw new PermanentException("永久性异常:数据格式错误");
} else if (result < 15) {
throw new TemporaryException("临时异常:外部服务不可用");
}
// 其他情况:处理成功
}
}
/**
* 自定义异常类型
*/
class TemporaryException extends Exception {
public TemporaryException(String message) {
super(message);
}
}
class PermanentException extends Exception {
public PermanentException(String message) {
super(message);
}
} factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);`
`#/**
* 消费者手动确认配置
*
* 关键配置:
* 1. acknowledgeMode = MANUAL(手动确认)
* 2. prefetchCount = 1(公平分发,防止消息堆积)
*/
@Configuration
public class ConsumerAckConfig {
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
// 设置手动确认模式
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 设置预取数量为1,确保公平分发
factory.setPrefetch(1);
return factory;
}
}
/**
* 消费者监听器(手动确认)
*/
@Component
public class ManualAckConsumer {
@RabbitListener(queues = "durable.queue")
public void handleMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
try {
// 1. 业务逻辑处理
processMessage(message);
// 2. 处理成功,手动确认
// multiple=false:只确认当前消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + message);
} catch (TemporaryException e) {
// 临时异常:拒绝消息并重新入队
try {
// requeue=true:消息重新入队,稍后重试
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败(临时异常),重新入队: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
} catch (PermanentException e) {
// 永久异常:拒绝消息且不重新入队(进入死信队列)
try {
// requeue=false:消息进入死信队列
channel.basicNack(deliveryTag, false, false);
System.err.println("消息处理失败(永久异常),进入死信队列: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
}
}
private void processMessage(String message) throws TemporaryException, PermanentException {
// 模拟业务逻辑
Random random = new Random();
int result = random.nextInt(100);
if (result < 5) {
throw new PermanentException("永久性异常:数据格式错误");
} else if (result < 15) {
throw new TemporaryException("临时异常:外部服务不可用");
}
// 其他情况:处理成功
}
}
/**
* 自定义异常类型
*/
class TemporaryException extends Exception {
public TemporaryException(String message) {
super(message);
}
}
class PermanentException extends Exception {
public PermanentException(String message) {
super(message);
}
} `
`#/**
* 消费者手动确认配置
*
* 关键配置:
* 1. acknowledgeMode = MANUAL(手动确认)
* 2. prefetchCount = 1(公平分发,防止消息堆积)
*/
@Configuration
public class ConsumerAckConfig {
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
// 设置手动确认模式
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 设置预取数量为1,确保公平分发
factory.setPrefetch(1);
return factory;
}
}
/**
* 消费者监听器(手动确认)
*/
@Component
public class ManualAckConsumer {
@RabbitListener(queues = "durable.queue")
public void handleMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
try {
// 1. 业务逻辑处理
processMessage(message);
// 2. 处理成功,手动确认
// multiple=false:只确认当前消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + message);
} catch (TemporaryException e) {
// 临时异常:拒绝消息并重新入队
try {
// requeue=true:消息重新入队,稍后重试
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败(临时异常),重新入队: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
} catch (PermanentException e) {
// 永久异常:拒绝消息且不重新入队(进入死信队列)
try {
// requeue=false:消息进入死信队列
channel.basicNack(deliveryTag, false, false);
System.err.println("消息处理失败(永久异常),进入死信队列: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
}
}
private void processMessage(String message) throws TemporaryException, PermanentException {
// 模拟业务逻辑
Random random = new Random();
int result = random.nextInt(100);
if (result < 5) {
throw new PermanentException("永久性异常:数据格式错误");
} else if (result < 15) {
throw new TemporaryException("临时异常:外部服务不可用");
}
// 其他情况:处理成功
}
}
/**
* 自定义异常类型
*/
class TemporaryException extends Exception {
public TemporaryException(String message) {
super(message);
}
}
class PermanentException extends Exception {
public PermanentException(String message) {
super(message);
}
} // 设置预取数量为1,确保公平分发`
`#/**
* 消费者手动确认配置
*
* 关键配置:
* 1. acknowledgeMode = MANUAL(手动确认)
* 2. prefetchCount = 1(公平分发,防止消息堆积)
*/
@Configuration
public class ConsumerAckConfig {
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
// 设置手动确认模式
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 设置预取数量为1,确保公平分发
factory.setPrefetch(1);
return factory;
}
}
/**
* 消费者监听器(手动确认)
*/
@Component
public class ManualAckConsumer {
@RabbitListener(queues = "durable.queue")
public void handleMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
try {
// 1. 业务逻辑处理
processMessage(message);
// 2. 处理成功,手动确认
// multiple=false:只确认当前消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + message);
} catch (TemporaryException e) {
// 临时异常:拒绝消息并重新入队
try {
// requeue=true:消息重新入队,稍后重试
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败(临时异常),重新入队: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
} catch (PermanentException e) {
// 永久异常:拒绝消息且不重新入队(进入死信队列)
try {
// requeue=false:消息进入死信队列
channel.basicNack(deliveryTag, false, false);
System.err.println("消息处理失败(永久异常),进入死信队列: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
}
}
private void processMessage(String message) throws TemporaryException, PermanentException {
// 模拟业务逻辑
Random random = new Random();
int result = random.nextInt(100);
if (result < 5) {
throw new PermanentException("永久性异常:数据格式错误");
} else if (result < 15) {
throw new TemporaryException("临时异常:外部服务不可用");
}
// 其他情况:处理成功
}
}
/**
* 自定义异常类型
*/
class TemporaryException extends Exception {
public TemporaryException(String message) {
super(message);
}
}
class PermanentException extends Exception {
public PermanentException(String message) {
super(message);
}
} factory.setPrefetch(1);`
`#/**
* 消费者手动确认配置
*
* 关键配置:
* 1. acknowledgeMode = MANUAL(手动确认)
* 2. prefetchCount = 1(公平分发,防止消息堆积)
*/
@Configuration
public class ConsumerAckConfig {
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
// 设置手动确认模式
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 设置预取数量为1,确保公平分发
factory.setPrefetch(1);
return factory;
}
}
/**
* 消费者监听器(手动确认)
*/
@Component
public class ManualAckConsumer {
@RabbitListener(queues = "durable.queue")
public void handleMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
try {
// 1. 业务逻辑处理
processMessage(message);
// 2. 处理成功,手动确认
// multiple=false:只确认当前消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + message);
} catch (TemporaryException e) {
// 临时异常:拒绝消息并重新入队
try {
// requeue=true:消息重新入队,稍后重试
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败(临时异常),重新入队: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
} catch (PermanentException e) {
// 永久异常:拒绝消息且不重新入队(进入死信队列)
try {
// requeue=false:消息进入死信队列
channel.basicNack(deliveryTag, false, false);
System.err.println("消息处理失败(永久异常),进入死信队列: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
}
}
private void processMessage(String message) throws TemporaryException, PermanentException {
// 模拟业务逻辑
Random random = new Random();
int result = random.nextInt(100);
if (result < 5) {
throw new PermanentException("永久性异常:数据格式错误");
} else if (result < 15) {
throw new TemporaryException("临时异常:外部服务不可用");
}
// 其他情况:处理成功
}
}
/**
* 自定义异常类型
*/
class TemporaryException extends Exception {
public TemporaryException(String message) {
super(message);
}
}
class PermanentException extends Exception {
public PermanentException(String message) {
super(message);
}
} `
`#/**
* 消费者手动确认配置
*
* 关键配置:
* 1. acknowledgeMode = MANUAL(手动确认)
* 2. prefetchCount = 1(公平分发,防止消息堆积)
*/
@Configuration
public class ConsumerAckConfig {
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
// 设置手动确认模式
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 设置预取数量为1,确保公平分发
factory.setPrefetch(1);
return factory;
}
}
/**
* 消费者监听器(手动确认)
*/
@Component
public class ManualAckConsumer {
@RabbitListener(queues = "durable.queue")
public void handleMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
try {
// 1. 业务逻辑处理
processMessage(message);
// 2. 处理成功,手动确认
// multiple=false:只确认当前消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + message);
} catch (TemporaryException e) {
// 临时异常:拒绝消息并重新入队
try {
// requeue=true:消息重新入队,稍后重试
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败(临时异常),重新入队: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
} catch (PermanentException e) {
// 永久异常:拒绝消息且不重新入队(进入死信队列)
try {
// requeue=false:消息进入死信队列
channel.basicNack(deliveryTag, false, false);
System.err.println("消息处理失败(永久异常),进入死信队列: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
}
}
private void processMessage(String message) throws TemporaryException, PermanentException {
// 模拟业务逻辑
Random random = new Random();
int result = random.nextInt(100);
if (result < 5) {
throw new PermanentException("永久性异常:数据格式错误");
} else if (result < 15) {
throw new TemporaryException("临时异常:外部服务不可用");
}
// 其他情况:处理成功
}
}
/**
* 自定义异常类型
*/
class TemporaryException extends Exception {
public TemporaryException(String message) {
super(message);
}
}
class PermanentException extends Exception {
public PermanentException(String message) {
super(message);
}
} return factory;`
`#/**
* 消费者手动确认配置
*
* 关键配置:
* 1. acknowledgeMode = MANUAL(手动确认)
* 2. prefetchCount = 1(公平分发,防止消息堆积)
*/
@Configuration
public class ConsumerAckConfig {
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
// 设置手动确认模式
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 设置预取数量为1,确保公平分发
factory.setPrefetch(1);
return factory;
}
}
/**
* 消费者监听器(手动确认)
*/
@Component
public class ManualAckConsumer {
@RabbitListener(queues = "durable.queue")
public void handleMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
try {
// 1. 业务逻辑处理
processMessage(message);
// 2. 处理成功,手动确认
// multiple=false:只确认当前消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + message);
} catch (TemporaryException e) {
// 临时异常:拒绝消息并重新入队
try {
// requeue=true:消息重新入队,稍后重试
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败(临时异常),重新入队: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
} catch (PermanentException e) {
// 永久异常:拒绝消息且不重新入队(进入死信队列)
try {
// requeue=false:消息进入死信队列
channel.basicNack(deliveryTag, false, false);
System.err.println("消息处理失败(永久异常),进入死信队列: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
}
}
private void processMessage(String message) throws TemporaryException, PermanentException {
// 模拟业务逻辑
Random random = new Random();
int result = random.nextInt(100);
if (result < 5) {
throw new PermanentException("永久性异常:数据格式错误");
} else if (result < 15) {
throw new TemporaryException("临时异常:外部服务不可用");
}
// 其他情况:处理成功
}
}
/**
* 自定义异常类型
*/
class TemporaryException extends Exception {
public TemporaryException(String message) {
super(message);
}
}
class PermanentException extends Exception {
public PermanentException(String message) {
super(message);
}
} }`
`#/**
* 消费者手动确认配置
*
* 关键配置:
* 1. acknowledgeMode = MANUAL(手动确认)
* 2. prefetchCount = 1(公平分发,防止消息堆积)
*/
@Configuration
public class ConsumerAckConfig {
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
// 设置手动确认模式
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 设置预取数量为1,确保公平分发
factory.setPrefetch(1);
return factory;
}
}
/**
* 消费者监听器(手动确认)
*/
@Component
public class ManualAckConsumer {
@RabbitListener(queues = "durable.queue")
public void handleMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
try {
// 1. 业务逻辑处理
processMessage(message);
// 2. 处理成功,手动确认
// multiple=false:只确认当前消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + message);
} catch (TemporaryException e) {
// 临时异常:拒绝消息并重新入队
try {
// requeue=true:消息重新入队,稍后重试
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败(临时异常),重新入队: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
} catch (PermanentException e) {
// 永久异常:拒绝消息且不重新入队(进入死信队列)
try {
// requeue=false:消息进入死信队列
channel.basicNack(deliveryTag, false, false);
System.err.println("消息处理失败(永久异常),进入死信队列: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
}
}
private void processMessage(String message) throws TemporaryException, PermanentException {
// 模拟业务逻辑
Random random = new Random();
int result = random.nextInt(100);
if (result < 5) {
throw new PermanentException("永久性异常:数据格式错误");
} else if (result < 15) {
throw new TemporaryException("临时异常:外部服务不可用");
}
// 其他情况:处理成功
}
}
/**
* 自定义异常类型
*/
class TemporaryException extends Exception {
public TemporaryException(String message) {
super(message);
}
}
class PermanentException extends Exception {
public PermanentException(String message) {
super(message);
}
}}`
`#/**
* 消费者手动确认配置
*
* 关键配置:
* 1. acknowledgeMode = MANUAL(手动确认)
* 2. prefetchCount = 1(公平分发,防止消息堆积)
*/
@Configuration
public class ConsumerAckConfig {
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
// 设置手动确认模式
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 设置预取数量为1,确保公平分发
factory.setPrefetch(1);
return factory;
}
}
/**
* 消费者监听器(手动确认)
*/
@Component
public class ManualAckConsumer {
@RabbitListener(queues = "durable.queue")
public void handleMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
try {
// 1. 业务逻辑处理
processMessage(message);
// 2. 处理成功,手动确认
// multiple=false:只确认当前消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + message);
} catch (TemporaryException e) {
// 临时异常:拒绝消息并重新入队
try {
// requeue=true:消息重新入队,稍后重试
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败(临时异常),重新入队: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
} catch (PermanentException e) {
// 永久异常:拒绝消息且不重新入队(进入死信队列)
try {
// requeue=false:消息进入死信队列
channel.basicNack(deliveryTag, false, false);
System.err.println("消息处理失败(永久异常),进入死信队列: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
}
}
private void processMessage(String message) throws TemporaryException, PermanentException {
// 模拟业务逻辑
Random random = new Random();
int result = random.nextInt(100);
if (result < 5) {
throw new PermanentException("永久性异常:数据格式错误");
} else if (result < 15) {
throw new TemporaryException("临时异常:外部服务不可用");
}
// 其他情况:处理成功
}
}
/**
* 自定义异常类型
*/
class TemporaryException extends Exception {
public TemporaryException(String message) {
super(message);
}
}
class PermanentException extends Exception {
public PermanentException(String message) {
super(message);
}
}`
`#/**
* 消费者手动确认配置
*
* 关键配置:
* 1. acknowledgeMode = MANUAL(手动确认)
* 2. prefetchCount = 1(公平分发,防止消息堆积)
*/
@Configuration
public class ConsumerAckConfig {
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
// 设置手动确认模式
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 设置预取数量为1,确保公平分发
factory.setPrefetch(1);
return factory;
}
}
/**
* 消费者监听器(手动确认)
*/
@Component
public class ManualAckConsumer {
@RabbitListener(queues = "durable.queue")
public void handleMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
try {
// 1. 业务逻辑处理
processMessage(message);
// 2. 处理成功,手动确认
// multiple=false:只确认当前消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + message);
} catch (TemporaryException e) {
// 临时异常:拒绝消息并重新入队
try {
// requeue=true:消息重新入队,稍后重试
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败(临时异常),重新入队: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
} catch (PermanentException e) {
// 永久异常:拒绝消息且不重新入队(进入死信队列)
try {
// requeue=false:消息进入死信队列
channel.basicNack(deliveryTag, false, false);
System.err.println("消息处理失败(永久异常),进入死信队列: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
}
}
private void processMessage(String message) throws TemporaryException, PermanentException {
// 模拟业务逻辑
Random random = new Random();
int result = random.nextInt(100);
if (result < 5) {
throw new PermanentException("永久性异常:数据格式错误");
} else if (result < 15) {
throw new TemporaryException("临时异常:外部服务不可用");
}
// 其他情况:处理成功
}
}
/**
* 自定义异常类型
*/
class TemporaryException extends Exception {
public TemporaryException(String message) {
super(message);
}
}
class PermanentException extends Exception {
public PermanentException(String message) {
super(message);
}
}/**`
`#/**
* 消费者手动确认配置
*
* 关键配置:
* 1. acknowledgeMode = MANUAL(手动确认)
* 2. prefetchCount = 1(公平分发,防止消息堆积)
*/
@Configuration
public class ConsumerAckConfig {
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
// 设置手动确认模式
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 设置预取数量为1,确保公平分发
factory.setPrefetch(1);
return factory;
}
}
/**
* 消费者监听器(手动确认)
*/
@Component
public class ManualAckConsumer {
@RabbitListener(queues = "durable.queue")
public void handleMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
try {
// 1. 业务逻辑处理
processMessage(message);
// 2. 处理成功,手动确认
// multiple=false:只确认当前消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + message);
} catch (TemporaryException e) {
// 临时异常:拒绝消息并重新入队
try {
// requeue=true:消息重新入队,稍后重试
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败(临时异常),重新入队: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
} catch (PermanentException e) {
// 永久异常:拒绝消息且不重新入队(进入死信队列)
try {
// requeue=false:消息进入死信队列
channel.basicNack(deliveryTag, false, false);
System.err.println("消息处理失败(永久异常),进入死信队列: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
}
}
private void processMessage(String message) throws TemporaryException, PermanentException {
// 模拟业务逻辑
Random random = new Random();
int result = random.nextInt(100);
if (result < 5) {
throw new PermanentException("永久性异常:数据格式错误");
} else if (result < 15) {
throw new TemporaryException("临时异常:外部服务不可用");
}
// 其他情况:处理成功
}
}
/**
* 自定义异常类型
*/
class TemporaryException extends Exception {
public TemporaryException(String message) {
super(message);
}
}
class PermanentException extends Exception {
public PermanentException(String message) {
super(message);
}
} * 消费者监听器(手动确认)`
`#/**
* 消费者手动确认配置
*
* 关键配置:
* 1. acknowledgeMode = MANUAL(手动确认)
* 2. prefetchCount = 1(公平分发,防止消息堆积)
*/
@Configuration
public class ConsumerAckConfig {
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
// 设置手动确认模式
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 设置预取数量为1,确保公平分发
factory.setPrefetch(1);
return factory;
}
}
/**
* 消费者监听器(手动确认)
*/
@Component
public class ManualAckConsumer {
@RabbitListener(queues = "durable.queue")
public void handleMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
try {
// 1. 业务逻辑处理
processMessage(message);
// 2. 处理成功,手动确认
// multiple=false:只确认当前消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + message);
} catch (TemporaryException e) {
// 临时异常:拒绝消息并重新入队
try {
// requeue=true:消息重新入队,稍后重试
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败(临时异常),重新入队: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
} catch (PermanentException e) {
// 永久异常:拒绝消息且不重新入队(进入死信队列)
try {
// requeue=false:消息进入死信队列
channel.basicNack(deliveryTag, false, false);
System.err.println("消息处理失败(永久异常),进入死信队列: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
}
}
private void processMessage(String message) throws TemporaryException, PermanentException {
// 模拟业务逻辑
Random random = new Random();
int result = random.nextInt(100);
if (result < 5) {
throw new PermanentException("永久性异常:数据格式错误");
} else if (result < 15) {
throw new TemporaryException("临时异常:外部服务不可用");
}
// 其他情况:处理成功
}
}
/**
* 自定义异常类型
*/
class TemporaryException extends Exception {
public TemporaryException(String message) {
super(message);
}
}
class PermanentException extends Exception {
public PermanentException(String message) {
super(message);
}
} */`
`#/**
* 消费者手动确认配置
*
* 关键配置:
* 1. acknowledgeMode = MANUAL(手动确认)
* 2. prefetchCount = 1(公平分发,防止消息堆积)
*/
@Configuration
public class ConsumerAckConfig {
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
// 设置手动确认模式
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 设置预取数量为1,确保公平分发
factory.setPrefetch(1);
return factory;
}
}
/**
* 消费者监听器(手动确认)
*/
@Component
public class ManualAckConsumer {
@RabbitListener(queues = "durable.queue")
public void handleMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
try {
// 1. 业务逻辑处理
processMessage(message);
// 2. 处理成功,手动确认
// multiple=false:只确认当前消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + message);
} catch (TemporaryException e) {
// 临时异常:拒绝消息并重新入队
try {
// requeue=true:消息重新入队,稍后重试
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败(临时异常),重新入队: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
} catch (PermanentException e) {
// 永久异常:拒绝消息且不重新入队(进入死信队列)
try {
// requeue=false:消息进入死信队列
channel.basicNack(deliveryTag, false, false);
System.err.println("消息处理失败(永久异常),进入死信队列: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
}
}
private void processMessage(String message) throws TemporaryException, PermanentException {
// 模拟业务逻辑
Random random = new Random();
int result = random.nextInt(100);
if (result < 5) {
throw new PermanentException("永久性异常:数据格式错误");
} else if (result < 15) {
throw new TemporaryException("临时异常:外部服务不可用");
}
// 其他情况:处理成功
}
}
/**
* 自定义异常类型
*/
class TemporaryException extends Exception {
public TemporaryException(String message) {
super(message);
}
}
class PermanentException extends Exception {
public PermanentException(String message) {
super(message);
}
}@Component`
`#/**
* 消费者手动确认配置
*
* 关键配置:
* 1. acknowledgeMode = MANUAL(手动确认)
* 2. prefetchCount = 1(公平分发,防止消息堆积)
*/
@Configuration
public class ConsumerAckConfig {
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
// 设置手动确认模式
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 设置预取数量为1,确保公平分发
factory.setPrefetch(1);
return factory;
}
}
/**
* 消费者监听器(手动确认)
*/
@Component
public class ManualAckConsumer {
@RabbitListener(queues = "durable.queue")
public void handleMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
try {
// 1. 业务逻辑处理
processMessage(message);
// 2. 处理成功,手动确认
// multiple=false:只确认当前消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + message);
} catch (TemporaryException e) {
// 临时异常:拒绝消息并重新入队
try {
// requeue=true:消息重新入队,稍后重试
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败(临时异常),重新入队: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
} catch (PermanentException e) {
// 永久异常:拒绝消息且不重新入队(进入死信队列)
try {
// requeue=false:消息进入死信队列
channel.basicNack(deliveryTag, false, false);
System.err.println("消息处理失败(永久异常),进入死信队列: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
}
}
private void processMessage(String message) throws TemporaryException, PermanentException {
// 模拟业务逻辑
Random random = new Random();
int result = random.nextInt(100);
if (result < 5) {
throw new PermanentException("永久性异常:数据格式错误");
} else if (result < 15) {
throw new TemporaryException("临时异常:外部服务不可用");
}
// 其他情况:处理成功
}
}
/**
* 自定义异常类型
*/
class TemporaryException extends Exception {
public TemporaryException(String message) {
super(message);
}
}
class PermanentException extends Exception {
public PermanentException(String message) {
super(message);
}
}public class ManualAckConsumer {`
`#/**
* 消费者手动确认配置
*
* 关键配置:
* 1. acknowledgeMode = MANUAL(手动确认)
* 2. prefetchCount = 1(公平分发,防止消息堆积)
*/
@Configuration
public class ConsumerAckConfig {
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
// 设置手动确认模式
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 设置预取数量为1,确保公平分发
factory.setPrefetch(1);
return factory;
}
}
/**
* 消费者监听器(手动确认)
*/
@Component
public class ManualAckConsumer {
@RabbitListener(queues = "durable.queue")
public void handleMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
try {
// 1. 业务逻辑处理
processMessage(message);
// 2. 处理成功,手动确认
// multiple=false:只确认当前消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + message);
} catch (TemporaryException e) {
// 临时异常:拒绝消息并重新入队
try {
// requeue=true:消息重新入队,稍后重试
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败(临时异常),重新入队: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
} catch (PermanentException e) {
// 永久异常:拒绝消息且不重新入队(进入死信队列)
try {
// requeue=false:消息进入死信队列
channel.basicNack(deliveryTag, false, false);
System.err.println("消息处理失败(永久异常),进入死信队列: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
}
}
private void processMessage(String message) throws TemporaryException, PermanentException {
// 模拟业务逻辑
Random random = new Random();
int result = random.nextInt(100);
if (result < 5) {
throw new PermanentException("永久性异常:数据格式错误");
} else if (result < 15) {
throw new TemporaryException("临时异常:外部服务不可用");
}
// 其他情况:处理成功
}
}
/**
* 自定义异常类型
*/
class TemporaryException extends Exception {
public TemporaryException(String message) {
super(message);
}
}
class PermanentException extends Exception {
public PermanentException(String message) {
super(message);
}
}`
`#/**
* 消费者手动确认配置
*
* 关键配置:
* 1. acknowledgeMode = MANUAL(手动确认)
* 2. prefetchCount = 1(公平分发,防止消息堆积)
*/
@Configuration
public class ConsumerAckConfig {
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
// 设置手动确认模式
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 设置预取数量为1,确保公平分发
factory.setPrefetch(1);
return factory;
}
}
/**
* 消费者监听器(手动确认)
*/
@Component
public class ManualAckConsumer {
@RabbitListener(queues = "durable.queue")
public void handleMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
try {
// 1. 业务逻辑处理
processMessage(message);
// 2. 处理成功,手动确认
// multiple=false:只确认当前消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + message);
} catch (TemporaryException e) {
// 临时异常:拒绝消息并重新入队
try {
// requeue=true:消息重新入队,稍后重试
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败(临时异常),重新入队: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
} catch (PermanentException e) {
// 永久异常:拒绝消息且不重新入队(进入死信队列)
try {
// requeue=false:消息进入死信队列
channel.basicNack(deliveryTag, false, false);
System.err.println("消息处理失败(永久异常),进入死信队列: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
}
}
private void processMessage(String message) throws TemporaryException, PermanentException {
// 模拟业务逻辑
Random random = new Random();
int result = random.nextInt(100);
if (result < 5) {
throw new PermanentException("永久性异常:数据格式错误");
} else if (result < 15) {
throw new TemporaryException("临时异常:外部服务不可用");
}
// 其他情况:处理成功
}
}
/**
* 自定义异常类型
*/
class TemporaryException extends Exception {
public TemporaryException(String message) {
super(message);
}
}
class PermanentException extends Exception {
public PermanentException(String message) {
super(message);
}
} @RabbitListener(queues = "durable.queue")`
`#/**
* 消费者手动确认配置
*
* 关键配置:
* 1. acknowledgeMode = MANUAL(手动确认)
* 2. prefetchCount = 1(公平分发,防止消息堆积)
*/
@Configuration
public class ConsumerAckConfig {
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
// 设置手动确认模式
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 设置预取数量为1,确保公平分发
factory.setPrefetch(1);
return factory;
}
}
/**
* 消费者监听器(手动确认)
*/
@Component
public class ManualAckConsumer {
@RabbitListener(queues = "durable.queue")
public void handleMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
try {
// 1. 业务逻辑处理
processMessage(message);
// 2. 处理成功,手动确认
// multiple=false:只确认当前消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + message);
} catch (TemporaryException e) {
// 临时异常:拒绝消息并重新入队
try {
// requeue=true:消息重新入队,稍后重试
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败(临时异常),重新入队: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
} catch (PermanentException e) {
// 永久异常:拒绝消息且不重新入队(进入死信队列)
try {
// requeue=false:消息进入死信队列
channel.basicNack(deliveryTag, false, false);
System.err.println("消息处理失败(永久异常),进入死信队列: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
}
}
private void processMessage(String message) throws TemporaryException, PermanentException {
// 模拟业务逻辑
Random random = new Random();
int result = random.nextInt(100);
if (result < 5) {
throw new PermanentException("永久性异常:数据格式错误");
} else if (result < 15) {
throw new TemporaryException("临时异常:外部服务不可用");
}
// 其他情况:处理成功
}
}
/**
* 自定义异常类型
*/
class TemporaryException extends Exception {
public TemporaryException(String message) {
super(message);
}
}
class PermanentException extends Exception {
public PermanentException(String message) {
super(message);
}
} public void handleMessage(`
`#/**
* 消费者手动确认配置
*
* 关键配置:
* 1. acknowledgeMode = MANUAL(手动确认)
* 2. prefetchCount = 1(公平分发,防止消息堆积)
*/
@Configuration
public class ConsumerAckConfig {
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
// 设置手动确认模式
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 设置预取数量为1,确保公平分发
factory.setPrefetch(1);
return factory;
}
}
/**
* 消费者监听器(手动确认)
*/
@Component
public class ManualAckConsumer {
@RabbitListener(queues = "durable.queue")
public void handleMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
try {
// 1. 业务逻辑处理
processMessage(message);
// 2. 处理成功,手动确认
// multiple=false:只确认当前消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + message);
} catch (TemporaryException e) {
// 临时异常:拒绝消息并重新入队
try {
// requeue=true:消息重新入队,稍后重试
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败(临时异常),重新入队: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
} catch (PermanentException e) {
// 永久异常:拒绝消息且不重新入队(进入死信队列)
try {
// requeue=false:消息进入死信队列
channel.basicNack(deliveryTag, false, false);
System.err.println("消息处理失败(永久异常),进入死信队列: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
}
}
private void processMessage(String message) throws TemporaryException, PermanentException {
// 模拟业务逻辑
Random random = new Random();
int result = random.nextInt(100);
if (result < 5) {
throw new PermanentException("永久性异常:数据格式错误");
} else if (result < 15) {
throw new TemporaryException("临时异常:外部服务不可用");
}
// 其他情况:处理成功
}
}
/**
* 自定义异常类型
*/
class TemporaryException extends Exception {
public TemporaryException(String message) {
super(message);
}
}
class PermanentException extends Exception {
public PermanentException(String message) {
super(message);
}
} String message,`
`#/**
* 消费者手动确认配置
*
* 关键配置:
* 1. acknowledgeMode = MANUAL(手动确认)
* 2. prefetchCount = 1(公平分发,防止消息堆积)
*/
@Configuration
public class ConsumerAckConfig {
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
// 设置手动确认模式
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 设置预取数量为1,确保公平分发
factory.setPrefetch(1);
return factory;
}
}
/**
* 消费者监听器(手动确认)
*/
@Component
public class ManualAckConsumer {
@RabbitListener(queues = "durable.queue")
public void handleMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
try {
// 1. 业务逻辑处理
processMessage(message);
// 2. 处理成功,手动确认
// multiple=false:只确认当前消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + message);
} catch (TemporaryException e) {
// 临时异常:拒绝消息并重新入队
try {
// requeue=true:消息重新入队,稍后重试
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败(临时异常),重新入队: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
} catch (PermanentException e) {
// 永久异常:拒绝消息且不重新入队(进入死信队列)
try {
// requeue=false:消息进入死信队列
channel.basicNack(deliveryTag, false, false);
System.err.println("消息处理失败(永久异常),进入死信队列: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
}
}
private void processMessage(String message) throws TemporaryException, PermanentException {
// 模拟业务逻辑
Random random = new Random();
int result = random.nextInt(100);
if (result < 5) {
throw new PermanentException("永久性异常:数据格式错误");
} else if (result < 15) {
throw new TemporaryException("临时异常:外部服务不可用");
}
// 其他情况:处理成功
}
}
/**
* 自定义异常类型
*/
class TemporaryException extends Exception {
public TemporaryException(String message) {
super(message);
}
}
class PermanentException extends Exception {
public PermanentException(String message) {
super(message);
}
} Channel channel,`
`#/**
* 消费者手动确认配置
*
* 关键配置:
* 1. acknowledgeMode = MANUAL(手动确认)
* 2. prefetchCount = 1(公平分发,防止消息堆积)
*/
@Configuration
public class ConsumerAckConfig {
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
// 设置手动确认模式
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 设置预取数量为1,确保公平分发
factory.setPrefetch(1);
return factory;
}
}
/**
* 消费者监听器(手动确认)
*/
@Component
public class ManualAckConsumer {
@RabbitListener(queues = "durable.queue")
public void handleMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
try {
// 1. 业务逻辑处理
processMessage(message);
// 2. 处理成功,手动确认
// multiple=false:只确认当前消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + message);
} catch (TemporaryException e) {
// 临时异常:拒绝消息并重新入队
try {
// requeue=true:消息重新入队,稍后重试
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败(临时异常),重新入队: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
} catch (PermanentException e) {
// 永久异常:拒绝消息且不重新入队(进入死信队列)
try {
// requeue=false:消息进入死信队列
channel.basicNack(deliveryTag, false, false);
System.err.println("消息处理失败(永久异常),进入死信队列: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
}
}
private void processMessage(String message) throws TemporaryException, PermanentException {
// 模拟业务逻辑
Random random = new Random();
int result = random.nextInt(100);
if (result < 5) {
throw new PermanentException("永久性异常:数据格式错误");
} else if (result < 15) {
throw new TemporaryException("临时异常:外部服务不可用");
}
// 其他情况:处理成功
}
}
/**
* 自定义异常类型
*/
class TemporaryException extends Exception {
public TemporaryException(String message) {
super(message);
}
}
class PermanentException extends Exception {
public PermanentException(String message) {
super(message);
}
} @Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {`
`#/**
* 消费者手动确认配置
*
* 关键配置:
* 1. acknowledgeMode = MANUAL(手动确认)
* 2. prefetchCount = 1(公平分发,防止消息堆积)
*/
@Configuration
public class ConsumerAckConfig {
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
// 设置手动确认模式
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 设置预取数量为1,确保公平分发
factory.setPrefetch(1);
return factory;
}
}
/**
* 消费者监听器(手动确认)
*/
@Component
public class ManualAckConsumer {
@RabbitListener(queues = "durable.queue")
public void handleMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
try {
// 1. 业务逻辑处理
processMessage(message);
// 2. 处理成功,手动确认
// multiple=false:只确认当前消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + message);
} catch (TemporaryException e) {
// 临时异常:拒绝消息并重新入队
try {
// requeue=true:消息重新入队,稍后重试
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败(临时异常),重新入队: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
} catch (PermanentException e) {
// 永久异常:拒绝消息且不重新入队(进入死信队列)
try {
// requeue=false:消息进入死信队列
channel.basicNack(deliveryTag, false, false);
System.err.println("消息处理失败(永久异常),进入死信队列: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
}
}
private void processMessage(String message) throws TemporaryException, PermanentException {
// 模拟业务逻辑
Random random = new Random();
int result = random.nextInt(100);
if (result < 5) {
throw new PermanentException("永久性异常:数据格式错误");
} else if (result < 15) {
throw new TemporaryException("临时异常:外部服务不可用");
}
// 其他情况:处理成功
}
}
/**
* 自定义异常类型
*/
class TemporaryException extends Exception {
public TemporaryException(String message) {
super(message);
}
}
class PermanentException extends Exception {
public PermanentException(String message) {
super(message);
}
} `
`#/**
* 消费者手动确认配置
*
* 关键配置:
* 1. acknowledgeMode = MANUAL(手动确认)
* 2. prefetchCount = 1(公平分发,防止消息堆积)
*/
@Configuration
public class ConsumerAckConfig {
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
// 设置手动确认模式
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 设置预取数量为1,确保公平分发
factory.setPrefetch(1);
return factory;
}
}
/**
* 消费者监听器(手动确认)
*/
@Component
public class ManualAckConsumer {
@RabbitListener(queues = "durable.queue")
public void handleMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
try {
// 1. 业务逻辑处理
processMessage(message);
// 2. 处理成功,手动确认
// multiple=false:只确认当前消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + message);
} catch (TemporaryException e) {
// 临时异常:拒绝消息并重新入队
try {
// requeue=true:消息重新入队,稍后重试
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败(临时异常),重新入队: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
} catch (PermanentException e) {
// 永久异常:拒绝消息且不重新入队(进入死信队列)
try {
// requeue=false:消息进入死信队列
channel.basicNack(deliveryTag, false, false);
System.err.println("消息处理失败(永久异常),进入死信队列: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
}
}
private void processMessage(String message) throws TemporaryException, PermanentException {
// 模拟业务逻辑
Random random = new Random();
int result = random.nextInt(100);
if (result < 5) {
throw new PermanentException("永久性异常:数据格式错误");
} else if (result < 15) {
throw new TemporaryException("临时异常:外部服务不可用");
}
// 其他情况:处理成功
}
}
/**
* 自定义异常类型
*/
class TemporaryException extends Exception {
public TemporaryException(String message) {
super(message);
}
}
class PermanentException extends Exception {
public PermanentException(String message) {
super(message);
}
} try {`
`#/**
* 消费者手动确认配置
*
* 关键配置:
* 1. acknowledgeMode = MANUAL(手动确认)
* 2. prefetchCount = 1(公平分发,防止消息堆积)
*/
@Configuration
public class ConsumerAckConfig {
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
// 设置手动确认模式
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 设置预取数量为1,确保公平分发
factory.setPrefetch(1);
return factory;
}
}
/**
* 消费者监听器(手动确认)
*/
@Component
public class ManualAckConsumer {
@RabbitListener(queues = "durable.queue")
public void handleMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
try {
// 1. 业务逻辑处理
processMessage(message);
// 2. 处理成功,手动确认
// multiple=false:只确认当前消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + message);
} catch (TemporaryException e) {
// 临时异常:拒绝消息并重新入队
try {
// requeue=true:消息重新入队,稍后重试
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败(临时异常),重新入队: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
} catch (PermanentException e) {
// 永久异常:拒绝消息且不重新入队(进入死信队列)
try {
// requeue=false:消息进入死信队列
channel.basicNack(deliveryTag, false, false);
System.err.println("消息处理失败(永久异常),进入死信队列: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
}
}
private void processMessage(String message) throws TemporaryException, PermanentException {
// 模拟业务逻辑
Random random = new Random();
int result = random.nextInt(100);
if (result < 5) {
throw new PermanentException("永久性异常:数据格式错误");
} else if (result < 15) {
throw new TemporaryException("临时异常:外部服务不可用");
}
// 其他情况:处理成功
}
}
/**
* 自定义异常类型
*/
class TemporaryException extends Exception {
public TemporaryException(String message) {
super(message);
}
}
class PermanentException extends Exception {
public PermanentException(String message) {
super(message);
}
} // 1. 业务逻辑处理`
`#/**
* 消费者手动确认配置
*
* 关键配置:
* 1. acknowledgeMode = MANUAL(手动确认)
* 2. prefetchCount = 1(公平分发,防止消息堆积)
*/
@Configuration
public class ConsumerAckConfig {
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
// 设置手动确认模式
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 设置预取数量为1,确保公平分发
factory.setPrefetch(1);
return factory;
}
}
/**
* 消费者监听器(手动确认)
*/
@Component
public class ManualAckConsumer {
@RabbitListener(queues = "durable.queue")
public void handleMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
try {
// 1. 业务逻辑处理
processMessage(message);
// 2. 处理成功,手动确认
// multiple=false:只确认当前消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + message);
} catch (TemporaryException e) {
// 临时异常:拒绝消息并重新入队
try {
// requeue=true:消息重新入队,稍后重试
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败(临时异常),重新入队: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
} catch (PermanentException e) {
// 永久异常:拒绝消息且不重新入队(进入死信队列)
try {
// requeue=false:消息进入死信队列
channel.basicNack(deliveryTag, false, false);
System.err.println("消息处理失败(永久异常),进入死信队列: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
}
}
private void processMessage(String message) throws TemporaryException, PermanentException {
// 模拟业务逻辑
Random random = new Random();
int result = random.nextInt(100);
if (result < 5) {
throw new PermanentException("永久性异常:数据格式错误");
} else if (result < 15) {
throw new TemporaryException("临时异常:外部服务不可用");
}
// 其他情况:处理成功
}
}
/**
* 自定义异常类型
*/
class TemporaryException extends Exception {
public TemporaryException(String message) {
super(message);
}
}
class PermanentException extends Exception {
public PermanentException(String message) {
super(message);
}
} processMessage(message);`
`#/**
* 消费者手动确认配置
*
* 关键配置:
* 1. acknowledgeMode = MANUAL(手动确认)
* 2. prefetchCount = 1(公平分发,防止消息堆积)
*/
@Configuration
public class ConsumerAckConfig {
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
// 设置手动确认模式
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 设置预取数量为1,确保公平分发
factory.setPrefetch(1);
return factory;
}
}
/**
* 消费者监听器(手动确认)
*/
@Component
public class ManualAckConsumer {
@RabbitListener(queues = "durable.queue")
public void handleMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
try {
// 1. 业务逻辑处理
processMessage(message);
// 2. 处理成功,手动确认
// multiple=false:只确认当前消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + message);
} catch (TemporaryException e) {
// 临时异常:拒绝消息并重新入队
try {
// requeue=true:消息重新入队,稍后重试
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败(临时异常),重新入队: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
} catch (PermanentException e) {
// 永久异常:拒绝消息且不重新入队(进入死信队列)
try {
// requeue=false:消息进入死信队列
channel.basicNack(deliveryTag, false, false);
System.err.println("消息处理失败(永久异常),进入死信队列: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
}
}
private void processMessage(String message) throws TemporaryException, PermanentException {
// 模拟业务逻辑
Random random = new Random();
int result = random.nextInt(100);
if (result < 5) {
throw new PermanentException("永久性异常:数据格式错误");
} else if (result < 15) {
throw new TemporaryException("临时异常:外部服务不可用");
}
// 其他情况:处理成功
}
}
/**
* 自定义异常类型
*/
class TemporaryException extends Exception {
public TemporaryException(String message) {
super(message);
}
}
class PermanentException extends Exception {
public PermanentException(String message) {
super(message);
}
} `
`#/**
* 消费者手动确认配置
*
* 关键配置:
* 1. acknowledgeMode = MANUAL(手动确认)
* 2. prefetchCount = 1(公平分发,防止消息堆积)
*/
@Configuration
public class ConsumerAckConfig {
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
// 设置手动确认模式
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 设置预取数量为1,确保公平分发
factory.setPrefetch(1);
return factory;
}
}
/**
* 消费者监听器(手动确认)
*/
@Component
public class ManualAckConsumer {
@RabbitListener(queues = "durable.queue")
public void handleMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
try {
// 1. 业务逻辑处理
processMessage(message);
// 2. 处理成功,手动确认
// multiple=false:只确认当前消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + message);
} catch (TemporaryException e) {
// 临时异常:拒绝消息并重新入队
try {
// requeue=true:消息重新入队,稍后重试
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败(临时异常),重新入队: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
} catch (PermanentException e) {
// 永久异常:拒绝消息且不重新入队(进入死信队列)
try {
// requeue=false:消息进入死信队列
channel.basicNack(deliveryTag, false, false);
System.err.println("消息处理失败(永久异常),进入死信队列: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
}
}
private void processMessage(String message) throws TemporaryException, PermanentException {
// 模拟业务逻辑
Random random = new Random();
int result = random.nextInt(100);
if (result < 5) {
throw new PermanentException("永久性异常:数据格式错误");
} else if (result < 15) {
throw new TemporaryException("临时异常:外部服务不可用");
}
// 其他情况:处理成功
}
}
/**
* 自定义异常类型
*/
class TemporaryException extends Exception {
public TemporaryException(String message) {
super(message);
}
}
class PermanentException extends Exception {
public PermanentException(String message) {
super(message);
}
} // 2. 处理成功,手动确认`
`#/**
* 消费者手动确认配置
*
* 关键配置:
* 1. acknowledgeMode = MANUAL(手动确认)
* 2. prefetchCount = 1(公平分发,防止消息堆积)
*/
@Configuration
public class ConsumerAckConfig {
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
// 设置手动确认模式
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 设置预取数量为1,确保公平分发
factory.setPrefetch(1);
return factory;
}
}
/**
* 消费者监听器(手动确认)
*/
@Component
public class ManualAckConsumer {
@RabbitListener(queues = "durable.queue")
public void handleMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
try {
// 1. 业务逻辑处理
processMessage(message);
// 2. 处理成功,手动确认
// multiple=false:只确认当前消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + message);
} catch (TemporaryException e) {
// 临时异常:拒绝消息并重新入队
try {
// requeue=true:消息重新入队,稍后重试
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败(临时异常),重新入队: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
} catch (PermanentException e) {
// 永久异常:拒绝消息且不重新入队(进入死信队列)
try {
// requeue=false:消息进入死信队列
channel.basicNack(deliveryTag, false, false);
System.err.println("消息处理失败(永久异常),进入死信队列: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
}
}
private void processMessage(String message) throws TemporaryException, PermanentException {
// 模拟业务逻辑
Random random = new Random();
int result = random.nextInt(100);
if (result < 5) {
throw new PermanentException("永久性异常:数据格式错误");
} else if (result < 15) {
throw new TemporaryException("临时异常:外部服务不可用");
}
// 其他情况:处理成功
}
}
/**
* 自定义异常类型
*/
class TemporaryException extends Exception {
public TemporaryException(String message) {
super(message);
}
}
class PermanentException extends Exception {
public PermanentException(String message) {
super(message);
}
} // multiple=false:只确认当前消息`
`#/**
* 消费者手动确认配置
*
* 关键配置:
* 1. acknowledgeMode = MANUAL(手动确认)
* 2. prefetchCount = 1(公平分发,防止消息堆积)
*/
@Configuration
public class ConsumerAckConfig {
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
// 设置手动确认模式
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 设置预取数量为1,确保公平分发
factory.setPrefetch(1);
return factory;
}
}
/**
* 消费者监听器(手动确认)
*/
@Component
public class ManualAckConsumer {
@RabbitListener(queues = "durable.queue")
public void handleMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
try {
// 1. 业务逻辑处理
processMessage(message);
// 2. 处理成功,手动确认
// multiple=false:只确认当前消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + message);
} catch (TemporaryException e) {
// 临时异常:拒绝消息并重新入队
try {
// requeue=true:消息重新入队,稍后重试
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败(临时异常),重新入队: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
} catch (PermanentException e) {
// 永久异常:拒绝消息且不重新入队(进入死信队列)
try {
// requeue=false:消息进入死信队列
channel.basicNack(deliveryTag, false, false);
System.err.println("消息处理失败(永久异常),进入死信队列: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
}
}
private void processMessage(String message) throws TemporaryException, PermanentException {
// 模拟业务逻辑
Random random = new Random();
int result = random.nextInt(100);
if (result < 5) {
throw new PermanentException("永久性异常:数据格式错误");
} else if (result < 15) {
throw new TemporaryException("临时异常:外部服务不可用");
}
// 其他情况:处理成功
}
}
/**
* 自定义异常类型
*/
class TemporaryException extends Exception {
public TemporaryException(String message) {
super(message);
}
}
class PermanentException extends Exception {
public PermanentException(String message) {
super(message);
}
} channel.basicAck(deliveryTag, false);`
`#/**
* 消费者手动确认配置
*
* 关键配置:
* 1. acknowledgeMode = MANUAL(手动确认)
* 2. prefetchCount = 1(公平分发,防止消息堆积)
*/
@Configuration
public class ConsumerAckConfig {
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
// 设置手动确认模式
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 设置预取数量为1,确保公平分发
factory.setPrefetch(1);
return factory;
}
}
/**
* 消费者监听器(手动确认)
*/
@Component
public class ManualAckConsumer {
@RabbitListener(queues = "durable.queue")
public void handleMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
try {
// 1. 业务逻辑处理
processMessage(message);
// 2. 处理成功,手动确认
// multiple=false:只确认当前消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + message);
} catch (TemporaryException e) {
// 临时异常:拒绝消息并重新入队
try {
// requeue=true:消息重新入队,稍后重试
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败(临时异常),重新入队: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
} catch (PermanentException e) {
// 永久异常:拒绝消息且不重新入队(进入死信队列)
try {
// requeue=false:消息进入死信队列
channel.basicNack(deliveryTag, false, false);
System.err.println("消息处理失败(永久异常),进入死信队列: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
}
}
private void processMessage(String message) throws TemporaryException, PermanentException {
// 模拟业务逻辑
Random random = new Random();
int result = random.nextInt(100);
if (result < 5) {
throw new PermanentException("永久性异常:数据格式错误");
} else if (result < 15) {
throw new TemporaryException("临时异常:外部服务不可用");
}
// 其他情况:处理成功
}
}
/**
* 自定义异常类型
*/
class TemporaryException extends Exception {
public TemporaryException(String message) {
super(message);
}
}
class PermanentException extends Exception {
public PermanentException(String message) {
super(message);
}
} `
`#/**
* 消费者手动确认配置
*
* 关键配置:
* 1. acknowledgeMode = MANUAL(手动确认)
* 2. prefetchCount = 1(公平分发,防止消息堆积)
*/
@Configuration
public class ConsumerAckConfig {
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
// 设置手动确认模式
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 设置预取数量为1,确保公平分发
factory.setPrefetch(1);
return factory;
}
}
/**
* 消费者监听器(手动确认)
*/
@Component
public class ManualAckConsumer {
@RabbitListener(queues = "durable.queue")
public void handleMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
try {
// 1. 业务逻辑处理
processMessage(message);
// 2. 处理成功,手动确认
// multiple=false:只确认当前消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + message);
} catch (TemporaryException e) {
// 临时异常:拒绝消息并重新入队
try {
// requeue=true:消息重新入队,稍后重试
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败(临时异常),重新入队: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
} catch (PermanentException e) {
// 永久异常:拒绝消息且不重新入队(进入死信队列)
try {
// requeue=false:消息进入死信队列
channel.basicNack(deliveryTag, false, false);
System.err.println("消息处理失败(永久异常),进入死信队列: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
}
}
private void processMessage(String message) throws TemporaryException, PermanentException {
// 模拟业务逻辑
Random random = new Random();
int result = random.nextInt(100);
if (result < 5) {
throw new PermanentException("永久性异常:数据格式错误");
} else if (result < 15) {
throw new TemporaryException("临时异常:外部服务不可用");
}
// 其他情况:处理成功
}
}
/**
* 自定义异常类型
*/
class TemporaryException extends Exception {
public TemporaryException(String message) {
super(message);
}
}
class PermanentException extends Exception {
public PermanentException(String message) {
super(message);
}
} System.out.println("消息处理成功: " + message);`
`#/**
* 消费者手动确认配置
*
* 关键配置:
* 1. acknowledgeMode = MANUAL(手动确认)
* 2. prefetchCount = 1(公平分发,防止消息堆积)
*/
@Configuration
public class ConsumerAckConfig {
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
// 设置手动确认模式
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 设置预取数量为1,确保公平分发
factory.setPrefetch(1);
return factory;
}
}
/**
* 消费者监听器(手动确认)
*/
@Component
public class ManualAckConsumer {
@RabbitListener(queues = "durable.queue")
public void handleMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
try {
// 1. 业务逻辑处理
processMessage(message);
// 2. 处理成功,手动确认
// multiple=false:只确认当前消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + message);
} catch (TemporaryException e) {
// 临时异常:拒绝消息并重新入队
try {
// requeue=true:消息重新入队,稍后重试
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败(临时异常),重新入队: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
} catch (PermanentException e) {
// 永久异常:拒绝消息且不重新入队(进入死信队列)
try {
// requeue=false:消息进入死信队列
channel.basicNack(deliveryTag, false, false);
System.err.println("消息处理失败(永久异常),进入死信队列: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
}
}
private void processMessage(String message) throws TemporaryException, PermanentException {
// 模拟业务逻辑
Random random = new Random();
int result = random.nextInt(100);
if (result < 5) {
throw new PermanentException("永久性异常:数据格式错误");
} else if (result < 15) {
throw new TemporaryException("临时异常:外部服务不可用");
}
// 其他情况:处理成功
}
}
/**
* 自定义异常类型
*/
class TemporaryException extends Exception {
public TemporaryException(String message) {
super(message);
}
}
class PermanentException extends Exception {
public PermanentException(String message) {
super(message);
}
} `
`#/**
* 消费者手动确认配置
*
* 关键配置:
* 1. acknowledgeMode = MANUAL(手动确认)
* 2. prefetchCount = 1(公平分发,防止消息堆积)
*/
@Configuration
public class ConsumerAckConfig {
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
// 设置手动确认模式
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 设置预取数量为1,确保公平分发
factory.setPrefetch(1);
return factory;
}
}
/**
* 消费者监听器(手动确认)
*/
@Component
public class ManualAckConsumer {
@RabbitListener(queues = "durable.queue")
public void handleMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
try {
// 1. 业务逻辑处理
processMessage(message);
// 2. 处理成功,手动确认
// multiple=false:只确认当前消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + message);
} catch (TemporaryException e) {
// 临时异常:拒绝消息并重新入队
try {
// requeue=true:消息重新入队,稍后重试
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败(临时异常),重新入队: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
} catch (PermanentException e) {
// 永久异常:拒绝消息且不重新入队(进入死信队列)
try {
// requeue=false:消息进入死信队列
channel.basicNack(deliveryTag, false, false);
System.err.println("消息处理失败(永久异常),进入死信队列: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
}
}
private void processMessage(String message) throws TemporaryException, PermanentException {
// 模拟业务逻辑
Random random = new Random();
int result = random.nextInt(100);
if (result < 5) {
throw new PermanentException("永久性异常:数据格式错误");
} else if (result < 15) {
throw new TemporaryException("临时异常:外部服务不可用");
}
// 其他情况:处理成功
}
}
/**
* 自定义异常类型
*/
class TemporaryException extends Exception {
public TemporaryException(String message) {
super(message);
}
}
class PermanentException extends Exception {
public PermanentException(String message) {
super(message);
}
} } catch (TemporaryException e) {`
`#/**
* 消费者手动确认配置
*
* 关键配置:
* 1. acknowledgeMode = MANUAL(手动确认)
* 2. prefetchCount = 1(公平分发,防止消息堆积)
*/
@Configuration
public class ConsumerAckConfig {
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
// 设置手动确认模式
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 设置预取数量为1,确保公平分发
factory.setPrefetch(1);
return factory;
}
}
/**
* 消费者监听器(手动确认)
*/
@Component
public class ManualAckConsumer {
@RabbitListener(queues = "durable.queue")
public void handleMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
try {
// 1. 业务逻辑处理
processMessage(message);
// 2. 处理成功,手动确认
// multiple=false:只确认当前消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + message);
} catch (TemporaryException e) {
// 临时异常:拒绝消息并重新入队
try {
// requeue=true:消息重新入队,稍后重试
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败(临时异常),重新入队: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
} catch (PermanentException e) {
// 永久异常:拒绝消息且不重新入队(进入死信队列)
try {
// requeue=false:消息进入死信队列
channel.basicNack(deliveryTag, false, false);
System.err.println("消息处理失败(永久异常),进入死信队列: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
}
}
private void processMessage(String message) throws TemporaryException, PermanentException {
// 模拟业务逻辑
Random random = new Random();
int result = random.nextInt(100);
if (result < 5) {
throw new PermanentException("永久性异常:数据格式错误");
} else if (result < 15) {
throw new TemporaryException("临时异常:外部服务不可用");
}
// 其他情况:处理成功
}
}
/**
* 自定义异常类型
*/
class TemporaryException extends Exception {
public TemporaryException(String message) {
super(message);
}
}
class PermanentException extends Exception {
public PermanentException(String message) {
super(message);
}
} // 临时异常:拒绝消息并重新入队`
`#/**
* 消费者手动确认配置
*
* 关键配置:
* 1. acknowledgeMode = MANUAL(手动确认)
* 2. prefetchCount = 1(公平分发,防止消息堆积)
*/
@Configuration
public class ConsumerAckConfig {
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
// 设置手动确认模式
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 设置预取数量为1,确保公平分发
factory.setPrefetch(1);
return factory;
}
}
/**
* 消费者监听器(手动确认)
*/
@Component
public class ManualAckConsumer {
@RabbitListener(queues = "durable.queue")
public void handleMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
try {
// 1. 业务逻辑处理
processMessage(message);
// 2. 处理成功,手动确认
// multiple=false:只确认当前消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + message);
} catch (TemporaryException e) {
// 临时异常:拒绝消息并重新入队
try {
// requeue=true:消息重新入队,稍后重试
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败(临时异常),重新入队: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
} catch (PermanentException e) {
// 永久异常:拒绝消息且不重新入队(进入死信队列)
try {
// requeue=false:消息进入死信队列
channel.basicNack(deliveryTag, false, false);
System.err.println("消息处理失败(永久异常),进入死信队列: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
}
}
private void processMessage(String message) throws TemporaryException, PermanentException {
// 模拟业务逻辑
Random random = new Random();
int result = random.nextInt(100);
if (result < 5) {
throw new PermanentException("永久性异常:数据格式错误");
} else if (result < 15) {
throw new TemporaryException("临时异常:外部服务不可用");
}
// 其他情况:处理成功
}
}
/**
* 自定义异常类型
*/
class TemporaryException extends Exception {
public TemporaryException(String message) {
super(message);
}
}
class PermanentException extends Exception {
public PermanentException(String message) {
super(message);
}
} try {`
`#/**
* 消费者手动确认配置
*
* 关键配置:
* 1. acknowledgeMode = MANUAL(手动确认)
* 2. prefetchCount = 1(公平分发,防止消息堆积)
*/
@Configuration
public class ConsumerAckConfig {
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
// 设置手动确认模式
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 设置预取数量为1,确保公平分发
factory.setPrefetch(1);
return factory;
}
}
/**
* 消费者监听器(手动确认)
*/
@Component
public class ManualAckConsumer {
@RabbitListener(queues = "durable.queue")
public void handleMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
try {
// 1. 业务逻辑处理
processMessage(message);
// 2. 处理成功,手动确认
// multiple=false:只确认当前消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + message);
} catch (TemporaryException e) {
// 临时异常:拒绝消息并重新入队
try {
// requeue=true:消息重新入队,稍后重试
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败(临时异常),重新入队: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
} catch (PermanentException e) {
// 永久异常:拒绝消息且不重新入队(进入死信队列)
try {
// requeue=false:消息进入死信队列
channel.basicNack(deliveryTag, false, false);
System.err.println("消息处理失败(永久异常),进入死信队列: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
}
}
private void processMessage(String message) throws TemporaryException, PermanentException {
// 模拟业务逻辑
Random random = new Random();
int result = random.nextInt(100);
if (result < 5) {
throw new PermanentException("永久性异常:数据格式错误");
} else if (result < 15) {
throw new TemporaryException("临时异常:外部服务不可用");
}
// 其他情况:处理成功
}
}
/**
* 自定义异常类型
*/
class TemporaryException extends Exception {
public TemporaryException(String message) {
super(message);
}
}
class PermanentException extends Exception {
public PermanentException(String message) {
super(message);
}
} // requeue=true:消息重新入队,稍后重试`
`#/**
* 消费者手动确认配置
*
* 关键配置:
* 1. acknowledgeMode = MANUAL(手动确认)
* 2. prefetchCount = 1(公平分发,防止消息堆积)
*/
@Configuration
public class ConsumerAckConfig {
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
// 设置手动确认模式
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 设置预取数量为1,确保公平分发
factory.setPrefetch(1);
return factory;
}
}
/**
* 消费者监听器(手动确认)
*/
@Component
public class ManualAckConsumer {
@RabbitListener(queues = "durable.queue")
public void handleMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
try {
// 1. 业务逻辑处理
processMessage(message);
// 2. 处理成功,手动确认
// multiple=false:只确认当前消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + message);
} catch (TemporaryException e) {
// 临时异常:拒绝消息并重新入队
try {
// requeue=true:消息重新入队,稍后重试
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败(临时异常),重新入队: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
} catch (PermanentException e) {
// 永久异常:拒绝消息且不重新入队(进入死信队列)
try {
// requeue=false:消息进入死信队列
channel.basicNack(deliveryTag, false, false);
System.err.println("消息处理失败(永久异常),进入死信队列: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
}
}
private void processMessage(String message) throws TemporaryException, PermanentException {
// 模拟业务逻辑
Random random = new Random();
int result = random.nextInt(100);
if (result < 5) {
throw new PermanentException("永久性异常:数据格式错误");
} else if (result < 15) {
throw new TemporaryException("临时异常:外部服务不可用");
}
// 其他情况:处理成功
}
}
/**
* 自定义异常类型
*/
class TemporaryException extends Exception {
public TemporaryException(String message) {
super(message);
}
}
class PermanentException extends Exception {
public PermanentException(String message) {
super(message);
}
} channel.basicNack(deliveryTag, false, true);`
`#/**
* 消费者手动确认配置
*
* 关键配置:
* 1. acknowledgeMode = MANUAL(手动确认)
* 2. prefetchCount = 1(公平分发,防止消息堆积)
*/
@Configuration
public class ConsumerAckConfig {
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
// 设置手动确认模式
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 设置预取数量为1,确保公平分发
factory.setPrefetch(1);
return factory;
}
}
/**
* 消费者监听器(手动确认)
*/
@Component
public class ManualAckConsumer {
@RabbitListener(queues = "durable.queue")
public void handleMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
try {
// 1. 业务逻辑处理
processMessage(message);
// 2. 处理成功,手动确认
// multiple=false:只确认当前消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + message);
} catch (TemporaryException e) {
// 临时异常:拒绝消息并重新入队
try {
// requeue=true:消息重新入队,稍后重试
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败(临时异常),重新入队: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
} catch (PermanentException e) {
// 永久异常:拒绝消息且不重新入队(进入死信队列)
try {
// requeue=false:消息进入死信队列
channel.basicNack(deliveryTag, false, false);
System.err.println("消息处理失败(永久异常),进入死信队列: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
}
}
private void processMessage(String message) throws TemporaryException, PermanentException {
// 模拟业务逻辑
Random random = new Random();
int result = random.nextInt(100);
if (result < 5) {
throw new PermanentException("永久性异常:数据格式错误");
} else if (result < 15) {
throw new TemporaryException("临时异常:外部服务不可用");
}
// 其他情况:处理成功
}
}
/**
* 自定义异常类型
*/
class TemporaryException extends Exception {
public TemporaryException(String message) {
super(message);
}
}
class PermanentException extends Exception {
public PermanentException(String message) {
super(message);
}
} System.err.println("消息处理失败(临时异常),重新入队: " + e.getMessage());`
`#/**
* 消费者手动确认配置
*
* 关键配置:
* 1. acknowledgeMode = MANUAL(手动确认)
* 2. prefetchCount = 1(公平分发,防止消息堆积)
*/
@Configuration
public class ConsumerAckConfig {
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
// 设置手动确认模式
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 设置预取数量为1,确保公平分发
factory.setPrefetch(1);
return factory;
}
}
/**
* 消费者监听器(手动确认)
*/
@Component
public class ManualAckConsumer {
@RabbitListener(queues = "durable.queue")
public void handleMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
try {
// 1. 业务逻辑处理
processMessage(message);
// 2. 处理成功,手动确认
// multiple=false:只确认当前消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + message);
} catch (TemporaryException e) {
// 临时异常:拒绝消息并重新入队
try {
// requeue=true:消息重新入队,稍后重试
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败(临时异常),重新入队: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
} catch (PermanentException e) {
// 永久异常:拒绝消息且不重新入队(进入死信队列)
try {
// requeue=false:消息进入死信队列
channel.basicNack(deliveryTag, false, false);
System.err.println("消息处理失败(永久异常),进入死信队列: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
}
}
private void processMessage(String message) throws TemporaryException, PermanentException {
// 模拟业务逻辑
Random random = new Random();
int result = random.nextInt(100);
if (result < 5) {
throw new PermanentException("永久性异常:数据格式错误");
} else if (result < 15) {
throw new TemporaryException("临时异常:外部服务不可用");
}
// 其他情况:处理成功
}
}
/**
* 自定义异常类型
*/
class TemporaryException extends Exception {
public TemporaryException(String message) {
super(message);
}
}
class PermanentException extends Exception {
public PermanentException(String message) {
super(message);
}
} } catch (IOException ex) {`
`#/**
* 消费者手动确认配置
*
* 关键配置:
* 1. acknowledgeMode = MANUAL(手动确认)
* 2. prefetchCount = 1(公平分发,防止消息堆积)
*/
@Configuration
public class ConsumerAckConfig {
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
// 设置手动确认模式
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 设置预取数量为1,确保公平分发
factory.setPrefetch(1);
return factory;
}
}
/**
* 消费者监听器(手动确认)
*/
@Component
public class ManualAckConsumer {
@RabbitListener(queues = "durable.queue")
public void handleMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
try {
// 1. 业务逻辑处理
processMessage(message);
// 2. 处理成功,手动确认
// multiple=false:只确认当前消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + message);
} catch (TemporaryException e) {
// 临时异常:拒绝消息并重新入队
try {
// requeue=true:消息重新入队,稍后重试
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败(临时异常),重新入队: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
} catch (PermanentException e) {
// 永久异常:拒绝消息且不重新入队(进入死信队列)
try {
// requeue=false:消息进入死信队列
channel.basicNack(deliveryTag, false, false);
System.err.println("消息处理失败(永久异常),进入死信队列: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
}
}
private void processMessage(String message) throws TemporaryException, PermanentException {
// 模拟业务逻辑
Random random = new Random();
int result = random.nextInt(100);
if (result < 5) {
throw new PermanentException("永久性异常:数据格式错误");
} else if (result < 15) {
throw new TemporaryException("临时异常:外部服务不可用");
}
// 其他情况:处理成功
}
}
/**
* 自定义异常类型
*/
class TemporaryException extends Exception {
public TemporaryException(String message) {
super(message);
}
}
class PermanentException extends Exception {
public PermanentException(String message) {
super(message);
}
} System.err.println("Nack 失败: " + ex.getMessage());`
`#/**
* 消费者手动确认配置
*
* 关键配置:
* 1. acknowledgeMode = MANUAL(手动确认)
* 2. prefetchCount = 1(公平分发,防止消息堆积)
*/
@Configuration
public class ConsumerAckConfig {
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
// 设置手动确认模式
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 设置预取数量为1,确保公平分发
factory.setPrefetch(1);
return factory;
}
}
/**
* 消费者监听器(手动确认)
*/
@Component
public class ManualAckConsumer {
@RabbitListener(queues = "durable.queue")
public void handleMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
try {
// 1. 业务逻辑处理
processMessage(message);
// 2. 处理成功,手动确认
// multiple=false:只确认当前消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + message);
} catch (TemporaryException e) {
// 临时异常:拒绝消息并重新入队
try {
// requeue=true:消息重新入队,稍后重试
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败(临时异常),重新入队: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
} catch (PermanentException e) {
// 永久异常:拒绝消息且不重新入队(进入死信队列)
try {
// requeue=false:消息进入死信队列
channel.basicNack(deliveryTag, false, false);
System.err.println("消息处理失败(永久异常),进入死信队列: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
}
}
private void processMessage(String message) throws TemporaryException, PermanentException {
// 模拟业务逻辑
Random random = new Random();
int result = random.nextInt(100);
if (result < 5) {
throw new PermanentException("永久性异常:数据格式错误");
} else if (result < 15) {
throw new TemporaryException("临时异常:外部服务不可用");
}
// 其他情况:处理成功
}
}
/**
* 自定义异常类型
*/
class TemporaryException extends Exception {
public TemporaryException(String message) {
super(message);
}
}
class PermanentException extends Exception {
public PermanentException(String message) {
super(message);
}
} }`
`#/**
* 消费者手动确认配置
*
* 关键配置:
* 1. acknowledgeMode = MANUAL(手动确认)
* 2. prefetchCount = 1(公平分发,防止消息堆积)
*/
@Configuration
public class ConsumerAckConfig {
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
// 设置手动确认模式
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 设置预取数量为1,确保公平分发
factory.setPrefetch(1);
return factory;
}
}
/**
* 消费者监听器(手动确认)
*/
@Component
public class ManualAckConsumer {
@RabbitListener(queues = "durable.queue")
public void handleMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
try {
// 1. 业务逻辑处理
processMessage(message);
// 2. 处理成功,手动确认
// multiple=false:只确认当前消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + message);
} catch (TemporaryException e) {
// 临时异常:拒绝消息并重新入队
try {
// requeue=true:消息重新入队,稍后重试
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败(临时异常),重新入队: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
} catch (PermanentException e) {
// 永久异常:拒绝消息且不重新入队(进入死信队列)
try {
// requeue=false:消息进入死信队列
channel.basicNack(deliveryTag, false, false);
System.err.println("消息处理失败(永久异常),进入死信队列: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
}
}
private void processMessage(String message) throws TemporaryException, PermanentException {
// 模拟业务逻辑
Random random = new Random();
int result = random.nextInt(100);
if (result < 5) {
throw new PermanentException("永久性异常:数据格式错误");
} else if (result < 15) {
throw new TemporaryException("临时异常:外部服务不可用");
}
// 其他情况:处理成功
}
}
/**
* 自定义异常类型
*/
class TemporaryException extends Exception {
public TemporaryException(String message) {
super(message);
}
}
class PermanentException extends Exception {
public PermanentException(String message) {
super(message);
}
} `
`#/**
* 消费者手动确认配置
*
* 关键配置:
* 1. acknowledgeMode = MANUAL(手动确认)
* 2. prefetchCount = 1(公平分发,防止消息堆积)
*/
@Configuration
public class ConsumerAckConfig {
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
// 设置手动确认模式
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 设置预取数量为1,确保公平分发
factory.setPrefetch(1);
return factory;
}
}
/**
* 消费者监听器(手动确认)
*/
@Component
public class ManualAckConsumer {
@RabbitListener(queues = "durable.queue")
public void handleMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
try {
// 1. 业务逻辑处理
processMessage(message);
// 2. 处理成功,手动确认
// multiple=false:只确认当前消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + message);
} catch (TemporaryException e) {
// 临时异常:拒绝消息并重新入队
try {
// requeue=true:消息重新入队,稍后重试
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败(临时异常),重新入队: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
} catch (PermanentException e) {
// 永久异常:拒绝消息且不重新入队(进入死信队列)
try {
// requeue=false:消息进入死信队列
channel.basicNack(deliveryTag, false, false);
System.err.println("消息处理失败(永久异常),进入死信队列: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
}
}
private void processMessage(String message) throws TemporaryException, PermanentException {
// 模拟业务逻辑
Random random = new Random();
int result = random.nextInt(100);
if (result < 5) {
throw new PermanentException("永久性异常:数据格式错误");
} else if (result < 15) {
throw new TemporaryException("临时异常:外部服务不可用");
}
// 其他情况:处理成功
}
}
/**
* 自定义异常类型
*/
class TemporaryException extends Exception {
public TemporaryException(String message) {
super(message);
}
}
class PermanentException extends Exception {
public PermanentException(String message) {
super(message);
}
} } catch (PermanentException e) {`
`#/**
* 消费者手动确认配置
*
* 关键配置:
* 1. acknowledgeMode = MANUAL(手动确认)
* 2. prefetchCount = 1(公平分发,防止消息堆积)
*/
@Configuration
public class ConsumerAckConfig {
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
// 设置手动确认模式
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 设置预取数量为1,确保公平分发
factory.setPrefetch(1);
return factory;
}
}
/**
* 消费者监听器(手动确认)
*/
@Component
public class ManualAckConsumer {
@RabbitListener(queues = "durable.queue")
public void handleMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
try {
// 1. 业务逻辑处理
processMessage(message);
// 2. 处理成功,手动确认
// multiple=false:只确认当前消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + message);
} catch (TemporaryException e) {
// 临时异常:拒绝消息并重新入队
try {
// requeue=true:消息重新入队,稍后重试
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败(临时异常),重新入队: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
} catch (PermanentException e) {
// 永久异常:拒绝消息且不重新入队(进入死信队列)
try {
// requeue=false:消息进入死信队列
channel.basicNack(deliveryTag, false, false);
System.err.println("消息处理失败(永久异常),进入死信队列: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
}
}
private void processMessage(String message) throws TemporaryException, PermanentException {
// 模拟业务逻辑
Random random = new Random();
int result = random.nextInt(100);
if (result < 5) {
throw new PermanentException("永久性异常:数据格式错误");
} else if (result < 15) {
throw new TemporaryException("临时异常:外部服务不可用");
}
// 其他情况:处理成功
}
}
/**
* 自定义异常类型
*/
class TemporaryException extends Exception {
public TemporaryException(String message) {
super(message);
}
}
class PermanentException extends Exception {
public PermanentException(String message) {
super(message);
}
} // 永久异常:拒绝消息且不重新入队(进入死信队列)`
`#/**
* 消费者手动确认配置
*
* 关键配置:
* 1. acknowledgeMode = MANUAL(手动确认)
* 2. prefetchCount = 1(公平分发,防止消息堆积)
*/
@Configuration
public class ConsumerAckConfig {
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
// 设置手动确认模式
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 设置预取数量为1,确保公平分发
factory.setPrefetch(1);
return factory;
}
}
/**
* 消费者监听器(手动确认)
*/
@Component
public class ManualAckConsumer {
@RabbitListener(queues = "durable.queue")
public void handleMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
try {
// 1. 业务逻辑处理
processMessage(message);
// 2. 处理成功,手动确认
// multiple=false:只确认当前消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + message);
} catch (TemporaryException e) {
// 临时异常:拒绝消息并重新入队
try {
// requeue=true:消息重新入队,稍后重试
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败(临时异常),重新入队: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
} catch (PermanentException e) {
// 永久异常:拒绝消息且不重新入队(进入死信队列)
try {
// requeue=false:消息进入死信队列
channel.basicNack(deliveryTag, false, false);
System.err.println("消息处理失败(永久异常),进入死信队列: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
}
}
private void processMessage(String message) throws TemporaryException, PermanentException {
// 模拟业务逻辑
Random random = new Random();
int result = random.nextInt(100);
if (result < 5) {
throw new PermanentException("永久性异常:数据格式错误");
} else if (result < 15) {
throw new TemporaryException("临时异常:外部服务不可用");
}
// 其他情况:处理成功
}
}
/**
* 自定义异常类型
*/
class TemporaryException extends Exception {
public TemporaryException(String message) {
super(message);
}
}
class PermanentException extends Exception {
public PermanentException(String message) {
super(message);
}
} try {`
`#/**
* 消费者手动确认配置
*
* 关键配置:
* 1. acknowledgeMode = MANUAL(手动确认)
* 2. prefetchCount = 1(公平分发,防止消息堆积)
*/
@Configuration
public class ConsumerAckConfig {
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
// 设置手动确认模式
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 设置预取数量为1,确保公平分发
factory.setPrefetch(1);
return factory;
}
}
/**
* 消费者监听器(手动确认)
*/
@Component
public class ManualAckConsumer {
@RabbitListener(queues = "durable.queue")
public void handleMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
try {
// 1. 业务逻辑处理
processMessage(message);
// 2. 处理成功,手动确认
// multiple=false:只确认当前消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + message);
} catch (TemporaryException e) {
// 临时异常:拒绝消息并重新入队
try {
// requeue=true:消息重新入队,稍后重试
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败(临时异常),重新入队: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
} catch (PermanentException e) {
// 永久异常:拒绝消息且不重新入队(进入死信队列)
try {
// requeue=false:消息进入死信队列
channel.basicNack(deliveryTag, false, false);
System.err.println("消息处理失败(永久异常),进入死信队列: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
}
}
private void processMessage(String message) throws TemporaryException, PermanentException {
// 模拟业务逻辑
Random random = new Random();
int result = random.nextInt(100);
if (result < 5) {
throw new PermanentException("永久性异常:数据格式错误");
} else if (result < 15) {
throw new TemporaryException("临时异常:外部服务不可用");
}
// 其他情况:处理成功
}
}
/**
* 自定义异常类型
*/
class TemporaryException extends Exception {
public TemporaryException(String message) {
super(message);
}
}
class PermanentException extends Exception {
public PermanentException(String message) {
super(message);
}
} // requeue=false:消息进入死信队列`
`#/**
* 消费者手动确认配置
*
* 关键配置:
* 1. acknowledgeMode = MANUAL(手动确认)
* 2. prefetchCount = 1(公平分发,防止消息堆积)
*/
@Configuration
public class ConsumerAckConfig {
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
// 设置手动确认模式
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 设置预取数量为1,确保公平分发
factory.setPrefetch(1);
return factory;
}
}
/**
* 消费者监听器(手动确认)
*/
@Component
public class ManualAckConsumer {
@RabbitListener(queues = "durable.queue")
public void handleMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
try {
// 1. 业务逻辑处理
processMessage(message);
// 2. 处理成功,手动确认
// multiple=false:只确认当前消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + message);
} catch (TemporaryException e) {
// 临时异常:拒绝消息并重新入队
try {
// requeue=true:消息重新入队,稍后重试
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败(临时异常),重新入队: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
} catch (PermanentException e) {
// 永久异常:拒绝消息且不重新入队(进入死信队列)
try {
// requeue=false:消息进入死信队列
channel.basicNack(deliveryTag, false, false);
System.err.println("消息处理失败(永久异常),进入死信队列: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
}
}
private void processMessage(String message) throws TemporaryException, PermanentException {
// 模拟业务逻辑
Random random = new Random();
int result = random.nextInt(100);
if (result < 5) {
throw new PermanentException("永久性异常:数据格式错误");
} else if (result < 15) {
throw new TemporaryException("临时异常:外部服务不可用");
}
// 其他情况:处理成功
}
}
/**
* 自定义异常类型
*/
class TemporaryException extends Exception {
public TemporaryException(String message) {
super(message);
}
}
class PermanentException extends Exception {
public PermanentException(String message) {
super(message);
}
} channel.basicNack(deliveryTag, false, false);`
`#/**
* 消费者手动确认配置
*
* 关键配置:
* 1. acknowledgeMode = MANUAL(手动确认)
* 2. prefetchCount = 1(公平分发,防止消息堆积)
*/
@Configuration
public class ConsumerAckConfig {
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
// 设置手动确认模式
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 设置预取数量为1,确保公平分发
factory.setPrefetch(1);
return factory;
}
}
/**
* 消费者监听器(手动确认)
*/
@Component
public class ManualAckConsumer {
@RabbitListener(queues = "durable.queue")
public void handleMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
try {
// 1. 业务逻辑处理
processMessage(message);
// 2. 处理成功,手动确认
// multiple=false:只确认当前消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + message);
} catch (TemporaryException e) {
// 临时异常:拒绝消息并重新入队
try {
// requeue=true:消息重新入队,稍后重试
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败(临时异常),重新入队: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
} catch (PermanentException e) {
// 永久异常:拒绝消息且不重新入队(进入死信队列)
try {
// requeue=false:消息进入死信队列
channel.basicNack(deliveryTag, false, false);
System.err.println("消息处理失败(永久异常),进入死信队列: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
}
}
private void processMessage(String message) throws TemporaryException, PermanentException {
// 模拟业务逻辑
Random random = new Random();
int result = random.nextInt(100);
if (result < 5) {
throw new PermanentException("永久性异常:数据格式错误");
} else if (result < 15) {
throw new TemporaryException("临时异常:外部服务不可用");
}
// 其他情况:处理成功
}
}
/**
* 自定义异常类型
*/
class TemporaryException extends Exception {
public TemporaryException(String message) {
super(message);
}
}
class PermanentException extends Exception {
public PermanentException(String message) {
super(message);
}
} System.err.println("消息处理失败(永久异常),进入死信队列: " + e.getMessage());`
`#/**
* 消费者手动确认配置
*
* 关键配置:
* 1. acknowledgeMode = MANUAL(手动确认)
* 2. prefetchCount = 1(公平分发,防止消息堆积)
*/
@Configuration
public class ConsumerAckConfig {
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
// 设置手动确认模式
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 设置预取数量为1,确保公平分发
factory.setPrefetch(1);
return factory;
}
}
/**
* 消费者监听器(手动确认)
*/
@Component
public class ManualAckConsumer {
@RabbitListener(queues = "durable.queue")
public void handleMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
try {
// 1. 业务逻辑处理
processMessage(message);
// 2. 处理成功,手动确认
// multiple=false:只确认当前消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + message);
} catch (TemporaryException e) {
// 临时异常:拒绝消息并重新入队
try {
// requeue=true:消息重新入队,稍后重试
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败(临时异常),重新入队: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
} catch (PermanentException e) {
// 永久异常:拒绝消息且不重新入队(进入死信队列)
try {
// requeue=false:消息进入死信队列
channel.basicNack(deliveryTag, false, false);
System.err.println("消息处理失败(永久异常),进入死信队列: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
}
}
private void processMessage(String message) throws TemporaryException, PermanentException {
// 模拟业务逻辑
Random random = new Random();
int result = random.nextInt(100);
if (result < 5) {
throw new PermanentException("永久性异常:数据格式错误");
} else if (result < 15) {
throw new TemporaryException("临时异常:外部服务不可用");
}
// 其他情况:处理成功
}
}
/**
* 自定义异常类型
*/
class TemporaryException extends Exception {
public TemporaryException(String message) {
super(message);
}
}
class PermanentException extends Exception {
public PermanentException(String message) {
super(message);
}
} } catch (IOException ex) {`
`#/**
* 消费者手动确认配置
*
* 关键配置:
* 1. acknowledgeMode = MANUAL(手动确认)
* 2. prefetchCount = 1(公平分发,防止消息堆积)
*/
@Configuration
public class ConsumerAckConfig {
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
// 设置手动确认模式
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 设置预取数量为1,确保公平分发
factory.setPrefetch(1);
return factory;
}
}
/**
* 消费者监听器(手动确认)
*/
@Component
public class ManualAckConsumer {
@RabbitListener(queues = "durable.queue")
public void handleMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
try {
// 1. 业务逻辑处理
processMessage(message);
// 2. 处理成功,手动确认
// multiple=false:只确认当前消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + message);
} catch (TemporaryException e) {
// 临时异常:拒绝消息并重新入队
try {
// requeue=true:消息重新入队,稍后重试
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败(临时异常),重新入队: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
} catch (PermanentException e) {
// 永久异常:拒绝消息且不重新入队(进入死信队列)
try {
// requeue=false:消息进入死信队列
channel.basicNack(deliveryTag, false, false);
System.err.println("消息处理失败(永久异常),进入死信队列: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
}
}
private void processMessage(String message) throws TemporaryException, PermanentException {
// 模拟业务逻辑
Random random = new Random();
int result = random.nextInt(100);
if (result < 5) {
throw new PermanentException("永久性异常:数据格式错误");
} else if (result < 15) {
throw new TemporaryException("临时异常:外部服务不可用");
}
// 其他情况:处理成功
}
}
/**
* 自定义异常类型
*/
class TemporaryException extends Exception {
public TemporaryException(String message) {
super(message);
}
}
class PermanentException extends Exception {
public PermanentException(String message) {
super(message);
}
} System.err.println("Nack 失败: " + ex.getMessage());`
`#/**
* 消费者手动确认配置
*
* 关键配置:
* 1. acknowledgeMode = MANUAL(手动确认)
* 2. prefetchCount = 1(公平分发,防止消息堆积)
*/
@Configuration
public class ConsumerAckConfig {
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
// 设置手动确认模式
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 设置预取数量为1,确保公平分发
factory.setPrefetch(1);
return factory;
}
}
/**
* 消费者监听器(手动确认)
*/
@Component
public class ManualAckConsumer {
@RabbitListener(queues = "durable.queue")
public void handleMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
try {
// 1. 业务逻辑处理
processMessage(message);
// 2. 处理成功,手动确认
// multiple=false:只确认当前消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + message);
} catch (TemporaryException e) {
// 临时异常:拒绝消息并重新入队
try {
// requeue=true:消息重新入队,稍后重试
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败(临时异常),重新入队: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
} catch (PermanentException e) {
// 永久异常:拒绝消息且不重新入队(进入死信队列)
try {
// requeue=false:消息进入死信队列
channel.basicNack(deliveryTag, false, false);
System.err.println("消息处理失败(永久异常),进入死信队列: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
}
}
private void processMessage(String message) throws TemporaryException, PermanentException {
// 模拟业务逻辑
Random random = new Random();
int result = random.nextInt(100);
if (result < 5) {
throw new PermanentException("永久性异常:数据格式错误");
} else if (result < 15) {
throw new TemporaryException("临时异常:外部服务不可用");
}
// 其他情况:处理成功
}
}
/**
* 自定义异常类型
*/
class TemporaryException extends Exception {
public TemporaryException(String message) {
super(message);
}
}
class PermanentException extends Exception {
public PermanentException(String message) {
super(message);
}
} }`
`#/**
* 消费者手动确认配置
*
* 关键配置:
* 1. acknowledgeMode = MANUAL(手动确认)
* 2. prefetchCount = 1(公平分发,防止消息堆积)
*/
@Configuration
public class ConsumerAckConfig {
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
// 设置手动确认模式
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 设置预取数量为1,确保公平分发
factory.setPrefetch(1);
return factory;
}
}
/**
* 消费者监听器(手动确认)
*/
@Component
public class ManualAckConsumer {
@RabbitListener(queues = "durable.queue")
public void handleMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
try {
// 1. 业务逻辑处理
processMessage(message);
// 2. 处理成功,手动确认
// multiple=false:只确认当前消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + message);
} catch (TemporaryException e) {
// 临时异常:拒绝消息并重新入队
try {
// requeue=true:消息重新入队,稍后重试
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败(临时异常),重新入队: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
} catch (PermanentException e) {
// 永久异常:拒绝消息且不重新入队(进入死信队列)
try {
// requeue=false:消息进入死信队列
channel.basicNack(deliveryTag, false, false);
System.err.println("消息处理失败(永久异常),进入死信队列: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
}
}
private void processMessage(String message) throws TemporaryException, PermanentException {
// 模拟业务逻辑
Random random = new Random();
int result = random.nextInt(100);
if (result < 5) {
throw new PermanentException("永久性异常:数据格式错误");
} else if (result < 15) {
throw new TemporaryException("临时异常:外部服务不可用");
}
// 其他情况:处理成功
}
}
/**
* 自定义异常类型
*/
class TemporaryException extends Exception {
public TemporaryException(String message) {
super(message);
}
}
class PermanentException extends Exception {
public PermanentException(String message) {
super(message);
}
} }`
`#/**
* 消费者手动确认配置
*
* 关键配置:
* 1. acknowledgeMode = MANUAL(手动确认)
* 2. prefetchCount = 1(公平分发,防止消息堆积)
*/
@Configuration
public class ConsumerAckConfig {
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
// 设置手动确认模式
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 设置预取数量为1,确保公平分发
factory.setPrefetch(1);
return factory;
}
}
/**
* 消费者监听器(手动确认)
*/
@Component
public class ManualAckConsumer {
@RabbitListener(queues = "durable.queue")
public void handleMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
try {
// 1. 业务逻辑处理
processMessage(message);
// 2. 处理成功,手动确认
// multiple=false:只确认当前消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + message);
} catch (TemporaryException e) {
// 临时异常:拒绝消息并重新入队
try {
// requeue=true:消息重新入队,稍后重试
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败(临时异常),重新入队: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
} catch (PermanentException e) {
// 永久异常:拒绝消息且不重新入队(进入死信队列)
try {
// requeue=false:消息进入死信队列
channel.basicNack(deliveryTag, false, false);
System.err.println("消息处理失败(永久异常),进入死信队列: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
}
}
private void processMessage(String message) throws TemporaryException, PermanentException {
// 模拟业务逻辑
Random random = new Random();
int result = random.nextInt(100);
if (result < 5) {
throw new PermanentException("永久性异常:数据格式错误");
} else if (result < 15) {
throw new TemporaryException("临时异常:外部服务不可用");
}
// 其他情况:处理成功
}
}
/**
* 自定义异常类型
*/
class TemporaryException extends Exception {
public TemporaryException(String message) {
super(message);
}
}
class PermanentException extends Exception {
public PermanentException(String message) {
super(message);
}
} }`
`#/**
* 消费者手动确认配置
*
* 关键配置:
* 1. acknowledgeMode = MANUAL(手动确认)
* 2. prefetchCount = 1(公平分发,防止消息堆积)
*/
@Configuration
public class ConsumerAckConfig {
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
// 设置手动确认模式
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 设置预取数量为1,确保公平分发
factory.setPrefetch(1);
return factory;
}
}
/**
* 消费者监听器(手动确认)
*/
@Component
public class ManualAckConsumer {
@RabbitListener(queues = "durable.queue")
public void handleMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
try {
// 1. 业务逻辑处理
processMessage(message);
// 2. 处理成功,手动确认
// multiple=false:只确认当前消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + message);
} catch (TemporaryException e) {
// 临时异常:拒绝消息并重新入队
try {
// requeue=true:消息重新入队,稍后重试
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败(临时异常),重新入队: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
} catch (PermanentException e) {
// 永久异常:拒绝消息且不重新入队(进入死信队列)
try {
// requeue=false:消息进入死信队列
channel.basicNack(deliveryTag, false, false);
System.err.println("消息处理失败(永久异常),进入死信队列: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
}
}
private void processMessage(String message) throws TemporaryException, PermanentException {
// 模拟业务逻辑
Random random = new Random();
int result = random.nextInt(100);
if (result < 5) {
throw new PermanentException("永久性异常:数据格式错误");
} else if (result < 15) {
throw new TemporaryException("临时异常:外部服务不可用");
}
// 其他情况:处理成功
}
}
/**
* 自定义异常类型
*/
class TemporaryException extends Exception {
public TemporaryException(String message) {
super(message);
}
}
class PermanentException extends Exception {
public PermanentException(String message) {
super(message);
}
}`
`#/**
* 消费者手动确认配置
*
* 关键配置:
* 1. acknowledgeMode = MANUAL(手动确认)
* 2. prefetchCount = 1(公平分发,防止消息堆积)
*/
@Configuration
public class ConsumerAckConfig {
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
// 设置手动确认模式
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 设置预取数量为1,确保公平分发
factory.setPrefetch(1);
return factory;
}
}
/**
* 消费者监听器(手动确认)
*/
@Component
public class ManualAckConsumer {
@RabbitListener(queues = "durable.queue")
public void handleMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
try {
// 1. 业务逻辑处理
processMessage(message);
// 2. 处理成功,手动确认
// multiple=false:只确认当前消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + message);
} catch (TemporaryException e) {
// 临时异常:拒绝消息并重新入队
try {
// requeue=true:消息重新入队,稍后重试
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败(临时异常),重新入队: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
} catch (PermanentException e) {
// 永久异常:拒绝消息且不重新入队(进入死信队列)
try {
// requeue=false:消息进入死信队列
channel.basicNack(deliveryTag, false, false);
System.err.println("消息处理失败(永久异常),进入死信队列: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
}
}
private void processMessage(String message) throws TemporaryException, PermanentException {
// 模拟业务逻辑
Random random = new Random();
int result = random.nextInt(100);
if (result < 5) {
throw new PermanentException("永久性异常:数据格式错误");
} else if (result < 15) {
throw new TemporaryException("临时异常:外部服务不可用");
}
// 其他情况:处理成功
}
}
/**
* 自定义异常类型
*/
class TemporaryException extends Exception {
public TemporaryException(String message) {
super(message);
}
}
class PermanentException extends Exception {
public PermanentException(String message) {
super(message);
}
} private void processMessage(String message) throws TemporaryException, PermanentException {`
`#/**
* 消费者手动确认配置
*
* 关键配置:
* 1. acknowledgeMode = MANUAL(手动确认)
* 2. prefetchCount = 1(公平分发,防止消息堆积)
*/
@Configuration
public class ConsumerAckConfig {
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
// 设置手动确认模式
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 设置预取数量为1,确保公平分发
factory.setPrefetch(1);
return factory;
}
}
/**
* 消费者监听器(手动确认)
*/
@Component
public class ManualAckConsumer {
@RabbitListener(queues = "durable.queue")
public void handleMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
try {
// 1. 业务逻辑处理
processMessage(message);
// 2. 处理成功,手动确认
// multiple=false:只确认当前消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + message);
} catch (TemporaryException e) {
// 临时异常:拒绝消息并重新入队
try {
// requeue=true:消息重新入队,稍后重试
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败(临时异常),重新入队: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
} catch (PermanentException e) {
// 永久异常:拒绝消息且不重新入队(进入死信队列)
try {
// requeue=false:消息进入死信队列
channel.basicNack(deliveryTag, false, false);
System.err.println("消息处理失败(永久异常),进入死信队列: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
}
}
private void processMessage(String message) throws TemporaryException, PermanentException {
// 模拟业务逻辑
Random random = new Random();
int result = random.nextInt(100);
if (result < 5) {
throw new PermanentException("永久性异常:数据格式错误");
} else if (result < 15) {
throw new TemporaryException("临时异常:外部服务不可用");
}
// 其他情况:处理成功
}
}
/**
* 自定义异常类型
*/
class TemporaryException extends Exception {
public TemporaryException(String message) {
super(message);
}
}
class PermanentException extends Exception {
public PermanentException(String message) {
super(message);
}
} // 模拟业务逻辑`
`#/**
* 消费者手动确认配置
*
* 关键配置:
* 1. acknowledgeMode = MANUAL(手动确认)
* 2. prefetchCount = 1(公平分发,防止消息堆积)
*/
@Configuration
public class ConsumerAckConfig {
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
// 设置手动确认模式
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 设置预取数量为1,确保公平分发
factory.setPrefetch(1);
return factory;
}
}
/**
* 消费者监听器(手动确认)
*/
@Component
public class ManualAckConsumer {
@RabbitListener(queues = "durable.queue")
public void handleMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
try {
// 1. 业务逻辑处理
processMessage(message);
// 2. 处理成功,手动确认
// multiple=false:只确认当前消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + message);
} catch (TemporaryException e) {
// 临时异常:拒绝消息并重新入队
try {
// requeue=true:消息重新入队,稍后重试
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败(临时异常),重新入队: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
} catch (PermanentException e) {
// 永久异常:拒绝消息且不重新入队(进入死信队列)
try {
// requeue=false:消息进入死信队列
channel.basicNack(deliveryTag, false, false);
System.err.println("消息处理失败(永久异常),进入死信队列: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
}
}
private void processMessage(String message) throws TemporaryException, PermanentException {
// 模拟业务逻辑
Random random = new Random();
int result = random.nextInt(100);
if (result < 5) {
throw new PermanentException("永久性异常:数据格式错误");
} else if (result < 15) {
throw new TemporaryException("临时异常:外部服务不可用");
}
// 其他情况:处理成功
}
}
/**
* 自定义异常类型
*/
class TemporaryException extends Exception {
public TemporaryException(String message) {
super(message);
}
}
class PermanentException extends Exception {
public PermanentException(String message) {
super(message);
}
} Random random = new Random();`
`#/**
* 消费者手动确认配置
*
* 关键配置:
* 1. acknowledgeMode = MANUAL(手动确认)
* 2. prefetchCount = 1(公平分发,防止消息堆积)
*/
@Configuration
public class ConsumerAckConfig {
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
// 设置手动确认模式
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 设置预取数量为1,确保公平分发
factory.setPrefetch(1);
return factory;
}
}
/**
* 消费者监听器(手动确认)
*/
@Component
public class ManualAckConsumer {
@RabbitListener(queues = "durable.queue")
public void handleMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
try {
// 1. 业务逻辑处理
processMessage(message);
// 2. 处理成功,手动确认
// multiple=false:只确认当前消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + message);
} catch (TemporaryException e) {
// 临时异常:拒绝消息并重新入队
try {
// requeue=true:消息重新入队,稍后重试
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败(临时异常),重新入队: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
} catch (PermanentException e) {
// 永久异常:拒绝消息且不重新入队(进入死信队列)
try {
// requeue=false:消息进入死信队列
channel.basicNack(deliveryTag, false, false);
System.err.println("消息处理失败(永久异常),进入死信队列: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
}
}
private void processMessage(String message) throws TemporaryException, PermanentException {
// 模拟业务逻辑
Random random = new Random();
int result = random.nextInt(100);
if (result < 5) {
throw new PermanentException("永久性异常:数据格式错误");
} else if (result < 15) {
throw new TemporaryException("临时异常:外部服务不可用");
}
// 其他情况:处理成功
}
}
/**
* 自定义异常类型
*/
class TemporaryException extends Exception {
public TemporaryException(String message) {
super(message);
}
}
class PermanentException extends Exception {
public PermanentException(String message) {
super(message);
}
} int result = random.nextInt(100);`
`#/**
* 消费者手动确认配置
*
* 关键配置:
* 1. acknowledgeMode = MANUAL(手动确认)
* 2. prefetchCount = 1(公平分发,防止消息堆积)
*/
@Configuration
public class ConsumerAckConfig {
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
// 设置手动确认模式
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 设置预取数量为1,确保公平分发
factory.setPrefetch(1);
return factory;
}
}
/**
* 消费者监听器(手动确认)
*/
@Component
public class ManualAckConsumer {
@RabbitListener(queues = "durable.queue")
public void handleMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
try {
// 1. 业务逻辑处理
processMessage(message);
// 2. 处理成功,手动确认
// multiple=false:只确认当前消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + message);
} catch (TemporaryException e) {
// 临时异常:拒绝消息并重新入队
try {
// requeue=true:消息重新入队,稍后重试
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败(临时异常),重新入队: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
} catch (PermanentException e) {
// 永久异常:拒绝消息且不重新入队(进入死信队列)
try {
// requeue=false:消息进入死信队列
channel.basicNack(deliveryTag, false, false);
System.err.println("消息处理失败(永久异常),进入死信队列: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
}
}
private void processMessage(String message) throws TemporaryException, PermanentException {
// 模拟业务逻辑
Random random = new Random();
int result = random.nextInt(100);
if (result < 5) {
throw new PermanentException("永久性异常:数据格式错误");
} else if (result < 15) {
throw new TemporaryException("临时异常:外部服务不可用");
}
// 其他情况:处理成功
}
}
/**
* 自定义异常类型
*/
class TemporaryException extends Exception {
public TemporaryException(String message) {
super(message);
}
}
class PermanentException extends Exception {
public PermanentException(String message) {
super(message);
}
} `
`#/**
* 消费者手动确认配置
*
* 关键配置:
* 1. acknowledgeMode = MANUAL(手动确认)
* 2. prefetchCount = 1(公平分发,防止消息堆积)
*/
@Configuration
public class ConsumerAckConfig {
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
// 设置手动确认模式
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 设置预取数量为1,确保公平分发
factory.setPrefetch(1);
return factory;
}
}
/**
* 消费者监听器(手动确认)
*/
@Component
public class ManualAckConsumer {
@RabbitListener(queues = "durable.queue")
public void handleMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
try {
// 1. 业务逻辑处理
processMessage(message);
// 2. 处理成功,手动确认
// multiple=false:只确认当前消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + message);
} catch (TemporaryException e) {
// 临时异常:拒绝消息并重新入队
try {
// requeue=true:消息重新入队,稍后重试
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败(临时异常),重新入队: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
} catch (PermanentException e) {
// 永久异常:拒绝消息且不重新入队(进入死信队列)
try {
// requeue=false:消息进入死信队列
channel.basicNack(deliveryTag, false, false);
System.err.println("消息处理失败(永久异常),进入死信队列: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
}
}
private void processMessage(String message) throws TemporaryException, PermanentException {
// 模拟业务逻辑
Random random = new Random();
int result = random.nextInt(100);
if (result < 5) {
throw new PermanentException("永久性异常:数据格式错误");
} else if (result < 15) {
throw new TemporaryException("临时异常:外部服务不可用");
}
// 其他情况:处理成功
}
}
/**
* 自定义异常类型
*/
class TemporaryException extends Exception {
public TemporaryException(String message) {
super(message);
}
}
class PermanentException extends Exception {
public PermanentException(String message) {
super(message);
}
} if (result < 5) {`
`#/**
* 消费者手动确认配置
*
* 关键配置:
* 1. acknowledgeMode = MANUAL(手动确认)
* 2. prefetchCount = 1(公平分发,防止消息堆积)
*/
@Configuration
public class ConsumerAckConfig {
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
// 设置手动确认模式
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 设置预取数量为1,确保公平分发
factory.setPrefetch(1);
return factory;
}
}
/**
* 消费者监听器(手动确认)
*/
@Component
public class ManualAckConsumer {
@RabbitListener(queues = "durable.queue")
public void handleMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
try {
// 1. 业务逻辑处理
processMessage(message);
// 2. 处理成功,手动确认
// multiple=false:只确认当前消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + message);
} catch (TemporaryException e) {
// 临时异常:拒绝消息并重新入队
try {
// requeue=true:消息重新入队,稍后重试
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败(临时异常),重新入队: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
} catch (PermanentException e) {
// 永久异常:拒绝消息且不重新入队(进入死信队列)
try {
// requeue=false:消息进入死信队列
channel.basicNack(deliveryTag, false, false);
System.err.println("消息处理失败(永久异常),进入死信队列: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
}
}
private void processMessage(String message) throws TemporaryException, PermanentException {
// 模拟业务逻辑
Random random = new Random();
int result = random.nextInt(100);
if (result < 5) {
throw new PermanentException("永久性异常:数据格式错误");
} else if (result < 15) {
throw new TemporaryException("临时异常:外部服务不可用");
}
// 其他情况:处理成功
}
}
/**
* 自定义异常类型
*/
class TemporaryException extends Exception {
public TemporaryException(String message) {
super(message);
}
}
class PermanentException extends Exception {
public PermanentException(String message) {
super(message);
}
} throw new PermanentException("永久性异常:数据格式错误");`
`#/**
* 消费者手动确认配置
*
* 关键配置:
* 1. acknowledgeMode = MANUAL(手动确认)
* 2. prefetchCount = 1(公平分发,防止消息堆积)
*/
@Configuration
public class ConsumerAckConfig {
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
// 设置手动确认模式
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 设置预取数量为1,确保公平分发
factory.setPrefetch(1);
return factory;
}
}
/**
* 消费者监听器(手动确认)
*/
@Component
public class ManualAckConsumer {
@RabbitListener(queues = "durable.queue")
public void handleMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
try {
// 1. 业务逻辑处理
processMessage(message);
// 2. 处理成功,手动确认
// multiple=false:只确认当前消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + message);
} catch (TemporaryException e) {
// 临时异常:拒绝消息并重新入队
try {
// requeue=true:消息重新入队,稍后重试
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败(临时异常),重新入队: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
} catch (PermanentException e) {
// 永久异常:拒绝消息且不重新入队(进入死信队列)
try {
// requeue=false:消息进入死信队列
channel.basicNack(deliveryTag, false, false);
System.err.println("消息处理失败(永久异常),进入死信队列: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
}
}
private void processMessage(String message) throws TemporaryException, PermanentException {
// 模拟业务逻辑
Random random = new Random();
int result = random.nextInt(100);
if (result < 5) {
throw new PermanentException("永久性异常:数据格式错误");
} else if (result < 15) {
throw new TemporaryException("临时异常:外部服务不可用");
}
// 其他情况:处理成功
}
}
/**
* 自定义异常类型
*/
class TemporaryException extends Exception {
public TemporaryException(String message) {
super(message);
}
}
class PermanentException extends Exception {
public PermanentException(String message) {
super(message);
}
} } else if (result < 15) {`
`#/**
* 消费者手动确认配置
*
* 关键配置:
* 1. acknowledgeMode = MANUAL(手动确认)
* 2. prefetchCount = 1(公平分发,防止消息堆积)
*/
@Configuration
public class ConsumerAckConfig {
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
// 设置手动确认模式
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 设置预取数量为1,确保公平分发
factory.setPrefetch(1);
return factory;
}
}
/**
* 消费者监听器(手动确认)
*/
@Component
public class ManualAckConsumer {
@RabbitListener(queues = "durable.queue")
public void handleMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
try {
// 1. 业务逻辑处理
processMessage(message);
// 2. 处理成功,手动确认
// multiple=false:只确认当前消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + message);
} catch (TemporaryException e) {
// 临时异常:拒绝消息并重新入队
try {
// requeue=true:消息重新入队,稍后重试
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败(临时异常),重新入队: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
} catch (PermanentException e) {
// 永久异常:拒绝消息且不重新入队(进入死信队列)
try {
// requeue=false:消息进入死信队列
channel.basicNack(deliveryTag, false, false);
System.err.println("消息处理失败(永久异常),进入死信队列: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
}
}
private void processMessage(String message) throws TemporaryException, PermanentException {
// 模拟业务逻辑
Random random = new Random();
int result = random.nextInt(100);
if (result < 5) {
throw new PermanentException("永久性异常:数据格式错误");
} else if (result < 15) {
throw new TemporaryException("临时异常:外部服务不可用");
}
// 其他情况:处理成功
}
}
/**
* 自定义异常类型
*/
class TemporaryException extends Exception {
public TemporaryException(String message) {
super(message);
}
}
class PermanentException extends Exception {
public PermanentException(String message) {
super(message);
}
} throw new TemporaryException("临时异常:外部服务不可用");`
`#/**
* 消费者手动确认配置
*
* 关键配置:
* 1. acknowledgeMode = MANUAL(手动确认)
* 2. prefetchCount = 1(公平分发,防止消息堆积)
*/
@Configuration
public class ConsumerAckConfig {
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
// 设置手动确认模式
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 设置预取数量为1,确保公平分发
factory.setPrefetch(1);
return factory;
}
}
/**
* 消费者监听器(手动确认)
*/
@Component
public class ManualAckConsumer {
@RabbitListener(queues = "durable.queue")
public void handleMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
try {
// 1. 业务逻辑处理
processMessage(message);
// 2. 处理成功,手动确认
// multiple=false:只确认当前消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + message);
} catch (TemporaryException e) {
// 临时异常:拒绝消息并重新入队
try {
// requeue=true:消息重新入队,稍后重试
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败(临时异常),重新入队: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
} catch (PermanentException e) {
// 永久异常:拒绝消息且不重新入队(进入死信队列)
try {
// requeue=false:消息进入死信队列
channel.basicNack(deliveryTag, false, false);
System.err.println("消息处理失败(永久异常),进入死信队列: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
}
}
private void processMessage(String message) throws TemporaryException, PermanentException {
// 模拟业务逻辑
Random random = new Random();
int result = random.nextInt(100);
if (result < 5) {
throw new PermanentException("永久性异常:数据格式错误");
} else if (result < 15) {
throw new TemporaryException("临时异常:外部服务不可用");
}
// 其他情况:处理成功
}
}
/**
* 自定义异常类型
*/
class TemporaryException extends Exception {
public TemporaryException(String message) {
super(message);
}
}
class PermanentException extends Exception {
public PermanentException(String message) {
super(message);
}
} }`
`#/**
* 消费者手动确认配置
*
* 关键配置:
* 1. acknowledgeMode = MANUAL(手动确认)
* 2. prefetchCount = 1(公平分发,防止消息堆积)
*/
@Configuration
public class ConsumerAckConfig {
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
// 设置手动确认模式
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 设置预取数量为1,确保公平分发
factory.setPrefetch(1);
return factory;
}
}
/**
* 消费者监听器(手动确认)
*/
@Component
public class ManualAckConsumer {
@RabbitListener(queues = "durable.queue")
public void handleMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
try {
// 1. 业务逻辑处理
processMessage(message);
// 2. 处理成功,手动确认
// multiple=false:只确认当前消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + message);
} catch (TemporaryException e) {
// 临时异常:拒绝消息并重新入队
try {
// requeue=true:消息重新入队,稍后重试
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败(临时异常),重新入队: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
} catch (PermanentException e) {
// 永久异常:拒绝消息且不重新入队(进入死信队列)
try {
// requeue=false:消息进入死信队列
channel.basicNack(deliveryTag, false, false);
System.err.println("消息处理失败(永久异常),进入死信队列: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
}
}
private void processMessage(String message) throws TemporaryException, PermanentException {
// 模拟业务逻辑
Random random = new Random();
int result = random.nextInt(100);
if (result < 5) {
throw new PermanentException("永久性异常:数据格式错误");
} else if (result < 15) {
throw new TemporaryException("临时异常:外部服务不可用");
}
// 其他情况:处理成功
}
}
/**
* 自定义异常类型
*/
class TemporaryException extends Exception {
public TemporaryException(String message) {
super(message);
}
}
class PermanentException extends Exception {
public PermanentException(String message) {
super(message);
}
} // 其他情况:处理成功`
`#/**
* 消费者手动确认配置
*
* 关键配置:
* 1. acknowledgeMode = MANUAL(手动确认)
* 2. prefetchCount = 1(公平分发,防止消息堆积)
*/
@Configuration
public class ConsumerAckConfig {
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
// 设置手动确认模式
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 设置预取数量为1,确保公平分发
factory.setPrefetch(1);
return factory;
}
}
/**
* 消费者监听器(手动确认)
*/
@Component
public class ManualAckConsumer {
@RabbitListener(queues = "durable.queue")
public void handleMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
try {
// 1. 业务逻辑处理
processMessage(message);
// 2. 处理成功,手动确认
// multiple=false:只确认当前消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + message);
} catch (TemporaryException e) {
// 临时异常:拒绝消息并重新入队
try {
// requeue=true:消息重新入队,稍后重试
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败(临时异常),重新入队: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
} catch (PermanentException e) {
// 永久异常:拒绝消息且不重新入队(进入死信队列)
try {
// requeue=false:消息进入死信队列
channel.basicNack(deliveryTag, false, false);
System.err.println("消息处理失败(永久异常),进入死信队列: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
}
}
private void processMessage(String message) throws TemporaryException, PermanentException {
// 模拟业务逻辑
Random random = new Random();
int result = random.nextInt(100);
if (result < 5) {
throw new PermanentException("永久性异常:数据格式错误");
} else if (result < 15) {
throw new TemporaryException("临时异常:外部服务不可用");
}
// 其他情况:处理成功
}
}
/**
* 自定义异常类型
*/
class TemporaryException extends Exception {
public TemporaryException(String message) {
super(message);
}
}
class PermanentException extends Exception {
public PermanentException(String message) {
super(message);
}
} }`
`#/**
* 消费者手动确认配置
*
* 关键配置:
* 1. acknowledgeMode = MANUAL(手动确认)
* 2. prefetchCount = 1(公平分发,防止消息堆积)
*/
@Configuration
public class ConsumerAckConfig {
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
// 设置手动确认模式
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 设置预取数量为1,确保公平分发
factory.setPrefetch(1);
return factory;
}
}
/**
* 消费者监听器(手动确认)
*/
@Component
public class ManualAckConsumer {
@RabbitListener(queues = "durable.queue")
public void handleMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
try {
// 1. 业务逻辑处理
processMessage(message);
// 2. 处理成功,手动确认
// multiple=false:只确认当前消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + message);
} catch (TemporaryException e) {
// 临时异常:拒绝消息并重新入队
try {
// requeue=true:消息重新入队,稍后重试
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败(临时异常),重新入队: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
} catch (PermanentException e) {
// 永久异常:拒绝消息且不重新入队(进入死信队列)
try {
// requeue=false:消息进入死信队列
channel.basicNack(deliveryTag, false, false);
System.err.println("消息处理失败(永久异常),进入死信队列: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
}
}
private void processMessage(String message) throws TemporaryException, PermanentException {
// 模拟业务逻辑
Random random = new Random();
int result = random.nextInt(100);
if (result < 5) {
throw new PermanentException("永久性异常:数据格式错误");
} else if (result < 15) {
throw new TemporaryException("临时异常:外部服务不可用");
}
// 其他情况:处理成功
}
}
/**
* 自定义异常类型
*/
class TemporaryException extends Exception {
public TemporaryException(String message) {
super(message);
}
}
class PermanentException extends Exception {
public PermanentException(String message) {
super(message);
}
}}`
`#/**
* 消费者手动确认配置
*
* 关键配置:
* 1. acknowledgeMode = MANUAL(手动确认)
* 2. prefetchCount = 1(公平分发,防止消息堆积)
*/
@Configuration
public class ConsumerAckConfig {
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
// 设置手动确认模式
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 设置预取数量为1,确保公平分发
factory.setPrefetch(1);
return factory;
}
}
/**
* 消费者监听器(手动确认)
*/
@Component
public class ManualAckConsumer {
@RabbitListener(queues = "durable.queue")
public void handleMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
try {
// 1. 业务逻辑处理
processMessage(message);
// 2. 处理成功,手动确认
// multiple=false:只确认当前消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + message);
} catch (TemporaryException e) {
// 临时异常:拒绝消息并重新入队
try {
// requeue=true:消息重新入队,稍后重试
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败(临时异常),重新入队: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
} catch (PermanentException e) {
// 永久异常:拒绝消息且不重新入队(进入死信队列)
try {
// requeue=false:消息进入死信队列
channel.basicNack(deliveryTag, false, false);
System.err.println("消息处理失败(永久异常),进入死信队列: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
}
}
private void processMessage(String message) throws TemporaryException, PermanentException {
// 模拟业务逻辑
Random random = new Random();
int result = random.nextInt(100);
if (result < 5) {
throw new PermanentException("永久性异常:数据格式错误");
} else if (result < 15) {
throw new TemporaryException("临时异常:外部服务不可用");
}
// 其他情况:处理成功
}
}
/**
* 自定义异常类型
*/
class TemporaryException extends Exception {
public TemporaryException(String message) {
super(message);
}
}
class PermanentException extends Exception {
public PermanentException(String message) {
super(message);
}
}`
`#/**
* 消费者手动确认配置
*
* 关键配置:
* 1. acknowledgeMode = MANUAL(手动确认)
* 2. prefetchCount = 1(公平分发,防止消息堆积)
*/
@Configuration
public class ConsumerAckConfig {
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
// 设置手动确认模式
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 设置预取数量为1,确保公平分发
factory.setPrefetch(1);
return factory;
}
}
/**
* 消费者监听器(手动确认)
*/
@Component
public class ManualAckConsumer {
@RabbitListener(queues = "durable.queue")
public void handleMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
try {
// 1. 业务逻辑处理
processMessage(message);
// 2. 处理成功,手动确认
// multiple=false:只确认当前消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + message);
} catch (TemporaryException e) {
// 临时异常:拒绝消息并重新入队
try {
// requeue=true:消息重新入队,稍后重试
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败(临时异常),重新入队: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
} catch (PermanentException e) {
// 永久异常:拒绝消息且不重新入队(进入死信队列)
try {
// requeue=false:消息进入死信队列
channel.basicNack(deliveryTag, false, false);
System.err.println("消息处理失败(永久异常),进入死信队列: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
}
}
private void processMessage(String message) throws TemporaryException, PermanentException {
// 模拟业务逻辑
Random random = new Random();
int result = random.nextInt(100);
if (result < 5) {
throw new PermanentException("永久性异常:数据格式错误");
} else if (result < 15) {
throw new TemporaryException("临时异常:外部服务不可用");
}
// 其他情况:处理成功
}
}
/**
* 自定义异常类型
*/
class TemporaryException extends Exception {
public TemporaryException(String message) {
super(message);
}
}
class PermanentException extends Exception {
public PermanentException(String message) {
super(message);
}
}/**`
`#/**
* 消费者手动确认配置
*
* 关键配置:
* 1. acknowledgeMode = MANUAL(手动确认)
* 2. prefetchCount = 1(公平分发,防止消息堆积)
*/
@Configuration
public class ConsumerAckConfig {
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
// 设置手动确认模式
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 设置预取数量为1,确保公平分发
factory.setPrefetch(1);
return factory;
}
}
/**
* 消费者监听器(手动确认)
*/
@Component
public class ManualAckConsumer {
@RabbitListener(queues = "durable.queue")
public void handleMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
try {
// 1. 业务逻辑处理
processMessage(message);
// 2. 处理成功,手动确认
// multiple=false:只确认当前消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + message);
} catch (TemporaryException e) {
// 临时异常:拒绝消息并重新入队
try {
// requeue=true:消息重新入队,稍后重试
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败(临时异常),重新入队: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
} catch (PermanentException e) {
// 永久异常:拒绝消息且不重新入队(进入死信队列)
try {
// requeue=false:消息进入死信队列
channel.basicNack(deliveryTag, false, false);
System.err.println("消息处理失败(永久异常),进入死信队列: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
}
}
private void processMessage(String message) throws TemporaryException, PermanentException {
// 模拟业务逻辑
Random random = new Random();
int result = random.nextInt(100);
if (result < 5) {
throw new PermanentException("永久性异常:数据格式错误");
} else if (result < 15) {
throw new TemporaryException("临时异常:外部服务不可用");
}
// 其他情况:处理成功
}
}
/**
* 自定义异常类型
*/
class TemporaryException extends Exception {
public TemporaryException(String message) {
super(message);
}
}
class PermanentException extends Exception {
public PermanentException(String message) {
super(message);
}
} * 自定义异常类型`
`#/**
* 消费者手动确认配置
*
* 关键配置:
* 1. acknowledgeMode = MANUAL(手动确认)
* 2. prefetchCount = 1(公平分发,防止消息堆积)
*/
@Configuration
public class ConsumerAckConfig {
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
// 设置手动确认模式
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 设置预取数量为1,确保公平分发
factory.setPrefetch(1);
return factory;
}
}
/**
* 消费者监听器(手动确认)
*/
@Component
public class ManualAckConsumer {
@RabbitListener(queues = "durable.queue")
public void handleMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
try {
// 1. 业务逻辑处理
processMessage(message);
// 2. 处理成功,手动确认
// multiple=false:只确认当前消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + message);
} catch (TemporaryException e) {
// 临时异常:拒绝消息并重新入队
try {
// requeue=true:消息重新入队,稍后重试
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败(临时异常),重新入队: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
} catch (PermanentException e) {
// 永久异常:拒绝消息且不重新入队(进入死信队列)
try {
// requeue=false:消息进入死信队列
channel.basicNack(deliveryTag, false, false);
System.err.println("消息处理失败(永久异常),进入死信队列: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
}
}
private void processMessage(String message) throws TemporaryException, PermanentException {
// 模拟业务逻辑
Random random = new Random();
int result = random.nextInt(100);
if (result < 5) {
throw new PermanentException("永久性异常:数据格式错误");
} else if (result < 15) {
throw new TemporaryException("临时异常:外部服务不可用");
}
// 其他情况:处理成功
}
}
/**
* 自定义异常类型
*/
class TemporaryException extends Exception {
public TemporaryException(String message) {
super(message);
}
}
class PermanentException extends Exception {
public PermanentException(String message) {
super(message);
}
} */`
`#/**
* 消费者手动确认配置
*
* 关键配置:
* 1. acknowledgeMode = MANUAL(手动确认)
* 2. prefetchCount = 1(公平分发,防止消息堆积)
*/
@Configuration
public class ConsumerAckConfig {
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
// 设置手动确认模式
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 设置预取数量为1,确保公平分发
factory.setPrefetch(1);
return factory;
}
}
/**
* 消费者监听器(手动确认)
*/
@Component
public class ManualAckConsumer {
@RabbitListener(queues = "durable.queue")
public void handleMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
try {
// 1. 业务逻辑处理
processMessage(message);
// 2. 处理成功,手动确认
// multiple=false:只确认当前消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + message);
} catch (TemporaryException e) {
// 临时异常:拒绝消息并重新入队
try {
// requeue=true:消息重新入队,稍后重试
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败(临时异常),重新入队: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
} catch (PermanentException e) {
// 永久异常:拒绝消息且不重新入队(进入死信队列)
try {
// requeue=false:消息进入死信队列
channel.basicNack(deliveryTag, false, false);
System.err.println("消息处理失败(永久异常),进入死信队列: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
}
}
private void processMessage(String message) throws TemporaryException, PermanentException {
// 模拟业务逻辑
Random random = new Random();
int result = random.nextInt(100);
if (result < 5) {
throw new PermanentException("永久性异常:数据格式错误");
} else if (result < 15) {
throw new TemporaryException("临时异常:外部服务不可用");
}
// 其他情况:处理成功
}
}
/**
* 自定义异常类型
*/
class TemporaryException extends Exception {
public TemporaryException(String message) {
super(message);
}
}
class PermanentException extends Exception {
public PermanentException(String message) {
super(message);
}
}class TemporaryException extends Exception {`
`#/**
* 消费者手动确认配置
*
* 关键配置:
* 1. acknowledgeMode = MANUAL(手动确认)
* 2. prefetchCount = 1(公平分发,防止消息堆积)
*/
@Configuration
public class ConsumerAckConfig {
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
// 设置手动确认模式
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 设置预取数量为1,确保公平分发
factory.setPrefetch(1);
return factory;
}
}
/**
* 消费者监听器(手动确认)
*/
@Component
public class ManualAckConsumer {
@RabbitListener(queues = "durable.queue")
public void handleMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
try {
// 1. 业务逻辑处理
processMessage(message);
// 2. 处理成功,手动确认
// multiple=false:只确认当前消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + message);
} catch (TemporaryException e) {
// 临时异常:拒绝消息并重新入队
try {
// requeue=true:消息重新入队,稍后重试
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败(临时异常),重新入队: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
} catch (PermanentException e) {
// 永久异常:拒绝消息且不重新入队(进入死信队列)
try {
// requeue=false:消息进入死信队列
channel.basicNack(deliveryTag, false, false);
System.err.println("消息处理失败(永久异常),进入死信队列: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
}
}
private void processMessage(String message) throws TemporaryException, PermanentException {
// 模拟业务逻辑
Random random = new Random();
int result = random.nextInt(100);
if (result < 5) {
throw new PermanentException("永久性异常:数据格式错误");
} else if (result < 15) {
throw new TemporaryException("临时异常:外部服务不可用");
}
// 其他情况:处理成功
}
}
/**
* 自定义异常类型
*/
class TemporaryException extends Exception {
public TemporaryException(String message) {
super(message);
}
}
class PermanentException extends Exception {
public PermanentException(String message) {
super(message);
}
} public TemporaryException(String message) {`
`#/**
* 消费者手动确认配置
*
* 关键配置:
* 1. acknowledgeMode = MANUAL(手动确认)
* 2. prefetchCount = 1(公平分发,防止消息堆积)
*/
@Configuration
public class ConsumerAckConfig {
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
// 设置手动确认模式
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 设置预取数量为1,确保公平分发
factory.setPrefetch(1);
return factory;
}
}
/**
* 消费者监听器(手动确认)
*/
@Component
public class ManualAckConsumer {
@RabbitListener(queues = "durable.queue")
public void handleMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
try {
// 1. 业务逻辑处理
processMessage(message);
// 2. 处理成功,手动确认
// multiple=false:只确认当前消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + message);
} catch (TemporaryException e) {
// 临时异常:拒绝消息并重新入队
try {
// requeue=true:消息重新入队,稍后重试
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败(临时异常),重新入队: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
} catch (PermanentException e) {
// 永久异常:拒绝消息且不重新入队(进入死信队列)
try {
// requeue=false:消息进入死信队列
channel.basicNack(deliveryTag, false, false);
System.err.println("消息处理失败(永久异常),进入死信队列: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
}
}
private void processMessage(String message) throws TemporaryException, PermanentException {
// 模拟业务逻辑
Random random = new Random();
int result = random.nextInt(100);
if (result < 5) {
throw new PermanentException("永久性异常:数据格式错误");
} else if (result < 15) {
throw new TemporaryException("临时异常:外部服务不可用");
}
// 其他情况:处理成功
}
}
/**
* 自定义异常类型
*/
class TemporaryException extends Exception {
public TemporaryException(String message) {
super(message);
}
}
class PermanentException extends Exception {
public PermanentException(String message) {
super(message);
}
} super(message);`
`#/**
* 消费者手动确认配置
*
* 关键配置:
* 1. acknowledgeMode = MANUAL(手动确认)
* 2. prefetchCount = 1(公平分发,防止消息堆积)
*/
@Configuration
public class ConsumerAckConfig {
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
// 设置手动确认模式
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 设置预取数量为1,确保公平分发
factory.setPrefetch(1);
return factory;
}
}
/**
* 消费者监听器(手动确认)
*/
@Component
public class ManualAckConsumer {
@RabbitListener(queues = "durable.queue")
public void handleMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
try {
// 1. 业务逻辑处理
processMessage(message);
// 2. 处理成功,手动确认
// multiple=false:只确认当前消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + message);
} catch (TemporaryException e) {
// 临时异常:拒绝消息并重新入队
try {
// requeue=true:消息重新入队,稍后重试
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败(临时异常),重新入队: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
} catch (PermanentException e) {
// 永久异常:拒绝消息且不重新入队(进入死信队列)
try {
// requeue=false:消息进入死信队列
channel.basicNack(deliveryTag, false, false);
System.err.println("消息处理失败(永久异常),进入死信队列: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
}
}
private void processMessage(String message) throws TemporaryException, PermanentException {
// 模拟业务逻辑
Random random = new Random();
int result = random.nextInt(100);
if (result < 5) {
throw new PermanentException("永久性异常:数据格式错误");
} else if (result < 15) {
throw new TemporaryException("临时异常:外部服务不可用");
}
// 其他情况:处理成功
}
}
/**
* 自定义异常类型
*/
class TemporaryException extends Exception {
public TemporaryException(String message) {
super(message);
}
}
class PermanentException extends Exception {
public PermanentException(String message) {
super(message);
}
} }`
`#/**
* 消费者手动确认配置
*
* 关键配置:
* 1. acknowledgeMode = MANUAL(手动确认)
* 2. prefetchCount = 1(公平分发,防止消息堆积)
*/
@Configuration
public class ConsumerAckConfig {
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
// 设置手动确认模式
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 设置预取数量为1,确保公平分发
factory.setPrefetch(1);
return factory;
}
}
/**
* 消费者监听器(手动确认)
*/
@Component
public class ManualAckConsumer {
@RabbitListener(queues = "durable.queue")
public void handleMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
try {
// 1. 业务逻辑处理
processMessage(message);
// 2. 处理成功,手动确认
// multiple=false:只确认当前消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + message);
} catch (TemporaryException e) {
// 临时异常:拒绝消息并重新入队
try {
// requeue=true:消息重新入队,稍后重试
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败(临时异常),重新入队: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
} catch (PermanentException e) {
// 永久异常:拒绝消息且不重新入队(进入死信队列)
try {
// requeue=false:消息进入死信队列
channel.basicNack(deliveryTag, false, false);
System.err.println("消息处理失败(永久异常),进入死信队列: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
}
}
private void processMessage(String message) throws TemporaryException, PermanentException {
// 模拟业务逻辑
Random random = new Random();
int result = random.nextInt(100);
if (result < 5) {
throw new PermanentException("永久性异常:数据格式错误");
} else if (result < 15) {
throw new TemporaryException("临时异常:外部服务不可用");
}
// 其他情况:处理成功
}
}
/**
* 自定义异常类型
*/
class TemporaryException extends Exception {
public TemporaryException(String message) {
super(message);
}
}
class PermanentException extends Exception {
public PermanentException(String message) {
super(message);
}
}}`
`#/**
* 消费者手动确认配置
*
* 关键配置:
* 1. acknowledgeMode = MANUAL(手动确认)
* 2. prefetchCount = 1(公平分发,防止消息堆积)
*/
@Configuration
public class ConsumerAckConfig {
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
// 设置手动确认模式
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 设置预取数量为1,确保公平分发
factory.setPrefetch(1);
return factory;
}
}
/**
* 消费者监听器(手动确认)
*/
@Component
public class ManualAckConsumer {
@RabbitListener(queues = "durable.queue")
public void handleMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
try {
// 1. 业务逻辑处理
processMessage(message);
// 2. 处理成功,手动确认
// multiple=false:只确认当前消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + message);
} catch (TemporaryException e) {
// 临时异常:拒绝消息并重新入队
try {
// requeue=true:消息重新入队,稍后重试
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败(临时异常),重新入队: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
} catch (PermanentException e) {
// 永久异常:拒绝消息且不重新入队(进入死信队列)
try {
// requeue=false:消息进入死信队列
channel.basicNack(deliveryTag, false, false);
System.err.println("消息处理失败(永久异常),进入死信队列: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
}
}
private void processMessage(String message) throws TemporaryException, PermanentException {
// 模拟业务逻辑
Random random = new Random();
int result = random.nextInt(100);
if (result < 5) {
throw new PermanentException("永久性异常:数据格式错误");
} else if (result < 15) {
throw new TemporaryException("临时异常:外部服务不可用");
}
// 其他情况:处理成功
}
}
/**
* 自定义异常类型
*/
class TemporaryException extends Exception {
public TemporaryException(String message) {
super(message);
}
}
class PermanentException extends Exception {
public PermanentException(String message) {
super(message);
}
}`
`#/**
* 消费者手动确认配置
*
* 关键配置:
* 1. acknowledgeMode = MANUAL(手动确认)
* 2. prefetchCount = 1(公平分发,防止消息堆积)
*/
@Configuration
public class ConsumerAckConfig {
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
// 设置手动确认模式
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 设置预取数量为1,确保公平分发
factory.setPrefetch(1);
return factory;
}
}
/**
* 消费者监听器(手动确认)
*/
@Component
public class ManualAckConsumer {
@RabbitListener(queues = "durable.queue")
public void handleMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
try {
// 1. 业务逻辑处理
processMessage(message);
// 2. 处理成功,手动确认
// multiple=false:只确认当前消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + message);
} catch (TemporaryException e) {
// 临时异常:拒绝消息并重新入队
try {
// requeue=true:消息重新入队,稍后重试
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败(临时异常),重新入队: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
} catch (PermanentException e) {
// 永久异常:拒绝消息且不重新入队(进入死信队列)
try {
// requeue=false:消息进入死信队列
channel.basicNack(deliveryTag, false, false);
System.err.println("消息处理失败(永久异常),进入死信队列: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
}
}
private void processMessage(String message) throws TemporaryException, PermanentException {
// 模拟业务逻辑
Random random = new Random();
int result = random.nextInt(100);
if (result < 5) {
throw new PermanentException("永久性异常:数据格式错误");
} else if (result < 15) {
throw new TemporaryException("临时异常:外部服务不可用");
}
// 其他情况:处理成功
}
}
/**
* 自定义异常类型
*/
class TemporaryException extends Exception {
public TemporaryException(String message) {
super(message);
}
}
class PermanentException extends Exception {
public PermanentException(String message) {
super(message);
}
}class PermanentException extends Exception {`
`#/**
* 消费者手动确认配置
*
* 关键配置:
* 1. acknowledgeMode = MANUAL(手动确认)
* 2. prefetchCount = 1(公平分发,防止消息堆积)
*/
@Configuration
public class ConsumerAckConfig {
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
// 设置手动确认模式
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 设置预取数量为1,确保公平分发
factory.setPrefetch(1);
return factory;
}
}
/**
* 消费者监听器(手动确认)
*/
@Component
public class ManualAckConsumer {
@RabbitListener(queues = "durable.queue")
public void handleMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
try {
// 1. 业务逻辑处理
processMessage(message);
// 2. 处理成功,手动确认
// multiple=false:只确认当前消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + message);
} catch (TemporaryException e) {
// 临时异常:拒绝消息并重新入队
try {
// requeue=true:消息重新入队,稍后重试
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败(临时异常),重新入队: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
} catch (PermanentException e) {
// 永久异常:拒绝消息且不重新入队(进入死信队列)
try {
// requeue=false:消息进入死信队列
channel.basicNack(deliveryTag, false, false);
System.err.println("消息处理失败(永久异常),进入死信队列: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
}
}
private void processMessage(String message) throws TemporaryException, PermanentException {
// 模拟业务逻辑
Random random = new Random();
int result = random.nextInt(100);
if (result < 5) {
throw new PermanentException("永久性异常:数据格式错误");
} else if (result < 15) {
throw new TemporaryException("临时异常:外部服务不可用");
}
// 其他情况:处理成功
}
}
/**
* 自定义异常类型
*/
class TemporaryException extends Exception {
public TemporaryException(String message) {
super(message);
}
}
class PermanentException extends Exception {
public PermanentException(String message) {
super(message);
}
} public PermanentException(String message) {`
`#/**
* 消费者手动确认配置
*
* 关键配置:
* 1. acknowledgeMode = MANUAL(手动确认)
* 2. prefetchCount = 1(公平分发,防止消息堆积)
*/
@Configuration
public class ConsumerAckConfig {
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
// 设置手动确认模式
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 设置预取数量为1,确保公平分发
factory.setPrefetch(1);
return factory;
}
}
/**
* 消费者监听器(手动确认)
*/
@Component
public class ManualAckConsumer {
@RabbitListener(queues = "durable.queue")
public void handleMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
try {
// 1. 业务逻辑处理
processMessage(message);
// 2. 处理成功,手动确认
// multiple=false:只确认当前消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + message);
} catch (TemporaryException e) {
// 临时异常:拒绝消息并重新入队
try {
// requeue=true:消息重新入队,稍后重试
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败(临时异常),重新入队: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
} catch (PermanentException e) {
// 永久异常:拒绝消息且不重新入队(进入死信队列)
try {
// requeue=false:消息进入死信队列
channel.basicNack(deliveryTag, false, false);
System.err.println("消息处理失败(永久异常),进入死信队列: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
}
}
private void processMessage(String message) throws TemporaryException, PermanentException {
// 模拟业务逻辑
Random random = new Random();
int result = random.nextInt(100);
if (result < 5) {
throw new PermanentException("永久性异常:数据格式错误");
} else if (result < 15) {
throw new TemporaryException("临时异常:外部服务不可用");
}
// 其他情况:处理成功
}
}
/**
* 自定义异常类型
*/
class TemporaryException extends Exception {
public TemporaryException(String message) {
super(message);
}
}
class PermanentException extends Exception {
public PermanentException(String message) {
super(message);
}
} super(message);`
`#/**
* 消费者手动确认配置
*
* 关键配置:
* 1. acknowledgeMode = MANUAL(手动确认)
* 2. prefetchCount = 1(公平分发,防止消息堆积)
*/
@Configuration
public class ConsumerAckConfig {
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
// 设置手动确认模式
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 设置预取数量为1,确保公平分发
factory.setPrefetch(1);
return factory;
}
}
/**
* 消费者监听器(手动确认)
*/
@Component
public class ManualAckConsumer {
@RabbitListener(queues = "durable.queue")
public void handleMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
try {
// 1. 业务逻辑处理
processMessage(message);
// 2. 处理成功,手动确认
// multiple=false:只确认当前消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + message);
} catch (TemporaryException e) {
// 临时异常:拒绝消息并重新入队
try {
// requeue=true:消息重新入队,稍后重试
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败(临时异常),重新入队: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
} catch (PermanentException e) {
// 永久异常:拒绝消息且不重新入队(进入死信队列)
try {
// requeue=false:消息进入死信队列
channel.basicNack(deliveryTag, false, false);
System.err.println("消息处理失败(永久异常),进入死信队列: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
}
}
private void processMessage(String message) throws TemporaryException, PermanentException {
// 模拟业务逻辑
Random random = new Random();
int result = random.nextInt(100);
if (result < 5) {
throw new PermanentException("永久性异常:数据格式错误");
} else if (result < 15) {
throw new TemporaryException("临时异常:外部服务不可用");
}
// 其他情况:处理成功
}
}
/**
* 自定义异常类型
*/
class TemporaryException extends Exception {
public TemporaryException(String message) {
super(message);
}
}
class PermanentException extends Exception {
public PermanentException(String message) {
super(message);
}
} }`
`#/**
* 消费者手动确认配置
*
* 关键配置:
* 1. acknowledgeMode = MANUAL(手动确认)
* 2. prefetchCount = 1(公平分发,防止消息堆积)
*/
@Configuration
public class ConsumerAckConfig {
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
// 设置手动确认模式
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 设置预取数量为1,确保公平分发
factory.setPrefetch(1);
return factory;
}
}
/**
* 消费者监听器(手动确认)
*/
@Component
public class ManualAckConsumer {
@RabbitListener(queues = "durable.queue")
public void handleMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
try {
// 1. 业务逻辑处理
processMessage(message);
// 2. 处理成功,手动确认
// multiple=false:只确认当前消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + message);
} catch (TemporaryException e) {
// 临时异常:拒绝消息并重新入队
try {
// requeue=true:消息重新入队,稍后重试
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败(临时异常),重新入队: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
} catch (PermanentException e) {
// 永久异常:拒绝消息且不重新入队(进入死信队列)
try {
// requeue=false:消息进入死信队列
channel.basicNack(deliveryTag, false, false);
System.err.println("消息处理失败(永久异常),进入死信队列: " + e.getMessage());
} catch (IOException ex) {
System.err.println("Nack 失败: " + ex.getMessage());
}
}
}
private void processMessage(String message) throws TemporaryException, PermanentException {
// 模拟业务逻辑
Random random = new Random();
int result = random.nextInt(100);
if (result < 5) {
throw new PermanentException("永久性异常:数据格式错误");
} else if (result < 15) {
throw new TemporaryException("临时异常:外部服务不可用");
}
// 其他情况:处理成功
}
}
/**
* 自定义异常类型
*/
class TemporaryException extends Exception {
public TemporaryException(String message) {
super(message);
}
}
class PermanentException extends Exception {
public PermanentException(String message) {
super(message);
}
}}
3.4 幂等性:防止消息重复消费
即使使用确认机制,在某些极端情况下仍可能出现消息重复,因此幂等性设计是必要的。
graph TD
A[接收消息] --> B{消息ID是否已处理?}
B -->|是| C[直接返回成功<br/>(幂等)]
B -->|否| D[执行业务逻辑]
D --> E{处理结果}
E -->|成功| F[记录消息ID<br/>标记已处理]
E -->|失败| G[抛出异常<br/>触发重试]
style C fill:#e1ffe1
style F fill:#e1ffe1
style G fill:#ffe1e1
幂等性实现示例:
java
#/**
* 基于 Redis 的幂等性实现
*
* 核心思路:
* 1. 每条消息生成唯一ID
* 2. 处理前检查Redis是否已存在该ID
* 3. 处理完成后将ID写入Redis
*/
@Service
public class IdempotentConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
private static final String MESSAGE_ID_PREFIX = "message:processed:";
@RabbitListener(queues = "durable.queue")
public void handleIdempotentMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag,
@Header(AmqpHeaders.MESSAGE_ID) String messageId) throws IOException {
// 1. 检查消息是否已处理
String key = MESSAGE_ID_PREFIX + messageId;
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(key, "processed", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 消息已处理过,直接确认(幂等返回)
channel.basicAck(deliveryTag, false);
System.out.println("消息重复,直接返回成功: " + messageId);
return;
}
try {
// 2. 首次处理消息
processBusinessLogic(message);
// 3. 确认消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + messageId);
} catch (Exception e) {
// 4. 处理失败,删除幂等标记(允许重试)
redisTemplate.delete(key);
// 拒绝消息并重新入队
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败,允许重试: " + e.getMessage());
}
}
private void processBusinessLogic(String message) {
// 实际业务逻辑
System.out.println("处理业务逻辑: " + message);
}
}/**`
`#/**
* 基于 Redis 的幂等性实现
*
* 核心思路:
* 1. 每条消息生成唯一ID
* 2. 处理前检查Redis是否已存在该ID
* 3. 处理完成后将ID写入Redis
*/
@Service
public class IdempotentConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
private static final String MESSAGE_ID_PREFIX = "message:processed:";
@RabbitListener(queues = "durable.queue")
public void handleIdempotentMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag,
@Header(AmqpHeaders.MESSAGE_ID) String messageId) throws IOException {
// 1. 检查消息是否已处理
String key = MESSAGE_ID_PREFIX + messageId;
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(key, "processed", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 消息已处理过,直接确认(幂等返回)
channel.basicAck(deliveryTag, false);
System.out.println("消息重复,直接返回成功: " + messageId);
return;
}
try {
// 2. 首次处理消息
processBusinessLogic(message);
// 3. 确认消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + messageId);
} catch (Exception e) {
// 4. 处理失败,删除幂等标记(允许重试)
redisTemplate.delete(key);
// 拒绝消息并重新入队
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败,允许重试: " + e.getMessage());
}
}
private void processBusinessLogic(String message) {
// 实际业务逻辑
System.out.println("处理业务逻辑: " + message);
}
} * 基于 Redis 的幂等性实现`
`#/**
* 基于 Redis 的幂等性实现
*
* 核心思路:
* 1. 每条消息生成唯一ID
* 2. 处理前检查Redis是否已存在该ID
* 3. 处理完成后将ID写入Redis
*/
@Service
public class IdempotentConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
private static final String MESSAGE_ID_PREFIX = "message:processed:";
@RabbitListener(queues = "durable.queue")
public void handleIdempotentMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag,
@Header(AmqpHeaders.MESSAGE_ID) String messageId) throws IOException {
// 1. 检查消息是否已处理
String key = MESSAGE_ID_PREFIX + messageId;
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(key, "processed", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 消息已处理过,直接确认(幂等返回)
channel.basicAck(deliveryTag, false);
System.out.println("消息重复,直接返回成功: " + messageId);
return;
}
try {
// 2. 首次处理消息
processBusinessLogic(message);
// 3. 确认消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + messageId);
} catch (Exception e) {
// 4. 处理失败,删除幂等标记(允许重试)
redisTemplate.delete(key);
// 拒绝消息并重新入队
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败,允许重试: " + e.getMessage());
}
}
private void processBusinessLogic(String message) {
// 实际业务逻辑
System.out.println("处理业务逻辑: " + message);
}
} * `
`#/**
* 基于 Redis 的幂等性实现
*
* 核心思路:
* 1. 每条消息生成唯一ID
* 2. 处理前检查Redis是否已存在该ID
* 3. 处理完成后将ID写入Redis
*/
@Service
public class IdempotentConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
private static final String MESSAGE_ID_PREFIX = "message:processed:";
@RabbitListener(queues = "durable.queue")
public void handleIdempotentMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag,
@Header(AmqpHeaders.MESSAGE_ID) String messageId) throws IOException {
// 1. 检查消息是否已处理
String key = MESSAGE_ID_PREFIX + messageId;
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(key, "processed", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 消息已处理过,直接确认(幂等返回)
channel.basicAck(deliveryTag, false);
System.out.println("消息重复,直接返回成功: " + messageId);
return;
}
try {
// 2. 首次处理消息
processBusinessLogic(message);
// 3. 确认消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + messageId);
} catch (Exception e) {
// 4. 处理失败,删除幂等标记(允许重试)
redisTemplate.delete(key);
// 拒绝消息并重新入队
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败,允许重试: " + e.getMessage());
}
}
private void processBusinessLogic(String message) {
// 实际业务逻辑
System.out.println("处理业务逻辑: " + message);
}
} * 核心思路:`
`#/**
* 基于 Redis 的幂等性实现
*
* 核心思路:
* 1. 每条消息生成唯一ID
* 2. 处理前检查Redis是否已存在该ID
* 3. 处理完成后将ID写入Redis
*/
@Service
public class IdempotentConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
private static final String MESSAGE_ID_PREFIX = "message:processed:";
@RabbitListener(queues = "durable.queue")
public void handleIdempotentMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag,
@Header(AmqpHeaders.MESSAGE_ID) String messageId) throws IOException {
// 1. 检查消息是否已处理
String key = MESSAGE_ID_PREFIX + messageId;
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(key, "processed", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 消息已处理过,直接确认(幂等返回)
channel.basicAck(deliveryTag, false);
System.out.println("消息重复,直接返回成功: " + messageId);
return;
}
try {
// 2. 首次处理消息
processBusinessLogic(message);
// 3. 确认消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + messageId);
} catch (Exception e) {
// 4. 处理失败,删除幂等标记(允许重试)
redisTemplate.delete(key);
// 拒绝消息并重新入队
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败,允许重试: " + e.getMessage());
}
}
private void processBusinessLogic(String message) {
// 实际业务逻辑
System.out.println("处理业务逻辑: " + message);
}
} * 1. 每条消息生成唯一ID`
`#/**
* 基于 Redis 的幂等性实现
*
* 核心思路:
* 1. 每条消息生成唯一ID
* 2. 处理前检查Redis是否已存在该ID
* 3. 处理完成后将ID写入Redis
*/
@Service
public class IdempotentConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
private static final String MESSAGE_ID_PREFIX = "message:processed:";
@RabbitListener(queues = "durable.queue")
public void handleIdempotentMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag,
@Header(AmqpHeaders.MESSAGE_ID) String messageId) throws IOException {
// 1. 检查消息是否已处理
String key = MESSAGE_ID_PREFIX + messageId;
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(key, "processed", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 消息已处理过,直接确认(幂等返回)
channel.basicAck(deliveryTag, false);
System.out.println("消息重复,直接返回成功: " + messageId);
return;
}
try {
// 2. 首次处理消息
processBusinessLogic(message);
// 3. 确认消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + messageId);
} catch (Exception e) {
// 4. 处理失败,删除幂等标记(允许重试)
redisTemplate.delete(key);
// 拒绝消息并重新入队
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败,允许重试: " + e.getMessage());
}
}
private void processBusinessLogic(String message) {
// 实际业务逻辑
System.out.println("处理业务逻辑: " + message);
}
} * 2. 处理前检查Redis是否已存在该ID`
`#/**
* 基于 Redis 的幂等性实现
*
* 核心思路:
* 1. 每条消息生成唯一ID
* 2. 处理前检查Redis是否已存在该ID
* 3. 处理完成后将ID写入Redis
*/
@Service
public class IdempotentConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
private static final String MESSAGE_ID_PREFIX = "message:processed:";
@RabbitListener(queues = "durable.queue")
public void handleIdempotentMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag,
@Header(AmqpHeaders.MESSAGE_ID) String messageId) throws IOException {
// 1. 检查消息是否已处理
String key = MESSAGE_ID_PREFIX + messageId;
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(key, "processed", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 消息已处理过,直接确认(幂等返回)
channel.basicAck(deliveryTag, false);
System.out.println("消息重复,直接返回成功: " + messageId);
return;
}
try {
// 2. 首次处理消息
processBusinessLogic(message);
// 3. 确认消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + messageId);
} catch (Exception e) {
// 4. 处理失败,删除幂等标记(允许重试)
redisTemplate.delete(key);
// 拒绝消息并重新入队
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败,允许重试: " + e.getMessage());
}
}
private void processBusinessLogic(String message) {
// 实际业务逻辑
System.out.println("处理业务逻辑: " + message);
}
} * 3. 处理完成后将ID写入Redis`
`#/**
* 基于 Redis 的幂等性实现
*
* 核心思路:
* 1. 每条消息生成唯一ID
* 2. 处理前检查Redis是否已存在该ID
* 3. 处理完成后将ID写入Redis
*/
@Service
public class IdempotentConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
private static final String MESSAGE_ID_PREFIX = "message:processed:";
@RabbitListener(queues = "durable.queue")
public void handleIdempotentMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag,
@Header(AmqpHeaders.MESSAGE_ID) String messageId) throws IOException {
// 1. 检查消息是否已处理
String key = MESSAGE_ID_PREFIX + messageId;
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(key, "processed", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 消息已处理过,直接确认(幂等返回)
channel.basicAck(deliveryTag, false);
System.out.println("消息重复,直接返回成功: " + messageId);
return;
}
try {
// 2. 首次处理消息
processBusinessLogic(message);
// 3. 确认消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + messageId);
} catch (Exception e) {
// 4. 处理失败,删除幂等标记(允许重试)
redisTemplate.delete(key);
// 拒绝消息并重新入队
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败,允许重试: " + e.getMessage());
}
}
private void processBusinessLogic(String message) {
// 实际业务逻辑
System.out.println("处理业务逻辑: " + message);
}
} */`
`#/**
* 基于 Redis 的幂等性实现
*
* 核心思路:
* 1. 每条消息生成唯一ID
* 2. 处理前检查Redis是否已存在该ID
* 3. 处理完成后将ID写入Redis
*/
@Service
public class IdempotentConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
private static final String MESSAGE_ID_PREFIX = "message:processed:";
@RabbitListener(queues = "durable.queue")
public void handleIdempotentMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag,
@Header(AmqpHeaders.MESSAGE_ID) String messageId) throws IOException {
// 1. 检查消息是否已处理
String key = MESSAGE_ID_PREFIX + messageId;
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(key, "processed", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 消息已处理过,直接确认(幂等返回)
channel.basicAck(deliveryTag, false);
System.out.println("消息重复,直接返回成功: " + messageId);
return;
}
try {
// 2. 首次处理消息
processBusinessLogic(message);
// 3. 确认消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + messageId);
} catch (Exception e) {
// 4. 处理失败,删除幂等标记(允许重试)
redisTemplate.delete(key);
// 拒绝消息并重新入队
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败,允许重试: " + e.getMessage());
}
}
private void processBusinessLogic(String message) {
// 实际业务逻辑
System.out.println("处理业务逻辑: " + message);
}
}@Service`
`#/**
* 基于 Redis 的幂等性实现
*
* 核心思路:
* 1. 每条消息生成唯一ID
* 2. 处理前检查Redis是否已存在该ID
* 3. 处理完成后将ID写入Redis
*/
@Service
public class IdempotentConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
private static final String MESSAGE_ID_PREFIX = "message:processed:";
@RabbitListener(queues = "durable.queue")
public void handleIdempotentMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag,
@Header(AmqpHeaders.MESSAGE_ID) String messageId) throws IOException {
// 1. 检查消息是否已处理
String key = MESSAGE_ID_PREFIX + messageId;
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(key, "processed", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 消息已处理过,直接确认(幂等返回)
channel.basicAck(deliveryTag, false);
System.out.println("消息重复,直接返回成功: " + messageId);
return;
}
try {
// 2. 首次处理消息
processBusinessLogic(message);
// 3. 确认消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + messageId);
} catch (Exception e) {
// 4. 处理失败,删除幂等标记(允许重试)
redisTemplate.delete(key);
// 拒绝消息并重新入队
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败,允许重试: " + e.getMessage());
}
}
private void processBusinessLogic(String message) {
// 实际业务逻辑
System.out.println("处理业务逻辑: " + message);
}
}public class IdempotentConsumer {`
`#/**
* 基于 Redis 的幂等性实现
*
* 核心思路:
* 1. 每条消息生成唯一ID
* 2. 处理前检查Redis是否已存在该ID
* 3. 处理完成后将ID写入Redis
*/
@Service
public class IdempotentConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
private static final String MESSAGE_ID_PREFIX = "message:processed:";
@RabbitListener(queues = "durable.queue")
public void handleIdempotentMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag,
@Header(AmqpHeaders.MESSAGE_ID) String messageId) throws IOException {
// 1. 检查消息是否已处理
String key = MESSAGE_ID_PREFIX + messageId;
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(key, "processed", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 消息已处理过,直接确认(幂等返回)
channel.basicAck(deliveryTag, false);
System.out.println("消息重复,直接返回成功: " + messageId);
return;
}
try {
// 2. 首次处理消息
processBusinessLogic(message);
// 3. 确认消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + messageId);
} catch (Exception e) {
// 4. 处理失败,删除幂等标记(允许重试)
redisTemplate.delete(key);
// 拒绝消息并重新入队
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败,允许重试: " + e.getMessage());
}
}
private void processBusinessLogic(String message) {
// 实际业务逻辑
System.out.println("处理业务逻辑: " + message);
}
}`
`#/**
* 基于 Redis 的幂等性实现
*
* 核心思路:
* 1. 每条消息生成唯一ID
* 2. 处理前检查Redis是否已存在该ID
* 3. 处理完成后将ID写入Redis
*/
@Service
public class IdempotentConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
private static final String MESSAGE_ID_PREFIX = "message:processed:";
@RabbitListener(queues = "durable.queue")
public void handleIdempotentMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag,
@Header(AmqpHeaders.MESSAGE_ID) String messageId) throws IOException {
// 1. 检查消息是否已处理
String key = MESSAGE_ID_PREFIX + messageId;
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(key, "processed", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 消息已处理过,直接确认(幂等返回)
channel.basicAck(deliveryTag, false);
System.out.println("消息重复,直接返回成功: " + messageId);
return;
}
try {
// 2. 首次处理消息
processBusinessLogic(message);
// 3. 确认消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + messageId);
} catch (Exception e) {
// 4. 处理失败,删除幂等标记(允许重试)
redisTemplate.delete(key);
// 拒绝消息并重新入队
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败,允许重试: " + e.getMessage());
}
}
private void processBusinessLogic(String message) {
// 实际业务逻辑
System.out.println("处理业务逻辑: " + message);
}
} @Autowired`
`#/**
* 基于 Redis 的幂等性实现
*
* 核心思路:
* 1. 每条消息生成唯一ID
* 2. 处理前检查Redis是否已存在该ID
* 3. 处理完成后将ID写入Redis
*/
@Service
public class IdempotentConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
private static final String MESSAGE_ID_PREFIX = "message:processed:";
@RabbitListener(queues = "durable.queue")
public void handleIdempotentMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag,
@Header(AmqpHeaders.MESSAGE_ID) String messageId) throws IOException {
// 1. 检查消息是否已处理
String key = MESSAGE_ID_PREFIX + messageId;
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(key, "processed", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 消息已处理过,直接确认(幂等返回)
channel.basicAck(deliveryTag, false);
System.out.println("消息重复,直接返回成功: " + messageId);
return;
}
try {
// 2. 首次处理消息
processBusinessLogic(message);
// 3. 确认消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + messageId);
} catch (Exception e) {
// 4. 处理失败,删除幂等标记(允许重试)
redisTemplate.delete(key);
// 拒绝消息并重新入队
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败,允许重试: " + e.getMessage());
}
}
private void processBusinessLogic(String message) {
// 实际业务逻辑
System.out.println("处理业务逻辑: " + message);
}
} private RedisTemplate<String, String> redisTemplate;`
`#/**
* 基于 Redis 的幂等性实现
*
* 核心思路:
* 1. 每条消息生成唯一ID
* 2. 处理前检查Redis是否已存在该ID
* 3. 处理完成后将ID写入Redis
*/
@Service
public class IdempotentConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
private static final String MESSAGE_ID_PREFIX = "message:processed:";
@RabbitListener(queues = "durable.queue")
public void handleIdempotentMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag,
@Header(AmqpHeaders.MESSAGE_ID) String messageId) throws IOException {
// 1. 检查消息是否已处理
String key = MESSAGE_ID_PREFIX + messageId;
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(key, "processed", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 消息已处理过,直接确认(幂等返回)
channel.basicAck(deliveryTag, false);
System.out.println("消息重复,直接返回成功: " + messageId);
return;
}
try {
// 2. 首次处理消息
processBusinessLogic(message);
// 3. 确认消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + messageId);
} catch (Exception e) {
// 4. 处理失败,删除幂等标记(允许重试)
redisTemplate.delete(key);
// 拒绝消息并重新入队
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败,允许重试: " + e.getMessage());
}
}
private void processBusinessLogic(String message) {
// 实际业务逻辑
System.out.println("处理业务逻辑: " + message);
}
}`
`#/**
* 基于 Redis 的幂等性实现
*
* 核心思路:
* 1. 每条消息生成唯一ID
* 2. 处理前检查Redis是否已存在该ID
* 3. 处理完成后将ID写入Redis
*/
@Service
public class IdempotentConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
private static final String MESSAGE_ID_PREFIX = "message:processed:";
@RabbitListener(queues = "durable.queue")
public void handleIdempotentMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag,
@Header(AmqpHeaders.MESSAGE_ID) String messageId) throws IOException {
// 1. 检查消息是否已处理
String key = MESSAGE_ID_PREFIX + messageId;
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(key, "processed", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 消息已处理过,直接确认(幂等返回)
channel.basicAck(deliveryTag, false);
System.out.println("消息重复,直接返回成功: " + messageId);
return;
}
try {
// 2. 首次处理消息
processBusinessLogic(message);
// 3. 确认消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + messageId);
} catch (Exception e) {
// 4. 处理失败,删除幂等标记(允许重试)
redisTemplate.delete(key);
// 拒绝消息并重新入队
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败,允许重试: " + e.getMessage());
}
}
private void processBusinessLogic(String message) {
// 实际业务逻辑
System.out.println("处理业务逻辑: " + message);
}
} private static final String MESSAGE_ID_PREFIX = "message:processed:";`
`#/**
* 基于 Redis 的幂等性实现
*
* 核心思路:
* 1. 每条消息生成唯一ID
* 2. 处理前检查Redis是否已存在该ID
* 3. 处理完成后将ID写入Redis
*/
@Service
public class IdempotentConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
private static final String MESSAGE_ID_PREFIX = "message:processed:";
@RabbitListener(queues = "durable.queue")
public void handleIdempotentMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag,
@Header(AmqpHeaders.MESSAGE_ID) String messageId) throws IOException {
// 1. 检查消息是否已处理
String key = MESSAGE_ID_PREFIX + messageId;
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(key, "processed", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 消息已处理过,直接确认(幂等返回)
channel.basicAck(deliveryTag, false);
System.out.println("消息重复,直接返回成功: " + messageId);
return;
}
try {
// 2. 首次处理消息
processBusinessLogic(message);
// 3. 确认消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + messageId);
} catch (Exception e) {
// 4. 处理失败,删除幂等标记(允许重试)
redisTemplate.delete(key);
// 拒绝消息并重新入队
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败,允许重试: " + e.getMessage());
}
}
private void processBusinessLogic(String message) {
// 实际业务逻辑
System.out.println("处理业务逻辑: " + message);
}
}`
`#/**
* 基于 Redis 的幂等性实现
*
* 核心思路:
* 1. 每条消息生成唯一ID
* 2. 处理前检查Redis是否已存在该ID
* 3. 处理完成后将ID写入Redis
*/
@Service
public class IdempotentConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
private static final String MESSAGE_ID_PREFIX = "message:processed:";
@RabbitListener(queues = "durable.queue")
public void handleIdempotentMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag,
@Header(AmqpHeaders.MESSAGE_ID) String messageId) throws IOException {
// 1. 检查消息是否已处理
String key = MESSAGE_ID_PREFIX + messageId;
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(key, "processed", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 消息已处理过,直接确认(幂等返回)
channel.basicAck(deliveryTag, false);
System.out.println("消息重复,直接返回成功: " + messageId);
return;
}
try {
// 2. 首次处理消息
processBusinessLogic(message);
// 3. 确认消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + messageId);
} catch (Exception e) {
// 4. 处理失败,删除幂等标记(允许重试)
redisTemplate.delete(key);
// 拒绝消息并重新入队
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败,允许重试: " + e.getMessage());
}
}
private void processBusinessLogic(String message) {
// 实际业务逻辑
System.out.println("处理业务逻辑: " + message);
}
} @RabbitListener(queues = "durable.queue")`
`#/**
* 基于 Redis 的幂等性实现
*
* 核心思路:
* 1. 每条消息生成唯一ID
* 2. 处理前检查Redis是否已存在该ID
* 3. 处理完成后将ID写入Redis
*/
@Service
public class IdempotentConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
private static final String MESSAGE_ID_PREFIX = "message:processed:";
@RabbitListener(queues = "durable.queue")
public void handleIdempotentMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag,
@Header(AmqpHeaders.MESSAGE_ID) String messageId) throws IOException {
// 1. 检查消息是否已处理
String key = MESSAGE_ID_PREFIX + messageId;
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(key, "processed", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 消息已处理过,直接确认(幂等返回)
channel.basicAck(deliveryTag, false);
System.out.println("消息重复,直接返回成功: " + messageId);
return;
}
try {
// 2. 首次处理消息
processBusinessLogic(message);
// 3. 确认消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + messageId);
} catch (Exception e) {
// 4. 处理失败,删除幂等标记(允许重试)
redisTemplate.delete(key);
// 拒绝消息并重新入队
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败,允许重试: " + e.getMessage());
}
}
private void processBusinessLogic(String message) {
// 实际业务逻辑
System.out.println("处理业务逻辑: " + message);
}
} public void handleIdempotentMessage(`
`#/**
* 基于 Redis 的幂等性实现
*
* 核心思路:
* 1. 每条消息生成唯一ID
* 2. 处理前检查Redis是否已存在该ID
* 3. 处理完成后将ID写入Redis
*/
@Service
public class IdempotentConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
private static final String MESSAGE_ID_PREFIX = "message:processed:";
@RabbitListener(queues = "durable.queue")
public void handleIdempotentMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag,
@Header(AmqpHeaders.MESSAGE_ID) String messageId) throws IOException {
// 1. 检查消息是否已处理
String key = MESSAGE_ID_PREFIX + messageId;
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(key, "processed", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 消息已处理过,直接确认(幂等返回)
channel.basicAck(deliveryTag, false);
System.out.println("消息重复,直接返回成功: " + messageId);
return;
}
try {
// 2. 首次处理消息
processBusinessLogic(message);
// 3. 确认消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + messageId);
} catch (Exception e) {
// 4. 处理失败,删除幂等标记(允许重试)
redisTemplate.delete(key);
// 拒绝消息并重新入队
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败,允许重试: " + e.getMessage());
}
}
private void processBusinessLogic(String message) {
// 实际业务逻辑
System.out.println("处理业务逻辑: " + message);
}
} String message,`
`#/**
* 基于 Redis 的幂等性实现
*
* 核心思路:
* 1. 每条消息生成唯一ID
* 2. 处理前检查Redis是否已存在该ID
* 3. 处理完成后将ID写入Redis
*/
@Service
public class IdempotentConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
private static final String MESSAGE_ID_PREFIX = "message:processed:";
@RabbitListener(queues = "durable.queue")
public void handleIdempotentMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag,
@Header(AmqpHeaders.MESSAGE_ID) String messageId) throws IOException {
// 1. 检查消息是否已处理
String key = MESSAGE_ID_PREFIX + messageId;
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(key, "processed", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 消息已处理过,直接确认(幂等返回)
channel.basicAck(deliveryTag, false);
System.out.println("消息重复,直接返回成功: " + messageId);
return;
}
try {
// 2. 首次处理消息
processBusinessLogic(message);
// 3. 确认消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + messageId);
} catch (Exception e) {
// 4. 处理失败,删除幂等标记(允许重试)
redisTemplate.delete(key);
// 拒绝消息并重新入队
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败,允许重试: " + e.getMessage());
}
}
private void processBusinessLogic(String message) {
// 实际业务逻辑
System.out.println("处理业务逻辑: " + message);
}
} Channel channel,`
`#/**
* 基于 Redis 的幂等性实现
*
* 核心思路:
* 1. 每条消息生成唯一ID
* 2. 处理前检查Redis是否已存在该ID
* 3. 处理完成后将ID写入Redis
*/
@Service
public class IdempotentConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
private static final String MESSAGE_ID_PREFIX = "message:processed:";
@RabbitListener(queues = "durable.queue")
public void handleIdempotentMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag,
@Header(AmqpHeaders.MESSAGE_ID) String messageId) throws IOException {
// 1. 检查消息是否已处理
String key = MESSAGE_ID_PREFIX + messageId;
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(key, "processed", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 消息已处理过,直接确认(幂等返回)
channel.basicAck(deliveryTag, false);
System.out.println("消息重复,直接返回成功: " + messageId);
return;
}
try {
// 2. 首次处理消息
processBusinessLogic(message);
// 3. 确认消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + messageId);
} catch (Exception e) {
// 4. 处理失败,删除幂等标记(允许重试)
redisTemplate.delete(key);
// 拒绝消息并重新入队
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败,允许重试: " + e.getMessage());
}
}
private void processBusinessLogic(String message) {
// 实际业务逻辑
System.out.println("处理业务逻辑: " + message);
}
} @Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag,`
`#/**
* 基于 Redis 的幂等性实现
*
* 核心思路:
* 1. 每条消息生成唯一ID
* 2. 处理前检查Redis是否已存在该ID
* 3. 处理完成后将ID写入Redis
*/
@Service
public class IdempotentConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
private static final String MESSAGE_ID_PREFIX = "message:processed:";
@RabbitListener(queues = "durable.queue")
public void handleIdempotentMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag,
@Header(AmqpHeaders.MESSAGE_ID) String messageId) throws IOException {
// 1. 检查消息是否已处理
String key = MESSAGE_ID_PREFIX + messageId;
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(key, "processed", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 消息已处理过,直接确认(幂等返回)
channel.basicAck(deliveryTag, false);
System.out.println("消息重复,直接返回成功: " + messageId);
return;
}
try {
// 2. 首次处理消息
processBusinessLogic(message);
// 3. 确认消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + messageId);
} catch (Exception e) {
// 4. 处理失败,删除幂等标记(允许重试)
redisTemplate.delete(key);
// 拒绝消息并重新入队
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败,允许重试: " + e.getMessage());
}
}
private void processBusinessLogic(String message) {
// 实际业务逻辑
System.out.println("处理业务逻辑: " + message);
}
} @Header(AmqpHeaders.MESSAGE_ID) String messageId) throws IOException {`
`#/**
* 基于 Redis 的幂等性实现
*
* 核心思路:
* 1. 每条消息生成唯一ID
* 2. 处理前检查Redis是否已存在该ID
* 3. 处理完成后将ID写入Redis
*/
@Service
public class IdempotentConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
private static final String MESSAGE_ID_PREFIX = "message:processed:";
@RabbitListener(queues = "durable.queue")
public void handleIdempotentMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag,
@Header(AmqpHeaders.MESSAGE_ID) String messageId) throws IOException {
// 1. 检查消息是否已处理
String key = MESSAGE_ID_PREFIX + messageId;
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(key, "processed", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 消息已处理过,直接确认(幂等返回)
channel.basicAck(deliveryTag, false);
System.out.println("消息重复,直接返回成功: " + messageId);
return;
}
try {
// 2. 首次处理消息
processBusinessLogic(message);
// 3. 确认消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + messageId);
} catch (Exception e) {
// 4. 处理失败,删除幂等标记(允许重试)
redisTemplate.delete(key);
// 拒绝消息并重新入队
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败,允许重试: " + e.getMessage());
}
}
private void processBusinessLogic(String message) {
// 实际业务逻辑
System.out.println("处理业务逻辑: " + message);
}
} `
`#/**
* 基于 Redis 的幂等性实现
*
* 核心思路:
* 1. 每条消息生成唯一ID
* 2. 处理前检查Redis是否已存在该ID
* 3. 处理完成后将ID写入Redis
*/
@Service
public class IdempotentConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
private static final String MESSAGE_ID_PREFIX = "message:processed:";
@RabbitListener(queues = "durable.queue")
public void handleIdempotentMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag,
@Header(AmqpHeaders.MESSAGE_ID) String messageId) throws IOException {
// 1. 检查消息是否已处理
String key = MESSAGE_ID_PREFIX + messageId;
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(key, "processed", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 消息已处理过,直接确认(幂等返回)
channel.basicAck(deliveryTag, false);
System.out.println("消息重复,直接返回成功: " + messageId);
return;
}
try {
// 2. 首次处理消息
processBusinessLogic(message);
// 3. 确认消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + messageId);
} catch (Exception e) {
// 4. 处理失败,删除幂等标记(允许重试)
redisTemplate.delete(key);
// 拒绝消息并重新入队
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败,允许重试: " + e.getMessage());
}
}
private void processBusinessLogic(String message) {
// 实际业务逻辑
System.out.println("处理业务逻辑: " + message);
}
} // 1. 检查消息是否已处理`
`#/**
* 基于 Redis 的幂等性实现
*
* 核心思路:
* 1. 每条消息生成唯一ID
* 2. 处理前检查Redis是否已存在该ID
* 3. 处理完成后将ID写入Redis
*/
@Service
public class IdempotentConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
private static final String MESSAGE_ID_PREFIX = "message:processed:";
@RabbitListener(queues = "durable.queue")
public void handleIdempotentMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag,
@Header(AmqpHeaders.MESSAGE_ID) String messageId) throws IOException {
// 1. 检查消息是否已处理
String key = MESSAGE_ID_PREFIX + messageId;
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(key, "processed", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 消息已处理过,直接确认(幂等返回)
channel.basicAck(deliveryTag, false);
System.out.println("消息重复,直接返回成功: " + messageId);
return;
}
try {
// 2. 首次处理消息
processBusinessLogic(message);
// 3. 确认消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + messageId);
} catch (Exception e) {
// 4. 处理失败,删除幂等标记(允许重试)
redisTemplate.delete(key);
// 拒绝消息并重新入队
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败,允许重试: " + e.getMessage());
}
}
private void processBusinessLogic(String message) {
// 实际业务逻辑
System.out.println("处理业务逻辑: " + message);
}
} String key = MESSAGE_ID_PREFIX + messageId;`
`#/**
* 基于 Redis 的幂等性实现
*
* 核心思路:
* 1. 每条消息生成唯一ID
* 2. 处理前检查Redis是否已存在该ID
* 3. 处理完成后将ID写入Redis
*/
@Service
public class IdempotentConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
private static final String MESSAGE_ID_PREFIX = "message:processed:";
@RabbitListener(queues = "durable.queue")
public void handleIdempotentMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag,
@Header(AmqpHeaders.MESSAGE_ID) String messageId) throws IOException {
// 1. 检查消息是否已处理
String key = MESSAGE_ID_PREFIX + messageId;
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(key, "processed", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 消息已处理过,直接确认(幂等返回)
channel.basicAck(deliveryTag, false);
System.out.println("消息重复,直接返回成功: " + messageId);
return;
}
try {
// 2. 首次处理消息
processBusinessLogic(message);
// 3. 确认消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + messageId);
} catch (Exception e) {
// 4. 处理失败,删除幂等标记(允许重试)
redisTemplate.delete(key);
// 拒绝消息并重新入队
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败,允许重试: " + e.getMessage());
}
}
private void processBusinessLogic(String message) {
// 实际业务逻辑
System.out.println("处理业务逻辑: " + message);
}
} Boolean isFirstTime = redisTemplate.opsForValue()`
`#/**
* 基于 Redis 的幂等性实现
*
* 核心思路:
* 1. 每条消息生成唯一ID
* 2. 处理前检查Redis是否已存在该ID
* 3. 处理完成后将ID写入Redis
*/
@Service
public class IdempotentConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
private static final String MESSAGE_ID_PREFIX = "message:processed:";
@RabbitListener(queues = "durable.queue")
public void handleIdempotentMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag,
@Header(AmqpHeaders.MESSAGE_ID) String messageId) throws IOException {
// 1. 检查消息是否已处理
String key = MESSAGE_ID_PREFIX + messageId;
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(key, "processed", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 消息已处理过,直接确认(幂等返回)
channel.basicAck(deliveryTag, false);
System.out.println("消息重复,直接返回成功: " + messageId);
return;
}
try {
// 2. 首次处理消息
processBusinessLogic(message);
// 3. 确认消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + messageId);
} catch (Exception e) {
// 4. 处理失败,删除幂等标记(允许重试)
redisTemplate.delete(key);
// 拒绝消息并重新入队
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败,允许重试: " + e.getMessage());
}
}
private void processBusinessLogic(String message) {
// 实际业务逻辑
System.out.println("处理业务逻辑: " + message);
}
} .setIfAbsent(key, "processed", 24, TimeUnit.HOURS);`
`#/**
* 基于 Redis 的幂等性实现
*
* 核心思路:
* 1. 每条消息生成唯一ID
* 2. 处理前检查Redis是否已存在该ID
* 3. 处理完成后将ID写入Redis
*/
@Service
public class IdempotentConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
private static final String MESSAGE_ID_PREFIX = "message:processed:";
@RabbitListener(queues = "durable.queue")
public void handleIdempotentMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag,
@Header(AmqpHeaders.MESSAGE_ID) String messageId) throws IOException {
// 1. 检查消息是否已处理
String key = MESSAGE_ID_PREFIX + messageId;
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(key, "processed", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 消息已处理过,直接确认(幂等返回)
channel.basicAck(deliveryTag, false);
System.out.println("消息重复,直接返回成功: " + messageId);
return;
}
try {
// 2. 首次处理消息
processBusinessLogic(message);
// 3. 确认消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + messageId);
} catch (Exception e) {
// 4. 处理失败,删除幂等标记(允许重试)
redisTemplate.delete(key);
// 拒绝消息并重新入队
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败,允许重试: " + e.getMessage());
}
}
private void processBusinessLogic(String message) {
// 实际业务逻辑
System.out.println("处理业务逻辑: " + message);
}
} `
`#/**
* 基于 Redis 的幂等性实现
*
* 核心思路:
* 1. 每条消息生成唯一ID
* 2. 处理前检查Redis是否已存在该ID
* 3. 处理完成后将ID写入Redis
*/
@Service
public class IdempotentConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
private static final String MESSAGE_ID_PREFIX = "message:processed:";
@RabbitListener(queues = "durable.queue")
public void handleIdempotentMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag,
@Header(AmqpHeaders.MESSAGE_ID) String messageId) throws IOException {
// 1. 检查消息是否已处理
String key = MESSAGE_ID_PREFIX + messageId;
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(key, "processed", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 消息已处理过,直接确认(幂等返回)
channel.basicAck(deliveryTag, false);
System.out.println("消息重复,直接返回成功: " + messageId);
return;
}
try {
// 2. 首次处理消息
processBusinessLogic(message);
// 3. 确认消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + messageId);
} catch (Exception e) {
// 4. 处理失败,删除幂等标记(允许重试)
redisTemplate.delete(key);
// 拒绝消息并重新入队
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败,允许重试: " + e.getMessage());
}
}
private void processBusinessLogic(String message) {
// 实际业务逻辑
System.out.println("处理业务逻辑: " + message);
}
} if (Boolean.FALSE.equals(isFirstTime)) {`
`#/**
* 基于 Redis 的幂等性实现
*
* 核心思路:
* 1. 每条消息生成唯一ID
* 2. 处理前检查Redis是否已存在该ID
* 3. 处理完成后将ID写入Redis
*/
@Service
public class IdempotentConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
private static final String MESSAGE_ID_PREFIX = "message:processed:";
@RabbitListener(queues = "durable.queue")
public void handleIdempotentMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag,
@Header(AmqpHeaders.MESSAGE_ID) String messageId) throws IOException {
// 1. 检查消息是否已处理
String key = MESSAGE_ID_PREFIX + messageId;
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(key, "processed", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 消息已处理过,直接确认(幂等返回)
channel.basicAck(deliveryTag, false);
System.out.println("消息重复,直接返回成功: " + messageId);
return;
}
try {
// 2. 首次处理消息
processBusinessLogic(message);
// 3. 确认消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + messageId);
} catch (Exception e) {
// 4. 处理失败,删除幂等标记(允许重试)
redisTemplate.delete(key);
// 拒绝消息并重新入队
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败,允许重试: " + e.getMessage());
}
}
private void processBusinessLogic(String message) {
// 实际业务逻辑
System.out.println("处理业务逻辑: " + message);
}
} // 消息已处理过,直接确认(幂等返回)`
`#/**
* 基于 Redis 的幂等性实现
*
* 核心思路:
* 1. 每条消息生成唯一ID
* 2. 处理前检查Redis是否已存在该ID
* 3. 处理完成后将ID写入Redis
*/
@Service
public class IdempotentConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
private static final String MESSAGE_ID_PREFIX = "message:processed:";
@RabbitListener(queues = "durable.queue")
public void handleIdempotentMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag,
@Header(AmqpHeaders.MESSAGE_ID) String messageId) throws IOException {
// 1. 检查消息是否已处理
String key = MESSAGE_ID_PREFIX + messageId;
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(key, "processed", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 消息已处理过,直接确认(幂等返回)
channel.basicAck(deliveryTag, false);
System.out.println("消息重复,直接返回成功: " + messageId);
return;
}
try {
// 2. 首次处理消息
processBusinessLogic(message);
// 3. 确认消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + messageId);
} catch (Exception e) {
// 4. 处理失败,删除幂等标记(允许重试)
redisTemplate.delete(key);
// 拒绝消息并重新入队
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败,允许重试: " + e.getMessage());
}
}
private void processBusinessLogic(String message) {
// 实际业务逻辑
System.out.println("处理业务逻辑: " + message);
}
} channel.basicAck(deliveryTag, false);`
`#/**
* 基于 Redis 的幂等性实现
*
* 核心思路:
* 1. 每条消息生成唯一ID
* 2. 处理前检查Redis是否已存在该ID
* 3. 处理完成后将ID写入Redis
*/
@Service
public class IdempotentConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
private static final String MESSAGE_ID_PREFIX = "message:processed:";
@RabbitListener(queues = "durable.queue")
public void handleIdempotentMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag,
@Header(AmqpHeaders.MESSAGE_ID) String messageId) throws IOException {
// 1. 检查消息是否已处理
String key = MESSAGE_ID_PREFIX + messageId;
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(key, "processed", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 消息已处理过,直接确认(幂等返回)
channel.basicAck(deliveryTag, false);
System.out.println("消息重复,直接返回成功: " + messageId);
return;
}
try {
// 2. 首次处理消息
processBusinessLogic(message);
// 3. 确认消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + messageId);
} catch (Exception e) {
// 4. 处理失败,删除幂等标记(允许重试)
redisTemplate.delete(key);
// 拒绝消息并重新入队
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败,允许重试: " + e.getMessage());
}
}
private void processBusinessLogic(String message) {
// 实际业务逻辑
System.out.println("处理业务逻辑: " + message);
}
} System.out.println("消息重复,直接返回成功: " + messageId);`
`#/**
* 基于 Redis 的幂等性实现
*
* 核心思路:
* 1. 每条消息生成唯一ID
* 2. 处理前检查Redis是否已存在该ID
* 3. 处理完成后将ID写入Redis
*/
@Service
public class IdempotentConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
private static final String MESSAGE_ID_PREFIX = "message:processed:";
@RabbitListener(queues = "durable.queue")
public void handleIdempotentMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag,
@Header(AmqpHeaders.MESSAGE_ID) String messageId) throws IOException {
// 1. 检查消息是否已处理
String key = MESSAGE_ID_PREFIX + messageId;
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(key, "processed", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 消息已处理过,直接确认(幂等返回)
channel.basicAck(deliveryTag, false);
System.out.println("消息重复,直接返回成功: " + messageId);
return;
}
try {
// 2. 首次处理消息
processBusinessLogic(message);
// 3. 确认消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + messageId);
} catch (Exception e) {
// 4. 处理失败,删除幂等标记(允许重试)
redisTemplate.delete(key);
// 拒绝消息并重新入队
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败,允许重试: " + e.getMessage());
}
}
private void processBusinessLogic(String message) {
// 实际业务逻辑
System.out.println("处理业务逻辑: " + message);
}
} return;`
`#/**
* 基于 Redis 的幂等性实现
*
* 核心思路:
* 1. 每条消息生成唯一ID
* 2. 处理前检查Redis是否已存在该ID
* 3. 处理完成后将ID写入Redis
*/
@Service
public class IdempotentConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
private static final String MESSAGE_ID_PREFIX = "message:processed:";
@RabbitListener(queues = "durable.queue")
public void handleIdempotentMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag,
@Header(AmqpHeaders.MESSAGE_ID) String messageId) throws IOException {
// 1. 检查消息是否已处理
String key = MESSAGE_ID_PREFIX + messageId;
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(key, "processed", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 消息已处理过,直接确认(幂等返回)
channel.basicAck(deliveryTag, false);
System.out.println("消息重复,直接返回成功: " + messageId);
return;
}
try {
// 2. 首次处理消息
processBusinessLogic(message);
// 3. 确认消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + messageId);
} catch (Exception e) {
// 4. 处理失败,删除幂等标记(允许重试)
redisTemplate.delete(key);
// 拒绝消息并重新入队
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败,允许重试: " + e.getMessage());
}
}
private void processBusinessLogic(String message) {
// 实际业务逻辑
System.out.println("处理业务逻辑: " + message);
}
} }`
`#/**
* 基于 Redis 的幂等性实现
*
* 核心思路:
* 1. 每条消息生成唯一ID
* 2. 处理前检查Redis是否已存在该ID
* 3. 处理完成后将ID写入Redis
*/
@Service
public class IdempotentConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
private static final String MESSAGE_ID_PREFIX = "message:processed:";
@RabbitListener(queues = "durable.queue")
public void handleIdempotentMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag,
@Header(AmqpHeaders.MESSAGE_ID) String messageId) throws IOException {
// 1. 检查消息是否已处理
String key = MESSAGE_ID_PREFIX + messageId;
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(key, "processed", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 消息已处理过,直接确认(幂等返回)
channel.basicAck(deliveryTag, false);
System.out.println("消息重复,直接返回成功: " + messageId);
return;
}
try {
// 2. 首次处理消息
processBusinessLogic(message);
// 3. 确认消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + messageId);
} catch (Exception e) {
// 4. 处理失败,删除幂等标记(允许重试)
redisTemplate.delete(key);
// 拒绝消息并重新入队
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败,允许重试: " + e.getMessage());
}
}
private void processBusinessLogic(String message) {
// 实际业务逻辑
System.out.println("处理业务逻辑: " + message);
}
} `
`#/**
* 基于 Redis 的幂等性实现
*
* 核心思路:
* 1. 每条消息生成唯一ID
* 2. 处理前检查Redis是否已存在该ID
* 3. 处理完成后将ID写入Redis
*/
@Service
public class IdempotentConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
private static final String MESSAGE_ID_PREFIX = "message:processed:";
@RabbitListener(queues = "durable.queue")
public void handleIdempotentMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag,
@Header(AmqpHeaders.MESSAGE_ID) String messageId) throws IOException {
// 1. 检查消息是否已处理
String key = MESSAGE_ID_PREFIX + messageId;
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(key, "processed", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 消息已处理过,直接确认(幂等返回)
channel.basicAck(deliveryTag, false);
System.out.println("消息重复,直接返回成功: " + messageId);
return;
}
try {
// 2. 首次处理消息
processBusinessLogic(message);
// 3. 确认消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + messageId);
} catch (Exception e) {
// 4. 处理失败,删除幂等标记(允许重试)
redisTemplate.delete(key);
// 拒绝消息并重新入队
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败,允许重试: " + e.getMessage());
}
}
private void processBusinessLogic(String message) {
// 实际业务逻辑
System.out.println("处理业务逻辑: " + message);
}
} try {`
`#/**
* 基于 Redis 的幂等性实现
*
* 核心思路:
* 1. 每条消息生成唯一ID
* 2. 处理前检查Redis是否已存在该ID
* 3. 处理完成后将ID写入Redis
*/
@Service
public class IdempotentConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
private static final String MESSAGE_ID_PREFIX = "message:processed:";
@RabbitListener(queues = "durable.queue")
public void handleIdempotentMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag,
@Header(AmqpHeaders.MESSAGE_ID) String messageId) throws IOException {
// 1. 检查消息是否已处理
String key = MESSAGE_ID_PREFIX + messageId;
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(key, "processed", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 消息已处理过,直接确认(幂等返回)
channel.basicAck(deliveryTag, false);
System.out.println("消息重复,直接返回成功: " + messageId);
return;
}
try {
// 2. 首次处理消息
processBusinessLogic(message);
// 3. 确认消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + messageId);
} catch (Exception e) {
// 4. 处理失败,删除幂等标记(允许重试)
redisTemplate.delete(key);
// 拒绝消息并重新入队
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败,允许重试: " + e.getMessage());
}
}
private void processBusinessLogic(String message) {
// 实际业务逻辑
System.out.println("处理业务逻辑: " + message);
}
} // 2. 首次处理消息`
`#/**
* 基于 Redis 的幂等性实现
*
* 核心思路:
* 1. 每条消息生成唯一ID
* 2. 处理前检查Redis是否已存在该ID
* 3. 处理完成后将ID写入Redis
*/
@Service
public class IdempotentConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
private static final String MESSAGE_ID_PREFIX = "message:processed:";
@RabbitListener(queues = "durable.queue")
public void handleIdempotentMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag,
@Header(AmqpHeaders.MESSAGE_ID) String messageId) throws IOException {
// 1. 检查消息是否已处理
String key = MESSAGE_ID_PREFIX + messageId;
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(key, "processed", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 消息已处理过,直接确认(幂等返回)
channel.basicAck(deliveryTag, false);
System.out.println("消息重复,直接返回成功: " + messageId);
return;
}
try {
// 2. 首次处理消息
processBusinessLogic(message);
// 3. 确认消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + messageId);
} catch (Exception e) {
// 4. 处理失败,删除幂等标记(允许重试)
redisTemplate.delete(key);
// 拒绝消息并重新入队
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败,允许重试: " + e.getMessage());
}
}
private void processBusinessLogic(String message) {
// 实际业务逻辑
System.out.println("处理业务逻辑: " + message);
}
} processBusinessLogic(message);`
`#/**
* 基于 Redis 的幂等性实现
*
* 核心思路:
* 1. 每条消息生成唯一ID
* 2. 处理前检查Redis是否已存在该ID
* 3. 处理完成后将ID写入Redis
*/
@Service
public class IdempotentConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
private static final String MESSAGE_ID_PREFIX = "message:processed:";
@RabbitListener(queues = "durable.queue")
public void handleIdempotentMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag,
@Header(AmqpHeaders.MESSAGE_ID) String messageId) throws IOException {
// 1. 检查消息是否已处理
String key = MESSAGE_ID_PREFIX + messageId;
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(key, "processed", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 消息已处理过,直接确认(幂等返回)
channel.basicAck(deliveryTag, false);
System.out.println("消息重复,直接返回成功: " + messageId);
return;
}
try {
// 2. 首次处理消息
processBusinessLogic(message);
// 3. 确认消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + messageId);
} catch (Exception e) {
// 4. 处理失败,删除幂等标记(允许重试)
redisTemplate.delete(key);
// 拒绝消息并重新入队
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败,允许重试: " + e.getMessage());
}
}
private void processBusinessLogic(String message) {
// 实际业务逻辑
System.out.println("处理业务逻辑: " + message);
}
} `
`#/**
* 基于 Redis 的幂等性实现
*
* 核心思路:
* 1. 每条消息生成唯一ID
* 2. 处理前检查Redis是否已存在该ID
* 3. 处理完成后将ID写入Redis
*/
@Service
public class IdempotentConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
private static final String MESSAGE_ID_PREFIX = "message:processed:";
@RabbitListener(queues = "durable.queue")
public void handleIdempotentMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag,
@Header(AmqpHeaders.MESSAGE_ID) String messageId) throws IOException {
// 1. 检查消息是否已处理
String key = MESSAGE_ID_PREFIX + messageId;
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(key, "processed", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 消息已处理过,直接确认(幂等返回)
channel.basicAck(deliveryTag, false);
System.out.println("消息重复,直接返回成功: " + messageId);
return;
}
try {
// 2. 首次处理消息
processBusinessLogic(message);
// 3. 确认消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + messageId);
} catch (Exception e) {
// 4. 处理失败,删除幂等标记(允许重试)
redisTemplate.delete(key);
// 拒绝消息并重新入队
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败,允许重试: " + e.getMessage());
}
}
private void processBusinessLogic(String message) {
// 实际业务逻辑
System.out.println("处理业务逻辑: " + message);
}
} // 3. 确认消息`
`#/**
* 基于 Redis 的幂等性实现
*
* 核心思路:
* 1. 每条消息生成唯一ID
* 2. 处理前检查Redis是否已存在该ID
* 3. 处理完成后将ID写入Redis
*/
@Service
public class IdempotentConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
private static final String MESSAGE_ID_PREFIX = "message:processed:";
@RabbitListener(queues = "durable.queue")
public void handleIdempotentMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag,
@Header(AmqpHeaders.MESSAGE_ID) String messageId) throws IOException {
// 1. 检查消息是否已处理
String key = MESSAGE_ID_PREFIX + messageId;
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(key, "processed", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 消息已处理过,直接确认(幂等返回)
channel.basicAck(deliveryTag, false);
System.out.println("消息重复,直接返回成功: " + messageId);
return;
}
try {
// 2. 首次处理消息
processBusinessLogic(message);
// 3. 确认消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + messageId);
} catch (Exception e) {
// 4. 处理失败,删除幂等标记(允许重试)
redisTemplate.delete(key);
// 拒绝消息并重新入队
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败,允许重试: " + e.getMessage());
}
}
private void processBusinessLogic(String message) {
// 实际业务逻辑
System.out.println("处理业务逻辑: " + message);
}
} channel.basicAck(deliveryTag, false);`
`#/**
* 基于 Redis 的幂等性实现
*
* 核心思路:
* 1. 每条消息生成唯一ID
* 2. 处理前检查Redis是否已存在该ID
* 3. 处理完成后将ID写入Redis
*/
@Service
public class IdempotentConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
private static final String MESSAGE_ID_PREFIX = "message:processed:";
@RabbitListener(queues = "durable.queue")
public void handleIdempotentMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag,
@Header(AmqpHeaders.MESSAGE_ID) String messageId) throws IOException {
// 1. 检查消息是否已处理
String key = MESSAGE_ID_PREFIX + messageId;
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(key, "processed", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 消息已处理过,直接确认(幂等返回)
channel.basicAck(deliveryTag, false);
System.out.println("消息重复,直接返回成功: " + messageId);
return;
}
try {
// 2. 首次处理消息
processBusinessLogic(message);
// 3. 确认消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + messageId);
} catch (Exception e) {
// 4. 处理失败,删除幂等标记(允许重试)
redisTemplate.delete(key);
// 拒绝消息并重新入队
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败,允许重试: " + e.getMessage());
}
}
private void processBusinessLogic(String message) {
// 实际业务逻辑
System.out.println("处理业务逻辑: " + message);
}
} System.out.println("消息处理成功: " + messageId);`
`#/**
* 基于 Redis 的幂等性实现
*
* 核心思路:
* 1. 每条消息生成唯一ID
* 2. 处理前检查Redis是否已存在该ID
* 3. 处理完成后将ID写入Redis
*/
@Service
public class IdempotentConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
private static final String MESSAGE_ID_PREFIX = "message:processed:";
@RabbitListener(queues = "durable.queue")
public void handleIdempotentMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag,
@Header(AmqpHeaders.MESSAGE_ID) String messageId) throws IOException {
// 1. 检查消息是否已处理
String key = MESSAGE_ID_PREFIX + messageId;
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(key, "processed", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 消息已处理过,直接确认(幂等返回)
channel.basicAck(deliveryTag, false);
System.out.println("消息重复,直接返回成功: " + messageId);
return;
}
try {
// 2. 首次处理消息
processBusinessLogic(message);
// 3. 确认消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + messageId);
} catch (Exception e) {
// 4. 处理失败,删除幂等标记(允许重试)
redisTemplate.delete(key);
// 拒绝消息并重新入队
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败,允许重试: " + e.getMessage());
}
}
private void processBusinessLogic(String message) {
// 实际业务逻辑
System.out.println("处理业务逻辑: " + message);
}
} `
`#/**
* 基于 Redis 的幂等性实现
*
* 核心思路:
* 1. 每条消息生成唯一ID
* 2. 处理前检查Redis是否已存在该ID
* 3. 处理完成后将ID写入Redis
*/
@Service
public class IdempotentConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
private static final String MESSAGE_ID_PREFIX = "message:processed:";
@RabbitListener(queues = "durable.queue")
public void handleIdempotentMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag,
@Header(AmqpHeaders.MESSAGE_ID) String messageId) throws IOException {
// 1. 检查消息是否已处理
String key = MESSAGE_ID_PREFIX + messageId;
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(key, "processed", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 消息已处理过,直接确认(幂等返回)
channel.basicAck(deliveryTag, false);
System.out.println("消息重复,直接返回成功: " + messageId);
return;
}
try {
// 2. 首次处理消息
processBusinessLogic(message);
// 3. 确认消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + messageId);
} catch (Exception e) {
// 4. 处理失败,删除幂等标记(允许重试)
redisTemplate.delete(key);
// 拒绝消息并重新入队
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败,允许重试: " + e.getMessage());
}
}
private void processBusinessLogic(String message) {
// 实际业务逻辑
System.out.println("处理业务逻辑: " + message);
}
} } catch (Exception e) {`
`#/**
* 基于 Redis 的幂等性实现
*
* 核心思路:
* 1. 每条消息生成唯一ID
* 2. 处理前检查Redis是否已存在该ID
* 3. 处理完成后将ID写入Redis
*/
@Service
public class IdempotentConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
private static final String MESSAGE_ID_PREFIX = "message:processed:";
@RabbitListener(queues = "durable.queue")
public void handleIdempotentMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag,
@Header(AmqpHeaders.MESSAGE_ID) String messageId) throws IOException {
// 1. 检查消息是否已处理
String key = MESSAGE_ID_PREFIX + messageId;
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(key, "processed", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 消息已处理过,直接确认(幂等返回)
channel.basicAck(deliveryTag, false);
System.out.println("消息重复,直接返回成功: " + messageId);
return;
}
try {
// 2. 首次处理消息
processBusinessLogic(message);
// 3. 确认消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + messageId);
} catch (Exception e) {
// 4. 处理失败,删除幂等标记(允许重试)
redisTemplate.delete(key);
// 拒绝消息并重新入队
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败,允许重试: " + e.getMessage());
}
}
private void processBusinessLogic(String message) {
// 实际业务逻辑
System.out.println("处理业务逻辑: " + message);
}
} // 4. 处理失败,删除幂等标记(允许重试)`
`#/**
* 基于 Redis 的幂等性实现
*
* 核心思路:
* 1. 每条消息生成唯一ID
* 2. 处理前检查Redis是否已存在该ID
* 3. 处理完成后将ID写入Redis
*/
@Service
public class IdempotentConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
private static final String MESSAGE_ID_PREFIX = "message:processed:";
@RabbitListener(queues = "durable.queue")
public void handleIdempotentMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag,
@Header(AmqpHeaders.MESSAGE_ID) String messageId) throws IOException {
// 1. 检查消息是否已处理
String key = MESSAGE_ID_PREFIX + messageId;
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(key, "processed", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 消息已处理过,直接确认(幂等返回)
channel.basicAck(deliveryTag, false);
System.out.println("消息重复,直接返回成功: " + messageId);
return;
}
try {
// 2. 首次处理消息
processBusinessLogic(message);
// 3. 确认消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + messageId);
} catch (Exception e) {
// 4. 处理失败,删除幂等标记(允许重试)
redisTemplate.delete(key);
// 拒绝消息并重新入队
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败,允许重试: " + e.getMessage());
}
}
private void processBusinessLogic(String message) {
// 实际业务逻辑
System.out.println("处理业务逻辑: " + message);
}
} redisTemplate.delete(key);`
`#/**
* 基于 Redis 的幂等性实现
*
* 核心思路:
* 1. 每条消息生成唯一ID
* 2. 处理前检查Redis是否已存在该ID
* 3. 处理完成后将ID写入Redis
*/
@Service
public class IdempotentConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
private static final String MESSAGE_ID_PREFIX = "message:processed:";
@RabbitListener(queues = "durable.queue")
public void handleIdempotentMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag,
@Header(AmqpHeaders.MESSAGE_ID) String messageId) throws IOException {
// 1. 检查消息是否已处理
String key = MESSAGE_ID_PREFIX + messageId;
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(key, "processed", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 消息已处理过,直接确认(幂等返回)
channel.basicAck(deliveryTag, false);
System.out.println("消息重复,直接返回成功: " + messageId);
return;
}
try {
// 2. 首次处理消息
processBusinessLogic(message);
// 3. 确认消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + messageId);
} catch (Exception e) {
// 4. 处理失败,删除幂等标记(允许重试)
redisTemplate.delete(key);
// 拒绝消息并重新入队
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败,允许重试: " + e.getMessage());
}
}
private void processBusinessLogic(String message) {
// 实际业务逻辑
System.out.println("处理业务逻辑: " + message);
}
} `
`#/**
* 基于 Redis 的幂等性实现
*
* 核心思路:
* 1. 每条消息生成唯一ID
* 2. 处理前检查Redis是否已存在该ID
* 3. 处理完成后将ID写入Redis
*/
@Service
public class IdempotentConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
private static final String MESSAGE_ID_PREFIX = "message:processed:";
@RabbitListener(queues = "durable.queue")
public void handleIdempotentMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag,
@Header(AmqpHeaders.MESSAGE_ID) String messageId) throws IOException {
// 1. 检查消息是否已处理
String key = MESSAGE_ID_PREFIX + messageId;
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(key, "processed", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 消息已处理过,直接确认(幂等返回)
channel.basicAck(deliveryTag, false);
System.out.println("消息重复,直接返回成功: " + messageId);
return;
}
try {
// 2. 首次处理消息
processBusinessLogic(message);
// 3. 确认消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + messageId);
} catch (Exception e) {
// 4. 处理失败,删除幂等标记(允许重试)
redisTemplate.delete(key);
// 拒绝消息并重新入队
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败,允许重试: " + e.getMessage());
}
}
private void processBusinessLogic(String message) {
// 实际业务逻辑
System.out.println("处理业务逻辑: " + message);
}
} // 拒绝消息并重新入队`
`#/**
* 基于 Redis 的幂等性实现
*
* 核心思路:
* 1. 每条消息生成唯一ID
* 2. 处理前检查Redis是否已存在该ID
* 3. 处理完成后将ID写入Redis
*/
@Service
public class IdempotentConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
private static final String MESSAGE_ID_PREFIX = "message:processed:";
@RabbitListener(queues = "durable.queue")
public void handleIdempotentMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag,
@Header(AmqpHeaders.MESSAGE_ID) String messageId) throws IOException {
// 1. 检查消息是否已处理
String key = MESSAGE_ID_PREFIX + messageId;
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(key, "processed", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 消息已处理过,直接确认(幂等返回)
channel.basicAck(deliveryTag, false);
System.out.println("消息重复,直接返回成功: " + messageId);
return;
}
try {
// 2. 首次处理消息
processBusinessLogic(message);
// 3. 确认消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + messageId);
} catch (Exception e) {
// 4. 处理失败,删除幂等标记(允许重试)
redisTemplate.delete(key);
// 拒绝消息并重新入队
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败,允许重试: " + e.getMessage());
}
}
private void processBusinessLogic(String message) {
// 实际业务逻辑
System.out.println("处理业务逻辑: " + message);
}
} channel.basicNack(deliveryTag, false, true);`
`#/**
* 基于 Redis 的幂等性实现
*
* 核心思路:
* 1. 每条消息生成唯一ID
* 2. 处理前检查Redis是否已存在该ID
* 3. 处理完成后将ID写入Redis
*/
@Service
public class IdempotentConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
private static final String MESSAGE_ID_PREFIX = "message:processed:";
@RabbitListener(queues = "durable.queue")
public void handleIdempotentMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag,
@Header(AmqpHeaders.MESSAGE_ID) String messageId) throws IOException {
// 1. 检查消息是否已处理
String key = MESSAGE_ID_PREFIX + messageId;
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(key, "processed", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 消息已处理过,直接确认(幂等返回)
channel.basicAck(deliveryTag, false);
System.out.println("消息重复,直接返回成功: " + messageId);
return;
}
try {
// 2. 首次处理消息
processBusinessLogic(message);
// 3. 确认消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + messageId);
} catch (Exception e) {
// 4. 处理失败,删除幂等标记(允许重试)
redisTemplate.delete(key);
// 拒绝消息并重新入队
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败,允许重试: " + e.getMessage());
}
}
private void processBusinessLogic(String message) {
// 实际业务逻辑
System.out.println("处理业务逻辑: " + message);
}
} System.err.println("消息处理失败,允许重试: " + e.getMessage());`
`#/**
* 基于 Redis 的幂等性实现
*
* 核心思路:
* 1. 每条消息生成唯一ID
* 2. 处理前检查Redis是否已存在该ID
* 3. 处理完成后将ID写入Redis
*/
@Service
public class IdempotentConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
private static final String MESSAGE_ID_PREFIX = "message:processed:";
@RabbitListener(queues = "durable.queue")
public void handleIdempotentMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag,
@Header(AmqpHeaders.MESSAGE_ID) String messageId) throws IOException {
// 1. 检查消息是否已处理
String key = MESSAGE_ID_PREFIX + messageId;
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(key, "processed", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 消息已处理过,直接确认(幂等返回)
channel.basicAck(deliveryTag, false);
System.out.println("消息重复,直接返回成功: " + messageId);
return;
}
try {
// 2. 首次处理消息
processBusinessLogic(message);
// 3. 确认消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + messageId);
} catch (Exception e) {
// 4. 处理失败,删除幂等标记(允许重试)
redisTemplate.delete(key);
// 拒绝消息并重新入队
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败,允许重试: " + e.getMessage());
}
}
private void processBusinessLogic(String message) {
// 实际业务逻辑
System.out.println("处理业务逻辑: " + message);
}
} }`
`#/**
* 基于 Redis 的幂等性实现
*
* 核心思路:
* 1. 每条消息生成唯一ID
* 2. 处理前检查Redis是否已存在该ID
* 3. 处理完成后将ID写入Redis
*/
@Service
public class IdempotentConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
private static final String MESSAGE_ID_PREFIX = "message:processed:";
@RabbitListener(queues = "durable.queue")
public void handleIdempotentMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag,
@Header(AmqpHeaders.MESSAGE_ID) String messageId) throws IOException {
// 1. 检查消息是否已处理
String key = MESSAGE_ID_PREFIX + messageId;
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(key, "processed", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 消息已处理过,直接确认(幂等返回)
channel.basicAck(deliveryTag, false);
System.out.println("消息重复,直接返回成功: " + messageId);
return;
}
try {
// 2. 首次处理消息
processBusinessLogic(message);
// 3. 确认消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + messageId);
} catch (Exception e) {
// 4. 处理失败,删除幂等标记(允许重试)
redisTemplate.delete(key);
// 拒绝消息并重新入队
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败,允许重试: " + e.getMessage());
}
}
private void processBusinessLogic(String message) {
// 实际业务逻辑
System.out.println("处理业务逻辑: " + message);
}
} }`
`#/**
* 基于 Redis 的幂等性实现
*
* 核心思路:
* 1. 每条消息生成唯一ID
* 2. 处理前检查Redis是否已存在该ID
* 3. 处理完成后将ID写入Redis
*/
@Service
public class IdempotentConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
private static final String MESSAGE_ID_PREFIX = "message:processed:";
@RabbitListener(queues = "durable.queue")
public void handleIdempotentMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag,
@Header(AmqpHeaders.MESSAGE_ID) String messageId) throws IOException {
// 1. 检查消息是否已处理
String key = MESSAGE_ID_PREFIX + messageId;
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(key, "processed", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 消息已处理过,直接确认(幂等返回)
channel.basicAck(deliveryTag, false);
System.out.println("消息重复,直接返回成功: " + messageId);
return;
}
try {
// 2. 首次处理消息
processBusinessLogic(message);
// 3. 确认消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + messageId);
} catch (Exception e) {
// 4. 处理失败,删除幂等标记(允许重试)
redisTemplate.delete(key);
// 拒绝消息并重新入队
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败,允许重试: " + e.getMessage());
}
}
private void processBusinessLogic(String message) {
// 实际业务逻辑
System.out.println("处理业务逻辑: " + message);
}
}`
`#/**
* 基于 Redis 的幂等性实现
*
* 核心思路:
* 1. 每条消息生成唯一ID
* 2. 处理前检查Redis是否已存在该ID
* 3. 处理完成后将ID写入Redis
*/
@Service
public class IdempotentConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
private static final String MESSAGE_ID_PREFIX = "message:processed:";
@RabbitListener(queues = "durable.queue")
public void handleIdempotentMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag,
@Header(AmqpHeaders.MESSAGE_ID) String messageId) throws IOException {
// 1. 检查消息是否已处理
String key = MESSAGE_ID_PREFIX + messageId;
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(key, "processed", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 消息已处理过,直接确认(幂等返回)
channel.basicAck(deliveryTag, false);
System.out.println("消息重复,直接返回成功: " + messageId);
return;
}
try {
// 2. 首次处理消息
processBusinessLogic(message);
// 3. 确认消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + messageId);
} catch (Exception e) {
// 4. 处理失败,删除幂等标记(允许重试)
redisTemplate.delete(key);
// 拒绝消息并重新入队
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败,允许重试: " + e.getMessage());
}
}
private void processBusinessLogic(String message) {
// 实际业务逻辑
System.out.println("处理业务逻辑: " + message);
}
} private void processBusinessLogic(String message) {`
`#/**
* 基于 Redis 的幂等性实现
*
* 核心思路:
* 1. 每条消息生成唯一ID
* 2. 处理前检查Redis是否已存在该ID
* 3. 处理完成后将ID写入Redis
*/
@Service
public class IdempotentConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
private static final String MESSAGE_ID_PREFIX = "message:processed:";
@RabbitListener(queues = "durable.queue")
public void handleIdempotentMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag,
@Header(AmqpHeaders.MESSAGE_ID) String messageId) throws IOException {
// 1. 检查消息是否已处理
String key = MESSAGE_ID_PREFIX + messageId;
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(key, "processed", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 消息已处理过,直接确认(幂等返回)
channel.basicAck(deliveryTag, false);
System.out.println("消息重复,直接返回成功: " + messageId);
return;
}
try {
// 2. 首次处理消息
processBusinessLogic(message);
// 3. 确认消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + messageId);
} catch (Exception e) {
// 4. 处理失败,删除幂等标记(允许重试)
redisTemplate.delete(key);
// 拒绝消息并重新入队
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败,允许重试: " + e.getMessage());
}
}
private void processBusinessLogic(String message) {
// 实际业务逻辑
System.out.println("处理业务逻辑: " + message);
}
} // 实际业务逻辑`
`#/**
* 基于 Redis 的幂等性实现
*
* 核心思路:
* 1. 每条消息生成唯一ID
* 2. 处理前检查Redis是否已存在该ID
* 3. 处理完成后将ID写入Redis
*/
@Service
public class IdempotentConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
private static final String MESSAGE_ID_PREFIX = "message:processed:";
@RabbitListener(queues = "durable.queue")
public void handleIdempotentMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag,
@Header(AmqpHeaders.MESSAGE_ID) String messageId) throws IOException {
// 1. 检查消息是否已处理
String key = MESSAGE_ID_PREFIX + messageId;
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(key, "processed", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 消息已处理过,直接确认(幂等返回)
channel.basicAck(deliveryTag, false);
System.out.println("消息重复,直接返回成功: " + messageId);
return;
}
try {
// 2. 首次处理消息
processBusinessLogic(message);
// 3. 确认消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + messageId);
} catch (Exception e) {
// 4. 处理失败,删除幂等标记(允许重试)
redisTemplate.delete(key);
// 拒绝消息并重新入队
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败,允许重试: " + e.getMessage());
}
}
private void processBusinessLogic(String message) {
// 实际业务逻辑
System.out.println("处理业务逻辑: " + message);
}
} System.out.println("处理业务逻辑: " + message);`
`#/**
* 基于 Redis 的幂等性实现
*
* 核心思路:
* 1. 每条消息生成唯一ID
* 2. 处理前检查Redis是否已存在该ID
* 3. 处理完成后将ID写入Redis
*/
@Service
public class IdempotentConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
private static final String MESSAGE_ID_PREFIX = "message:processed:";
@RabbitListener(queues = "durable.queue")
public void handleIdempotentMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag,
@Header(AmqpHeaders.MESSAGE_ID) String messageId) throws IOException {
// 1. 检查消息是否已处理
String key = MESSAGE_ID_PREFIX + messageId;
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(key, "processed", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 消息已处理过,直接确认(幂等返回)
channel.basicAck(deliveryTag, false);
System.out.println("消息重复,直接返回成功: " + messageId);
return;
}
try {
// 2. 首次处理消息
processBusinessLogic(message);
// 3. 确认消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + messageId);
} catch (Exception e) {
// 4. 处理失败,删除幂等标记(允许重试)
redisTemplate.delete(key);
// 拒绝消息并重新入队
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败,允许重试: " + e.getMessage());
}
}
private void processBusinessLogic(String message) {
// 实际业务逻辑
System.out.println("处理业务逻辑: " + message);
}
} }`
`#/**
* 基于 Redis 的幂等性实现
*
* 核心思路:
* 1. 每条消息生成唯一ID
* 2. 处理前检查Redis是否已存在该ID
* 3. 处理完成后将ID写入Redis
*/
@Service
public class IdempotentConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
private static final String MESSAGE_ID_PREFIX = "message:processed:";
@RabbitListener(queues = "durable.queue")
public void handleIdempotentMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag,
@Header(AmqpHeaders.MESSAGE_ID) String messageId) throws IOException {
// 1. 检查消息是否已处理
String key = MESSAGE_ID_PREFIX + messageId;
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(key, "processed", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 消息已处理过,直接确认(幂等返回)
channel.basicAck(deliveryTag, false);
System.out.println("消息重复,直接返回成功: " + messageId);
return;
}
try {
// 2. 首次处理消息
processBusinessLogic(message);
// 3. 确认消息
channel.basicAck(deliveryTag, false);
System.out.println("消息处理成功: " + messageId);
} catch (Exception e) {
// 4. 处理失败,删除幂等标记(允许重试)
redisTemplate.delete(key);
// 拒绝消息并重新入队
channel.basicNack(deliveryTag, false, true);
System.err.println("消息处理失败,允许重试: " + e.getMessage());
}
}
private void processBusinessLogic(String message) {
// 实际业务逻辑
System.out.println("处理业务逻辑: " + message);
}
}}
4. 死信队列:异常处理的最后一道防线
4.1 死信队列的触发场景
死信(Dead Letter)是无法被正常消费的消息。RabbitMQ 在以下情况下将消息路由到死信队列:
graph TD
A[消息进入队列] --> B{消费情况}
B -->|basicNack<br/>requeue=false| C[进入死信队列]
B -->|basicReject<br/>requeue=false| C
B -->|消息过期| C
B -->|队列达到最大长度| C
B -->|正常消费| D[消息正常处理完成]
C --> E[死信队列处理器]
E --> F{分析死因}
F -->|可修复| G[修复后重新投递]
F -->|不可修复| H[记录日志<br/>人工介入]
style C fill:#ffe1e1
style E fill:#fff4e1
style H fill:#ffe1e1
4.2 死信队列配置实战
4.2.1 声明死信交换机和队列
java
#/**
* 死信队列完整配置
*
* 配置要点:
* 1. 业务队列配置 x-dead-letter-exchange 指向死信交换机
* 2. 死信队列绑定到死信交换机
* 3. 死信队列也需持久化
*/
@Configuration
public class DeadLetterConfig {
// ========== 死信交换机和队列 ==========
@Bean
public DirectExchange deadLetterExchange() {
return new DirectExchange("dead.letter.exchange", true, false);
}
@Bean
public Queue deadLetterQueue() {
return QueueBuilder
.durable("dead.letter.queue")
.ttl(60000) // 死信消息也设置TTL,防止无限堆积
.build();
}
@Bean
public Binding deadLetterBinding() {
return BindingBuilder
.bind(deadLetterQueue())
.to(deadLetterExchange())
.with("dead.letter.routing.key");
}
// ========== 业务队列(配置死信转发) ==========
@Bean
public Queue businessQueue() {
return QueueBuilder
.durable("business.queue")
// 关键配置:指定死信交换机
.withArgument("x-dead-letter-exchange", "dead.letter.exchange")
// 指定死信路由键(可选,默认使用原队列的路由键)
.withArgument("x-dead-letter-routing-key", "dead.letter.routing.key")
// 消息TTL(示例:30秒未消费则进入死信队列)
.withArgument("x-message-ttl", 30000)
// 队列最大长度(超出则进入死信队列)
.withArgument("x-max-length", 10000)
.build();
}
@Bean
public DirectExchange businessExchange() {
return new DirectExchange("business.exchange", true, false);
}
@Bean
public Binding businessBinding() {
return BindingBuilder
.bind(businessQueue())
.to(businessExchange())
.with("business.routing.key");
}
}/**`
`#/**
* 死信队列完整配置
*
* 配置要点:
* 1. 业务队列配置 x-dead-letter-exchange 指向死信交换机
* 2. 死信队列绑定到死信交换机
* 3. 死信队列也需持久化
*/
@Configuration
public class DeadLetterConfig {
// ========== 死信交换机和队列 ==========
@Bean
public DirectExchange deadLetterExchange() {
return new DirectExchange("dead.letter.exchange", true, false);
}
@Bean
public Queue deadLetterQueue() {
return QueueBuilder
.durable("dead.letter.queue")
.ttl(60000) // 死信消息也设置TTL,防止无限堆积
.build();
}
@Bean
public Binding deadLetterBinding() {
return BindingBuilder
.bind(deadLetterQueue())
.to(deadLetterExchange())
.with("dead.letter.routing.key");
}
// ========== 业务队列(配置死信转发) ==========
@Bean
public Queue businessQueue() {
return QueueBuilder
.durable("business.queue")
// 关键配置:指定死信交换机
.withArgument("x-dead-letter-exchange", "dead.letter.exchange")
// 指定死信路由键(可选,默认使用原队列的路由键)
.withArgument("x-dead-letter-routing-key", "dead.letter.routing.key")
// 消息TTL(示例:30秒未消费则进入死信队列)
.withArgument("x-message-ttl", 30000)
// 队列最大长度(超出则进入死信队列)
.withArgument("x-max-length", 10000)
.build();
}
@Bean
public DirectExchange businessExchange() {
return new DirectExchange("business.exchange", true, false);
}
@Bean
public Binding businessBinding() {
return BindingBuilder
.bind(businessQueue())
.to(businessExchange())
.with("business.routing.key");
}
} * 死信队列完整配置`
`#/**
* 死信队列完整配置
*
* 配置要点:
* 1. 业务队列配置 x-dead-letter-exchange 指向死信交换机
* 2. 死信队列绑定到死信交换机
* 3. 死信队列也需持久化
*/
@Configuration
public class DeadLetterConfig {
// ========== 死信交换机和队列 ==========
@Bean
public DirectExchange deadLetterExchange() {
return new DirectExchange("dead.letter.exchange", true, false);
}
@Bean
public Queue deadLetterQueue() {
return QueueBuilder
.durable("dead.letter.queue")
.ttl(60000) // 死信消息也设置TTL,防止无限堆积
.build();
}
@Bean
public Binding deadLetterBinding() {
return BindingBuilder
.bind(deadLetterQueue())
.to(deadLetterExchange())
.with("dead.letter.routing.key");
}
// ========== 业务队列(配置死信转发) ==========
@Bean
public Queue businessQueue() {
return QueueBuilder
.durable("business.queue")
// 关键配置:指定死信交换机
.withArgument("x-dead-letter-exchange", "dead.letter.exchange")
// 指定死信路由键(可选,默认使用原队列的路由键)
.withArgument("x-dead-letter-routing-key", "dead.letter.routing.key")
// 消息TTL(示例:30秒未消费则进入死信队列)
.withArgument("x-message-ttl", 30000)
// 队列最大长度(超出则进入死信队列)
.withArgument("x-max-length", 10000)
.build();
}
@Bean
public DirectExchange businessExchange() {
return new DirectExchange("business.exchange", true, false);
}
@Bean
public Binding businessBinding() {
return BindingBuilder
.bind(businessQueue())
.to(businessExchange())
.with("business.routing.key");
}
} * `
`#/**
* 死信队列完整配置
*
* 配置要点:
* 1. 业务队列配置 x-dead-letter-exchange 指向死信交换机
* 2. 死信队列绑定到死信交换机
* 3. 死信队列也需持久化
*/
@Configuration
public class DeadLetterConfig {
// ========== 死信交换机和队列 ==========
@Bean
public DirectExchange deadLetterExchange() {
return new DirectExchange("dead.letter.exchange", true, false);
}
@Bean
public Queue deadLetterQueue() {
return QueueBuilder
.durable("dead.letter.queue")
.ttl(60000) // 死信消息也设置TTL,防止无限堆积
.build();
}
@Bean
public Binding deadLetterBinding() {
return BindingBuilder
.bind(deadLetterQueue())
.to(deadLetterExchange())
.with("dead.letter.routing.key");
}
// ========== 业务队列(配置死信转发) ==========
@Bean
public Queue businessQueue() {
return QueueBuilder
.durable("business.queue")
// 关键配置:指定死信交换机
.withArgument("x-dead-letter-exchange", "dead.letter.exchange")
// 指定死信路由键(可选,默认使用原队列的路由键)
.withArgument("x-dead-letter-routing-key", "dead.letter.routing.key")
// 消息TTL(示例:30秒未消费则进入死信队列)
.withArgument("x-message-ttl", 30000)
// 队列最大长度(超出则进入死信队列)
.withArgument("x-max-length", 10000)
.build();
}
@Bean
public DirectExchange businessExchange() {
return new DirectExchange("business.exchange", true, false);
}
@Bean
public Binding businessBinding() {
return BindingBuilder
.bind(businessQueue())
.to(businessExchange())
.with("business.routing.key");
}
} * 配置要点:`
`#/**
* 死信队列完整配置
*
* 配置要点:
* 1. 业务队列配置 x-dead-letter-exchange 指向死信交换机
* 2. 死信队列绑定到死信交换机
* 3. 死信队列也需持久化
*/
@Configuration
public class DeadLetterConfig {
// ========== 死信交换机和队列 ==========
@Bean
public DirectExchange deadLetterExchange() {
return new DirectExchange("dead.letter.exchange", true, false);
}
@Bean
public Queue deadLetterQueue() {
return QueueBuilder
.durable("dead.letter.queue")
.ttl(60000) // 死信消息也设置TTL,防止无限堆积
.build();
}
@Bean
public Binding deadLetterBinding() {
return BindingBuilder
.bind(deadLetterQueue())
.to(deadLetterExchange())
.with("dead.letter.routing.key");
}
// ========== 业务队列(配置死信转发) ==========
@Bean
public Queue businessQueue() {
return QueueBuilder
.durable("business.queue")
// 关键配置:指定死信交换机
.withArgument("x-dead-letter-exchange", "dead.letter.exchange")
// 指定死信路由键(可选,默认使用原队列的路由键)
.withArgument("x-dead-letter-routing-key", "dead.letter.routing.key")
// 消息TTL(示例:30秒未消费则进入死信队列)
.withArgument("x-message-ttl", 30000)
// 队列最大长度(超出则进入死信队列)
.withArgument("x-max-length", 10000)
.build();
}
@Bean
public DirectExchange businessExchange() {
return new DirectExchange("business.exchange", true, false);
}
@Bean
public Binding businessBinding() {
return BindingBuilder
.bind(businessQueue())
.to(businessExchange())
.with("business.routing.key");
}
} * 1. 业务队列配置 x-dead-letter-exchange 指向死信交换机`
`#/**
* 死信队列完整配置
*
* 配置要点:
* 1. 业务队列配置 x-dead-letter-exchange 指向死信交换机
* 2. 死信队列绑定到死信交换机
* 3. 死信队列也需持久化
*/
@Configuration
public class DeadLetterConfig {
// ========== 死信交换机和队列 ==========
@Bean
public DirectExchange deadLetterExchange() {
return new DirectExchange("dead.letter.exchange", true, false);
}
@Bean
public Queue deadLetterQueue() {
return QueueBuilder
.durable("dead.letter.queue")
.ttl(60000) // 死信消息也设置TTL,防止无限堆积
.build();
}
@Bean
public Binding deadLetterBinding() {
return BindingBuilder
.bind(deadLetterQueue())
.to(deadLetterExchange())
.with("dead.letter.routing.key");
}
// ========== 业务队列(配置死信转发) ==========
@Bean
public Queue businessQueue() {
return QueueBuilder
.durable("business.queue")
// 关键配置:指定死信交换机
.withArgument("x-dead-letter-exchange", "dead.letter.exchange")
// 指定死信路由键(可选,默认使用原队列的路由键)
.withArgument("x-dead-letter-routing-key", "dead.letter.routing.key")
// 消息TTL(示例:30秒未消费则进入死信队列)
.withArgument("x-message-ttl", 30000)
// 队列最大长度(超出则进入死信队列)
.withArgument("x-max-length", 10000)
.build();
}
@Bean
public DirectExchange businessExchange() {
return new DirectExchange("business.exchange", true, false);
}
@Bean
public Binding businessBinding() {
return BindingBuilder
.bind(businessQueue())
.to(businessExchange())
.with("business.routing.key");
}
} * 2. 死信队列绑定到死信交换机`
`#/**
* 死信队列完整配置
*
* 配置要点:
* 1. 业务队列配置 x-dead-letter-exchange 指向死信交换机
* 2. 死信队列绑定到死信交换机
* 3. 死信队列也需持久化
*/
@Configuration
public class DeadLetterConfig {
// ========== 死信交换机和队列 ==========
@Bean
public DirectExchange deadLetterExchange() {
return new DirectExchange("dead.letter.exchange", true, false);
}
@Bean
public Queue deadLetterQueue() {
return QueueBuilder
.durable("dead.letter.queue")
.ttl(60000) // 死信消息也设置TTL,防止无限堆积
.build();
}
@Bean
public Binding deadLetterBinding() {
return BindingBuilder
.bind(deadLetterQueue())
.to(deadLetterExchange())
.with("dead.letter.routing.key");
}
// ========== 业务队列(配置死信转发) ==========
@Bean
public Queue businessQueue() {
return QueueBuilder
.durable("business.queue")
// 关键配置:指定死信交换机
.withArgument("x-dead-letter-exchange", "dead.letter.exchange")
// 指定死信路由键(可选,默认使用原队列的路由键)
.withArgument("x-dead-letter-routing-key", "dead.letter.routing.key")
// 消息TTL(示例:30秒未消费则进入死信队列)
.withArgument("x-message-ttl", 30000)
// 队列最大长度(超出则进入死信队列)
.withArgument("x-max-length", 10000)
.build();
}
@Bean
public DirectExchange businessExchange() {
return new DirectExchange("business.exchange", true, false);
}
@Bean
public Binding businessBinding() {
return BindingBuilder
.bind(businessQueue())
.to(businessExchange())
.with("business.routing.key");
}
} * 3. 死信队列也需持久化`
`#/**
* 死信队列完整配置
*
* 配置要点:
* 1. 业务队列配置 x-dead-letter-exchange 指向死信交换机
* 2. 死信队列绑定到死信交换机
* 3. 死信队列也需持久化
*/
@Configuration
public class DeadLetterConfig {
// ========== 死信交换机和队列 ==========
@Bean
public DirectExchange deadLetterExchange() {
return new DirectExchange("dead.letter.exchange", true, false);
}
@Bean
public Queue deadLetterQueue() {
return QueueBuilder
.durable("dead.letter.queue")
.ttl(60000) // 死信消息也设置TTL,防止无限堆积
.build();
}
@Bean
public Binding deadLetterBinding() {
return BindingBuilder
.bind(deadLetterQueue())
.to(deadLetterExchange())
.with("dead.letter.routing.key");
}
// ========== 业务队列(配置死信转发) ==========
@Bean
public Queue businessQueue() {
return QueueBuilder
.durable("business.queue")
// 关键配置:指定死信交换机
.withArgument("x-dead-letter-exchange", "dead.letter.exchange")
// 指定死信路由键(可选,默认使用原队列的路由键)
.withArgument("x-dead-letter-routing-key", "dead.letter.routing.key")
// 消息TTL(示例:30秒未消费则进入死信队列)
.withArgument("x-message-ttl", 30000)
// 队列最大长度(超出则进入死信队列)
.withArgument("x-max-length", 10000)
.build();
}
@Bean
public DirectExchange businessExchange() {
return new DirectExchange("business.exchange", true, false);
}
@Bean
public Binding businessBinding() {
return BindingBuilder
.bind(businessQueue())
.to(businessExchange())
.with("business.routing.key");
}
} */`
`#/**
* 死信队列完整配置
*
* 配置要点:
* 1. 业务队列配置 x-dead-letter-exchange 指向死信交换机
* 2. 死信队列绑定到死信交换机
* 3. 死信队列也需持久化
*/
@Configuration
public class DeadLetterConfig {
// ========== 死信交换机和队列 ==========
@Bean
public DirectExchange deadLetterExchange() {
return new DirectExchange("dead.letter.exchange", true, false);
}
@Bean
public Queue deadLetterQueue() {
return QueueBuilder
.durable("dead.letter.queue")
.ttl(60000) // 死信消息也设置TTL,防止无限堆积
.build();
}
@Bean
public Binding deadLetterBinding() {
return BindingBuilder
.bind(deadLetterQueue())
.to(deadLetterExchange())
.with("dead.letter.routing.key");
}
// ========== 业务队列(配置死信转发) ==========
@Bean
public Queue businessQueue() {
return QueueBuilder
.durable("business.queue")
// 关键配置:指定死信交换机
.withArgument("x-dead-letter-exchange", "dead.letter.exchange")
// 指定死信路由键(可选,默认使用原队列的路由键)
.withArgument("x-dead-letter-routing-key", "dead.letter.routing.key")
// 消息TTL(示例:30秒未消费则进入死信队列)
.withArgument("x-message-ttl", 30000)
// 队列最大长度(超出则进入死信队列)
.withArgument("x-max-length", 10000)
.build();
}
@Bean
public DirectExchange businessExchange() {
return new DirectExchange("business.exchange", true, false);
}
@Bean
public Binding businessBinding() {
return BindingBuilder
.bind(businessQueue())
.to(businessExchange())
.with("business.routing.key");
}
}@Configuration`
`#/**
* 死信队列完整配置
*
* 配置要点:
* 1. 业务队列配置 x-dead-letter-exchange 指向死信交换机
* 2. 死信队列绑定到死信交换机
* 3. 死信队列也需持久化
*/
@Configuration
public class DeadLetterConfig {
// ========== 死信交换机和队列 ==========
@Bean
public DirectExchange deadLetterExchange() {
return new DirectExchange("dead.letter.exchange", true, false);
}
@Bean
public Queue deadLetterQueue() {
return QueueBuilder
.durable("dead.letter.queue")
.ttl(60000) // 死信消息也设置TTL,防止无限堆积
.build();
}
@Bean
public Binding deadLetterBinding() {
return BindingBuilder
.bind(deadLetterQueue())
.to(deadLetterExchange())
.with("dead.letter.routing.key");
}
// ========== 业务队列(配置死信转发) ==========
@Bean
public Queue businessQueue() {
return QueueBuilder
.durable("business.queue")
// 关键配置:指定死信交换机
.withArgument("x-dead-letter-exchange", "dead.letter.exchange")
// 指定死信路由键(可选,默认使用原队列的路由键)
.withArgument("x-dead-letter-routing-key", "dead.letter.routing.key")
// 消息TTL(示例:30秒未消费则进入死信队列)
.withArgument("x-message-ttl", 30000)
// 队列最大长度(超出则进入死信队列)
.withArgument("x-max-length", 10000)
.build();
}
@Bean
public DirectExchange businessExchange() {
return new DirectExchange("business.exchange", true, false);
}
@Bean
public Binding businessBinding() {
return BindingBuilder
.bind(businessQueue())
.to(businessExchange())
.with("business.routing.key");
}
}public class DeadLetterConfig {`
`#/**
* 死信队列完整配置
*
* 配置要点:
* 1. 业务队列配置 x-dead-letter-exchange 指向死信交换机
* 2. 死信队列绑定到死信交换机
* 3. 死信队列也需持久化
*/
@Configuration
public class DeadLetterConfig {
// ========== 死信交换机和队列 ==========
@Bean
public DirectExchange deadLetterExchange() {
return new DirectExchange("dead.letter.exchange", true, false);
}
@Bean
public Queue deadLetterQueue() {
return QueueBuilder
.durable("dead.letter.queue")
.ttl(60000) // 死信消息也设置TTL,防止无限堆积
.build();
}
@Bean
public Binding deadLetterBinding() {
return BindingBuilder
.bind(deadLetterQueue())
.to(deadLetterExchange())
.with("dead.letter.routing.key");
}
// ========== 业务队列(配置死信转发) ==========
@Bean
public Queue businessQueue() {
return QueueBuilder
.durable("business.queue")
// 关键配置:指定死信交换机
.withArgument("x-dead-letter-exchange", "dead.letter.exchange")
// 指定死信路由键(可选,默认使用原队列的路由键)
.withArgument("x-dead-letter-routing-key", "dead.letter.routing.key")
// 消息TTL(示例:30秒未消费则进入死信队列)
.withArgument("x-message-ttl", 30000)
// 队列最大长度(超出则进入死信队列)
.withArgument("x-max-length", 10000)
.build();
}
@Bean
public DirectExchange businessExchange() {
return new DirectExchange("business.exchange", true, false);
}
@Bean
public Binding businessBinding() {
return BindingBuilder
.bind(businessQueue())
.to(businessExchange())
.with("business.routing.key");
}
}`
`#/**
* 死信队列完整配置
*
* 配置要点:
* 1. 业务队列配置 x-dead-letter-exchange 指向死信交换机
* 2. 死信队列绑定到死信交换机
* 3. 死信队列也需持久化
*/
@Configuration
public class DeadLetterConfig {
// ========== 死信交换机和队列 ==========
@Bean
public DirectExchange deadLetterExchange() {
return new DirectExchange("dead.letter.exchange", true, false);
}
@Bean
public Queue deadLetterQueue() {
return QueueBuilder
.durable("dead.letter.queue")
.ttl(60000) // 死信消息也设置TTL,防止无限堆积
.build();
}
@Bean
public Binding deadLetterBinding() {
return BindingBuilder
.bind(deadLetterQueue())
.to(deadLetterExchange())
.with("dead.letter.routing.key");
}
// ========== 业务队列(配置死信转发) ==========
@Bean
public Queue businessQueue() {
return QueueBuilder
.durable("business.queue")
// 关键配置:指定死信交换机
.withArgument("x-dead-letter-exchange", "dead.letter.exchange")
// 指定死信路由键(可选,默认使用原队列的路由键)
.withArgument("x-dead-letter-routing-key", "dead.letter.routing.key")
// 消息TTL(示例:30秒未消费则进入死信队列)
.withArgument("x-message-ttl", 30000)
// 队列最大长度(超出则进入死信队列)
.withArgument("x-max-length", 10000)
.build();
}
@Bean
public DirectExchange businessExchange() {
return new DirectExchange("business.exchange", true, false);
}
@Bean
public Binding businessBinding() {
return BindingBuilder
.bind(businessQueue())
.to(businessExchange())
.with("business.routing.key");
}
} // ========== 死信交换机和队列 ==========`
`#/**
* 死信队列完整配置
*
* 配置要点:
* 1. 业务队列配置 x-dead-letter-exchange 指向死信交换机
* 2. 死信队列绑定到死信交换机
* 3. 死信队列也需持久化
*/
@Configuration
public class DeadLetterConfig {
// ========== 死信交换机和队列 ==========
@Bean
public DirectExchange deadLetterExchange() {
return new DirectExchange("dead.letter.exchange", true, false);
}
@Bean
public Queue deadLetterQueue() {
return QueueBuilder
.durable("dead.letter.queue")
.ttl(60000) // 死信消息也设置TTL,防止无限堆积
.build();
}
@Bean
public Binding deadLetterBinding() {
return BindingBuilder
.bind(deadLetterQueue())
.to(deadLetterExchange())
.with("dead.letter.routing.key");
}
// ========== 业务队列(配置死信转发) ==========
@Bean
public Queue businessQueue() {
return QueueBuilder
.durable("business.queue")
// 关键配置:指定死信交换机
.withArgument("x-dead-letter-exchange", "dead.letter.exchange")
// 指定死信路由键(可选,默认使用原队列的路由键)
.withArgument("x-dead-letter-routing-key", "dead.letter.routing.key")
// 消息TTL(示例:30秒未消费则进入死信队列)
.withArgument("x-message-ttl", 30000)
// 队列最大长度(超出则进入死信队列)
.withArgument("x-max-length", 10000)
.build();
}
@Bean
public DirectExchange businessExchange() {
return new DirectExchange("business.exchange", true, false);
}
@Bean
public Binding businessBinding() {
return BindingBuilder
.bind(businessQueue())
.to(businessExchange())
.with("business.routing.key");
}
} `
`#/**
* 死信队列完整配置
*
* 配置要点:
* 1. 业务队列配置 x-dead-letter-exchange 指向死信交换机
* 2. 死信队列绑定到死信交换机
* 3. 死信队列也需持久化
*/
@Configuration
public class DeadLetterConfig {
// ========== 死信交换机和队列 ==========
@Bean
public DirectExchange deadLetterExchange() {
return new DirectExchange("dead.letter.exchange", true, false);
}
@Bean
public Queue deadLetterQueue() {
return QueueBuilder
.durable("dead.letter.queue")
.ttl(60000) // 死信消息也设置TTL,防止无限堆积
.build();
}
@Bean
public Binding deadLetterBinding() {
return BindingBuilder
.bind(deadLetterQueue())
.to(deadLetterExchange())
.with("dead.letter.routing.key");
}
// ========== 业务队列(配置死信转发) ==========
@Bean
public Queue businessQueue() {
return QueueBuilder
.durable("business.queue")
// 关键配置:指定死信交换机
.withArgument("x-dead-letter-exchange", "dead.letter.exchange")
// 指定死信路由键(可选,默认使用原队列的路由键)
.withArgument("x-dead-letter-routing-key", "dead.letter.routing.key")
// 消息TTL(示例:30秒未消费则进入死信队列)
.withArgument("x-message-ttl", 30000)
// 队列最大长度(超出则进入死信队列)
.withArgument("x-max-length", 10000)
.build();
}
@Bean
public DirectExchange businessExchange() {
return new DirectExchange("business.exchange", true, false);
}
@Bean
public Binding businessBinding() {
return BindingBuilder
.bind(businessQueue())
.to(businessExchange())
.with("business.routing.key");
}
} @Bean`
`#/**
* 死信队列完整配置
*
* 配置要点:
* 1. 业务队列配置 x-dead-letter-exchange 指向死信交换机
* 2. 死信队列绑定到死信交换机
* 3. 死信队列也需持久化
*/
@Configuration
public class DeadLetterConfig {
// ========== 死信交换机和队列 ==========
@Bean
public DirectExchange deadLetterExchange() {
return new DirectExchange("dead.letter.exchange", true, false);
}
@Bean
public Queue deadLetterQueue() {
return QueueBuilder
.durable("dead.letter.queue")
.ttl(60000) // 死信消息也设置TTL,防止无限堆积
.build();
}
@Bean
public Binding deadLetterBinding() {
return BindingBuilder
.bind(deadLetterQueue())
.to(deadLetterExchange())
.with("dead.letter.routing.key");
}
// ========== 业务队列(配置死信转发) ==========
@Bean
public Queue businessQueue() {
return QueueBuilder
.durable("business.queue")
// 关键配置:指定死信交换机
.withArgument("x-dead-letter-exchange", "dead.letter.exchange")
// 指定死信路由键(可选,默认使用原队列的路由键)
.withArgument("x-dead-letter-routing-key", "dead.letter.routing.key")
// 消息TTL(示例:30秒未消费则进入死信队列)
.withArgument("x-message-ttl", 30000)
// 队列最大长度(超出则进入死信队列)
.withArgument("x-max-length", 10000)
.build();
}
@Bean
public DirectExchange businessExchange() {
return new DirectExchange("business.exchange", true, false);
}
@Bean
public Binding businessBinding() {
return BindingBuilder
.bind(businessQueue())
.to(businessExchange())
.with("business.routing.key");
}
} public DirectExchange deadLetterExchange() {`
`#/**
* 死信队列完整配置
*
* 配置要点:
* 1. 业务队列配置 x-dead-letter-exchange 指向死信交换机
* 2. 死信队列绑定到死信交换机
* 3. 死信队列也需持久化
*/
@Configuration
public class DeadLetterConfig {
// ========== 死信交换机和队列 ==========
@Bean
public DirectExchange deadLetterExchange() {
return new DirectExchange("dead.letter.exchange", true, false);
}
@Bean
public Queue deadLetterQueue() {
return QueueBuilder
.durable("dead.letter.queue")
.ttl(60000) // 死信消息也设置TTL,防止无限堆积
.build();
}
@Bean
public Binding deadLetterBinding() {
return BindingBuilder
.bind(deadLetterQueue())
.to(deadLetterExchange())
.with("dead.letter.routing.key");
}
// ========== 业务队列(配置死信转发) ==========
@Bean
public Queue businessQueue() {
return QueueBuilder
.durable("business.queue")
// 关键配置:指定死信交换机
.withArgument("x-dead-letter-exchange", "dead.letter.exchange")
// 指定死信路由键(可选,默认使用原队列的路由键)
.withArgument("x-dead-letter-routing-key", "dead.letter.routing.key")
// 消息TTL(示例:30秒未消费则进入死信队列)
.withArgument("x-message-ttl", 30000)
// 队列最大长度(超出则进入死信队列)
.withArgument("x-max-length", 10000)
.build();
}
@Bean
public DirectExchange businessExchange() {
return new DirectExchange("business.exchange", true, false);
}
@Bean
public Binding businessBinding() {
return BindingBuilder
.bind(businessQueue())
.to(businessExchange())
.with("business.routing.key");
}
} return new DirectExchange("dead.letter.exchange", true, false);`
`#/**
* 死信队列完整配置
*
* 配置要点:
* 1. 业务队列配置 x-dead-letter-exchange 指向死信交换机
* 2. 死信队列绑定到死信交换机
* 3. 死信队列也需持久化
*/
@Configuration
public class DeadLetterConfig {
// ========== 死信交换机和队列 ==========
@Bean
public DirectExchange deadLetterExchange() {
return new DirectExchange("dead.letter.exchange", true, false);
}
@Bean
public Queue deadLetterQueue() {
return QueueBuilder
.durable("dead.letter.queue")
.ttl(60000) // 死信消息也设置TTL,防止无限堆积
.build();
}
@Bean
public Binding deadLetterBinding() {
return BindingBuilder
.bind(deadLetterQueue())
.to(deadLetterExchange())
.with("dead.letter.routing.key");
}
// ========== 业务队列(配置死信转发) ==========
@Bean
public Queue businessQueue() {
return QueueBuilder
.durable("business.queue")
// 关键配置:指定死信交换机
.withArgument("x-dead-letter-exchange", "dead.letter.exchange")
// 指定死信路由键(可选,默认使用原队列的路由键)
.withArgument("x-dead-letter-routing-key", "dead.letter.routing.key")
// 消息TTL(示例:30秒未消费则进入死信队列)
.withArgument("x-message-ttl", 30000)
// 队列最大长度(超出则进入死信队列)
.withArgument("x-max-length", 10000)
.build();
}
@Bean
public DirectExchange businessExchange() {
return new DirectExchange("business.exchange", true, false);
}
@Bean
public Binding businessBinding() {
return BindingBuilder
.bind(businessQueue())
.to(businessExchange())
.with("business.routing.key");
}
} }`
`#/**
* 死信队列完整配置
*
* 配置要点:
* 1. 业务队列配置 x-dead-letter-exchange 指向死信交换机
* 2. 死信队列绑定到死信交换机
* 3. 死信队列也需持久化
*/
@Configuration
public class DeadLetterConfig {
// ========== 死信交换机和队列 ==========
@Bean
public DirectExchange deadLetterExchange() {
return new DirectExchange("dead.letter.exchange", true, false);
}
@Bean
public Queue deadLetterQueue() {
return QueueBuilder
.durable("dead.letter.queue")
.ttl(60000) // 死信消息也设置TTL,防止无限堆积
.build();
}
@Bean
public Binding deadLetterBinding() {
return BindingBuilder
.bind(deadLetterQueue())
.to(deadLetterExchange())
.with("dead.letter.routing.key");
}
// ========== 业务队列(配置死信转发) ==========
@Bean
public Queue businessQueue() {
return QueueBuilder
.durable("business.queue")
// 关键配置:指定死信交换机
.withArgument("x-dead-letter-exchange", "dead.letter.exchange")
// 指定死信路由键(可选,默认使用原队列的路由键)
.withArgument("x-dead-letter-routing-key", "dead.letter.routing.key")
// 消息TTL(示例:30秒未消费则进入死信队列)
.withArgument("x-message-ttl", 30000)
// 队列最大长度(超出则进入死信队列)
.withArgument("x-max-length", 10000)
.build();
}
@Bean
public DirectExchange businessExchange() {
return new DirectExchange("business.exchange", true, false);
}
@Bean
public Binding businessBinding() {
return BindingBuilder
.bind(businessQueue())
.to(businessExchange())
.with("business.routing.key");
}
}`
`#/**
* 死信队列完整配置
*
* 配置要点:
* 1. 业务队列配置 x-dead-letter-exchange 指向死信交换机
* 2. 死信队列绑定到死信交换机
* 3. 死信队列也需持久化
*/
@Configuration
public class DeadLetterConfig {
// ========== 死信交换机和队列 ==========
@Bean
public DirectExchange deadLetterExchange() {
return new DirectExchange("dead.letter.exchange", true, false);
}
@Bean
public Queue deadLetterQueue() {
return QueueBuilder
.durable("dead.letter.queue")
.ttl(60000) // 死信消息也设置TTL,防止无限堆积
.build();
}
@Bean
public Binding deadLetterBinding() {
return BindingBuilder
.bind(deadLetterQueue())
.to(deadLetterExchange())
.with("dead.letter.routing.key");
}
// ========== 业务队列(配置死信转发) ==========
@Bean
public Queue businessQueue() {
return QueueBuilder
.durable("business.queue")
// 关键配置:指定死信交换机
.withArgument("x-dead-letter-exchange", "dead.letter.exchange")
// 指定死信路由键(可选,默认使用原队列的路由键)
.withArgument("x-dead-letter-routing-key", "dead.letter.routing.key")
// 消息TTL(示例:30秒未消费则进入死信队列)
.withArgument("x-message-ttl", 30000)
// 队列最大长度(超出则进入死信队列)
.withArgument("x-max-length", 10000)
.build();
}
@Bean
public DirectExchange businessExchange() {
return new DirectExchange("business.exchange", true, false);
}
@Bean
public Binding businessBinding() {
return BindingBuilder
.bind(businessQueue())
.to(businessExchange())
.with("business.routing.key");
}
} @Bean`
`#/**
* 死信队列完整配置
*
* 配置要点:
* 1. 业务队列配置 x-dead-letter-exchange 指向死信交换机
* 2. 死信队列绑定到死信交换机
* 3. 死信队列也需持久化
*/
@Configuration
public class DeadLetterConfig {
// ========== 死信交换机和队列 ==========
@Bean
public DirectExchange deadLetterExchange() {
return new DirectExchange("dead.letter.exchange", true, false);
}
@Bean
public Queue deadLetterQueue() {
return QueueBuilder
.durable("dead.letter.queue")
.ttl(60000) // 死信消息也设置TTL,防止无限堆积
.build();
}
@Bean
public Binding deadLetterBinding() {
return BindingBuilder
.bind(deadLetterQueue())
.to(deadLetterExchange())
.with("dead.letter.routing.key");
}
// ========== 业务队列(配置死信转发) ==========
@Bean
public Queue businessQueue() {
return QueueBuilder
.durable("business.queue")
// 关键配置:指定死信交换机
.withArgument("x-dead-letter-exchange", "dead.letter.exchange")
// 指定死信路由键(可选,默认使用原队列的路由键)
.withArgument("x-dead-letter-routing-key", "dead.letter.routing.key")
// 消息TTL(示例:30秒未消费则进入死信队列)
.withArgument("x-message-ttl", 30000)
// 队列最大长度(超出则进入死信队列)
.withArgument("x-max-length", 10000)
.build();
}
@Bean
public DirectExchange businessExchange() {
return new DirectExchange("business.exchange", true, false);
}
@Bean
public Binding businessBinding() {
return BindingBuilder
.bind(businessQueue())
.to(businessExchange())
.with("business.routing.key");
}
} public Queue deadLetterQueue() {`
`#/**
* 死信队列完整配置
*
* 配置要点:
* 1. 业务队列配置 x-dead-letter-exchange 指向死信交换机
* 2. 死信队列绑定到死信交换机
* 3. 死信队列也需持久化
*/
@Configuration
public class DeadLetterConfig {
// ========== 死信交换机和队列 ==========
@Bean
public DirectExchange deadLetterExchange() {
return new DirectExchange("dead.letter.exchange", true, false);
}
@Bean
public Queue deadLetterQueue() {
return QueueBuilder
.durable("dead.letter.queue")
.ttl(60000) // 死信消息也设置TTL,防止无限堆积
.build();
}
@Bean
public Binding deadLetterBinding() {
return BindingBuilder
.bind(deadLetterQueue())
.to(deadLetterExchange())
.with("dead.letter.routing.key");
}
// ========== 业务队列(配置死信转发) ==========
@Bean
public Queue businessQueue() {
return QueueBuilder
.durable("business.queue")
// 关键配置:指定死信交换机
.withArgument("x-dead-letter-exchange", "dead.letter.exchange")
// 指定死信路由键(可选,默认使用原队列的路由键)
.withArgument("x-dead-letter-routing-key", "dead.letter.routing.key")
// 消息TTL(示例:30秒未消费则进入死信队列)
.withArgument("x-message-ttl", 30000)
// 队列最大长度(超出则进入死信队列)
.withArgument("x-max-length", 10000)
.build();
}
@Bean
public DirectExchange businessExchange() {
return new DirectExchange("business.exchange", true, false);
}
@Bean
public Binding businessBinding() {
return BindingBuilder
.bind(businessQueue())
.to(businessExchange())
.with("business.routing.key");
}
} return QueueBuilder`
`#/**
* 死信队列完整配置
*
* 配置要点:
* 1. 业务队列配置 x-dead-letter-exchange 指向死信交换机
* 2. 死信队列绑定到死信交换机
* 3. 死信队列也需持久化
*/
@Configuration
public class DeadLetterConfig {
// ========== 死信交换机和队列 ==========
@Bean
public DirectExchange deadLetterExchange() {
return new DirectExchange("dead.letter.exchange", true, false);
}
@Bean
public Queue deadLetterQueue() {
return QueueBuilder
.durable("dead.letter.queue")
.ttl(60000) // 死信消息也设置TTL,防止无限堆积
.build();
}
@Bean
public Binding deadLetterBinding() {
return BindingBuilder
.bind(deadLetterQueue())
.to(deadLetterExchange())
.with("dead.letter.routing.key");
}
// ========== 业务队列(配置死信转发) ==========
@Bean
public Queue businessQueue() {
return QueueBuilder
.durable("business.queue")
// 关键配置:指定死信交换机
.withArgument("x-dead-letter-exchange", "dead.letter.exchange")
// 指定死信路由键(可选,默认使用原队列的路由键)
.withArgument("x-dead-letter-routing-key", "dead.letter.routing.key")
// 消息TTL(示例:30秒未消费则进入死信队列)
.withArgument("x-message-ttl", 30000)
// 队列最大长度(超出则进入死信队列)
.withArgument("x-max-length", 10000)
.build();
}
@Bean
public DirectExchange businessExchange() {
return new DirectExchange("business.exchange", true, false);
}
@Bean
public Binding businessBinding() {
return BindingBuilder
.bind(businessQueue())
.to(businessExchange())
.with("business.routing.key");
}
} .durable("dead.letter.queue")`
`#/**
* 死信队列完整配置
*
* 配置要点:
* 1. 业务队列配置 x-dead-letter-exchange 指向死信交换机
* 2. 死信队列绑定到死信交换机
* 3. 死信队列也需持久化
*/
@Configuration
public class DeadLetterConfig {
// ========== 死信交换机和队列 ==========
@Bean
public DirectExchange deadLetterExchange() {
return new DirectExchange("dead.letter.exchange", true, false);
}
@Bean
public Queue deadLetterQueue() {
return QueueBuilder
.durable("dead.letter.queue")
.ttl(60000) // 死信消息也设置TTL,防止无限堆积
.build();
}
@Bean
public Binding deadLetterBinding() {
return BindingBuilder
.bind(deadLetterQueue())
.to(deadLetterExchange())
.with("dead.letter.routing.key");
}
// ========== 业务队列(配置死信转发) ==========
@Bean
public Queue businessQueue() {
return QueueBuilder
.durable("business.queue")
// 关键配置:指定死信交换机
.withArgument("x-dead-letter-exchange", "dead.letter.exchange")
// 指定死信路由键(可选,默认使用原队列的路由键)
.withArgument("x-dead-letter-routing-key", "dead.letter.routing.key")
// 消息TTL(示例:30秒未消费则进入死信队列)
.withArgument("x-message-ttl", 30000)
// 队列最大长度(超出则进入死信队列)
.withArgument("x-max-length", 10000)
.build();
}
@Bean
public DirectExchange businessExchange() {
return new DirectExchange("business.exchange", true, false);
}
@Bean
public Binding businessBinding() {
return BindingBuilder
.bind(businessQueue())
.to(businessExchange())
.with("business.routing.key");
}
} .ttl(60000) // 死信消息也设置TTL,防止无限堆积`
`#/**
* 死信队列完整配置
*
* 配置要点:
* 1. 业务队列配置 x-dead-letter-exchange 指向死信交换机
* 2. 死信队列绑定到死信交换机
* 3. 死信队列也需持久化
*/
@Configuration
public class DeadLetterConfig {
// ========== 死信交换机和队列 ==========
@Bean
public DirectExchange deadLetterExchange() {
return new DirectExchange("dead.letter.exchange", true, false);
}
@Bean
public Queue deadLetterQueue() {
return QueueBuilder
.durable("dead.letter.queue")
.ttl(60000) // 死信消息也设置TTL,防止无限堆积
.build();
}
@Bean
public Binding deadLetterBinding() {
return BindingBuilder
.bind(deadLetterQueue())
.to(deadLetterExchange())
.with("dead.letter.routing.key");
}
// ========== 业务队列(配置死信转发) ==========
@Bean
public Queue businessQueue() {
return QueueBuilder
.durable("business.queue")
// 关键配置:指定死信交换机
.withArgument("x-dead-letter-exchange", "dead.letter.exchange")
// 指定死信路由键(可选,默认使用原队列的路由键)
.withArgument("x-dead-letter-routing-key", "dead.letter.routing.key")
// 消息TTL(示例:30秒未消费则进入死信队列)
.withArgument("x-message-ttl", 30000)
// 队列最大长度(超出则进入死信队列)
.withArgument("x-max-length", 10000)
.build();
}
@Bean
public DirectExchange businessExchange() {
return new DirectExchange("business.exchange", true, false);
}
@Bean
public Binding businessBinding() {
return BindingBuilder
.bind(businessQueue())
.to(businessExchange())
.with("business.routing.key");
}
} .build();`
`#/**
* 死信队列完整配置
*
* 配置要点:
* 1. 业务队列配置 x-dead-letter-exchange 指向死信交换机
* 2. 死信队列绑定到死信交换机
* 3. 死信队列也需持久化
*/
@Configuration
public class DeadLetterConfig {
// ========== 死信交换机和队列 ==========
@Bean
public DirectExchange deadLetterExchange() {
return new DirectExchange("dead.letter.exchange", true, false);
}
@Bean
public Queue deadLetterQueue() {
return QueueBuilder
.durable("dead.letter.queue")
.ttl(60000) // 死信消息也设置TTL,防止无限堆积
.build();
}
@Bean
public Binding deadLetterBinding() {
return BindingBuilder
.bind(deadLetterQueue())
.to(deadLetterExchange())
.with("dead.letter.routing.key");
}
// ========== 业务队列(配置死信转发) ==========
@Bean
public Queue businessQueue() {
return QueueBuilder
.durable("business.queue")
// 关键配置:指定死信交换机
.withArgument("x-dead-letter-exchange", "dead.letter.exchange")
// 指定死信路由键(可选,默认使用原队列的路由键)
.withArgument("x-dead-letter-routing-key", "dead.letter.routing.key")
// 消息TTL(示例:30秒未消费则进入死信队列)
.withArgument("x-message-ttl", 30000)
// 队列最大长度(超出则进入死信队列)
.withArgument("x-max-length", 10000)
.build();
}
@Bean
public DirectExchange businessExchange() {
return new DirectExchange("business.exchange", true, false);
}
@Bean
public Binding businessBinding() {
return BindingBuilder
.bind(businessQueue())
.to(businessExchange())
.with("business.routing.key");
}
} }`
`#/**
* 死信队列完整配置
*
* 配置要点:
* 1. 业务队列配置 x-dead-letter-exchange 指向死信交换机
* 2. 死信队列绑定到死信交换机
* 3. 死信队列也需持久化
*/
@Configuration
public class DeadLetterConfig {
// ========== 死信交换机和队列 ==========
@Bean
public DirectExchange deadLetterExchange() {
return new DirectExchange("dead.letter.exchange", true, false);
}
@Bean
public Queue deadLetterQueue() {
return QueueBuilder
.durable("dead.letter.queue")
.ttl(60000) // 死信消息也设置TTL,防止无限堆积
.build();
}
@Bean
public Binding deadLetterBinding() {
return BindingBuilder
.bind(deadLetterQueue())
.to(deadLetterExchange())
.with("dead.letter.routing.key");
}
// ========== 业务队列(配置死信转发) ==========
@Bean
public Queue businessQueue() {
return QueueBuilder
.durable("business.queue")
// 关键配置:指定死信交换机
.withArgument("x-dead-letter-exchange", "dead.letter.exchange")
// 指定死信路由键(可选,默认使用原队列的路由键)
.withArgument("x-dead-letter-routing-key", "dead.letter.routing.key")
// 消息TTL(示例:30秒未消费则进入死信队列)
.withArgument("x-message-ttl", 30000)
// 队列最大长度(超出则进入死信队列)
.withArgument("x-max-length", 10000)
.build();
}
@Bean
public DirectExchange businessExchange() {
return new DirectExchange("business.exchange", true, false);
}
@Bean
public Binding businessBinding() {
return BindingBuilder
.bind(businessQueue())
.to(businessExchange())
.with("business.routing.key");
}
}`
`#/**
* 死信队列完整配置
*
* 配置要点:
* 1. 业务队列配置 x-dead-letter-exchange 指向死信交换机
* 2. 死信队列绑定到死信交换机
* 3. 死信队列也需持久化
*/
@Configuration
public class DeadLetterConfig {
// ========== 死信交换机和队列 ==========
@Bean
public DirectExchange deadLetterExchange() {
return new DirectExchange("dead.letter.exchange", true, false);
}
@Bean
public Queue deadLetterQueue() {
return QueueBuilder
.durable("dead.letter.queue")
.ttl(60000) // 死信消息也设置TTL,防止无限堆积
.build();
}
@Bean
public Binding deadLetterBinding() {
return BindingBuilder
.bind(deadLetterQueue())
.to(deadLetterExchange())
.with("dead.letter.routing.key");
}
// ========== 业务队列(配置死信转发) ==========
@Bean
public Queue businessQueue() {
return QueueBuilder
.durable("business.queue")
// 关键配置:指定死信交换机
.withArgument("x-dead-letter-exchange", "dead.letter.exchange")
// 指定死信路由键(可选,默认使用原队列的路由键)
.withArgument("x-dead-letter-routing-key", "dead.letter.routing.key")
// 消息TTL(示例:30秒未消费则进入死信队列)
.withArgument("x-message-ttl", 30000)
// 队列最大长度(超出则进入死信队列)
.withArgument("x-max-length", 10000)
.build();
}
@Bean
public DirectExchange businessExchange() {
return new DirectExchange("business.exchange", true, false);
}
@Bean
public Binding businessBinding() {
return BindingBuilder
.bind(businessQueue())
.to(businessExchange())
.with("business.routing.key");
}
} @Bean`
`#/**
* 死信队列完整配置
*
* 配置要点:
* 1. 业务队列配置 x-dead-letter-exchange 指向死信交换机
* 2. 死信队列绑定到死信交换机
* 3. 死信队列也需持久化
*/
@Configuration
public class DeadLetterConfig {
// ========== 死信交换机和队列 ==========
@Bean
public DirectExchange deadLetterExchange() {
return new DirectExchange("dead.letter.exchange", true, false);
}
@Bean
public Queue deadLetterQueue() {
return QueueBuilder
.durable("dead.letter.queue")
.ttl(60000) // 死信消息也设置TTL,防止无限堆积
.build();
}
@Bean
public Binding deadLetterBinding() {
return BindingBuilder
.bind(deadLetterQueue())
.to(deadLetterExchange())
.with("dead.letter.routing.key");
}
// ========== 业务队列(配置死信转发) ==========
@Bean
public Queue businessQueue() {
return QueueBuilder
.durable("business.queue")
// 关键配置:指定死信交换机
.withArgument("x-dead-letter-exchange", "dead.letter.exchange")
// 指定死信路由键(可选,默认使用原队列的路由键)
.withArgument("x-dead-letter-routing-key", "dead.letter.routing.key")
// 消息TTL(示例:30秒未消费则进入死信队列)
.withArgument("x-message-ttl", 30000)
// 队列最大长度(超出则进入死信队列)
.withArgument("x-max-length", 10000)
.build();
}
@Bean
public DirectExchange businessExchange() {
return new DirectExchange("business.exchange", true, false);
}
@Bean
public Binding businessBinding() {
return BindingBuilder
.bind(businessQueue())
.to(businessExchange())
.with("business.routing.key");
}
} public Binding deadLetterBinding() {`
`#/**
* 死信队列完整配置
*
* 配置要点:
* 1. 业务队列配置 x-dead-letter-exchange 指向死信交换机
* 2. 死信队列绑定到死信交换机
* 3. 死信队列也需持久化
*/
@Configuration
public class DeadLetterConfig {
// ========== 死信交换机和队列 ==========
@Bean
public DirectExchange deadLetterExchange() {
return new DirectExchange("dead.letter.exchange", true, false);
}
@Bean
public Queue deadLetterQueue() {
return QueueBuilder
.durable("dead.letter.queue")
.ttl(60000) // 死信消息也设置TTL,防止无限堆积
.build();
}
@Bean
public Binding deadLetterBinding() {
return BindingBuilder
.bind(deadLetterQueue())
.to(deadLetterExchange())
.with("dead.letter.routing.key");
}
// ========== 业务队列(配置死信转发) ==========
@Bean
public Queue businessQueue() {
return QueueBuilder
.durable("business.queue")
// 关键配置:指定死信交换机
.withArgument("x-dead-letter-exchange", "dead.letter.exchange")
// 指定死信路由键(可选,默认使用原队列的路由键)
.withArgument("x-dead-letter-routing-key", "dead.letter.routing.key")
// 消息TTL(示例:30秒未消费则进入死信队列)
.withArgument("x-message-ttl", 30000)
// 队列最大长度(超出则进入死信队列)
.withArgument("x-max-length", 10000)
.build();
}
@Bean
public DirectExchange businessExchange() {
return new DirectExchange("business.exchange", true, false);
}
@Bean
public Binding businessBinding() {
return BindingBuilder
.bind(businessQueue())
.to(businessExchange())
.with("business.routing.key");
}
} return BindingBuilder`
`#/**
* 死信队列完整配置
*
* 配置要点:
* 1. 业务队列配置 x-dead-letter-exchange 指向死信交换机
* 2. 死信队列绑定到死信交换机
* 3. 死信队列也需持久化
*/
@Configuration
public class DeadLetterConfig {
// ========== 死信交换机和队列 ==========
@Bean
public DirectExchange deadLetterExchange() {
return new DirectExchange("dead.letter.exchange", true, false);
}
@Bean
public Queue deadLetterQueue() {
return QueueBuilder
.durable("dead.letter.queue")
.ttl(60000) // 死信消息也设置TTL,防止无限堆积
.build();
}
@Bean
public Binding deadLetterBinding() {
return BindingBuilder
.bind(deadLetterQueue())
.to(deadLetterExchange())
.with("dead.letter.routing.key");
}
// ========== 业务队列(配置死信转发) ==========
@Bean
public Queue businessQueue() {
return QueueBuilder
.durable("business.queue")
// 关键配置:指定死信交换机
.withArgument("x-dead-letter-exchange", "dead.letter.exchange")
// 指定死信路由键(可选,默认使用原队列的路由键)
.withArgument("x-dead-letter-routing-key", "dead.letter.routing.key")
// 消息TTL(示例:30秒未消费则进入死信队列)
.withArgument("x-message-ttl", 30000)
// 队列最大长度(超出则进入死信队列)
.withArgument("x-max-length", 10000)
.build();
}
@Bean
public DirectExchange businessExchange() {
return new DirectExchange("business.exchange", true, false);
}
@Bean
public Binding businessBinding() {
return BindingBuilder
.bind(businessQueue())
.to(businessExchange())
.with("business.routing.key");
}
} .bind(deadLetterQueue())`
`#/**
* 死信队列完整配置
*
* 配置要点:
* 1. 业务队列配置 x-dead-letter-exchange 指向死信交换机
* 2. 死信队列绑定到死信交换机
* 3. 死信队列也需持久化
*/
@Configuration
public class DeadLetterConfig {
// ========== 死信交换机和队列 ==========
@Bean
public DirectExchange deadLetterExchange() {
return new DirectExchange("dead.letter.exchange", true, false);
}
@Bean
public Queue deadLetterQueue() {
return QueueBuilder
.durable("dead.letter.queue")
.ttl(60000) // 死信消息也设置TTL,防止无限堆积
.build();
}
@Bean
public Binding deadLetterBinding() {
return BindingBuilder
.bind(deadLetterQueue())
.to(deadLetterExchange())
.with("dead.letter.routing.key");
}
// ========== 业务队列(配置死信转发) ==========
@Bean
public Queue businessQueue() {
return QueueBuilder
.durable("business.queue")
// 关键配置:指定死信交换机
.withArgument("x-dead-letter-exchange", "dead.letter.exchange")
// 指定死信路由键(可选,默认使用原队列的路由键)
.withArgument("x-dead-letter-routing-key", "dead.letter.routing.key")
// 消息TTL(示例:30秒未消费则进入死信队列)
.withArgument("x-message-ttl", 30000)
// 队列最大长度(超出则进入死信队列)
.withArgument("x-max-length", 10000)
.build();
}
@Bean
public DirectExchange businessExchange() {
return new DirectExchange("business.exchange", true, false);
}
@Bean
public Binding businessBinding() {
return BindingBuilder
.bind(businessQueue())
.to(businessExchange())
.with("business.routing.key");
}
} .to(deadLetterExchange())`
`#/**
* 死信队列完整配置
*
* 配置要点:
* 1. 业务队列配置 x-dead-letter-exchange 指向死信交换机
* 2. 死信队列绑定到死信交换机
* 3. 死信队列也需持久化
*/
@Configuration
public class DeadLetterConfig {
// ========== 死信交换机和队列 ==========
@Bean
public DirectExchange deadLetterExchange() {
return new DirectExchange("dead.letter.exchange", true, false);
}
@Bean
public Queue deadLetterQueue() {
return QueueBuilder
.durable("dead.letter.queue")
.ttl(60000) // 死信消息也设置TTL,防止无限堆积
.build();
}
@Bean
public Binding deadLetterBinding() {
return BindingBuilder
.bind(deadLetterQueue())
.to(deadLetterExchange())
.with("dead.letter.routing.key");
}
// ========== 业务队列(配置死信转发) ==========
@Bean
public Queue businessQueue() {
return QueueBuilder
.durable("business.queue")
// 关键配置:指定死信交换机
.withArgument("x-dead-letter-exchange", "dead.letter.exchange")
// 指定死信路由键(可选,默认使用原队列的路由键)
.withArgument("x-dead-letter-routing-key", "dead.letter.routing.key")
// 消息TTL(示例:30秒未消费则进入死信队列)
.withArgument("x-message-ttl", 30000)
// 队列最大长度(超出则进入死信队列)
.withArgument("x-max-length", 10000)
.build();
}
@Bean
public DirectExchange businessExchange() {
return new DirectExchange("business.exchange", true, false);
}
@Bean
public Binding businessBinding() {
return BindingBuilder
.bind(businessQueue())
.to(businessExchange())
.with("business.routing.key");
}
} .with("dead.letter.routing.key");`
`#/**
* 死信队列完整配置
*
* 配置要点:
* 1. 业务队列配置 x-dead-letter-exchange 指向死信交换机
* 2. 死信队列绑定到死信交换机
* 3. 死信队列也需持久化
*/
@Configuration
public class DeadLetterConfig {
// ========== 死信交换机和队列 ==========
@Bean
public DirectExchange deadLetterExchange() {
return new DirectExchange("dead.letter.exchange", true, false);
}
@Bean
public Queue deadLetterQueue() {
return QueueBuilder
.durable("dead.letter.queue")
.ttl(60000) // 死信消息也设置TTL,防止无限堆积
.build();
}
@Bean
public Binding deadLetterBinding() {
return BindingBuilder
.bind(deadLetterQueue())
.to(deadLetterExchange())
.with("dead.letter.routing.key");
}
// ========== 业务队列(配置死信转发) ==========
@Bean
public Queue businessQueue() {
return QueueBuilder
.durable("business.queue")
// 关键配置:指定死信交换机
.withArgument("x-dead-letter-exchange", "dead.letter.exchange")
// 指定死信路由键(可选,默认使用原队列的路由键)
.withArgument("x-dead-letter-routing-key", "dead.letter.routing.key")
// 消息TTL(示例:30秒未消费则进入死信队列)
.withArgument("x-message-ttl", 30000)
// 队列最大长度(超出则进入死信队列)
.withArgument("x-max-length", 10000)
.build();
}
@Bean
public DirectExchange businessExchange() {
return new DirectExchange("business.exchange", true, false);
}
@Bean
public Binding businessBinding() {
return BindingBuilder
.bind(businessQueue())
.to(businessExchange())
.with("business.routing.key");
}
} }`
`#/**
* 死信队列完整配置
*
* 配置要点:
* 1. 业务队列配置 x-dead-letter-exchange 指向死信交换机
* 2. 死信队列绑定到死信交换机
* 3. 死信队列也需持久化
*/
@Configuration
public class DeadLetterConfig {
// ========== 死信交换机和队列 ==========
@Bean
public DirectExchange deadLetterExchange() {
return new DirectExchange("dead.letter.exchange", true, false);
}
@Bean
public Queue deadLetterQueue() {
return QueueBuilder
.durable("dead.letter.queue")
.ttl(60000) // 死信消息也设置TTL,防止无限堆积
.build();
}
@Bean
public Binding deadLetterBinding() {
return BindingBuilder
.bind(deadLetterQueue())
.to(deadLetterExchange())
.with("dead.letter.routing.key");
}
// ========== 业务队列(配置死信转发) ==========
@Bean
public Queue businessQueue() {
return QueueBuilder
.durable("business.queue")
// 关键配置:指定死信交换机
.withArgument("x-dead-letter-exchange", "dead.letter.exchange")
// 指定死信路由键(可选,默认使用原队列的路由键)
.withArgument("x-dead-letter-routing-key", "dead.letter.routing.key")
// 消息TTL(示例:30秒未消费则进入死信队列)
.withArgument("x-message-ttl", 30000)
// 队列最大长度(超出则进入死信队列)
.withArgument("x-max-length", 10000)
.build();
}
@Bean
public DirectExchange businessExchange() {
return new DirectExchange("business.exchange", true, false);
}
@Bean
public Binding businessBinding() {
return BindingBuilder
.bind(businessQueue())
.to(businessExchange())
.with("business.routing.key");
}
}`
`#/**
* 死信队列完整配置
*
* 配置要点:
* 1. 业务队列配置 x-dead-letter-exchange 指向死信交换机
* 2. 死信队列绑定到死信交换机
* 3. 死信队列也需持久化
*/
@Configuration
public class DeadLetterConfig {
// ========== 死信交换机和队列 ==========
@Bean
public DirectExchange deadLetterExchange() {
return new DirectExchange("dead.letter.exchange", true, false);
}
@Bean
public Queue deadLetterQueue() {
return QueueBuilder
.durable("dead.letter.queue")
.ttl(60000) // 死信消息也设置TTL,防止无限堆积
.build();
}
@Bean
public Binding deadLetterBinding() {
return BindingBuilder
.bind(deadLetterQueue())
.to(deadLetterExchange())
.with("dead.letter.routing.key");
}
// ========== 业务队列(配置死信转发) ==========
@Bean
public Queue businessQueue() {
return QueueBuilder
.durable("business.queue")
// 关键配置:指定死信交换机
.withArgument("x-dead-letter-exchange", "dead.letter.exchange")
// 指定死信路由键(可选,默认使用原队列的路由键)
.withArgument("x-dead-letter-routing-key", "dead.letter.routing.key")
// 消息TTL(示例:30秒未消费则进入死信队列)
.withArgument("x-message-ttl", 30000)
// 队列最大长度(超出则进入死信队列)
.withArgument("x-max-length", 10000)
.build();
}
@Bean
public DirectExchange businessExchange() {
return new DirectExchange("business.exchange", true, false);
}
@Bean
public Binding businessBinding() {
return BindingBuilder
.bind(businessQueue())
.to(businessExchange())
.with("business.routing.key");
}
} // ========== 业务队列(配置死信转发) ==========`
`#/**
* 死信队列完整配置
*
* 配置要点:
* 1. 业务队列配置 x-dead-letter-exchange 指向死信交换机
* 2. 死信队列绑定到死信交换机
* 3. 死信队列也需持久化
*/
@Configuration
public class DeadLetterConfig {
// ========== 死信交换机和队列 ==========
@Bean
public DirectExchange deadLetterExchange() {
return new DirectExchange("dead.letter.exchange", true, false);
}
@Bean
public Queue deadLetterQueue() {
return QueueBuilder
.durable("dead.letter.queue")
.ttl(60000) // 死信消息也设置TTL,防止无限堆积
.build();
}
@Bean
public Binding deadLetterBinding() {
return BindingBuilder
.bind(deadLetterQueue())
.to(deadLetterExchange())
.with("dead.letter.routing.key");
}
// ========== 业务队列(配置死信转发) ==========
@Bean
public Queue businessQueue() {
return QueueBuilder
.durable("business.queue")
// 关键配置:指定死信交换机
.withArgument("x-dead-letter-exchange", "dead.letter.exchange")
// 指定死信路由键(可选,默认使用原队列的路由键)
.withArgument("x-dead-letter-routing-key", "dead.letter.routing.key")
// 消息TTL(示例:30秒未消费则进入死信队列)
.withArgument("x-message-ttl", 30000)
// 队列最大长度(超出则进入死信队列)
.withArgument("x-max-length", 10000)
.build();
}
@Bean
public DirectExchange businessExchange() {
return new DirectExchange("business.exchange", true, false);
}
@Bean
public Binding businessBinding() {
return BindingBuilder
.bind(businessQueue())
.to(businessExchange())
.with("business.routing.key");
}
}`
`#/**
* 死信队列完整配置
*
* 配置要点:
* 1. 业务队列配置 x-dead-letter-exchange 指向死信交换机
* 2. 死信队列绑定到死信交换机
* 3. 死信队列也需持久化
*/
@Configuration
public class DeadLetterConfig {
// ========== 死信交换机和队列 ==========
@Bean
public DirectExchange deadLetterExchange() {
return new DirectExchange("dead.letter.exchange", true, false);
}
@Bean
public Queue deadLetterQueue() {
return QueueBuilder
.durable("dead.letter.queue")
.ttl(60000) // 死信消息也设置TTL,防止无限堆积
.build();
}
@Bean
public Binding deadLetterBinding() {
return BindingBuilder
.bind(deadLetterQueue())
.to(deadLetterExchange())
.with("dead.letter.routing.key");
}
// ========== 业务队列(配置死信转发) ==========
@Bean
public Queue businessQueue() {
return QueueBuilder
.durable("business.queue")
// 关键配置:指定死信交换机
.withArgument("x-dead-letter-exchange", "dead.letter.exchange")
// 指定死信路由键(可选,默认使用原队列的路由键)
.withArgument("x-dead-letter-routing-key", "dead.letter.routing.key")
// 消息TTL(示例:30秒未消费则进入死信队列)
.withArgument("x-message-ttl", 30000)
// 队列最大长度(超出则进入死信队列)
.withArgument("x-max-length", 10000)
.build();
}
@Bean
public DirectExchange businessExchange() {
return new DirectExchange("business.exchange", true, false);
}
@Bean
public Binding businessBinding() {
return BindingBuilder
.bind(businessQueue())
.to(businessExchange())
.with("business.routing.key");
}
} @Bean`
`#/**
* 死信队列完整配置
*
* 配置要点:
* 1. 业务队列配置 x-dead-letter-exchange 指向死信交换机
* 2. 死信队列绑定到死信交换机
* 3. 死信队列也需持久化
*/
@Configuration
public class DeadLetterConfig {
// ========== 死信交换机和队列 ==========
@Bean
public DirectExchange deadLetterExchange() {
return new DirectExchange("dead.letter.exchange", true, false);
}
@Bean
public Queue deadLetterQueue() {
return QueueBuilder
.durable("dead.letter.queue")
.ttl(60000) // 死信消息也设置TTL,防止无限堆积
.build();
}
@Bean
public Binding deadLetterBinding() {
return BindingBuilder
.bind(deadLetterQueue())
.to(deadLetterExchange())
.with("dead.letter.routing.key");
}
// ========== 业务队列(配置死信转发) ==========
@Bean
public Queue businessQueue() {
return QueueBuilder
.durable("business.queue")
// 关键配置:指定死信交换机
.withArgument("x-dead-letter-exchange", "dead.letter.exchange")
// 指定死信路由键(可选,默认使用原队列的路由键)
.withArgument("x-dead-letter-routing-key", "dead.letter.routing.key")
// 消息TTL(示例:30秒未消费则进入死信队列)
.withArgument("x-message-ttl", 30000)
// 队列最大长度(超出则进入死信队列)
.withArgument("x-max-length", 10000)
.build();
}
@Bean
public DirectExchange businessExchange() {
return new DirectExchange("business.exchange", true, false);
}
@Bean
public Binding businessBinding() {
return BindingBuilder
.bind(businessQueue())
.to(businessExchange())
.with("business.routing.key");
}
} public Queue businessQueue() {`
`#/**
* 死信队列完整配置
*
* 配置要点:
* 1. 业务队列配置 x-dead-letter-exchange 指向死信交换机
* 2. 死信队列绑定到死信交换机
* 3. 死信队列也需持久化
*/
@Configuration
public class DeadLetterConfig {
// ========== 死信交换机和队列 ==========
@Bean
public DirectExchange deadLetterExchange() {
return new DirectExchange("dead.letter.exchange", true, false);
}
@Bean
public Queue deadLetterQueue() {
return QueueBuilder
.durable("dead.letter.queue")
.ttl(60000) // 死信消息也设置TTL,防止无限堆积
.build();
}
@Bean
public Binding deadLetterBinding() {
return BindingBuilder
.bind(deadLetterQueue())
.to(deadLetterExchange())
.with("dead.letter.routing.key");
}
// ========== 业务队列(配置死信转发) ==========
@Bean
public Queue businessQueue() {
return QueueBuilder
.durable("business.queue")
// 关键配置:指定死信交换机
.withArgument("x-dead-letter-exchange", "dead.letter.exchange")
// 指定死信路由键(可选,默认使用原队列的路由键)
.withArgument("x-dead-letter-routing-key", "dead.letter.routing.key")
// 消息TTL(示例:30秒未消费则进入死信队列)
.withArgument("x-message-ttl", 30000)
// 队列最大长度(超出则进入死信队列)
.withArgument("x-max-length", 10000)
.build();
}
@Bean
public DirectExchange businessExchange() {
return new DirectExchange("business.exchange", true, false);
}
@Bean
public Binding businessBinding() {
return BindingBuilder
.bind(businessQueue())
.to(businessExchange())
.with("business.routing.key");
}
} return QueueBuilder`
`#/**
* 死信队列完整配置
*
* 配置要点:
* 1. 业务队列配置 x-dead-letter-exchange 指向死信交换机
* 2. 死信队列绑定到死信交换机
* 3. 死信队列也需持久化
*/
@Configuration
public class DeadLetterConfig {
// ========== 死信交换机和队列 ==========
@Bean
public DirectExchange deadLetterExchange() {
return new DirectExchange("dead.letter.exchange", true, false);
}
@Bean
public Queue deadLetterQueue() {
return QueueBuilder
.durable("dead.letter.queue")
.ttl(60000) // 死信消息也设置TTL,防止无限堆积
.build();
}
@Bean
public Binding deadLetterBinding() {
return BindingBuilder
.bind(deadLetterQueue())
.to(deadLetterExchange())
.with("dead.letter.routing.key");
}
// ========== 业务队列(配置死信转发) ==========
@Bean
public Queue businessQueue() {
return QueueBuilder
.durable("business.queue")
// 关键配置:指定死信交换机
.withArgument("x-dead-letter-exchange", "dead.letter.exchange")
// 指定死信路由键(可选,默认使用原队列的路由键)
.withArgument("x-dead-letter-routing-key", "dead.letter.routing.key")
// 消息TTL(示例:30秒未消费则进入死信队列)
.withArgument("x-message-ttl", 30000)
// 队列最大长度(超出则进入死信队列)
.withArgument("x-max-length", 10000)
.build();
}
@Bean
public DirectExchange businessExchange() {
return new DirectExchange("business.exchange", true, false);
}
@Bean
public Binding businessBinding() {
return BindingBuilder
.bind(businessQueue())
.to(businessExchange())
.with("business.routing.key");
}
} .durable("business.queue")`
`#/**
* 死信队列完整配置
*
* 配置要点:
* 1. 业务队列配置 x-dead-letter-exchange 指向死信交换机
* 2. 死信队列绑定到死信交换机
* 3. 死信队列也需持久化
*/
@Configuration
public class DeadLetterConfig {
// ========== 死信交换机和队列 ==========
@Bean
public DirectExchange deadLetterExchange() {
return new DirectExchange("dead.letter.exchange", true, false);
}
@Bean
public Queue deadLetterQueue() {
return QueueBuilder
.durable("dead.letter.queue")
.ttl(60000) // 死信消息也设置TTL,防止无限堆积
.build();
}
@Bean
public Binding deadLetterBinding() {
return BindingBuilder
.bind(deadLetterQueue())
.to(deadLetterExchange())
.with("dead.letter.routing.key");
}
// ========== 业务队列(配置死信转发) ==========
@Bean
public Queue businessQueue() {
return QueueBuilder
.durable("business.queue")
// 关键配置:指定死信交换机
.withArgument("x-dead-letter-exchange", "dead.letter.exchange")
// 指定死信路由键(可选,默认使用原队列的路由键)
.withArgument("x-dead-letter-routing-key", "dead.letter.routing.key")
// 消息TTL(示例:30秒未消费则进入死信队列)
.withArgument("x-message-ttl", 30000)
// 队列最大长度(超出则进入死信队列)
.withArgument("x-max-length", 10000)
.build();
}
@Bean
public DirectExchange businessExchange() {
return new DirectExchange("business.exchange", true, false);
}
@Bean
public Binding businessBinding() {
return BindingBuilder
.bind(businessQueue())
.to(businessExchange())
.with("business.routing.key");
}
} // 关键配置:指定死信交换机`
`#/**
* 死信队列完整配置
*
* 配置要点:
* 1. 业务队列配置 x-dead-letter-exchange 指向死信交换机
* 2. 死信队列绑定到死信交换机
* 3. 死信队列也需持久化
*/
@Configuration
public class DeadLetterConfig {
// ========== 死信交换机和队列 ==========
@Bean
public DirectExchange deadLetterExchange() {
return new DirectExchange("dead.letter.exchange", true, false);
}
@Bean
public Queue deadLetterQueue() {
return QueueBuilder
.durable("dead.letter.queue")
.ttl(60000) // 死信消息也设置TTL,防止无限堆积
.build();
}
@Bean
public Binding deadLetterBinding() {
return BindingBuilder
.bind(deadLetterQueue())
.to(deadLetterExchange())
.with("dead.letter.routing.key");
}
// ========== 业务队列(配置死信转发) ==========
@Bean
public Queue businessQueue() {
return QueueBuilder
.durable("business.queue")
// 关键配置:指定死信交换机
.withArgument("x-dead-letter-exchange", "dead.letter.exchange")
// 指定死信路由键(可选,默认使用原队列的路由键)
.withArgument("x-dead-letter-routing-key", "dead.letter.routing.key")
// 消息TTL(示例:30秒未消费则进入死信队列)
.withArgument("x-message-ttl", 30000)
// 队列最大长度(超出则进入死信队列)
.withArgument("x-max-length", 10000)
.build();
}
@Bean
public DirectExchange businessExchange() {
return new DirectExchange("business.exchange", true, false);
}
@Bean
public Binding businessBinding() {
return BindingBuilder
.bind(businessQueue())
.to(businessExchange())
.with("business.routing.key");
}
} .withArgument("x-dead-letter-exchange", "dead.letter.exchange")`
`#/**
* 死信队列完整配置
*
* 配置要点:
* 1. 业务队列配置 x-dead-letter-exchange 指向死信交换机
* 2. 死信队列绑定到死信交换机
* 3. 死信队列也需持久化
*/
@Configuration
public class DeadLetterConfig {
// ========== 死信交换机和队列 ==========
@Bean
public DirectExchange deadLetterExchange() {
return new DirectExchange("dead.letter.exchange", true, false);
}
@Bean
public Queue deadLetterQueue() {
return QueueBuilder
.durable("dead.letter.queue")
.ttl(60000) // 死信消息也设置TTL,防止无限堆积
.build();
}
@Bean
public Binding deadLetterBinding() {
return BindingBuilder
.bind(deadLetterQueue())
.to(deadLetterExchange())
.with("dead.letter.routing.key");
}
// ========== 业务队列(配置死信转发) ==========
@Bean
public Queue businessQueue() {
return QueueBuilder
.durable("business.queue")
// 关键配置:指定死信交换机
.withArgument("x-dead-letter-exchange", "dead.letter.exchange")
// 指定死信路由键(可选,默认使用原队列的路由键)
.withArgument("x-dead-letter-routing-key", "dead.letter.routing.key")
// 消息TTL(示例:30秒未消费则进入死信队列)
.withArgument("x-message-ttl", 30000)
// 队列最大长度(超出则进入死信队列)
.withArgument("x-max-length", 10000)
.build();
}
@Bean
public DirectExchange businessExchange() {
return new DirectExchange("business.exchange", true, false);
}
@Bean
public Binding businessBinding() {
return BindingBuilder
.bind(businessQueue())
.to(businessExchange())
.with("business.routing.key");
}
} // 指定死信路由键(可选,默认使用原队列的路由键)`
`#/**
* 死信队列完整配置
*
* 配置要点:
* 1. 业务队列配置 x-dead-letter-exchange 指向死信交换机
* 2. 死信队列绑定到死信交换机
* 3. 死信队列也需持久化
*/
@Configuration
public class DeadLetterConfig {
// ========== 死信交换机和队列 ==========
@Bean
public DirectExchange deadLetterExchange() {
return new DirectExchange("dead.letter.exchange", true, false);
}
@Bean
public Queue deadLetterQueue() {
return QueueBuilder
.durable("dead.letter.queue")
.ttl(60000) // 死信消息也设置TTL,防止无限堆积
.build();
}
@Bean
public Binding deadLetterBinding() {
return BindingBuilder
.bind(deadLetterQueue())
.to(deadLetterExchange())
.with("dead.letter.routing.key");
}
// ========== 业务队列(配置死信转发) ==========
@Bean
public Queue businessQueue() {
return QueueBuilder
.durable("business.queue")
// 关键配置:指定死信交换机
.withArgument("x-dead-letter-exchange", "dead.letter.exchange")
// 指定死信路由键(可选,默认使用原队列的路由键)
.withArgument("x-dead-letter-routing-key", "dead.letter.routing.key")
// 消息TTL(示例:30秒未消费则进入死信队列)
.withArgument("x-message-ttl", 30000)
// 队列最大长度(超出则进入死信队列)
.withArgument("x-max-length", 10000)
.build();
}
@Bean
public DirectExchange businessExchange() {
return new DirectExchange("business.exchange", true, false);
}
@Bean
public Binding businessBinding() {
return BindingBuilder
.bind(businessQueue())
.to(businessExchange())
.with("business.routing.key");
}
} .withArgument("x-dead-letter-routing-key", "dead.letter.routing.key")`
`#/**
* 死信队列完整配置
*
* 配置要点:
* 1. 业务队列配置 x-dead-letter-exchange 指向死信交换机
* 2. 死信队列绑定到死信交换机
* 3. 死信队列也需持久化
*/
@Configuration
public class DeadLetterConfig {
// ========== 死信交换机和队列 ==========
@Bean
public DirectExchange deadLetterExchange() {
return new DirectExchange("dead.letter.exchange", true, false);
}
@Bean
public Queue deadLetterQueue() {
return QueueBuilder
.durable("dead.letter.queue")
.ttl(60000) // 死信消息也设置TTL,防止无限堆积
.build();
}
@Bean
public Binding deadLetterBinding() {
return BindingBuilder
.bind(deadLetterQueue())
.to(deadLetterExchange())
.with("dead.letter.routing.key");
}
// ========== 业务队列(配置死信转发) ==========
@Bean
public Queue businessQueue() {
return QueueBuilder
.durable("business.queue")
// 关键配置:指定死信交换机
.withArgument("x-dead-letter-exchange", "dead.letter.exchange")
// 指定死信路由键(可选,默认使用原队列的路由键)
.withArgument("x-dead-letter-routing-key", "dead.letter.routing.key")
// 消息TTL(示例:30秒未消费则进入死信队列)
.withArgument("x-message-ttl", 30000)
// 队列最大长度(超出则进入死信队列)
.withArgument("x-max-length", 10000)
.build();
}
@Bean
public DirectExchange businessExchange() {
return new DirectExchange("business.exchange", true, false);
}
@Bean
public Binding businessBinding() {
return BindingBuilder
.bind(businessQueue())
.to(businessExchange())
.with("business.routing.key");
}
} // 消息TTL(示例:30秒未消费则进入死信队列)`
`#/**
* 死信队列完整配置
*
* 配置要点:
* 1. 业务队列配置 x-dead-letter-exchange 指向死信交换机
* 2. 死信队列绑定到死信交换机
* 3. 死信队列也需持久化
*/
@Configuration
public class DeadLetterConfig {
// ========== 死信交换机和队列 ==========
@Bean
public DirectExchange deadLetterExchange() {
return new DirectExchange("dead.letter.exchange", true, false);
}
@Bean
public Queue deadLetterQueue() {
return QueueBuilder
.durable("dead.letter.queue")
.ttl(60000) // 死信消息也设置TTL,防止无限堆积
.build();
}
@Bean
public Binding deadLetterBinding() {
return BindingBuilder
.bind(deadLetterQueue())
.to(deadLetterExchange())
.with("dead.letter.routing.key");
}
// ========== 业务队列(配置死信转发) ==========
@Bean
public Queue businessQueue() {
return QueueBuilder
.durable("business.queue")
// 关键配置:指定死信交换机
.withArgument("x-dead-letter-exchange", "dead.letter.exchange")
// 指定死信路由键(可选,默认使用原队列的路由键)
.withArgument("x-dead-letter-routing-key", "dead.letter.routing.key")
// 消息TTL(示例:30秒未消费则进入死信队列)
.withArgument("x-message-ttl", 30000)
// 队列最大长度(超出则进入死信队列)
.withArgument("x-max-length", 10000)
.build();
}
@Bean
public DirectExchange businessExchange() {
return new DirectExchange("business.exchange", true, false);
}
@Bean
public Binding businessBinding() {
return BindingBuilder
.bind(businessQueue())
.to(businessExchange())
.with("business.routing.key");
}
} .withArgument("x-message-ttl", 30000)`
`#/**
* 死信队列完整配置
*
* 配置要点:
* 1. 业务队列配置 x-dead-letter-exchange 指向死信交换机
* 2. 死信队列绑定到死信交换机
* 3. 死信队列也需持久化
*/
@Configuration
public class DeadLetterConfig {
// ========== 死信交换机和队列 ==========
@Bean
public DirectExchange deadLetterExchange() {
return new DirectExchange("dead.letter.exchange", true, false);
}
@Bean
public Queue deadLetterQueue() {
return QueueBuilder
.durable("dead.letter.queue")
.ttl(60000) // 死信消息也设置TTL,防止无限堆积
.build();
}
@Bean
public Binding deadLetterBinding() {
return BindingBuilder
.bind(deadLetterQueue())
.to(deadLetterExchange())
.with("dead.letter.routing.key");
}
// ========== 业务队列(配置死信转发) ==========
@Bean
public Queue businessQueue() {
return QueueBuilder
.durable("business.queue")
// 关键配置:指定死信交换机
.withArgument("x-dead-letter-exchange", "dead.letter.exchange")
// 指定死信路由键(可选,默认使用原队列的路由键)
.withArgument("x-dead-letter-routing-key", "dead.letter.routing.key")
// 消息TTL(示例:30秒未消费则进入死信队列)
.withArgument("x-message-ttl", 30000)
// 队列最大长度(超出则进入死信队列)
.withArgument("x-max-length", 10000)
.build();
}
@Bean
public DirectExchange businessExchange() {
return new DirectExchange("business.exchange", true, false);
}
@Bean
public Binding businessBinding() {
return BindingBuilder
.bind(businessQueue())
.to(businessExchange())
.with("business.routing.key");
}
} // 队列最大长度(超出则进入死信队列)`
`#/**
* 死信队列完整配置
*
* 配置要点:
* 1. 业务队列配置 x-dead-letter-exchange 指向死信交换机
* 2. 死信队列绑定到死信交换机
* 3. 死信队列也需持久化
*/
@Configuration
public class DeadLetterConfig {
// ========== 死信交换机和队列 ==========
@Bean
public DirectExchange deadLetterExchange() {
return new DirectExchange("dead.letter.exchange", true, false);
}
@Bean
public Queue deadLetterQueue() {
return QueueBuilder
.durable("dead.letter.queue")
.ttl(60000) // 死信消息也设置TTL,防止无限堆积
.build();
}
@Bean
public Binding deadLetterBinding() {
return BindingBuilder
.bind(deadLetterQueue())
.to(deadLetterExchange())
.with("dead.letter.routing.key");
}
// ========== 业务队列(配置死信转发) ==========
@Bean
public Queue businessQueue() {
return QueueBuilder
.durable("business.queue")
// 关键配置:指定死信交换机
.withArgument("x-dead-letter-exchange", "dead.letter.exchange")
// 指定死信路由键(可选,默认使用原队列的路由键)
.withArgument("x-dead-letter-routing-key", "dead.letter.routing.key")
// 消息TTL(示例:30秒未消费则进入死信队列)
.withArgument("x-message-ttl", 30000)
// 队列最大长度(超出则进入死信队列)
.withArgument("x-max-length", 10000)
.build();
}
@Bean
public DirectExchange businessExchange() {
return new DirectExchange("business.exchange", true, false);
}
@Bean
public Binding businessBinding() {
return BindingBuilder
.bind(businessQueue())
.to(businessExchange())
.with("business.routing.key");
}
} .withArgument("x-max-length", 10000)`
`#/**
* 死信队列完整配置
*
* 配置要点:
* 1. 业务队列配置 x-dead-letter-exchange 指向死信交换机
* 2. 死信队列绑定到死信交换机
* 3. 死信队列也需持久化
*/
@Configuration
public class DeadLetterConfig {
// ========== 死信交换机和队列 ==========
@Bean
public DirectExchange deadLetterExchange() {
return new DirectExchange("dead.letter.exchange", true, false);
}
@Bean
public Queue deadLetterQueue() {
return QueueBuilder
.durable("dead.letter.queue")
.ttl(60000) // 死信消息也设置TTL,防止无限堆积
.build();
}
@Bean
public Binding deadLetterBinding() {
return BindingBuilder
.bind(deadLetterQueue())
.to(deadLetterExchange())
.with("dead.letter.routing.key");
}
// ========== 业务队列(配置死信转发) ==========
@Bean
public Queue businessQueue() {
return QueueBuilder
.durable("business.queue")
// 关键配置:指定死信交换机
.withArgument("x-dead-letter-exchange", "dead.letter.exchange")
// 指定死信路由键(可选,默认使用原队列的路由键)
.withArgument("x-dead-letter-routing-key", "dead.letter.routing.key")
// 消息TTL(示例:30秒未消费则进入死信队列)
.withArgument("x-message-ttl", 30000)
// 队列最大长度(超出则进入死信队列)
.withArgument("x-max-length", 10000)
.build();
}
@Bean
public DirectExchange businessExchange() {
return new DirectExchange("business.exchange", true, false);
}
@Bean
public Binding businessBinding() {
return BindingBuilder
.bind(businessQueue())
.to(businessExchange())
.with("business.routing.key");
}
} .build();`
`#/**
* 死信队列完整配置
*
* 配置要点:
* 1. 业务队列配置 x-dead-letter-exchange 指向死信交换机
* 2. 死信队列绑定到死信交换机
* 3. 死信队列也需持久化
*/
@Configuration
public class DeadLetterConfig {
// ========== 死信交换机和队列 ==========
@Bean
public DirectExchange deadLetterExchange() {
return new DirectExchange("dead.letter.exchange", true, false);
}
@Bean
public Queue deadLetterQueue() {
return QueueBuilder
.durable("dead.letter.queue")
.ttl(60000) // 死信消息也设置TTL,防止无限堆积
.build();
}
@Bean
public Binding deadLetterBinding() {
return BindingBuilder
.bind(deadLetterQueue())
.to(deadLetterExchange())
.with("dead.letter.routing.key");
}
// ========== 业务队列(配置死信转发) ==========
@Bean
public Queue businessQueue() {
return QueueBuilder
.durable("business.queue")
// 关键配置:指定死信交换机
.withArgument("x-dead-letter-exchange", "dead.letter.exchange")
// 指定死信路由键(可选,默认使用原队列的路由键)
.withArgument("x-dead-letter-routing-key", "dead.letter.routing.key")
// 消息TTL(示例:30秒未消费则进入死信队列)
.withArgument("x-message-ttl", 30000)
// 队列最大长度(超出则进入死信队列)
.withArgument("x-max-length", 10000)
.build();
}
@Bean
public DirectExchange businessExchange() {
return new DirectExchange("business.exchange", true, false);
}
@Bean
public Binding businessBinding() {
return BindingBuilder
.bind(businessQueue())
.to(businessExchange())
.with("business.routing.key");
}
} }`
`#/**
* 死信队列完整配置
*
* 配置要点:
* 1. 业务队列配置 x-dead-letter-exchange 指向死信交换机
* 2. 死信队列绑定到死信交换机
* 3. 死信队列也需持久化
*/
@Configuration
public class DeadLetterConfig {
// ========== 死信交换机和队列 ==========
@Bean
public DirectExchange deadLetterExchange() {
return new DirectExchange("dead.letter.exchange", true, false);
}
@Bean
public Queue deadLetterQueue() {
return QueueBuilder
.durable("dead.letter.queue")
.ttl(60000) // 死信消息也设置TTL,防止无限堆积
.build();
}
@Bean
public Binding deadLetterBinding() {
return BindingBuilder
.bind(deadLetterQueue())
.to(deadLetterExchange())
.with("dead.letter.routing.key");
}
// ========== 业务队列(配置死信转发) ==========
@Bean
public Queue businessQueue() {
return QueueBuilder
.durable("business.queue")
// 关键配置:指定死信交换机
.withArgument("x-dead-letter-exchange", "dead.letter.exchange")
// 指定死信路由键(可选,默认使用原队列的路由键)
.withArgument("x-dead-letter-routing-key", "dead.letter.routing.key")
// 消息TTL(示例:30秒未消费则进入死信队列)
.withArgument("x-message-ttl", 30000)
// 队列最大长度(超出则进入死信队列)
.withArgument("x-max-length", 10000)
.build();
}
@Bean
public DirectExchange businessExchange() {
return new DirectExchange("business.exchange", true, false);
}
@Bean
public Binding businessBinding() {
return BindingBuilder
.bind(businessQueue())
.to(businessExchange())
.with("business.routing.key");
}
}`
`#/**
* 死信队列完整配置
*
* 配置要点:
* 1. 业务队列配置 x-dead-letter-exchange 指向死信交换机
* 2. 死信队列绑定到死信交换机
* 3. 死信队列也需持久化
*/
@Configuration
public class DeadLetterConfig {
// ========== 死信交换机和队列 ==========
@Bean
public DirectExchange deadLetterExchange() {
return new DirectExchange("dead.letter.exchange", true, false);
}
@Bean
public Queue deadLetterQueue() {
return QueueBuilder
.durable("dead.letter.queue")
.ttl(60000) // 死信消息也设置TTL,防止无限堆积
.build();
}
@Bean
public Binding deadLetterBinding() {
return BindingBuilder
.bind(deadLetterQueue())
.to(deadLetterExchange())
.with("dead.letter.routing.key");
}
// ========== 业务队列(配置死信转发) ==========
@Bean
public Queue businessQueue() {
return QueueBuilder
.durable("business.queue")
// 关键配置:指定死信交换机
.withArgument("x-dead-letter-exchange", "dead.letter.exchange")
// 指定死信路由键(可选,默认使用原队列的路由键)
.withArgument("x-dead-letter-routing-key", "dead.letter.routing.key")
// 消息TTL(示例:30秒未消费则进入死信队列)
.withArgument("x-message-ttl", 30000)
// 队列最大长度(超出则进入死信队列)
.withArgument("x-max-length", 10000)
.build();
}
@Bean
public DirectExchange businessExchange() {
return new DirectExchange("business.exchange", true, false);
}
@Bean
public Binding businessBinding() {
return BindingBuilder
.bind(businessQueue())
.to(businessExchange())
.with("business.routing.key");
}
} @Bean`
`#/**
* 死信队列完整配置
*
* 配置要点:
* 1. 业务队列配置 x-dead-letter-exchange 指向死信交换机
* 2. 死信队列绑定到死信交换机
* 3. 死信队列也需持久化
*/
@Configuration
public class DeadLetterConfig {
// ========== 死信交换机和队列 ==========
@Bean
public DirectExchange deadLetterExchange() {
return new DirectExchange("dead.letter.exchange", true, false);
}
@Bean
public Queue deadLetterQueue() {
return QueueBuilder
.durable("dead.letter.queue")
.ttl(60000) // 死信消息也设置TTL,防止无限堆积
.build();
}
@Bean
public Binding deadLetterBinding() {
return BindingBuilder
.bind(deadLetterQueue())
.to(deadLetterExchange())
.with("dead.letter.routing.key");
}
// ========== 业务队列(配置死信转发) ==========
@Bean
public Queue businessQueue() {
return QueueBuilder
.durable("business.queue")
// 关键配置:指定死信交换机
.withArgument("x-dead-letter-exchange", "dead.letter.exchange")
// 指定死信路由键(可选,默认使用原队列的路由键)
.withArgument("x-dead-letter-routing-key", "dead.letter.routing.key")
// 消息TTL(示例:30秒未消费则进入死信队列)
.withArgument("x-message-ttl", 30000)
// 队列最大长度(超出则进入死信队列)
.withArgument("x-max-length", 10000)
.build();
}
@Bean
public DirectExchange businessExchange() {
return new DirectExchange("business.exchange", true, false);
}
@Bean
public Binding businessBinding() {
return BindingBuilder
.bind(businessQueue())
.to(businessExchange())
.with("business.routing.key");
}
} public DirectExchange businessExchange() {`
`#/**
* 死信队列完整配置
*
* 配置要点:
* 1. 业务队列配置 x-dead-letter-exchange 指向死信交换机
* 2. 死信队列绑定到死信交换机
* 3. 死信队列也需持久化
*/
@Configuration
public class DeadLetterConfig {
// ========== 死信交换机和队列 ==========
@Bean
public DirectExchange deadLetterExchange() {
return new DirectExchange("dead.letter.exchange", true, false);
}
@Bean
public Queue deadLetterQueue() {
return QueueBuilder
.durable("dead.letter.queue")
.ttl(60000) // 死信消息也设置TTL,防止无限堆积
.build();
}
@Bean
public Binding deadLetterBinding() {
return BindingBuilder
.bind(deadLetterQueue())
.to(deadLetterExchange())
.with("dead.letter.routing.key");
}
// ========== 业务队列(配置死信转发) ==========
@Bean
public Queue businessQueue() {
return QueueBuilder
.durable("business.queue")
// 关键配置:指定死信交换机
.withArgument("x-dead-letter-exchange", "dead.letter.exchange")
// 指定死信路由键(可选,默认使用原队列的路由键)
.withArgument("x-dead-letter-routing-key", "dead.letter.routing.key")
// 消息TTL(示例:30秒未消费则进入死信队列)
.withArgument("x-message-ttl", 30000)
// 队列最大长度(超出则进入死信队列)
.withArgument("x-max-length", 10000)
.build();
}
@Bean
public DirectExchange businessExchange() {
return new DirectExchange("business.exchange", true, false);
}
@Bean
public Binding businessBinding() {
return BindingBuilder
.bind(businessQueue())
.to(businessExchange())
.with("business.routing.key");
}
} return new DirectExchange("business.exchange", true, false);`
`#/**
* 死信队列完整配置
*
* 配置要点:
* 1. 业务队列配置 x-dead-letter-exchange 指向死信交换机
* 2. 死信队列绑定到死信交换机
* 3. 死信队列也需持久化
*/
@Configuration
public class DeadLetterConfig {
// ========== 死信交换机和队列 ==========
@Bean
public DirectExchange deadLetterExchange() {
return new DirectExchange("dead.letter.exchange", true, false);
}
@Bean
public Queue deadLetterQueue() {
return QueueBuilder
.durable("dead.letter.queue")
.ttl(60000) // 死信消息也设置TTL,防止无限堆积
.build();
}
@Bean
public Binding deadLetterBinding() {
return BindingBuilder
.bind(deadLetterQueue())
.to(deadLetterExchange())
.with("dead.letter.routing.key");
}
// ========== 业务队列(配置死信转发) ==========
@Bean
public Queue businessQueue() {
return QueueBuilder
.durable("business.queue")
// 关键配置:指定死信交换机
.withArgument("x-dead-letter-exchange", "dead.letter.exchange")
// 指定死信路由键(可选,默认使用原队列的路由键)
.withArgument("x-dead-letter-routing-key", "dead.letter.routing.key")
// 消息TTL(示例:30秒未消费则进入死信队列)
.withArgument("x-message-ttl", 30000)
// 队列最大长度(超出则进入死信队列)
.withArgument("x-max-length", 10000)
.build();
}
@Bean
public DirectExchange businessExchange() {
return new DirectExchange("business.exchange", true, false);
}
@Bean
public Binding businessBinding() {
return BindingBuilder
.bind(businessQueue())
.to(businessExchange())
.with("business.routing.key");
}
} }`
`#/**
* 死信队列完整配置
*
* 配置要点:
* 1. 业务队列配置 x-dead-letter-exchange 指向死信交换机
* 2. 死信队列绑定到死信交换机
* 3. 死信队列也需持久化
*/
@Configuration
public class DeadLetterConfig {
// ========== 死信交换机和队列 ==========
@Bean
public DirectExchange deadLetterExchange() {
return new DirectExchange("dead.letter.exchange", true, false);
}
@Bean
public Queue deadLetterQueue() {
return QueueBuilder
.durable("dead.letter.queue")
.ttl(60000) // 死信消息也设置TTL,防止无限堆积
.build();
}
@Bean
public Binding deadLetterBinding() {
return BindingBuilder
.bind(deadLetterQueue())
.to(deadLetterExchange())
.with("dead.letter.routing.key");
}
// ========== 业务队列(配置死信转发) ==========
@Bean
public Queue businessQueue() {
return QueueBuilder
.durable("business.queue")
// 关键配置:指定死信交换机
.withArgument("x-dead-letter-exchange", "dead.letter.exchange")
// 指定死信路由键(可选,默认使用原队列的路由键)
.withArgument("x-dead-letter-routing-key", "dead.letter.routing.key")
// 消息TTL(示例:30秒未消费则进入死信队列)
.withArgument("x-message-ttl", 30000)
// 队列最大长度(超出则进入死信队列)
.withArgument("x-max-length", 10000)
.build();
}
@Bean
public DirectExchange businessExchange() {
return new DirectExchange("business.exchange", true, false);
}
@Bean
public Binding businessBinding() {
return BindingBuilder
.bind(businessQueue())
.to(businessExchange())
.with("business.routing.key");
}
}`
`#/**
* 死信队列完整配置
*
* 配置要点:
* 1. 业务队列配置 x-dead-letter-exchange 指向死信交换机
* 2. 死信队列绑定到死信交换机
* 3. 死信队列也需持久化
*/
@Configuration
public class DeadLetterConfig {
// ========== 死信交换机和队列 ==========
@Bean
public DirectExchange deadLetterExchange() {
return new DirectExchange("dead.letter.exchange", true, false);
}
@Bean
public Queue deadLetterQueue() {
return QueueBuilder
.durable("dead.letter.queue")
.ttl(60000) // 死信消息也设置TTL,防止无限堆积
.build();
}
@Bean
public Binding deadLetterBinding() {
return BindingBuilder
.bind(deadLetterQueue())
.to(deadLetterExchange())
.with("dead.letter.routing.key");
}
// ========== 业务队列(配置死信转发) ==========
@Bean
public Queue businessQueue() {
return QueueBuilder
.durable("business.queue")
// 关键配置:指定死信交换机
.withArgument("x-dead-letter-exchange", "dead.letter.exchange")
// 指定死信路由键(可选,默认使用原队列的路由键)
.withArgument("x-dead-letter-routing-key", "dead.letter.routing.key")
// 消息TTL(示例:30秒未消费则进入死信队列)
.withArgument("x-message-ttl", 30000)
// 队列最大长度(超出则进入死信队列)
.withArgument("x-max-length", 10000)
.build();
}
@Bean
public DirectExchange businessExchange() {
return new DirectExchange("business.exchange", true, false);
}
@Bean
public Binding businessBinding() {
return BindingBuilder
.bind(businessQueue())
.to(businessExchange())
.with("business.routing.key");
}
} @Bean`
`#/**
* 死信队列完整配置
*
* 配置要点:
* 1. 业务队列配置 x-dead-letter-exchange 指向死信交换机
* 2. 死信队列绑定到死信交换机
* 3. 死信队列也需持久化
*/
@Configuration
public class DeadLetterConfig {
// ========== 死信交换机和队列 ==========
@Bean
public DirectExchange deadLetterExchange() {
return new DirectExchange("dead.letter.exchange", true, false);
}
@Bean
public Queue deadLetterQueue() {
return QueueBuilder
.durable("dead.letter.queue")
.ttl(60000) // 死信消息也设置TTL,防止无限堆积
.build();
}
@Bean
public Binding deadLetterBinding() {
return BindingBuilder
.bind(deadLetterQueue())
.to(deadLetterExchange())
.with("dead.letter.routing.key");
}
// ========== 业务队列(配置死信转发) ==========
@Bean
public Queue businessQueue() {
return QueueBuilder
.durable("business.queue")
// 关键配置:指定死信交换机
.withArgument("x-dead-letter-exchange", "dead.letter.exchange")
// 指定死信路由键(可选,默认使用原队列的路由键)
.withArgument("x-dead-letter-routing-key", "dead.letter.routing.key")
// 消息TTL(示例:30秒未消费则进入死信队列)
.withArgument("x-message-ttl", 30000)
// 队列最大长度(超出则进入死信队列)
.withArgument("x-max-length", 10000)
.build();
}
@Bean
public DirectExchange businessExchange() {
return new DirectExchange("business.exchange", true, false);
}
@Bean
public Binding businessBinding() {
return BindingBuilder
.bind(businessQueue())
.to(businessExchange())
.with("business.routing.key");
}
} public Binding businessBinding() {`
`#/**
* 死信队列完整配置
*
* 配置要点:
* 1. 业务队列配置 x-dead-letter-exchange 指向死信交换机
* 2. 死信队列绑定到死信交换机
* 3. 死信队列也需持久化
*/
@Configuration
public class DeadLetterConfig {
// ========== 死信交换机和队列 ==========
@Bean
public DirectExchange deadLetterExchange() {
return new DirectExchange("dead.letter.exchange", true, false);
}
@Bean
public Queue deadLetterQueue() {
return QueueBuilder
.durable("dead.letter.queue")
.ttl(60000) // 死信消息也设置TTL,防止无限堆积
.build();
}
@Bean
public Binding deadLetterBinding() {
return BindingBuilder
.bind(deadLetterQueue())
.to(deadLetterExchange())
.with("dead.letter.routing.key");
}
// ========== 业务队列(配置死信转发) ==========
@Bean
public Queue businessQueue() {
return QueueBuilder
.durable("business.queue")
// 关键配置:指定死信交换机
.withArgument("x-dead-letter-exchange", "dead.letter.exchange")
// 指定死信路由键(可选,默认使用原队列的路由键)
.withArgument("x-dead-letter-routing-key", "dead.letter.routing.key")
// 消息TTL(示例:30秒未消费则进入死信队列)
.withArgument("x-message-ttl", 30000)
// 队列最大长度(超出则进入死信队列)
.withArgument("x-max-length", 10000)
.build();
}
@Bean
public DirectExchange businessExchange() {
return new DirectExchange("business.exchange", true, false);
}
@Bean
public Binding businessBinding() {
return BindingBuilder
.bind(businessQueue())
.to(businessExchange())
.with("business.routing.key");
}
} return BindingBuilder`
`#/**
* 死信队列完整配置
*
* 配置要点:
* 1. 业务队列配置 x-dead-letter-exchange 指向死信交换机
* 2. 死信队列绑定到死信交换机
* 3. 死信队列也需持久化
*/
@Configuration
public class DeadLetterConfig {
// ========== 死信交换机和队列 ==========
@Bean
public DirectExchange deadLetterExchange() {
return new DirectExchange("dead.letter.exchange", true, false);
}
@Bean
public Queue deadLetterQueue() {
return QueueBuilder
.durable("dead.letter.queue")
.ttl(60000) // 死信消息也设置TTL,防止无限堆积
.build();
}
@Bean
public Binding deadLetterBinding() {
return BindingBuilder
.bind(deadLetterQueue())
.to(deadLetterExchange())
.with("dead.letter.routing.key");
}
// ========== 业务队列(配置死信转发) ==========
@Bean
public Queue businessQueue() {
return QueueBuilder
.durable("business.queue")
// 关键配置:指定死信交换机
.withArgument("x-dead-letter-exchange", "dead.letter.exchange")
// 指定死信路由键(可选,默认使用原队列的路由键)
.withArgument("x-dead-letter-routing-key", "dead.letter.routing.key")
// 消息TTL(示例:30秒未消费则进入死信队列)
.withArgument("x-message-ttl", 30000)
// 队列最大长度(超出则进入死信队列)
.withArgument("x-max-length", 10000)
.build();
}
@Bean
public DirectExchange businessExchange() {
return new DirectExchange("business.exchange", true, false);
}
@Bean
public Binding businessBinding() {
return BindingBuilder
.bind(businessQueue())
.to(businessExchange())
.with("business.routing.key");
}
} .bind(businessQueue())`
`#/**
* 死信队列完整配置
*
* 配置要点:
* 1. 业务队列配置 x-dead-letter-exchange 指向死信交换机
* 2. 死信队列绑定到死信交换机
* 3. 死信队列也需持久化
*/
@Configuration
public class DeadLetterConfig {
// ========== 死信交换机和队列 ==========
@Bean
public DirectExchange deadLetterExchange() {
return new DirectExchange("dead.letter.exchange", true, false);
}
@Bean
public Queue deadLetterQueue() {
return QueueBuilder
.durable("dead.letter.queue")
.ttl(60000) // 死信消息也设置TTL,防止无限堆积
.build();
}
@Bean
public Binding deadLetterBinding() {
return BindingBuilder
.bind(deadLetterQueue())
.to(deadLetterExchange())
.with("dead.letter.routing.key");
}
// ========== 业务队列(配置死信转发) ==========
@Bean
public Queue businessQueue() {
return QueueBuilder
.durable("business.queue")
// 关键配置:指定死信交换机
.withArgument("x-dead-letter-exchange", "dead.letter.exchange")
// 指定死信路由键(可选,默认使用原队列的路由键)
.withArgument("x-dead-letter-routing-key", "dead.letter.routing.key")
// 消息TTL(示例:30秒未消费则进入死信队列)
.withArgument("x-message-ttl", 30000)
// 队列最大长度(超出则进入死信队列)
.withArgument("x-max-length", 10000)
.build();
}
@Bean
public DirectExchange businessExchange() {
return new DirectExchange("business.exchange", true, false);
}
@Bean
public Binding businessBinding() {
return BindingBuilder
.bind(businessQueue())
.to(businessExchange())
.with("business.routing.key");
}
} .to(businessExchange())`
`#/**
* 死信队列完整配置
*
* 配置要点:
* 1. 业务队列配置 x-dead-letter-exchange 指向死信交换机
* 2. 死信队列绑定到死信交换机
* 3. 死信队列也需持久化
*/
@Configuration
public class DeadLetterConfig {
// ========== 死信交换机和队列 ==========
@Bean
public DirectExchange deadLetterExchange() {
return new DirectExchange("dead.letter.exchange", true, false);
}
@Bean
public Queue deadLetterQueue() {
return QueueBuilder
.durable("dead.letter.queue")
.ttl(60000) // 死信消息也设置TTL,防止无限堆积
.build();
}
@Bean
public Binding deadLetterBinding() {
return BindingBuilder
.bind(deadLetterQueue())
.to(deadLetterExchange())
.with("dead.letter.routing.key");
}
// ========== 业务队列(配置死信转发) ==========
@Bean
public Queue businessQueue() {
return QueueBuilder
.durable("business.queue")
// 关键配置:指定死信交换机
.withArgument("x-dead-letter-exchange", "dead.letter.exchange")
// 指定死信路由键(可选,默认使用原队列的路由键)
.withArgument("x-dead-letter-routing-key", "dead.letter.routing.key")
// 消息TTL(示例:30秒未消费则进入死信队列)
.withArgument("x-message-ttl", 30000)
// 队列最大长度(超出则进入死信队列)
.withArgument("x-max-length", 10000)
.build();
}
@Bean
public DirectExchange businessExchange() {
return new DirectExchange("business.exchange", true, false);
}
@Bean
public Binding businessBinding() {
return BindingBuilder
.bind(businessQueue())
.to(businessExchange())
.with("business.routing.key");
}
} .with("business.routing.key");`
`#/**
* 死信队列完整配置
*
* 配置要点:
* 1. 业务队列配置 x-dead-letter-exchange 指向死信交换机
* 2. 死信队列绑定到死信交换机
* 3. 死信队列也需持久化
*/
@Configuration
public class DeadLetterConfig {
// ========== 死信交换机和队列 ==========
@Bean
public DirectExchange deadLetterExchange() {
return new DirectExchange("dead.letter.exchange", true, false);
}
@Bean
public Queue deadLetterQueue() {
return QueueBuilder
.durable("dead.letter.queue")
.ttl(60000) // 死信消息也设置TTL,防止无限堆积
.build();
}
@Bean
public Binding deadLetterBinding() {
return BindingBuilder
.bind(deadLetterQueue())
.to(deadLetterExchange())
.with("dead.letter.routing.key");
}
// ========== 业务队列(配置死信转发) ==========
@Bean
public Queue businessQueue() {
return QueueBuilder
.durable("business.queue")
// 关键配置:指定死信交换机
.withArgument("x-dead-letter-exchange", "dead.letter.exchange")
// 指定死信路由键(可选,默认使用原队列的路由键)
.withArgument("x-dead-letter-routing-key", "dead.letter.routing.key")
// 消息TTL(示例:30秒未消费则进入死信队列)
.withArgument("x-message-ttl", 30000)
// 队列最大长度(超出则进入死信队列)
.withArgument("x-max-length", 10000)
.build();
}
@Bean
public DirectExchange businessExchange() {
return new DirectExchange("business.exchange", true, false);
}
@Bean
public Binding businessBinding() {
return BindingBuilder
.bind(businessQueue())
.to(businessExchange())
.with("business.routing.key");
}
} }`
`#/**
* 死信队列完整配置
*
* 配置要点:
* 1. 业务队列配置 x-dead-letter-exchange 指向死信交换机
* 2. 死信队列绑定到死信交换机
* 3. 死信队列也需持久化
*/
@Configuration
public class DeadLetterConfig {
// ========== 死信交换机和队列 ==========
@Bean
public DirectExchange deadLetterExchange() {
return new DirectExchange("dead.letter.exchange", true, false);
}
@Bean
public Queue deadLetterQueue() {
return QueueBuilder
.durable("dead.letter.queue")
.ttl(60000) // 死信消息也设置TTL,防止无限堆积
.build();
}
@Bean
public Binding deadLetterBinding() {
return BindingBuilder
.bind(deadLetterQueue())
.to(deadLetterExchange())
.with("dead.letter.routing.key");
}
// ========== 业务队列(配置死信转发) ==========
@Bean
public Queue businessQueue() {
return QueueBuilder
.durable("business.queue")
// 关键配置:指定死信交换机
.withArgument("x-dead-letter-exchange", "dead.letter.exchange")
// 指定死信路由键(可选,默认使用原队列的路由键)
.withArgument("x-dead-letter-routing-key", "dead.letter.routing.key")
// 消息TTL(示例:30秒未消费则进入死信队列)
.withArgument("x-message-ttl", 30000)
// 队列最大长度(超出则进入死信队列)
.withArgument("x-max-length", 10000)
.build();
}
@Bean
public DirectExchange businessExchange() {
return new DirectExchange("business.exchange", true, false);
}
@Bean
public Binding businessBinding() {
return BindingBuilder
.bind(businessQueue())
.to(businessExchange())
.with("business.routing.key");
}
}}
4.2.2 消息进入死信队列的模拟
java
#/**
* 生产者:发送可能失败的消息
*/
@Service
public class BusinessMessageProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
/**
* 发送测试消息
*/
public void sendBusinessMessage(String content) {
rabbitTemplate.convertAndSend(
"business.exchange",
"business.routing.key",
content,
message -> {
// 设置消息TTL(30秒)
message.getMessageProperties().setExpiration("30000");
return message;
}
);
}
}
/**
* 消费者:模拟处理失败
*/
@Component
public class BusinessMessageConsumer {
@RabbitListener(queues = "business.queue")
public void handleBusinessMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 模拟业务处理失败
if (message.contains("error")) {
throw new RuntimeException("业务处理失败");
}
// 正常处理
System.out.println("处理成功: " + message);
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 拒绝消息且不重新入队(进入死信队列)
channel.basicNack(deliveryTag, false, false);
System.err.println("消息进入死信队列: " + message);
}
}
}/**`
`#/**
* 生产者:发送可能失败的消息
*/
@Service
public class BusinessMessageProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
/**
* 发送测试消息
*/
public void sendBusinessMessage(String content) {
rabbitTemplate.convertAndSend(
"business.exchange",
"business.routing.key",
content,
message -> {
// 设置消息TTL(30秒)
message.getMessageProperties().setExpiration("30000");
return message;
}
);
}
}
/**
* 消费者:模拟处理失败
*/
@Component
public class BusinessMessageConsumer {
@RabbitListener(queues = "business.queue")
public void handleBusinessMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 模拟业务处理失败
if (message.contains("error")) {
throw new RuntimeException("业务处理失败");
}
// 正常处理
System.out.println("处理成功: " + message);
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 拒绝消息且不重新入队(进入死信队列)
channel.basicNack(deliveryTag, false, false);
System.err.println("消息进入死信队列: " + message);
}
}
} * 生产者:发送可能失败的消息`
`#/**
* 生产者:发送可能失败的消息
*/
@Service
public class BusinessMessageProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
/**
* 发送测试消息
*/
public void sendBusinessMessage(String content) {
rabbitTemplate.convertAndSend(
"business.exchange",
"business.routing.key",
content,
message -> {
// 设置消息TTL(30秒)
message.getMessageProperties().setExpiration("30000");
return message;
}
);
}
}
/**
* 消费者:模拟处理失败
*/
@Component
public class BusinessMessageConsumer {
@RabbitListener(queues = "business.queue")
public void handleBusinessMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 模拟业务处理失败
if (message.contains("error")) {
throw new RuntimeException("业务处理失败");
}
// 正常处理
System.out.println("处理成功: " + message);
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 拒绝消息且不重新入队(进入死信队列)
channel.basicNack(deliveryTag, false, false);
System.err.println("消息进入死信队列: " + message);
}
}
} */`
`#/**
* 生产者:发送可能失败的消息
*/
@Service
public class BusinessMessageProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
/**
* 发送测试消息
*/
public void sendBusinessMessage(String content) {
rabbitTemplate.convertAndSend(
"business.exchange",
"business.routing.key",
content,
message -> {
// 设置消息TTL(30秒)
message.getMessageProperties().setExpiration("30000");
return message;
}
);
}
}
/**
* 消费者:模拟处理失败
*/
@Component
public class BusinessMessageConsumer {
@RabbitListener(queues = "business.queue")
public void handleBusinessMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 模拟业务处理失败
if (message.contains("error")) {
throw new RuntimeException("业务处理失败");
}
// 正常处理
System.out.println("处理成功: " + message);
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 拒绝消息且不重新入队(进入死信队列)
channel.basicNack(deliveryTag, false, false);
System.err.println("消息进入死信队列: " + message);
}
}
}@Service`
`#/**
* 生产者:发送可能失败的消息
*/
@Service
public class BusinessMessageProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
/**
* 发送测试消息
*/
public void sendBusinessMessage(String content) {
rabbitTemplate.convertAndSend(
"business.exchange",
"business.routing.key",
content,
message -> {
// 设置消息TTL(30秒)
message.getMessageProperties().setExpiration("30000");
return message;
}
);
}
}
/**
* 消费者:模拟处理失败
*/
@Component
public class BusinessMessageConsumer {
@RabbitListener(queues = "business.queue")
public void handleBusinessMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 模拟业务处理失败
if (message.contains("error")) {
throw new RuntimeException("业务处理失败");
}
// 正常处理
System.out.println("处理成功: " + message);
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 拒绝消息且不重新入队(进入死信队列)
channel.basicNack(deliveryTag, false, false);
System.err.println("消息进入死信队列: " + message);
}
}
}public class BusinessMessageProducer {`
`#/**
* 生产者:发送可能失败的消息
*/
@Service
public class BusinessMessageProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
/**
* 发送测试消息
*/
public void sendBusinessMessage(String content) {
rabbitTemplate.convertAndSend(
"business.exchange",
"business.routing.key",
content,
message -> {
// 设置消息TTL(30秒)
message.getMessageProperties().setExpiration("30000");
return message;
}
);
}
}
/**
* 消费者:模拟处理失败
*/
@Component
public class BusinessMessageConsumer {
@RabbitListener(queues = "business.queue")
public void handleBusinessMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 模拟业务处理失败
if (message.contains("error")) {
throw new RuntimeException("业务处理失败");
}
// 正常处理
System.out.println("处理成功: " + message);
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 拒绝消息且不重新入队(进入死信队列)
channel.basicNack(deliveryTag, false, false);
System.err.println("消息进入死信队列: " + message);
}
}
}`
`#/**
* 生产者:发送可能失败的消息
*/
@Service
public class BusinessMessageProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
/**
* 发送测试消息
*/
public void sendBusinessMessage(String content) {
rabbitTemplate.convertAndSend(
"business.exchange",
"business.routing.key",
content,
message -> {
// 设置消息TTL(30秒)
message.getMessageProperties().setExpiration("30000");
return message;
}
);
}
}
/**
* 消费者:模拟处理失败
*/
@Component
public class BusinessMessageConsumer {
@RabbitListener(queues = "business.queue")
public void handleBusinessMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 模拟业务处理失败
if (message.contains("error")) {
throw new RuntimeException("业务处理失败");
}
// 正常处理
System.out.println("处理成功: " + message);
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 拒绝消息且不重新入队(进入死信队列)
channel.basicNack(deliveryTag, false, false);
System.err.println("消息进入死信队列: " + message);
}
}
} @Autowired`
`#/**
* 生产者:发送可能失败的消息
*/
@Service
public class BusinessMessageProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
/**
* 发送测试消息
*/
public void sendBusinessMessage(String content) {
rabbitTemplate.convertAndSend(
"business.exchange",
"business.routing.key",
content,
message -> {
// 设置消息TTL(30秒)
message.getMessageProperties().setExpiration("30000");
return message;
}
);
}
}
/**
* 消费者:模拟处理失败
*/
@Component
public class BusinessMessageConsumer {
@RabbitListener(queues = "business.queue")
public void handleBusinessMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 模拟业务处理失败
if (message.contains("error")) {
throw new RuntimeException("业务处理失败");
}
// 正常处理
System.out.println("处理成功: " + message);
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 拒绝消息且不重新入队(进入死信队列)
channel.basicNack(deliveryTag, false, false);
System.err.println("消息进入死信队列: " + message);
}
}
} private RabbitTemplate rabbitTemplate;`
`#/**
* 生产者:发送可能失败的消息
*/
@Service
public class BusinessMessageProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
/**
* 发送测试消息
*/
public void sendBusinessMessage(String content) {
rabbitTemplate.convertAndSend(
"business.exchange",
"business.routing.key",
content,
message -> {
// 设置消息TTL(30秒)
message.getMessageProperties().setExpiration("30000");
return message;
}
);
}
}
/**
* 消费者:模拟处理失败
*/
@Component
public class BusinessMessageConsumer {
@RabbitListener(queues = "business.queue")
public void handleBusinessMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 模拟业务处理失败
if (message.contains("error")) {
throw new RuntimeException("业务处理失败");
}
// 正常处理
System.out.println("处理成功: " + message);
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 拒绝消息且不重新入队(进入死信队列)
channel.basicNack(deliveryTag, false, false);
System.err.println("消息进入死信队列: " + message);
}
}
}`
`#/**
* 生产者:发送可能失败的消息
*/
@Service
public class BusinessMessageProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
/**
* 发送测试消息
*/
public void sendBusinessMessage(String content) {
rabbitTemplate.convertAndSend(
"business.exchange",
"business.routing.key",
content,
message -> {
// 设置消息TTL(30秒)
message.getMessageProperties().setExpiration("30000");
return message;
}
);
}
}
/**
* 消费者:模拟处理失败
*/
@Component
public class BusinessMessageConsumer {
@RabbitListener(queues = "business.queue")
public void handleBusinessMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 模拟业务处理失败
if (message.contains("error")) {
throw new RuntimeException("业务处理失败");
}
// 正常处理
System.out.println("处理成功: " + message);
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 拒绝消息且不重新入队(进入死信队列)
channel.basicNack(deliveryTag, false, false);
System.err.println("消息进入死信队列: " + message);
}
}
} /**`
`#/**
* 生产者:发送可能失败的消息
*/
@Service
public class BusinessMessageProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
/**
* 发送测试消息
*/
public void sendBusinessMessage(String content) {
rabbitTemplate.convertAndSend(
"business.exchange",
"business.routing.key",
content,
message -> {
// 设置消息TTL(30秒)
message.getMessageProperties().setExpiration("30000");
return message;
}
);
}
}
/**
* 消费者:模拟处理失败
*/
@Component
public class BusinessMessageConsumer {
@RabbitListener(queues = "business.queue")
public void handleBusinessMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 模拟业务处理失败
if (message.contains("error")) {
throw new RuntimeException("业务处理失败");
}
// 正常处理
System.out.println("处理成功: " + message);
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 拒绝消息且不重新入队(进入死信队列)
channel.basicNack(deliveryTag, false, false);
System.err.println("消息进入死信队列: " + message);
}
}
} * 发送测试消息`
`#/**
* 生产者:发送可能失败的消息
*/
@Service
public class BusinessMessageProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
/**
* 发送测试消息
*/
public void sendBusinessMessage(String content) {
rabbitTemplate.convertAndSend(
"business.exchange",
"business.routing.key",
content,
message -> {
// 设置消息TTL(30秒)
message.getMessageProperties().setExpiration("30000");
return message;
}
);
}
}
/**
* 消费者:模拟处理失败
*/
@Component
public class BusinessMessageConsumer {
@RabbitListener(queues = "business.queue")
public void handleBusinessMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 模拟业务处理失败
if (message.contains("error")) {
throw new RuntimeException("业务处理失败");
}
// 正常处理
System.out.println("处理成功: " + message);
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 拒绝消息且不重新入队(进入死信队列)
channel.basicNack(deliveryTag, false, false);
System.err.println("消息进入死信队列: " + message);
}
}
} */`
`#/**
* 生产者:发送可能失败的消息
*/
@Service
public class BusinessMessageProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
/**
* 发送测试消息
*/
public void sendBusinessMessage(String content) {
rabbitTemplate.convertAndSend(
"business.exchange",
"business.routing.key",
content,
message -> {
// 设置消息TTL(30秒)
message.getMessageProperties().setExpiration("30000");
return message;
}
);
}
}
/**
* 消费者:模拟处理失败
*/
@Component
public class BusinessMessageConsumer {
@RabbitListener(queues = "business.queue")
public void handleBusinessMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 模拟业务处理失败
if (message.contains("error")) {
throw new RuntimeException("业务处理失败");
}
// 正常处理
System.out.println("处理成功: " + message);
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 拒绝消息且不重新入队(进入死信队列)
channel.basicNack(deliveryTag, false, false);
System.err.println("消息进入死信队列: " + message);
}
}
} public void sendBusinessMessage(String content) {`
`#/**
* 生产者:发送可能失败的消息
*/
@Service
public class BusinessMessageProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
/**
* 发送测试消息
*/
public void sendBusinessMessage(String content) {
rabbitTemplate.convertAndSend(
"business.exchange",
"business.routing.key",
content,
message -> {
// 设置消息TTL(30秒)
message.getMessageProperties().setExpiration("30000");
return message;
}
);
}
}
/**
* 消费者:模拟处理失败
*/
@Component
public class BusinessMessageConsumer {
@RabbitListener(queues = "business.queue")
public void handleBusinessMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 模拟业务处理失败
if (message.contains("error")) {
throw new RuntimeException("业务处理失败");
}
// 正常处理
System.out.println("处理成功: " + message);
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 拒绝消息且不重新入队(进入死信队列)
channel.basicNack(deliveryTag, false, false);
System.err.println("消息进入死信队列: " + message);
}
}
} rabbitTemplate.convertAndSend(`
`#/**
* 生产者:发送可能失败的消息
*/
@Service
public class BusinessMessageProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
/**
* 发送测试消息
*/
public void sendBusinessMessage(String content) {
rabbitTemplate.convertAndSend(
"business.exchange",
"business.routing.key",
content,
message -> {
// 设置消息TTL(30秒)
message.getMessageProperties().setExpiration("30000");
return message;
}
);
}
}
/**
* 消费者:模拟处理失败
*/
@Component
public class BusinessMessageConsumer {
@RabbitListener(queues = "business.queue")
public void handleBusinessMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 模拟业务处理失败
if (message.contains("error")) {
throw new RuntimeException("业务处理失败");
}
// 正常处理
System.out.println("处理成功: " + message);
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 拒绝消息且不重新入队(进入死信队列)
channel.basicNack(deliveryTag, false, false);
System.err.println("消息进入死信队列: " + message);
}
}
} "business.exchange",`
`#/**
* 生产者:发送可能失败的消息
*/
@Service
public class BusinessMessageProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
/**
* 发送测试消息
*/
public void sendBusinessMessage(String content) {
rabbitTemplate.convertAndSend(
"business.exchange",
"business.routing.key",
content,
message -> {
// 设置消息TTL(30秒)
message.getMessageProperties().setExpiration("30000");
return message;
}
);
}
}
/**
* 消费者:模拟处理失败
*/
@Component
public class BusinessMessageConsumer {
@RabbitListener(queues = "business.queue")
public void handleBusinessMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 模拟业务处理失败
if (message.contains("error")) {
throw new RuntimeException("业务处理失败");
}
// 正常处理
System.out.println("处理成功: " + message);
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 拒绝消息且不重新入队(进入死信队列)
channel.basicNack(deliveryTag, false, false);
System.err.println("消息进入死信队列: " + message);
}
}
} "business.routing.key",`
`#/**
* 生产者:发送可能失败的消息
*/
@Service
public class BusinessMessageProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
/**
* 发送测试消息
*/
public void sendBusinessMessage(String content) {
rabbitTemplate.convertAndSend(
"business.exchange",
"business.routing.key",
content,
message -> {
// 设置消息TTL(30秒)
message.getMessageProperties().setExpiration("30000");
return message;
}
);
}
}
/**
* 消费者:模拟处理失败
*/
@Component
public class BusinessMessageConsumer {
@RabbitListener(queues = "business.queue")
public void handleBusinessMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 模拟业务处理失败
if (message.contains("error")) {
throw new RuntimeException("业务处理失败");
}
// 正常处理
System.out.println("处理成功: " + message);
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 拒绝消息且不重新入队(进入死信队列)
channel.basicNack(deliveryTag, false, false);
System.err.println("消息进入死信队列: " + message);
}
}
} content,`
`#/**
* 生产者:发送可能失败的消息
*/
@Service
public class BusinessMessageProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
/**
* 发送测试消息
*/
public void sendBusinessMessage(String content) {
rabbitTemplate.convertAndSend(
"business.exchange",
"business.routing.key",
content,
message -> {
// 设置消息TTL(30秒)
message.getMessageProperties().setExpiration("30000");
return message;
}
);
}
}
/**
* 消费者:模拟处理失败
*/
@Component
public class BusinessMessageConsumer {
@RabbitListener(queues = "business.queue")
public void handleBusinessMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 模拟业务处理失败
if (message.contains("error")) {
throw new RuntimeException("业务处理失败");
}
// 正常处理
System.out.println("处理成功: " + message);
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 拒绝消息且不重新入队(进入死信队列)
channel.basicNack(deliveryTag, false, false);
System.err.println("消息进入死信队列: " + message);
}
}
} message -> {`
`#/**
* 生产者:发送可能失败的消息
*/
@Service
public class BusinessMessageProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
/**
* 发送测试消息
*/
public void sendBusinessMessage(String content) {
rabbitTemplate.convertAndSend(
"business.exchange",
"business.routing.key",
content,
message -> {
// 设置消息TTL(30秒)
message.getMessageProperties().setExpiration("30000");
return message;
}
);
}
}
/**
* 消费者:模拟处理失败
*/
@Component
public class BusinessMessageConsumer {
@RabbitListener(queues = "business.queue")
public void handleBusinessMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 模拟业务处理失败
if (message.contains("error")) {
throw new RuntimeException("业务处理失败");
}
// 正常处理
System.out.println("处理成功: " + message);
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 拒绝消息且不重新入队(进入死信队列)
channel.basicNack(deliveryTag, false, false);
System.err.println("消息进入死信队列: " + message);
}
}
} // 设置消息TTL(30秒)`
`#/**
* 生产者:发送可能失败的消息
*/
@Service
public class BusinessMessageProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
/**
* 发送测试消息
*/
public void sendBusinessMessage(String content) {
rabbitTemplate.convertAndSend(
"business.exchange",
"business.routing.key",
content,
message -> {
// 设置消息TTL(30秒)
message.getMessageProperties().setExpiration("30000");
return message;
}
);
}
}
/**
* 消费者:模拟处理失败
*/
@Component
public class BusinessMessageConsumer {
@RabbitListener(queues = "business.queue")
public void handleBusinessMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 模拟业务处理失败
if (message.contains("error")) {
throw new RuntimeException("业务处理失败");
}
// 正常处理
System.out.println("处理成功: " + message);
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 拒绝消息且不重新入队(进入死信队列)
channel.basicNack(deliveryTag, false, false);
System.err.println("消息进入死信队列: " + message);
}
}
} message.getMessageProperties().setExpiration("30000");`
`#/**
* 生产者:发送可能失败的消息
*/
@Service
public class BusinessMessageProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
/**
* 发送测试消息
*/
public void sendBusinessMessage(String content) {
rabbitTemplate.convertAndSend(
"business.exchange",
"business.routing.key",
content,
message -> {
// 设置消息TTL(30秒)
message.getMessageProperties().setExpiration("30000");
return message;
}
);
}
}
/**
* 消费者:模拟处理失败
*/
@Component
public class BusinessMessageConsumer {
@RabbitListener(queues = "business.queue")
public void handleBusinessMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 模拟业务处理失败
if (message.contains("error")) {
throw new RuntimeException("业务处理失败");
}
// 正常处理
System.out.println("处理成功: " + message);
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 拒绝消息且不重新入队(进入死信队列)
channel.basicNack(deliveryTag, false, false);
System.err.println("消息进入死信队列: " + message);
}
}
} return message;`
`#/**
* 生产者:发送可能失败的消息
*/
@Service
public class BusinessMessageProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
/**
* 发送测试消息
*/
public void sendBusinessMessage(String content) {
rabbitTemplate.convertAndSend(
"business.exchange",
"business.routing.key",
content,
message -> {
// 设置消息TTL(30秒)
message.getMessageProperties().setExpiration("30000");
return message;
}
);
}
}
/**
* 消费者:模拟处理失败
*/
@Component
public class BusinessMessageConsumer {
@RabbitListener(queues = "business.queue")
public void handleBusinessMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 模拟业务处理失败
if (message.contains("error")) {
throw new RuntimeException("业务处理失败");
}
// 正常处理
System.out.println("处理成功: " + message);
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 拒绝消息且不重新入队(进入死信队列)
channel.basicNack(deliveryTag, false, false);
System.err.println("消息进入死信队列: " + message);
}
}
} }`
`#/**
* 生产者:发送可能失败的消息
*/
@Service
public class BusinessMessageProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
/**
* 发送测试消息
*/
public void sendBusinessMessage(String content) {
rabbitTemplate.convertAndSend(
"business.exchange",
"business.routing.key",
content,
message -> {
// 设置消息TTL(30秒)
message.getMessageProperties().setExpiration("30000");
return message;
}
);
}
}
/**
* 消费者:模拟处理失败
*/
@Component
public class BusinessMessageConsumer {
@RabbitListener(queues = "business.queue")
public void handleBusinessMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 模拟业务处理失败
if (message.contains("error")) {
throw new RuntimeException("业务处理失败");
}
// 正常处理
System.out.println("处理成功: " + message);
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 拒绝消息且不重新入队(进入死信队列)
channel.basicNack(deliveryTag, false, false);
System.err.println("消息进入死信队列: " + message);
}
}
} );`
`#/**
* 生产者:发送可能失败的消息
*/
@Service
public class BusinessMessageProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
/**
* 发送测试消息
*/
public void sendBusinessMessage(String content) {
rabbitTemplate.convertAndSend(
"business.exchange",
"business.routing.key",
content,
message -> {
// 设置消息TTL(30秒)
message.getMessageProperties().setExpiration("30000");
return message;
}
);
}
}
/**
* 消费者:模拟处理失败
*/
@Component
public class BusinessMessageConsumer {
@RabbitListener(queues = "business.queue")
public void handleBusinessMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 模拟业务处理失败
if (message.contains("error")) {
throw new RuntimeException("业务处理失败");
}
// 正常处理
System.out.println("处理成功: " + message);
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 拒绝消息且不重新入队(进入死信队列)
channel.basicNack(deliveryTag, false, false);
System.err.println("消息进入死信队列: " + message);
}
}
} }`
`#/**
* 生产者:发送可能失败的消息
*/
@Service
public class BusinessMessageProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
/**
* 发送测试消息
*/
public void sendBusinessMessage(String content) {
rabbitTemplate.convertAndSend(
"business.exchange",
"business.routing.key",
content,
message -> {
// 设置消息TTL(30秒)
message.getMessageProperties().setExpiration("30000");
return message;
}
);
}
}
/**
* 消费者:模拟处理失败
*/
@Component
public class BusinessMessageConsumer {
@RabbitListener(queues = "business.queue")
public void handleBusinessMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 模拟业务处理失败
if (message.contains("error")) {
throw new RuntimeException("业务处理失败");
}
// 正常处理
System.out.println("处理成功: " + message);
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 拒绝消息且不重新入队(进入死信队列)
channel.basicNack(deliveryTag, false, false);
System.err.println("消息进入死信队列: " + message);
}
}
}}`
`#/**
* 生产者:发送可能失败的消息
*/
@Service
public class BusinessMessageProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
/**
* 发送测试消息
*/
public void sendBusinessMessage(String content) {
rabbitTemplate.convertAndSend(
"business.exchange",
"business.routing.key",
content,
message -> {
// 设置消息TTL(30秒)
message.getMessageProperties().setExpiration("30000");
return message;
}
);
}
}
/**
* 消费者:模拟处理失败
*/
@Component
public class BusinessMessageConsumer {
@RabbitListener(queues = "business.queue")
public void handleBusinessMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 模拟业务处理失败
if (message.contains("error")) {
throw new RuntimeException("业务处理失败");
}
// 正常处理
System.out.println("处理成功: " + message);
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 拒绝消息且不重新入队(进入死信队列)
channel.basicNack(deliveryTag, false, false);
System.err.println("消息进入死信队列: " + message);
}
}
}`
`#/**
* 生产者:发送可能失败的消息
*/
@Service
public class BusinessMessageProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
/**
* 发送测试消息
*/
public void sendBusinessMessage(String content) {
rabbitTemplate.convertAndSend(
"business.exchange",
"business.routing.key",
content,
message -> {
// 设置消息TTL(30秒)
message.getMessageProperties().setExpiration("30000");
return message;
}
);
}
}
/**
* 消费者:模拟处理失败
*/
@Component
public class BusinessMessageConsumer {
@RabbitListener(queues = "business.queue")
public void handleBusinessMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 模拟业务处理失败
if (message.contains("error")) {
throw new RuntimeException("业务处理失败");
}
// 正常处理
System.out.println("处理成功: " + message);
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 拒绝消息且不重新入队(进入死信队列)
channel.basicNack(deliveryTag, false, false);
System.err.println("消息进入死信队列: " + message);
}
}
}/**`
`#/**
* 生产者:发送可能失败的消息
*/
@Service
public class BusinessMessageProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
/**
* 发送测试消息
*/
public void sendBusinessMessage(String content) {
rabbitTemplate.convertAndSend(
"business.exchange",
"business.routing.key",
content,
message -> {
// 设置消息TTL(30秒)
message.getMessageProperties().setExpiration("30000");
return message;
}
);
}
}
/**
* 消费者:模拟处理失败
*/
@Component
public class BusinessMessageConsumer {
@RabbitListener(queues = "business.queue")
public void handleBusinessMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 模拟业务处理失败
if (message.contains("error")) {
throw new RuntimeException("业务处理失败");
}
// 正常处理
System.out.println("处理成功: " + message);
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 拒绝消息且不重新入队(进入死信队列)
channel.basicNack(deliveryTag, false, false);
System.err.println("消息进入死信队列: " + message);
}
}
} * 消费者:模拟处理失败`
`#/**
* 生产者:发送可能失败的消息
*/
@Service
public class BusinessMessageProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
/**
* 发送测试消息
*/
public void sendBusinessMessage(String content) {
rabbitTemplate.convertAndSend(
"business.exchange",
"business.routing.key",
content,
message -> {
// 设置消息TTL(30秒)
message.getMessageProperties().setExpiration("30000");
return message;
}
);
}
}
/**
* 消费者:模拟处理失败
*/
@Component
public class BusinessMessageConsumer {
@RabbitListener(queues = "business.queue")
public void handleBusinessMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 模拟业务处理失败
if (message.contains("error")) {
throw new RuntimeException("业务处理失败");
}
// 正常处理
System.out.println("处理成功: " + message);
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 拒绝消息且不重新入队(进入死信队列)
channel.basicNack(deliveryTag, false, false);
System.err.println("消息进入死信队列: " + message);
}
}
} */`
`#/**
* 生产者:发送可能失败的消息
*/
@Service
public class BusinessMessageProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
/**
* 发送测试消息
*/
public void sendBusinessMessage(String content) {
rabbitTemplate.convertAndSend(
"business.exchange",
"business.routing.key",
content,
message -> {
// 设置消息TTL(30秒)
message.getMessageProperties().setExpiration("30000");
return message;
}
);
}
}
/**
* 消费者:模拟处理失败
*/
@Component
public class BusinessMessageConsumer {
@RabbitListener(queues = "business.queue")
public void handleBusinessMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 模拟业务处理失败
if (message.contains("error")) {
throw new RuntimeException("业务处理失败");
}
// 正常处理
System.out.println("处理成功: " + message);
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 拒绝消息且不重新入队(进入死信队列)
channel.basicNack(deliveryTag, false, false);
System.err.println("消息进入死信队列: " + message);
}
}
}@Component`
`#/**
* 生产者:发送可能失败的消息
*/
@Service
public class BusinessMessageProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
/**
* 发送测试消息
*/
public void sendBusinessMessage(String content) {
rabbitTemplate.convertAndSend(
"business.exchange",
"business.routing.key",
content,
message -> {
// 设置消息TTL(30秒)
message.getMessageProperties().setExpiration("30000");
return message;
}
);
}
}
/**
* 消费者:模拟处理失败
*/
@Component
public class BusinessMessageConsumer {
@RabbitListener(queues = "business.queue")
public void handleBusinessMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 模拟业务处理失败
if (message.contains("error")) {
throw new RuntimeException("业务处理失败");
}
// 正常处理
System.out.println("处理成功: " + message);
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 拒绝消息且不重新入队(进入死信队列)
channel.basicNack(deliveryTag, false, false);
System.err.println("消息进入死信队列: " + message);
}
}
}public class BusinessMessageConsumer {`
`#/**
* 生产者:发送可能失败的消息
*/
@Service
public class BusinessMessageProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
/**
* 发送测试消息
*/
public void sendBusinessMessage(String content) {
rabbitTemplate.convertAndSend(
"business.exchange",
"business.routing.key",
content,
message -> {
// 设置消息TTL(30秒)
message.getMessageProperties().setExpiration("30000");
return message;
}
);
}
}
/**
* 消费者:模拟处理失败
*/
@Component
public class BusinessMessageConsumer {
@RabbitListener(queues = "business.queue")
public void handleBusinessMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 模拟业务处理失败
if (message.contains("error")) {
throw new RuntimeException("业务处理失败");
}
// 正常处理
System.out.println("处理成功: " + message);
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 拒绝消息且不重新入队(进入死信队列)
channel.basicNack(deliveryTag, false, false);
System.err.println("消息进入死信队列: " + message);
}
}
}`
`#/**
* 生产者:发送可能失败的消息
*/
@Service
public class BusinessMessageProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
/**
* 发送测试消息
*/
public void sendBusinessMessage(String content) {
rabbitTemplate.convertAndSend(
"business.exchange",
"business.routing.key",
content,
message -> {
// 设置消息TTL(30秒)
message.getMessageProperties().setExpiration("30000");
return message;
}
);
}
}
/**
* 消费者:模拟处理失败
*/
@Component
public class BusinessMessageConsumer {
@RabbitListener(queues = "business.queue")
public void handleBusinessMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 模拟业务处理失败
if (message.contains("error")) {
throw new RuntimeException("业务处理失败");
}
// 正常处理
System.out.println("处理成功: " + message);
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 拒绝消息且不重新入队(进入死信队列)
channel.basicNack(deliveryTag, false, false);
System.err.println("消息进入死信队列: " + message);
}
}
} @RabbitListener(queues = "business.queue")`
`#/**
* 生产者:发送可能失败的消息
*/
@Service
public class BusinessMessageProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
/**
* 发送测试消息
*/
public void sendBusinessMessage(String content) {
rabbitTemplate.convertAndSend(
"business.exchange",
"business.routing.key",
content,
message -> {
// 设置消息TTL(30秒)
message.getMessageProperties().setExpiration("30000");
return message;
}
);
}
}
/**
* 消费者:模拟处理失败
*/
@Component
public class BusinessMessageConsumer {
@RabbitListener(queues = "business.queue")
public void handleBusinessMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 模拟业务处理失败
if (message.contains("error")) {
throw new RuntimeException("业务处理失败");
}
// 正常处理
System.out.println("处理成功: " + message);
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 拒绝消息且不重新入队(进入死信队列)
channel.basicNack(deliveryTag, false, false);
System.err.println("消息进入死信队列: " + message);
}
}
} public void handleBusinessMessage(`
`#/**
* 生产者:发送可能失败的消息
*/
@Service
public class BusinessMessageProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
/**
* 发送测试消息
*/
public void sendBusinessMessage(String content) {
rabbitTemplate.convertAndSend(
"business.exchange",
"business.routing.key",
content,
message -> {
// 设置消息TTL(30秒)
message.getMessageProperties().setExpiration("30000");
return message;
}
);
}
}
/**
* 消费者:模拟处理失败
*/
@Component
public class BusinessMessageConsumer {
@RabbitListener(queues = "business.queue")
public void handleBusinessMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 模拟业务处理失败
if (message.contains("error")) {
throw new RuntimeException("业务处理失败");
}
// 正常处理
System.out.println("处理成功: " + message);
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 拒绝消息且不重新入队(进入死信队列)
channel.basicNack(deliveryTag, false, false);
System.err.println("消息进入死信队列: " + message);
}
}
} String message,`
`#/**
* 生产者:发送可能失败的消息
*/
@Service
public class BusinessMessageProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
/**
* 发送测试消息
*/
public void sendBusinessMessage(String content) {
rabbitTemplate.convertAndSend(
"business.exchange",
"business.routing.key",
content,
message -> {
// 设置消息TTL(30秒)
message.getMessageProperties().setExpiration("30000");
return message;
}
);
}
}
/**
* 消费者:模拟处理失败
*/
@Component
public class BusinessMessageConsumer {
@RabbitListener(queues = "business.queue")
public void handleBusinessMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 模拟业务处理失败
if (message.contains("error")) {
throw new RuntimeException("业务处理失败");
}
// 正常处理
System.out.println("处理成功: " + message);
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 拒绝消息且不重新入队(进入死信队列)
channel.basicNack(deliveryTag, false, false);
System.err.println("消息进入死信队列: " + message);
}
}
} Channel channel,`
`#/**
* 生产者:发送可能失败的消息
*/
@Service
public class BusinessMessageProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
/**
* 发送测试消息
*/
public void sendBusinessMessage(String content) {
rabbitTemplate.convertAndSend(
"business.exchange",
"business.routing.key",
content,
message -> {
// 设置消息TTL(30秒)
message.getMessageProperties().setExpiration("30000");
return message;
}
);
}
}
/**
* 消费者:模拟处理失败
*/
@Component
public class BusinessMessageConsumer {
@RabbitListener(queues = "business.queue")
public void handleBusinessMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 模拟业务处理失败
if (message.contains("error")) {
throw new RuntimeException("业务处理失败");
}
// 正常处理
System.out.println("处理成功: " + message);
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 拒绝消息且不重新入队(进入死信队列)
channel.basicNack(deliveryTag, false, false);
System.err.println("消息进入死信队列: " + message);
}
}
} @Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {`
`#/**
* 生产者:发送可能失败的消息
*/
@Service
public class BusinessMessageProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
/**
* 发送测试消息
*/
public void sendBusinessMessage(String content) {
rabbitTemplate.convertAndSend(
"business.exchange",
"business.routing.key",
content,
message -> {
// 设置消息TTL(30秒)
message.getMessageProperties().setExpiration("30000");
return message;
}
);
}
}
/**
* 消费者:模拟处理失败
*/
@Component
public class BusinessMessageConsumer {
@RabbitListener(queues = "business.queue")
public void handleBusinessMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 模拟业务处理失败
if (message.contains("error")) {
throw new RuntimeException("业务处理失败");
}
// 正常处理
System.out.println("处理成功: " + message);
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 拒绝消息且不重新入队(进入死信队列)
channel.basicNack(deliveryTag, false, false);
System.err.println("消息进入死信队列: " + message);
}
}
} `
`#/**
* 生产者:发送可能失败的消息
*/
@Service
public class BusinessMessageProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
/**
* 发送测试消息
*/
public void sendBusinessMessage(String content) {
rabbitTemplate.convertAndSend(
"business.exchange",
"business.routing.key",
content,
message -> {
// 设置消息TTL(30秒)
message.getMessageProperties().setExpiration("30000");
return message;
}
);
}
}
/**
* 消费者:模拟处理失败
*/
@Component
public class BusinessMessageConsumer {
@RabbitListener(queues = "business.queue")
public void handleBusinessMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 模拟业务处理失败
if (message.contains("error")) {
throw new RuntimeException("业务处理失败");
}
// 正常处理
System.out.println("处理成功: " + message);
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 拒绝消息且不重新入队(进入死信队列)
channel.basicNack(deliveryTag, false, false);
System.err.println("消息进入死信队列: " + message);
}
}
} try {`
`#/**
* 生产者:发送可能失败的消息
*/
@Service
public class BusinessMessageProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
/**
* 发送测试消息
*/
public void sendBusinessMessage(String content) {
rabbitTemplate.convertAndSend(
"business.exchange",
"business.routing.key",
content,
message -> {
// 设置消息TTL(30秒)
message.getMessageProperties().setExpiration("30000");
return message;
}
);
}
}
/**
* 消费者:模拟处理失败
*/
@Component
public class BusinessMessageConsumer {
@RabbitListener(queues = "business.queue")
public void handleBusinessMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 模拟业务处理失败
if (message.contains("error")) {
throw new RuntimeException("业务处理失败");
}
// 正常处理
System.out.println("处理成功: " + message);
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 拒绝消息且不重新入队(进入死信队列)
channel.basicNack(deliveryTag, false, false);
System.err.println("消息进入死信队列: " + message);
}
}
} // 模拟业务处理失败`
`#/**
* 生产者:发送可能失败的消息
*/
@Service
public class BusinessMessageProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
/**
* 发送测试消息
*/
public void sendBusinessMessage(String content) {
rabbitTemplate.convertAndSend(
"business.exchange",
"business.routing.key",
content,
message -> {
// 设置消息TTL(30秒)
message.getMessageProperties().setExpiration("30000");
return message;
}
);
}
}
/**
* 消费者:模拟处理失败
*/
@Component
public class BusinessMessageConsumer {
@RabbitListener(queues = "business.queue")
public void handleBusinessMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 模拟业务处理失败
if (message.contains("error")) {
throw new RuntimeException("业务处理失败");
}
// 正常处理
System.out.println("处理成功: " + message);
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 拒绝消息且不重新入队(进入死信队列)
channel.basicNack(deliveryTag, false, false);
System.err.println("消息进入死信队列: " + message);
}
}
} if (message.contains("error")) {`
`#/**
* 生产者:发送可能失败的消息
*/
@Service
public class BusinessMessageProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
/**
* 发送测试消息
*/
public void sendBusinessMessage(String content) {
rabbitTemplate.convertAndSend(
"business.exchange",
"business.routing.key",
content,
message -> {
// 设置消息TTL(30秒)
message.getMessageProperties().setExpiration("30000");
return message;
}
);
}
}
/**
* 消费者:模拟处理失败
*/
@Component
public class BusinessMessageConsumer {
@RabbitListener(queues = "business.queue")
public void handleBusinessMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 模拟业务处理失败
if (message.contains("error")) {
throw new RuntimeException("业务处理失败");
}
// 正常处理
System.out.println("处理成功: " + message);
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 拒绝消息且不重新入队(进入死信队列)
channel.basicNack(deliveryTag, false, false);
System.err.println("消息进入死信队列: " + message);
}
}
} throw new RuntimeException("业务处理失败");`
`#/**
* 生产者:发送可能失败的消息
*/
@Service
public class BusinessMessageProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
/**
* 发送测试消息
*/
public void sendBusinessMessage(String content) {
rabbitTemplate.convertAndSend(
"business.exchange",
"business.routing.key",
content,
message -> {
// 设置消息TTL(30秒)
message.getMessageProperties().setExpiration("30000");
return message;
}
);
}
}
/**
* 消费者:模拟处理失败
*/
@Component
public class BusinessMessageConsumer {
@RabbitListener(queues = "business.queue")
public void handleBusinessMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 模拟业务处理失败
if (message.contains("error")) {
throw new RuntimeException("业务处理失败");
}
// 正常处理
System.out.println("处理成功: " + message);
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 拒绝消息且不重新入队(进入死信队列)
channel.basicNack(deliveryTag, false, false);
System.err.println("消息进入死信队列: " + message);
}
}
} }`
`#/**
* 生产者:发送可能失败的消息
*/
@Service
public class BusinessMessageProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
/**
* 发送测试消息
*/
public void sendBusinessMessage(String content) {
rabbitTemplate.convertAndSend(
"business.exchange",
"business.routing.key",
content,
message -> {
// 设置消息TTL(30秒)
message.getMessageProperties().setExpiration("30000");
return message;
}
);
}
}
/**
* 消费者:模拟处理失败
*/
@Component
public class BusinessMessageConsumer {
@RabbitListener(queues = "business.queue")
public void handleBusinessMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 模拟业务处理失败
if (message.contains("error")) {
throw new RuntimeException("业务处理失败");
}
// 正常处理
System.out.println("处理成功: " + message);
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 拒绝消息且不重新入队(进入死信队列)
channel.basicNack(deliveryTag, false, false);
System.err.println("消息进入死信队列: " + message);
}
}
} `
`#/**
* 生产者:发送可能失败的消息
*/
@Service
public class BusinessMessageProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
/**
* 发送测试消息
*/
public void sendBusinessMessage(String content) {
rabbitTemplate.convertAndSend(
"business.exchange",
"business.routing.key",
content,
message -> {
// 设置消息TTL(30秒)
message.getMessageProperties().setExpiration("30000");
return message;
}
);
}
}
/**
* 消费者:模拟处理失败
*/
@Component
public class BusinessMessageConsumer {
@RabbitListener(queues = "business.queue")
public void handleBusinessMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 模拟业务处理失败
if (message.contains("error")) {
throw new RuntimeException("业务处理失败");
}
// 正常处理
System.out.println("处理成功: " + message);
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 拒绝消息且不重新入队(进入死信队列)
channel.basicNack(deliveryTag, false, false);
System.err.println("消息进入死信队列: " + message);
}
}
} // 正常处理`
`#/**
* 生产者:发送可能失败的消息
*/
@Service
public class BusinessMessageProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
/**
* 发送测试消息
*/
public void sendBusinessMessage(String content) {
rabbitTemplate.convertAndSend(
"business.exchange",
"business.routing.key",
content,
message -> {
// 设置消息TTL(30秒)
message.getMessageProperties().setExpiration("30000");
return message;
}
);
}
}
/**
* 消费者:模拟处理失败
*/
@Component
public class BusinessMessageConsumer {
@RabbitListener(queues = "business.queue")
public void handleBusinessMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 模拟业务处理失败
if (message.contains("error")) {
throw new RuntimeException("业务处理失败");
}
// 正常处理
System.out.println("处理成功: " + message);
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 拒绝消息且不重新入队(进入死信队列)
channel.basicNack(deliveryTag, false, false);
System.err.println("消息进入死信队列: " + message);
}
}
} System.out.println("处理成功: " + message);`
`#/**
* 生产者:发送可能失败的消息
*/
@Service
public class BusinessMessageProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
/**
* 发送测试消息
*/
public void sendBusinessMessage(String content) {
rabbitTemplate.convertAndSend(
"business.exchange",
"business.routing.key",
content,
message -> {
// 设置消息TTL(30秒)
message.getMessageProperties().setExpiration("30000");
return message;
}
);
}
}
/**
* 消费者:模拟处理失败
*/
@Component
public class BusinessMessageConsumer {
@RabbitListener(queues = "business.queue")
public void handleBusinessMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 模拟业务处理失败
if (message.contains("error")) {
throw new RuntimeException("业务处理失败");
}
// 正常处理
System.out.println("处理成功: " + message);
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 拒绝消息且不重新入队(进入死信队列)
channel.basicNack(deliveryTag, false, false);
System.err.println("消息进入死信队列: " + message);
}
}
} channel.basicAck(deliveryTag, false);`
`#/**
* 生产者:发送可能失败的消息
*/
@Service
public class BusinessMessageProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
/**
* 发送测试消息
*/
public void sendBusinessMessage(String content) {
rabbitTemplate.convertAndSend(
"business.exchange",
"business.routing.key",
content,
message -> {
// 设置消息TTL(30秒)
message.getMessageProperties().setExpiration("30000");
return message;
}
);
}
}
/**
* 消费者:模拟处理失败
*/
@Component
public class BusinessMessageConsumer {
@RabbitListener(queues = "business.queue")
public void handleBusinessMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 模拟业务处理失败
if (message.contains("error")) {
throw new RuntimeException("业务处理失败");
}
// 正常处理
System.out.println("处理成功: " + message);
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 拒绝消息且不重新入队(进入死信队列)
channel.basicNack(deliveryTag, false, false);
System.err.println("消息进入死信队列: " + message);
}
}
} `
`#/**
* 生产者:发送可能失败的消息
*/
@Service
public class BusinessMessageProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
/**
* 发送测试消息
*/
public void sendBusinessMessage(String content) {
rabbitTemplate.convertAndSend(
"business.exchange",
"business.routing.key",
content,
message -> {
// 设置消息TTL(30秒)
message.getMessageProperties().setExpiration("30000");
return message;
}
);
}
}
/**
* 消费者:模拟处理失败
*/
@Component
public class BusinessMessageConsumer {
@RabbitListener(queues = "business.queue")
public void handleBusinessMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 模拟业务处理失败
if (message.contains("error")) {
throw new RuntimeException("业务处理失败");
}
// 正常处理
System.out.println("处理成功: " + message);
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 拒绝消息且不重新入队(进入死信队列)
channel.basicNack(deliveryTag, false, false);
System.err.println("消息进入死信队列: " + message);
}
}
} } catch (Exception e) {`
`#/**
* 生产者:发送可能失败的消息
*/
@Service
public class BusinessMessageProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
/**
* 发送测试消息
*/
public void sendBusinessMessage(String content) {
rabbitTemplate.convertAndSend(
"business.exchange",
"business.routing.key",
content,
message -> {
// 设置消息TTL(30秒)
message.getMessageProperties().setExpiration("30000");
return message;
}
);
}
}
/**
* 消费者:模拟处理失败
*/
@Component
public class BusinessMessageConsumer {
@RabbitListener(queues = "business.queue")
public void handleBusinessMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 模拟业务处理失败
if (message.contains("error")) {
throw new RuntimeException("业务处理失败");
}
// 正常处理
System.out.println("处理成功: " + message);
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 拒绝消息且不重新入队(进入死信队列)
channel.basicNack(deliveryTag, false, false);
System.err.println("消息进入死信队列: " + message);
}
}
} // 拒绝消息且不重新入队(进入死信队列)`
`#/**
* 生产者:发送可能失败的消息
*/
@Service
public class BusinessMessageProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
/**
* 发送测试消息
*/
public void sendBusinessMessage(String content) {
rabbitTemplate.convertAndSend(
"business.exchange",
"business.routing.key",
content,
message -> {
// 设置消息TTL(30秒)
message.getMessageProperties().setExpiration("30000");
return message;
}
);
}
}
/**
* 消费者:模拟处理失败
*/
@Component
public class BusinessMessageConsumer {
@RabbitListener(queues = "business.queue")
public void handleBusinessMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 模拟业务处理失败
if (message.contains("error")) {
throw new RuntimeException("业务处理失败");
}
// 正常处理
System.out.println("处理成功: " + message);
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 拒绝消息且不重新入队(进入死信队列)
channel.basicNack(deliveryTag, false, false);
System.err.println("消息进入死信队列: " + message);
}
}
} channel.basicNack(deliveryTag, false, false);`
`#/**
* 生产者:发送可能失败的消息
*/
@Service
public class BusinessMessageProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
/**
* 发送测试消息
*/
public void sendBusinessMessage(String content) {
rabbitTemplate.convertAndSend(
"business.exchange",
"business.routing.key",
content,
message -> {
// 设置消息TTL(30秒)
message.getMessageProperties().setExpiration("30000");
return message;
}
);
}
}
/**
* 消费者:模拟处理失败
*/
@Component
public class BusinessMessageConsumer {
@RabbitListener(queues = "business.queue")
public void handleBusinessMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 模拟业务处理失败
if (message.contains("error")) {
throw new RuntimeException("业务处理失败");
}
// 正常处理
System.out.println("处理成功: " + message);
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 拒绝消息且不重新入队(进入死信队列)
channel.basicNack(deliveryTag, false, false);
System.err.println("消息进入死信队列: " + message);
}
}
} System.err.println("消息进入死信队列: " + message);`
`#/**
* 生产者:发送可能失败的消息
*/
@Service
public class BusinessMessageProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
/**
* 发送测试消息
*/
public void sendBusinessMessage(String content) {
rabbitTemplate.convertAndSend(
"business.exchange",
"business.routing.key",
content,
message -> {
// 设置消息TTL(30秒)
message.getMessageProperties().setExpiration("30000");
return message;
}
);
}
}
/**
* 消费者:模拟处理失败
*/
@Component
public class BusinessMessageConsumer {
@RabbitListener(queues = "business.queue")
public void handleBusinessMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 模拟业务处理失败
if (message.contains("error")) {
throw new RuntimeException("业务处理失败");
}
// 正常处理
System.out.println("处理成功: " + message);
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 拒绝消息且不重新入队(进入死信队列)
channel.basicNack(deliveryTag, false, false);
System.err.println("消息进入死信队列: " + message);
}
}
} }`
`#/**
* 生产者:发送可能失败的消息
*/
@Service
public class BusinessMessageProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
/**
* 发送测试消息
*/
public void sendBusinessMessage(String content) {
rabbitTemplate.convertAndSend(
"business.exchange",
"business.routing.key",
content,
message -> {
// 设置消息TTL(30秒)
message.getMessageProperties().setExpiration("30000");
return message;
}
);
}
}
/**
* 消费者:模拟处理失败
*/
@Component
public class BusinessMessageConsumer {
@RabbitListener(queues = "business.queue")
public void handleBusinessMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 模拟业务处理失败
if (message.contains("error")) {
throw new RuntimeException("业务处理失败");
}
// 正常处理
System.out.println("处理成功: " + message);
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 拒绝消息且不重新入队(进入死信队列)
channel.basicNack(deliveryTag, false, false);
System.err.println("消息进入死信队列: " + message);
}
}
} }`
`#/**
* 生产者:发送可能失败的消息
*/
@Service
public class BusinessMessageProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
/**
* 发送测试消息
*/
public void sendBusinessMessage(String content) {
rabbitTemplate.convertAndSend(
"business.exchange",
"business.routing.key",
content,
message -> {
// 设置消息TTL(30秒)
message.getMessageProperties().setExpiration("30000");
return message;
}
);
}
}
/**
* 消费者:模拟处理失败
*/
@Component
public class BusinessMessageConsumer {
@RabbitListener(queues = "business.queue")
public void handleBusinessMessage(
String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 模拟业务处理失败
if (message.contains("error")) {
throw new RuntimeException("业务处理失败");
}
// 正常处理
System.out.println("处理成功: " + message);
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 拒绝消息且不重新入队(进入死信队列)
channel.basicNack(deliveryTag, false, false);
System.err.println("消息进入死信队列: " + message);
}
}
}}
4.2.3 死信队列处理器
java
#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
}/**`
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} * 死信队列消费者:处理异常消息`
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} * `
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} * 职责:`
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} * 1. 记录死信消息的详细信息`
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} * 2. 分析死因`
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} * 3. 尝试补偿或人工介入`
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} */`
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
}@Component`
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
}public class DeadLetterConsumer {`
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
}`
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} @Autowired`
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} private DeadLetterRepository deadLetterRepository;`
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
}`
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} @RabbitListener(queues = "dead.letter.queue")`
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} public void handleDeadLetter(`
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} Message message,`
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} Channel channel,`
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} @Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {`
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} `
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} try {`
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} // 1. 提取消息信息`
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} String messageBody = new String(message.getBody());`
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} MessageProperties props = message.getMessageProperties();`
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} `
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} // 2. 记录到数据库`
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} DeadLetterRecord record = new DeadLetterRecord();`
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} record.setMessageId(props.getMessageId());`
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} record.setOriginalQueue(props.getConsumerQueue());`
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} record.setRoutingKey(props.getReceivedRoutingKey());`
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} record.setContent(messageBody);`
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} record.setDeathReason(props.getHeaders()); // 死因可能存在header中`
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} record.setCreateTime(new Date());`
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} `
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} deadLetterRepository.save(record);`
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} `
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} // 3. 分析死因并决定处理策略`
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} String deathReason = analyzeDeathReason(props);`
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} `
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} if (canRetry(deathReason)) {`
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} // 可重试:重新投递到业务队列`
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} retryMessage(message);`
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} System.out.println("死信消息已重新投递: " + props.getMessageId());`
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} } else {`
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} // 不可重试:记录日志,等待人工处理`
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} System.err.println("死信消息需要人工介入: " + props.getMessageId());`
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} sendAlert(record);`
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} }`
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} `
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} // 4. 确认死信消息`
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} channel.basicAck(deliveryTag, false);`
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} `
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} } catch (Exception e) {`
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} // 死信处理也失败,记录日志但不NACK(防止无限循环)`
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} System.err.println("死信处理失败: " + e.getMessage());`
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} channel.basicAck(deliveryTag, false); // 直接确认,避免循环`
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} }`
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} }`
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
}`
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} /**`
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} * 分析死因`
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} */`
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} private String analyzeDeathReason(MessageProperties props) {`
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} // 从 x-death header 中获取死信历史`
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} Map<String, Object> headers = props.getHeaders();`
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} List<Map<String, Object>> xDeath = `
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} (List<Map<String, Object>>) headers.get("x-death");`
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} `
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} if (xDeath != null && !xDeath.isEmpty()) {`
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} Map<String, Object> deathInfo = xDeath.get(0);`
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} return (String) deathInfo.get("reason");`
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} }`
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} `
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} return "unknown";`
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} }`
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
}`
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} /**`
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} * 判断是否可重试`
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} */`
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} private boolean canRetry(String deathReason) {`
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} return "expired".equals(deathReason) || `
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} "maxlen".equals(deathReason);`
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} }`
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
}`
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} /**`
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} * 重新投递消息`
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} */`
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} private void retryMessage(Message originalMessage) {`
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} rabbitTemplate.send(`
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} "business.exchange",`
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} "business.routing.key",`
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} originalMessage`
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} );`
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} }`
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
}`
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} /**`
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} * 发送告警`
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} */`
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} private void sendAlert(DeadLetterRecord record) {`
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} // 实现告警逻辑:邮件、短信、钉钉等`
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} System.err.println("告警:死信消息需要处理 - " + record.getMessageId());`
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} }`
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
}}`
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
}`
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
}/**`
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} * 死信记录实体(JPA)`
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} */`
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
}@Entity`
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
}@Table(name = "dead_letter_record")`
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
}@Data`
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
}public class DeadLetterRecord {`
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} @Id`
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} @GeneratedValue(strategy = GenerationType.IDENTITY)`
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} private Long id;`
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} `
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} @Column(unique = true)`
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} private String messageId;`
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} `
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} private String originalQueue;`
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} private String routingKey;`
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} `
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} @Lob`
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} private String content;`
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} `
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} @Lob`
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} private Map<String, Object> deathReason;`
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} `
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
} private Date createTime;`
`#/**
* 死信队列消费者:处理异常消息
*
* 职责:
* 1. 记录死信消息的详细信息
* 2. 分析死因
* 3. 尝试补偿或人工介入
*/
@Component
public class DeadLetterConsumer {
@Autowired
private DeadLetterRepository deadLetterRepository;
@RabbitListener(queues = "dead.letter.queue")
public void handleDeadLetter(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
try {
// 1. 提取消息信息
String messageBody = new String(message.getBody());
MessageProperties props = message.getMessageProperties();
// 2. 记录到数据库
DeadLetterRecord record = new DeadLetterRecord();
record.setMessageId(props.getMessageId());
record.setOriginalQueue(props.getConsumerQueue());
record.setRoutingKey(props.getReceivedRoutingKey());
record.setContent(messageBody);
record.setDeathReason(props.getHeaders()); // 死因可能存在header中
record.setCreateTime(new Date());
deadLetterRepository.save(record);
// 3. 分析死因并决定处理策略
String deathReason = analyzeDeathReason(props);
if (canRetry(deathReason)) {
// 可重试:重新投递到业务队列
retryMessage(message);
System.out.println("死信消息已重新投递: " + props.getMessageId());
} else {
// 不可重试:记录日志,等待人工处理
System.err.println("死信消息需要人工介入: " + props.getMessageId());
sendAlert(record);
}
// 4. 确认死信消息
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 死信处理也失败,记录日志但不NACK(防止无限循环)
System.err.println("死信处理失败: " + e.getMessage());
channel.basicAck(deliveryTag, false); // 直接确认,避免循环
}
}
/**
* 分析死因
*/
private String analyzeDeathReason(MessageProperties props) {
// 从 x-death header 中获取死信历史
Map<String, Object> headers = props.getHeaders();
List<Map<String, Object>> xDeath =
(List<Map<String, Object>>) headers.get("x-death");
if (xDeath != null && !xDeath.isEmpty()) {
Map<String, Object> deathInfo = xDeath.get(0);
return (String) deathInfo.get("reason");
}
return "unknown";
}
/**
* 判断是否可重试
*/
private boolean canRetry(String deathReason) {
return "expired".equals(deathReason) ||
"maxlen".equals(deathReason);
}
/**
* 重新投递消息
*/
private void retryMessage(Message originalMessage) {
rabbitTemplate.send(
"business.exchange",
"business.routing.key",
originalMessage
);
}
/**
* 发送告警
*/
private void sendAlert(DeadLetterRecord record) {
// 实现告警逻辑:邮件、短信、钉钉等
System.err.println("告警:死信消息需要处理 - " + record.getMessageId());
}
}
/**
* 死信记录实体(JPA)
*/
@Entity
@Table(name = "dead_letter_record")
@Data
public class DeadLetterRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String messageId;
private String originalQueue;
private String routingKey;
@Lob
private String content;
@Lob
private Map<String, Object> deathReason;
private Date createTime;
}}
4.3 死信队列监控与告警
java
#/**
* 死信队列监控组件
*
* 功能:
* 1. 定期检查死信队列积压情况
* 2. 统计死信消息类型分布
* 3. 触发告警
*/
@Component
public class DeadLetterMonitor {
@Autowired
private RabbitAdmin rabbitAdmin;
@Autowired
private DeadLetterRepository repository;
/**
* 定时任务:每5分钟检查一次
*/
@Scheduled(fixedRate = 300000)
public void monitorDeadLetterQueue() {
// 获取死信队列消息数量
QueueInfo info = rabbitAdmin.getQueueInfo("dead.letter.queue");
int messageCount = info.getMessageCount();
if (messageCount > 100) {
// 死信积压严重,触发告警
sendAlert("死信队列积压: " + messageCount + " 条消息");
// 分析死信原因分布
Map<String, Long> reasonDistribution =
repository.groupByDeathReason();
System.err.println("死信原因分布: " + reasonDistribution);
}
}
private void sendAlert(String message) {
// 实现告警逻辑
}
}/**`
`#/**
* 死信队列监控组件
*
* 功能:
* 1. 定期检查死信队列积压情况
* 2. 统计死信消息类型分布
* 3. 触发告警
*/
@Component
public class DeadLetterMonitor {
@Autowired
private RabbitAdmin rabbitAdmin;
@Autowired
private DeadLetterRepository repository;
/**
* 定时任务:每5分钟检查一次
*/
@Scheduled(fixedRate = 300000)
public void monitorDeadLetterQueue() {
// 获取死信队列消息数量
QueueInfo info = rabbitAdmin.getQueueInfo("dead.letter.queue");
int messageCount = info.getMessageCount();
if (messageCount > 100) {
// 死信积压严重,触发告警
sendAlert("死信队列积压: " + messageCount + " 条消息");
// 分析死信原因分布
Map<String, Long> reasonDistribution =
repository.groupByDeathReason();
System.err.println("死信原因分布: " + reasonDistribution);
}
}
private void sendAlert(String message) {
// 实现告警逻辑
}
} * 死信队列监控组件`
`#/**
* 死信队列监控组件
*
* 功能:
* 1. 定期检查死信队列积压情况
* 2. 统计死信消息类型分布
* 3. 触发告警
*/
@Component
public class DeadLetterMonitor {
@Autowired
private RabbitAdmin rabbitAdmin;
@Autowired
private DeadLetterRepository repository;
/**
* 定时任务:每5分钟检查一次
*/
@Scheduled(fixedRate = 300000)
public void monitorDeadLetterQueue() {
// 获取死信队列消息数量
QueueInfo info = rabbitAdmin.getQueueInfo("dead.letter.queue");
int messageCount = info.getMessageCount();
if (messageCount > 100) {
// 死信积压严重,触发告警
sendAlert("死信队列积压: " + messageCount + " 条消息");
// 分析死信原因分布
Map<String, Long> reasonDistribution =
repository.groupByDeathReason();
System.err.println("死信原因分布: " + reasonDistribution);
}
}
private void sendAlert(String message) {
// 实现告警逻辑
}
} * `
`#/**
* 死信队列监控组件
*
* 功能:
* 1. 定期检查死信队列积压情况
* 2. 统计死信消息类型分布
* 3. 触发告警
*/
@Component
public class DeadLetterMonitor {
@Autowired
private RabbitAdmin rabbitAdmin;
@Autowired
private DeadLetterRepository repository;
/**
* 定时任务:每5分钟检查一次
*/
@Scheduled(fixedRate = 300000)
public void monitorDeadLetterQueue() {
// 获取死信队列消息数量
QueueInfo info = rabbitAdmin.getQueueInfo("dead.letter.queue");
int messageCount = info.getMessageCount();
if (messageCount > 100) {
// 死信积压严重,触发告警
sendAlert("死信队列积压: " + messageCount + " 条消息");
// 分析死信原因分布
Map<String, Long> reasonDistribution =
repository.groupByDeathReason();
System.err.println("死信原因分布: " + reasonDistribution);
}
}
private void sendAlert(String message) {
// 实现告警逻辑
}
} * 功能:`
`#/**
* 死信队列监控组件
*
* 功能:
* 1. 定期检查死信队列积压情况
* 2. 统计死信消息类型分布
* 3. 触发告警
*/
@Component
public class DeadLetterMonitor {
@Autowired
private RabbitAdmin rabbitAdmin;
@Autowired
private DeadLetterRepository repository;
/**
* 定时任务:每5分钟检查一次
*/
@Scheduled(fixedRate = 300000)
public void monitorDeadLetterQueue() {
// 获取死信队列消息数量
QueueInfo info = rabbitAdmin.getQueueInfo("dead.letter.queue");
int messageCount = info.getMessageCount();
if (messageCount > 100) {
// 死信积压严重,触发告警
sendAlert("死信队列积压: " + messageCount + " 条消息");
// 分析死信原因分布
Map<String, Long> reasonDistribution =
repository.groupByDeathReason();
System.err.println("死信原因分布: " + reasonDistribution);
}
}
private void sendAlert(String message) {
// 实现告警逻辑
}
} * 1. 定期检查死信队列积压情况`
`#/**
* 死信队列监控组件
*
* 功能:
* 1. 定期检查死信队列积压情况
* 2. 统计死信消息类型分布
* 3. 触发告警
*/
@Component
public class DeadLetterMonitor {
@Autowired
private RabbitAdmin rabbitAdmin;
@Autowired
private DeadLetterRepository repository;
/**
* 定时任务:每5分钟检查一次
*/
@Scheduled(fixedRate = 300000)
public void monitorDeadLetterQueue() {
// 获取死信队列消息数量
QueueInfo info = rabbitAdmin.getQueueInfo("dead.letter.queue");
int messageCount = info.getMessageCount();
if (messageCount > 100) {
// 死信积压严重,触发告警
sendAlert("死信队列积压: " + messageCount + " 条消息");
// 分析死信原因分布
Map<String, Long> reasonDistribution =
repository.groupByDeathReason();
System.err.println("死信原因分布: " + reasonDistribution);
}
}
private void sendAlert(String message) {
// 实现告警逻辑
}
} * 2. 统计死信消息类型分布`
`#/**
* 死信队列监控组件
*
* 功能:
* 1. 定期检查死信队列积压情况
* 2. 统计死信消息类型分布
* 3. 触发告警
*/
@Component
public class DeadLetterMonitor {
@Autowired
private RabbitAdmin rabbitAdmin;
@Autowired
private DeadLetterRepository repository;
/**
* 定时任务:每5分钟检查一次
*/
@Scheduled(fixedRate = 300000)
public void monitorDeadLetterQueue() {
// 获取死信队列消息数量
QueueInfo info = rabbitAdmin.getQueueInfo("dead.letter.queue");
int messageCount = info.getMessageCount();
if (messageCount > 100) {
// 死信积压严重,触发告警
sendAlert("死信队列积压: " + messageCount + " 条消息");
// 分析死信原因分布
Map<String, Long> reasonDistribution =
repository.groupByDeathReason();
System.err.println("死信原因分布: " + reasonDistribution);
}
}
private void sendAlert(String message) {
// 实现告警逻辑
}
} * 3. 触发告警`
`#/**
* 死信队列监控组件
*
* 功能:
* 1. 定期检查死信队列积压情况
* 2. 统计死信消息类型分布
* 3. 触发告警
*/
@Component
public class DeadLetterMonitor {
@Autowired
private RabbitAdmin rabbitAdmin;
@Autowired
private DeadLetterRepository repository;
/**
* 定时任务:每5分钟检查一次
*/
@Scheduled(fixedRate = 300000)
public void monitorDeadLetterQueue() {
// 获取死信队列消息数量
QueueInfo info = rabbitAdmin.getQueueInfo("dead.letter.queue");
int messageCount = info.getMessageCount();
if (messageCount > 100) {
// 死信积压严重,触发告警
sendAlert("死信队列积压: " + messageCount + " 条消息");
// 分析死信原因分布
Map<String, Long> reasonDistribution =
repository.groupByDeathReason();
System.err.println("死信原因分布: " + reasonDistribution);
}
}
private void sendAlert(String message) {
// 实现告警逻辑
}
} */`
`#/**
* 死信队列监控组件
*
* 功能:
* 1. 定期检查死信队列积压情况
* 2. 统计死信消息类型分布
* 3. 触发告警
*/
@Component
public class DeadLetterMonitor {
@Autowired
private RabbitAdmin rabbitAdmin;
@Autowired
private DeadLetterRepository repository;
/**
* 定时任务:每5分钟检查一次
*/
@Scheduled(fixedRate = 300000)
public void monitorDeadLetterQueue() {
// 获取死信队列消息数量
QueueInfo info = rabbitAdmin.getQueueInfo("dead.letter.queue");
int messageCount = info.getMessageCount();
if (messageCount > 100) {
// 死信积压严重,触发告警
sendAlert("死信队列积压: " + messageCount + " 条消息");
// 分析死信原因分布
Map<String, Long> reasonDistribution =
repository.groupByDeathReason();
System.err.println("死信原因分布: " + reasonDistribution);
}
}
private void sendAlert(String message) {
// 实现告警逻辑
}
}@Component`
`#/**
* 死信队列监控组件
*
* 功能:
* 1. 定期检查死信队列积压情况
* 2. 统计死信消息类型分布
* 3. 触发告警
*/
@Component
public class DeadLetterMonitor {
@Autowired
private RabbitAdmin rabbitAdmin;
@Autowired
private DeadLetterRepository repository;
/**
* 定时任务:每5分钟检查一次
*/
@Scheduled(fixedRate = 300000)
public void monitorDeadLetterQueue() {
// 获取死信队列消息数量
QueueInfo info = rabbitAdmin.getQueueInfo("dead.letter.queue");
int messageCount = info.getMessageCount();
if (messageCount > 100) {
// 死信积压严重,触发告警
sendAlert("死信队列积压: " + messageCount + " 条消息");
// 分析死信原因分布
Map<String, Long> reasonDistribution =
repository.groupByDeathReason();
System.err.println("死信原因分布: " + reasonDistribution);
}
}
private void sendAlert(String message) {
// 实现告警逻辑
}
}public class DeadLetterMonitor {`
`#/**
* 死信队列监控组件
*
* 功能:
* 1. 定期检查死信队列积压情况
* 2. 统计死信消息类型分布
* 3. 触发告警
*/
@Component
public class DeadLetterMonitor {
@Autowired
private RabbitAdmin rabbitAdmin;
@Autowired
private DeadLetterRepository repository;
/**
* 定时任务:每5分钟检查一次
*/
@Scheduled(fixedRate = 300000)
public void monitorDeadLetterQueue() {
// 获取死信队列消息数量
QueueInfo info = rabbitAdmin.getQueueInfo("dead.letter.queue");
int messageCount = info.getMessageCount();
if (messageCount > 100) {
// 死信积压严重,触发告警
sendAlert("死信队列积压: " + messageCount + " 条消息");
// 分析死信原因分布
Map<String, Long> reasonDistribution =
repository.groupByDeathReason();
System.err.println("死信原因分布: " + reasonDistribution);
}
}
private void sendAlert(String message) {
// 实现告警逻辑
}
}`
`#/**
* 死信队列监控组件
*
* 功能:
* 1. 定期检查死信队列积压情况
* 2. 统计死信消息类型分布
* 3. 触发告警
*/
@Component
public class DeadLetterMonitor {
@Autowired
private RabbitAdmin rabbitAdmin;
@Autowired
private DeadLetterRepository repository;
/**
* 定时任务:每5分钟检查一次
*/
@Scheduled(fixedRate = 300000)
public void monitorDeadLetterQueue() {
// 获取死信队列消息数量
QueueInfo info = rabbitAdmin.getQueueInfo("dead.letter.queue");
int messageCount = info.getMessageCount();
if (messageCount > 100) {
// 死信积压严重,触发告警
sendAlert("死信队列积压: " + messageCount + " 条消息");
// 分析死信原因分布
Map<String, Long> reasonDistribution =
repository.groupByDeathReason();
System.err.println("死信原因分布: " + reasonDistribution);
}
}
private void sendAlert(String message) {
// 实现告警逻辑
}
} @Autowired`
`#/**
* 死信队列监控组件
*
* 功能:
* 1. 定期检查死信队列积压情况
* 2. 统计死信消息类型分布
* 3. 触发告警
*/
@Component
public class DeadLetterMonitor {
@Autowired
private RabbitAdmin rabbitAdmin;
@Autowired
private DeadLetterRepository repository;
/**
* 定时任务:每5分钟检查一次
*/
@Scheduled(fixedRate = 300000)
public void monitorDeadLetterQueue() {
// 获取死信队列消息数量
QueueInfo info = rabbitAdmin.getQueueInfo("dead.letter.queue");
int messageCount = info.getMessageCount();
if (messageCount > 100) {
// 死信积压严重,触发告警
sendAlert("死信队列积压: " + messageCount + " 条消息");
// 分析死信原因分布
Map<String, Long> reasonDistribution =
repository.groupByDeathReason();
System.err.println("死信原因分布: " + reasonDistribution);
}
}
private void sendAlert(String message) {
// 实现告警逻辑
}
} private RabbitAdmin rabbitAdmin;`
`#/**
* 死信队列监控组件
*
* 功能:
* 1. 定期检查死信队列积压情况
* 2. 统计死信消息类型分布
* 3. 触发告警
*/
@Component
public class DeadLetterMonitor {
@Autowired
private RabbitAdmin rabbitAdmin;
@Autowired
private DeadLetterRepository repository;
/**
* 定时任务:每5分钟检查一次
*/
@Scheduled(fixedRate = 300000)
public void monitorDeadLetterQueue() {
// 获取死信队列消息数量
QueueInfo info = rabbitAdmin.getQueueInfo("dead.letter.queue");
int messageCount = info.getMessageCount();
if (messageCount > 100) {
// 死信积压严重,触发告警
sendAlert("死信队列积压: " + messageCount + " 条消息");
// 分析死信原因分布
Map<String, Long> reasonDistribution =
repository.groupByDeathReason();
System.err.println("死信原因分布: " + reasonDistribution);
}
}
private void sendAlert(String message) {
// 实现告警逻辑
}
}`
`#/**
* 死信队列监控组件
*
* 功能:
* 1. 定期检查死信队列积压情况
* 2. 统计死信消息类型分布
* 3. 触发告警
*/
@Component
public class DeadLetterMonitor {
@Autowired
private RabbitAdmin rabbitAdmin;
@Autowired
private DeadLetterRepository repository;
/**
* 定时任务:每5分钟检查一次
*/
@Scheduled(fixedRate = 300000)
public void monitorDeadLetterQueue() {
// 获取死信队列消息数量
QueueInfo info = rabbitAdmin.getQueueInfo("dead.letter.queue");
int messageCount = info.getMessageCount();
if (messageCount > 100) {
// 死信积压严重,触发告警
sendAlert("死信队列积压: " + messageCount + " 条消息");
// 分析死信原因分布
Map<String, Long> reasonDistribution =
repository.groupByDeathReason();
System.err.println("死信原因分布: " + reasonDistribution);
}
}
private void sendAlert(String message) {
// 实现告警逻辑
}
} @Autowired`
`#/**
* 死信队列监控组件
*
* 功能:
* 1. 定期检查死信队列积压情况
* 2. 统计死信消息类型分布
* 3. 触发告警
*/
@Component
public class DeadLetterMonitor {
@Autowired
private RabbitAdmin rabbitAdmin;
@Autowired
private DeadLetterRepository repository;
/**
* 定时任务:每5分钟检查一次
*/
@Scheduled(fixedRate = 300000)
public void monitorDeadLetterQueue() {
// 获取死信队列消息数量
QueueInfo info = rabbitAdmin.getQueueInfo("dead.letter.queue");
int messageCount = info.getMessageCount();
if (messageCount > 100) {
// 死信积压严重,触发告警
sendAlert("死信队列积压: " + messageCount + " 条消息");
// 分析死信原因分布
Map<String, Long> reasonDistribution =
repository.groupByDeathReason();
System.err.println("死信原因分布: " + reasonDistribution);
}
}
private void sendAlert(String message) {
// 实现告警逻辑
}
} private DeadLetterRepository repository;`
`#/**
* 死信队列监控组件
*
* 功能:
* 1. 定期检查死信队列积压情况
* 2. 统计死信消息类型分布
* 3. 触发告警
*/
@Component
public class DeadLetterMonitor {
@Autowired
private RabbitAdmin rabbitAdmin;
@Autowired
private DeadLetterRepository repository;
/**
* 定时任务:每5分钟检查一次
*/
@Scheduled(fixedRate = 300000)
public void monitorDeadLetterQueue() {
// 获取死信队列消息数量
QueueInfo info = rabbitAdmin.getQueueInfo("dead.letter.queue");
int messageCount = info.getMessageCount();
if (messageCount > 100) {
// 死信积压严重,触发告警
sendAlert("死信队列积压: " + messageCount + " 条消息");
// 分析死信原因分布
Map<String, Long> reasonDistribution =
repository.groupByDeathReason();
System.err.println("死信原因分布: " + reasonDistribution);
}
}
private void sendAlert(String message) {
// 实现告警逻辑
}
}`
`#/**
* 死信队列监控组件
*
* 功能:
* 1. 定期检查死信队列积压情况
* 2. 统计死信消息类型分布
* 3. 触发告警
*/
@Component
public class DeadLetterMonitor {
@Autowired
private RabbitAdmin rabbitAdmin;
@Autowired
private DeadLetterRepository repository;
/**
* 定时任务:每5分钟检查一次
*/
@Scheduled(fixedRate = 300000)
public void monitorDeadLetterQueue() {
// 获取死信队列消息数量
QueueInfo info = rabbitAdmin.getQueueInfo("dead.letter.queue");
int messageCount = info.getMessageCount();
if (messageCount > 100) {
// 死信积压严重,触发告警
sendAlert("死信队列积压: " + messageCount + " 条消息");
// 分析死信原因分布
Map<String, Long> reasonDistribution =
repository.groupByDeathReason();
System.err.println("死信原因分布: " + reasonDistribution);
}
}
private void sendAlert(String message) {
// 实现告警逻辑
}
} /**`
`#/**
* 死信队列监控组件
*
* 功能:
* 1. 定期检查死信队列积压情况
* 2. 统计死信消息类型分布
* 3. 触发告警
*/
@Component
public class DeadLetterMonitor {
@Autowired
private RabbitAdmin rabbitAdmin;
@Autowired
private DeadLetterRepository repository;
/**
* 定时任务:每5分钟检查一次
*/
@Scheduled(fixedRate = 300000)
public void monitorDeadLetterQueue() {
// 获取死信队列消息数量
QueueInfo info = rabbitAdmin.getQueueInfo("dead.letter.queue");
int messageCount = info.getMessageCount();
if (messageCount > 100) {
// 死信积压严重,触发告警
sendAlert("死信队列积压: " + messageCount + " 条消息");
// 分析死信原因分布
Map<String, Long> reasonDistribution =
repository.groupByDeathReason();
System.err.println("死信原因分布: " + reasonDistribution);
}
}
private void sendAlert(String message) {
// 实现告警逻辑
}
} * 定时任务:每5分钟检查一次`
`#/**
* 死信队列监控组件
*
* 功能:
* 1. 定期检查死信队列积压情况
* 2. 统计死信消息类型分布
* 3. 触发告警
*/
@Component
public class DeadLetterMonitor {
@Autowired
private RabbitAdmin rabbitAdmin;
@Autowired
private DeadLetterRepository repository;
/**
* 定时任务:每5分钟检查一次
*/
@Scheduled(fixedRate = 300000)
public void monitorDeadLetterQueue() {
// 获取死信队列消息数量
QueueInfo info = rabbitAdmin.getQueueInfo("dead.letter.queue");
int messageCount = info.getMessageCount();
if (messageCount > 100) {
// 死信积压严重,触发告警
sendAlert("死信队列积压: " + messageCount + " 条消息");
// 分析死信原因分布
Map<String, Long> reasonDistribution =
repository.groupByDeathReason();
System.err.println("死信原因分布: " + reasonDistribution);
}
}
private void sendAlert(String message) {
// 实现告警逻辑
}
} */`
`#/**
* 死信队列监控组件
*
* 功能:
* 1. 定期检查死信队列积压情况
* 2. 统计死信消息类型分布
* 3. 触发告警
*/
@Component
public class DeadLetterMonitor {
@Autowired
private RabbitAdmin rabbitAdmin;
@Autowired
private DeadLetterRepository repository;
/**
* 定时任务:每5分钟检查一次
*/
@Scheduled(fixedRate = 300000)
public void monitorDeadLetterQueue() {
// 获取死信队列消息数量
QueueInfo info = rabbitAdmin.getQueueInfo("dead.letter.queue");
int messageCount = info.getMessageCount();
if (messageCount > 100) {
// 死信积压严重,触发告警
sendAlert("死信队列积压: " + messageCount + " 条消息");
// 分析死信原因分布
Map<String, Long> reasonDistribution =
repository.groupByDeathReason();
System.err.println("死信原因分布: " + reasonDistribution);
}
}
private void sendAlert(String message) {
// 实现告警逻辑
}
} @Scheduled(fixedRate = 300000)`
`#/**
* 死信队列监控组件
*
* 功能:
* 1. 定期检查死信队列积压情况
* 2. 统计死信消息类型分布
* 3. 触发告警
*/
@Component
public class DeadLetterMonitor {
@Autowired
private RabbitAdmin rabbitAdmin;
@Autowired
private DeadLetterRepository repository;
/**
* 定时任务:每5分钟检查一次
*/
@Scheduled(fixedRate = 300000)
public void monitorDeadLetterQueue() {
// 获取死信队列消息数量
QueueInfo info = rabbitAdmin.getQueueInfo("dead.letter.queue");
int messageCount = info.getMessageCount();
if (messageCount > 100) {
// 死信积压严重,触发告警
sendAlert("死信队列积压: " + messageCount + " 条消息");
// 分析死信原因分布
Map<String, Long> reasonDistribution =
repository.groupByDeathReason();
System.err.println("死信原因分布: " + reasonDistribution);
}
}
private void sendAlert(String message) {
// 实现告警逻辑
}
} public void monitorDeadLetterQueue() {`
`#/**
* 死信队列监控组件
*
* 功能:
* 1. 定期检查死信队列积压情况
* 2. 统计死信消息类型分布
* 3. 触发告警
*/
@Component
public class DeadLetterMonitor {
@Autowired
private RabbitAdmin rabbitAdmin;
@Autowired
private DeadLetterRepository repository;
/**
* 定时任务:每5分钟检查一次
*/
@Scheduled(fixedRate = 300000)
public void monitorDeadLetterQueue() {
// 获取死信队列消息数量
QueueInfo info = rabbitAdmin.getQueueInfo("dead.letter.queue");
int messageCount = info.getMessageCount();
if (messageCount > 100) {
// 死信积压严重,触发告警
sendAlert("死信队列积压: " + messageCount + " 条消息");
// 分析死信原因分布
Map<String, Long> reasonDistribution =
repository.groupByDeathReason();
System.err.println("死信原因分布: " + reasonDistribution);
}
}
private void sendAlert(String message) {
// 实现告警逻辑
}
} // 获取死信队列消息数量`
`#/**
* 死信队列监控组件
*
* 功能:
* 1. 定期检查死信队列积压情况
* 2. 统计死信消息类型分布
* 3. 触发告警
*/
@Component
public class DeadLetterMonitor {
@Autowired
private RabbitAdmin rabbitAdmin;
@Autowired
private DeadLetterRepository repository;
/**
* 定时任务:每5分钟检查一次
*/
@Scheduled(fixedRate = 300000)
public void monitorDeadLetterQueue() {
// 获取死信队列消息数量
QueueInfo info = rabbitAdmin.getQueueInfo("dead.letter.queue");
int messageCount = info.getMessageCount();
if (messageCount > 100) {
// 死信积压严重,触发告警
sendAlert("死信队列积压: " + messageCount + " 条消息");
// 分析死信原因分布
Map<String, Long> reasonDistribution =
repository.groupByDeathReason();
System.err.println("死信原因分布: " + reasonDistribution);
}
}
private void sendAlert(String message) {
// 实现告警逻辑
}
} QueueInfo info = rabbitAdmin.getQueueInfo("dead.letter.queue");`
`#/**
* 死信队列监控组件
*
* 功能:
* 1. 定期检查死信队列积压情况
* 2. 统计死信消息类型分布
* 3. 触发告警
*/
@Component
public class DeadLetterMonitor {
@Autowired
private RabbitAdmin rabbitAdmin;
@Autowired
private DeadLetterRepository repository;
/**
* 定时任务:每5分钟检查一次
*/
@Scheduled(fixedRate = 300000)
public void monitorDeadLetterQueue() {
// 获取死信队列消息数量
QueueInfo info = rabbitAdmin.getQueueInfo("dead.letter.queue");
int messageCount = info.getMessageCount();
if (messageCount > 100) {
// 死信积压严重,触发告警
sendAlert("死信队列积压: " + messageCount + " 条消息");
// 分析死信原因分布
Map<String, Long> reasonDistribution =
repository.groupByDeathReason();
System.err.println("死信原因分布: " + reasonDistribution);
}
}
private void sendAlert(String message) {
// 实现告警逻辑
}
} int messageCount = info.getMessageCount();`
`#/**
* 死信队列监控组件
*
* 功能:
* 1. 定期检查死信队列积压情况
* 2. 统计死信消息类型分布
* 3. 触发告警
*/
@Component
public class DeadLetterMonitor {
@Autowired
private RabbitAdmin rabbitAdmin;
@Autowired
private DeadLetterRepository repository;
/**
* 定时任务:每5分钟检查一次
*/
@Scheduled(fixedRate = 300000)
public void monitorDeadLetterQueue() {
// 获取死信队列消息数量
QueueInfo info = rabbitAdmin.getQueueInfo("dead.letter.queue");
int messageCount = info.getMessageCount();
if (messageCount > 100) {
// 死信积压严重,触发告警
sendAlert("死信队列积压: " + messageCount + " 条消息");
// 分析死信原因分布
Map<String, Long> reasonDistribution =
repository.groupByDeathReason();
System.err.println("死信原因分布: " + reasonDistribution);
}
}
private void sendAlert(String message) {
// 实现告警逻辑
}
} `
`#/**
* 死信队列监控组件
*
* 功能:
* 1. 定期检查死信队列积压情况
* 2. 统计死信消息类型分布
* 3. 触发告警
*/
@Component
public class DeadLetterMonitor {
@Autowired
private RabbitAdmin rabbitAdmin;
@Autowired
private DeadLetterRepository repository;
/**
* 定时任务:每5分钟检查一次
*/
@Scheduled(fixedRate = 300000)
public void monitorDeadLetterQueue() {
// 获取死信队列消息数量
QueueInfo info = rabbitAdmin.getQueueInfo("dead.letter.queue");
int messageCount = info.getMessageCount();
if (messageCount > 100) {
// 死信积压严重,触发告警
sendAlert("死信队列积压: " + messageCount + " 条消息");
// 分析死信原因分布
Map<String, Long> reasonDistribution =
repository.groupByDeathReason();
System.err.println("死信原因分布: " + reasonDistribution);
}
}
private void sendAlert(String message) {
// 实现告警逻辑
}
} if (messageCount > 100) {`
`#/**
* 死信队列监控组件
*
* 功能:
* 1. 定期检查死信队列积压情况
* 2. 统计死信消息类型分布
* 3. 触发告警
*/
@Component
public class DeadLetterMonitor {
@Autowired
private RabbitAdmin rabbitAdmin;
@Autowired
private DeadLetterRepository repository;
/**
* 定时任务:每5分钟检查一次
*/
@Scheduled(fixedRate = 300000)
public void monitorDeadLetterQueue() {
// 获取死信队列消息数量
QueueInfo info = rabbitAdmin.getQueueInfo("dead.letter.queue");
int messageCount = info.getMessageCount();
if (messageCount > 100) {
// 死信积压严重,触发告警
sendAlert("死信队列积压: " + messageCount + " 条消息");
// 分析死信原因分布
Map<String, Long> reasonDistribution =
repository.groupByDeathReason();
System.err.println("死信原因分布: " + reasonDistribution);
}
}
private void sendAlert(String message) {
// 实现告警逻辑
}
} // 死信积压严重,触发告警`
`#/**
* 死信队列监控组件
*
* 功能:
* 1. 定期检查死信队列积压情况
* 2. 统计死信消息类型分布
* 3. 触发告警
*/
@Component
public class DeadLetterMonitor {
@Autowired
private RabbitAdmin rabbitAdmin;
@Autowired
private DeadLetterRepository repository;
/**
* 定时任务:每5分钟检查一次
*/
@Scheduled(fixedRate = 300000)
public void monitorDeadLetterQueue() {
// 获取死信队列消息数量
QueueInfo info = rabbitAdmin.getQueueInfo("dead.letter.queue");
int messageCount = info.getMessageCount();
if (messageCount > 100) {
// 死信积压严重,触发告警
sendAlert("死信队列积压: " + messageCount + " 条消息");
// 分析死信原因分布
Map<String, Long> reasonDistribution =
repository.groupByDeathReason();
System.err.println("死信原因分布: " + reasonDistribution);
}
}
private void sendAlert(String message) {
// 实现告警逻辑
}
} sendAlert("死信队列积压: " + messageCount + " 条消息");`
`#/**
* 死信队列监控组件
*
* 功能:
* 1. 定期检查死信队列积压情况
* 2. 统计死信消息类型分布
* 3. 触发告警
*/
@Component
public class DeadLetterMonitor {
@Autowired
private RabbitAdmin rabbitAdmin;
@Autowired
private DeadLetterRepository repository;
/**
* 定时任务:每5分钟检查一次
*/
@Scheduled(fixedRate = 300000)
public void monitorDeadLetterQueue() {
// 获取死信队列消息数量
QueueInfo info = rabbitAdmin.getQueueInfo("dead.letter.queue");
int messageCount = info.getMessageCount();
if (messageCount > 100) {
// 死信积压严重,触发告警
sendAlert("死信队列积压: " + messageCount + " 条消息");
// 分析死信原因分布
Map<String, Long> reasonDistribution =
repository.groupByDeathReason();
System.err.println("死信原因分布: " + reasonDistribution);
}
}
private void sendAlert(String message) {
// 实现告警逻辑
}
} `
`#/**
* 死信队列监控组件
*
* 功能:
* 1. 定期检查死信队列积压情况
* 2. 统计死信消息类型分布
* 3. 触发告警
*/
@Component
public class DeadLetterMonitor {
@Autowired
private RabbitAdmin rabbitAdmin;
@Autowired
private DeadLetterRepository repository;
/**
* 定时任务:每5分钟检查一次
*/
@Scheduled(fixedRate = 300000)
public void monitorDeadLetterQueue() {
// 获取死信队列消息数量
QueueInfo info = rabbitAdmin.getQueueInfo("dead.letter.queue");
int messageCount = info.getMessageCount();
if (messageCount > 100) {
// 死信积压严重,触发告警
sendAlert("死信队列积压: " + messageCount + " 条消息");
// 分析死信原因分布
Map<String, Long> reasonDistribution =
repository.groupByDeathReason();
System.err.println("死信原因分布: " + reasonDistribution);
}
}
private void sendAlert(String message) {
// 实现告警逻辑
}
} // 分析死信原因分布`
`#/**
* 死信队列监控组件
*
* 功能:
* 1. 定期检查死信队列积压情况
* 2. 统计死信消息类型分布
* 3. 触发告警
*/
@Component
public class DeadLetterMonitor {
@Autowired
private RabbitAdmin rabbitAdmin;
@Autowired
private DeadLetterRepository repository;
/**
* 定时任务:每5分钟检查一次
*/
@Scheduled(fixedRate = 300000)
public void monitorDeadLetterQueue() {
// 获取死信队列消息数量
QueueInfo info = rabbitAdmin.getQueueInfo("dead.letter.queue");
int messageCount = info.getMessageCount();
if (messageCount > 100) {
// 死信积压严重,触发告警
sendAlert("死信队列积压: " + messageCount + " 条消息");
// 分析死信原因分布
Map<String, Long> reasonDistribution =
repository.groupByDeathReason();
System.err.println("死信原因分布: " + reasonDistribution);
}
}
private void sendAlert(String message) {
// 实现告警逻辑
}
} Map<String, Long> reasonDistribution = `
`#/**
* 死信队列监控组件
*
* 功能:
* 1. 定期检查死信队列积压情况
* 2. 统计死信消息类型分布
* 3. 触发告警
*/
@Component
public class DeadLetterMonitor {
@Autowired
private RabbitAdmin rabbitAdmin;
@Autowired
private DeadLetterRepository repository;
/**
* 定时任务:每5分钟检查一次
*/
@Scheduled(fixedRate = 300000)
public void monitorDeadLetterQueue() {
// 获取死信队列消息数量
QueueInfo info = rabbitAdmin.getQueueInfo("dead.letter.queue");
int messageCount = info.getMessageCount();
if (messageCount > 100) {
// 死信积压严重,触发告警
sendAlert("死信队列积压: " + messageCount + " 条消息");
// 分析死信原因分布
Map<String, Long> reasonDistribution =
repository.groupByDeathReason();
System.err.println("死信原因分布: " + reasonDistribution);
}
}
private void sendAlert(String message) {
// 实现告警逻辑
}
} repository.groupByDeathReason();`
`#/**
* 死信队列监控组件
*
* 功能:
* 1. 定期检查死信队列积压情况
* 2. 统计死信消息类型分布
* 3. 触发告警
*/
@Component
public class DeadLetterMonitor {
@Autowired
private RabbitAdmin rabbitAdmin;
@Autowired
private DeadLetterRepository repository;
/**
* 定时任务:每5分钟检查一次
*/
@Scheduled(fixedRate = 300000)
public void monitorDeadLetterQueue() {
// 获取死信队列消息数量
QueueInfo info = rabbitAdmin.getQueueInfo("dead.letter.queue");
int messageCount = info.getMessageCount();
if (messageCount > 100) {
// 死信积压严重,触发告警
sendAlert("死信队列积压: " + messageCount + " 条消息");
// 分析死信原因分布
Map<String, Long> reasonDistribution =
repository.groupByDeathReason();
System.err.println("死信原因分布: " + reasonDistribution);
}
}
private void sendAlert(String message) {
// 实现告警逻辑
}
} System.err.println("死信原因分布: " + reasonDistribution);`
`#/**
* 死信队列监控组件
*
* 功能:
* 1. 定期检查死信队列积压情况
* 2. 统计死信消息类型分布
* 3. 触发告警
*/
@Component
public class DeadLetterMonitor {
@Autowired
private RabbitAdmin rabbitAdmin;
@Autowired
private DeadLetterRepository repository;
/**
* 定时任务:每5分钟检查一次
*/
@Scheduled(fixedRate = 300000)
public void monitorDeadLetterQueue() {
// 获取死信队列消息数量
QueueInfo info = rabbitAdmin.getQueueInfo("dead.letter.queue");
int messageCount = info.getMessageCount();
if (messageCount > 100) {
// 死信积压严重,触发告警
sendAlert("死信队列积压: " + messageCount + " 条消息");
// 分析死信原因分布
Map<String, Long> reasonDistribution =
repository.groupByDeathReason();
System.err.println("死信原因分布: " + reasonDistribution);
}
}
private void sendAlert(String message) {
// 实现告警逻辑
}
} }`
`#/**
* 死信队列监控组件
*
* 功能:
* 1. 定期检查死信队列积压情况
* 2. 统计死信消息类型分布
* 3. 触发告警
*/
@Component
public class DeadLetterMonitor {
@Autowired
private RabbitAdmin rabbitAdmin;
@Autowired
private DeadLetterRepository repository;
/**
* 定时任务:每5分钟检查一次
*/
@Scheduled(fixedRate = 300000)
public void monitorDeadLetterQueue() {
// 获取死信队列消息数量
QueueInfo info = rabbitAdmin.getQueueInfo("dead.letter.queue");
int messageCount = info.getMessageCount();
if (messageCount > 100) {
// 死信积压严重,触发告警
sendAlert("死信队列积压: " + messageCount + " 条消息");
// 分析死信原因分布
Map<String, Long> reasonDistribution =
repository.groupByDeathReason();
System.err.println("死信原因分布: " + reasonDistribution);
}
}
private void sendAlert(String message) {
// 实现告警逻辑
}
} }`
`#/**
* 死信队列监控组件
*
* 功能:
* 1. 定期检查死信队列积压情况
* 2. 统计死信消息类型分布
* 3. 触发告警
*/
@Component
public class DeadLetterMonitor {
@Autowired
private RabbitAdmin rabbitAdmin;
@Autowired
private DeadLetterRepository repository;
/**
* 定时任务:每5分钟检查一次
*/
@Scheduled(fixedRate = 300000)
public void monitorDeadLetterQueue() {
// 获取死信队列消息数量
QueueInfo info = rabbitAdmin.getQueueInfo("dead.letter.queue");
int messageCount = info.getMessageCount();
if (messageCount > 100) {
// 死信积压严重,触发告警
sendAlert("死信队列积压: " + messageCount + " 条消息");
// 分析死信原因分布
Map<String, Long> reasonDistribution =
repository.groupByDeathReason();
System.err.println("死信原因分布: " + reasonDistribution);
}
}
private void sendAlert(String message) {
// 实现告警逻辑
}
}`
`#/**
* 死信队列监控组件
*
* 功能:
* 1. 定期检查死信队列积压情况
* 2. 统计死信消息类型分布
* 3. 触发告警
*/
@Component
public class DeadLetterMonitor {
@Autowired
private RabbitAdmin rabbitAdmin;
@Autowired
private DeadLetterRepository repository;
/**
* 定时任务:每5分钟检查一次
*/
@Scheduled(fixedRate = 300000)
public void monitorDeadLetterQueue() {
// 获取死信队列消息数量
QueueInfo info = rabbitAdmin.getQueueInfo("dead.letter.queue");
int messageCount = info.getMessageCount();
if (messageCount > 100) {
// 死信积压严重,触发告警
sendAlert("死信队列积压: " + messageCount + " 条消息");
// 分析死信原因分布
Map<String, Long> reasonDistribution =
repository.groupByDeathReason();
System.err.println("死信原因分布: " + reasonDistribution);
}
}
private void sendAlert(String message) {
// 实现告警逻辑
}
} private void sendAlert(String message) {`
`#/**
* 死信队列监控组件
*
* 功能:
* 1. 定期检查死信队列积压情况
* 2. 统计死信消息类型分布
* 3. 触发告警
*/
@Component
public class DeadLetterMonitor {
@Autowired
private RabbitAdmin rabbitAdmin;
@Autowired
private DeadLetterRepository repository;
/**
* 定时任务:每5分钟检查一次
*/
@Scheduled(fixedRate = 300000)
public void monitorDeadLetterQueue() {
// 获取死信队列消息数量
QueueInfo info = rabbitAdmin.getQueueInfo("dead.letter.queue");
int messageCount = info.getMessageCount();
if (messageCount > 100) {
// 死信积压严重,触发告警
sendAlert("死信队列积压: " + messageCount + " 条消息");
// 分析死信原因分布
Map<String, Long> reasonDistribution =
repository.groupByDeathReason();
System.err.println("死信原因分布: " + reasonDistribution);
}
}
private void sendAlert(String message) {
// 实现告警逻辑
}
} // 实现告警逻辑`
`#/**
* 死信队列监控组件
*
* 功能:
* 1. 定期检查死信队列积压情况
* 2. 统计死信消息类型分布
* 3. 触发告警
*/
@Component
public class DeadLetterMonitor {
@Autowired
private RabbitAdmin rabbitAdmin;
@Autowired
private DeadLetterRepository repository;
/**
* 定时任务:每5分钟检查一次
*/
@Scheduled(fixedRate = 300000)
public void monitorDeadLetterQueue() {
// 获取死信队列消息数量
QueueInfo info = rabbitAdmin.getQueueInfo("dead.letter.queue");
int messageCount = info.getMessageCount();
if (messageCount > 100) {
// 死信积压严重,触发告警
sendAlert("死信队列积压: " + messageCount + " 条消息");
// 分析死信原因分布
Map<String, Long> reasonDistribution =
repository.groupByDeathReason();
System.err.println("死信原因分布: " + reasonDistribution);
}
}
private void sendAlert(String message) {
// 实现告警逻辑
}
} }`
`#/**
* 死信队列监控组件
*
* 功能:
* 1. 定期检查死信队列积压情况
* 2. 统计死信消息类型分布
* 3. 触发告警
*/
@Component
public class DeadLetterMonitor {
@Autowired
private RabbitAdmin rabbitAdmin;
@Autowired
private DeadLetterRepository repository;
/**
* 定时任务:每5分钟检查一次
*/
@Scheduled(fixedRate = 300000)
public void monitorDeadLetterQueue() {
// 获取死信队列消息数量
QueueInfo info = rabbitAdmin.getQueueInfo("dead.letter.queue");
int messageCount = info.getMessageCount();
if (messageCount > 100) {
// 死信积压严重,触发告警
sendAlert("死信队列积压: " + messageCount + " 条消息");
// 分析死信原因分布
Map<String, Long> reasonDistribution =
repository.groupByDeathReason();
System.err.println("死信原因分布: " + reasonDistribution);
}
}
private void sendAlert(String message) {
// 实现告警逻辑
}
}}
5. 可靠性投递完整方案设计
5.1 端到端可靠性方案
综合上述所有机制,设计一个完整的可靠性投递方案:
graph TB
subgraph "生产者侧"
A1[消息发送] --> A2[异步Confirm]
A2 -->|成功| A3[清除缓存]
A2 -->|失败| A4[重试机制]
A4 --> A5{重试次数}
A5 -->|<3次| A1
A5 -->|>=3次| A6[记录日志<br/>人工介入]
end
subgraph "Broker侧"
B1[接收消息] --> B2[持久化到磁盘]
B2 --> B3[返回Confirm]
B3 --> B4[投递到队列]
end
subgraph "消费者侧"
C1[接收消息] --> C2[幂等性检查]
C2 -->|已处理| C3[ACK]
C2 -->|未处理| C4[业务逻辑]
C4 -->|成功| C3
C4 -->|临时失败| C5[NACK+Requeue]
C4 -->|永久失败| C6[NACK+DLQ]
end
subgraph "死信处理"
D1[死信队列] --> D2[分析死因]
D2 -->|可修复| D3[重新投递]
D2 -->|不可修复| D4[记录+告警]
end
A3 --> B1
B4 --> C1
C6 --> D1
5.2 完整实现代码
5.2.1 生产者:带重试的可靠发送
java
#/**
* 高可靠性生产者
*
* 特性:
* 1. 异步Confirm
* 2. 自动重试
* 3. 消息持久化
* 4. 唯一ID生成
*/
@Service
@Slf4j
public class ReliableProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String RETRY_KEY_PREFIX = "message:retry:";
private static final int MAX_RETRY_COUNT = 3;
@PostConstruct
public void init() {
// 设置异步Confirm回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
log.info("消息发送成功: {}", correlationData);
// 清除重试缓存
String messageId = correlationData.getId();
redisTemplate.delete(RETRY_KEY_PREFIX + messageId);
} else {
log.error("消息发送失败: {}, 原因: {}", correlationData, cause);
// 触发重试
retryMessage(correlationData);
}
});
}
/**
* 发送消息(自动重试)
*/
public void sendWithRetry(String exchange, String routingKey, Object message) {
String messageId = UUID.randomUUID().toString();
// 记录重试次数
redisTemplate.opsForValue().set(
RETRY_KEY_PREFIX + messageId,
0,
24,
TimeUnit.HOURS
);
// 构建消息
MessageBuilder builder = MessageBuilder.withBody(JSON.toJSONString(message).getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_JSON)
.setDeliveryMode(MessageDeliveryMode.PERSISTENT)
.setMessageId(messageId);
// 发送消息
rabbitTemplate.send(
exchange,
routingKey,
builder.build(),
new CorrelationData(messageId)
);
}
/**
* 重试消息
*/
private void retryMessage(CorrelationData correlationData) {
String messageId = correlationData.getId();
String retryKey = RETRY_KEY_PREFIX + messageId;
Integer retryCount = (Integer) redisTemplate.opsForValue().get(retryKey);
if (retryCount == null) {
retryCount = 0;
}
if (retryCount < MAX_RETRY_COUNT) {
// 增加重试次数
redisTemplate.opsForValue().increment(retryKey);
// 从缓存中获取原始消息
String messageKey = "message:content:" + messageId;
Message originalMessage = (Message) redisTemplate.opsForValue().get(messageKey);
if (originalMessage != null) {
log.warn("消息重试 [{}/{}]: {}", retryCount + 1, MAX_RETRY_COUNT, messageId);
rabbitTemplate.send(
originalMessage.getMessageProperties().getReceivedExchange(),
originalMessage.getMessageProperties().getReceivedRoutingKey(),
originalMessage,
correlationData
);
}
} else {
log.error("消息超过最大重试次数,放弃: {}", messageId);
// 记录到数据库,人工介入
saveToDeadLetter(correlationData);
}
}
private void saveToDeadLetter(CorrelationData correlationData) {
// 实现持久化逻辑
}
}/**`
`#/**
* 高可靠性生产者
*
* 特性:
* 1. 异步Confirm
* 2. 自动重试
* 3. 消息持久化
* 4. 唯一ID生成
*/
@Service
@Slf4j
public class ReliableProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String RETRY_KEY_PREFIX = "message:retry:";
private static final int MAX_RETRY_COUNT = 3;
@PostConstruct
public void init() {
// 设置异步Confirm回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
log.info("消息发送成功: {}", correlationData);
// 清除重试缓存
String messageId = correlationData.getId();
redisTemplate.delete(RETRY_KEY_PREFIX + messageId);
} else {
log.error("消息发送失败: {}, 原因: {}", correlationData, cause);
// 触发重试
retryMessage(correlationData);
}
});
}
/**
* 发送消息(自动重试)
*/
public void sendWithRetry(String exchange, String routingKey, Object message) {
String messageId = UUID.randomUUID().toString();
// 记录重试次数
redisTemplate.opsForValue().set(
RETRY_KEY_PREFIX + messageId,
0,
24,
TimeUnit.HOURS
);
// 构建消息
MessageBuilder builder = MessageBuilder.withBody(JSON.toJSONString(message).getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_JSON)
.setDeliveryMode(MessageDeliveryMode.PERSISTENT)
.setMessageId(messageId);
// 发送消息
rabbitTemplate.send(
exchange,
routingKey,
builder.build(),
new CorrelationData(messageId)
);
}
/**
* 重试消息
*/
private void retryMessage(CorrelationData correlationData) {
String messageId = correlationData.getId();
String retryKey = RETRY_KEY_PREFIX + messageId;
Integer retryCount = (Integer) redisTemplate.opsForValue().get(retryKey);
if (retryCount == null) {
retryCount = 0;
}
if (retryCount < MAX_RETRY_COUNT) {
// 增加重试次数
redisTemplate.opsForValue().increment(retryKey);
// 从缓存中获取原始消息
String messageKey = "message:content:" + messageId;
Message originalMessage = (Message) redisTemplate.opsForValue().get(messageKey);
if (originalMessage != null) {
log.warn("消息重试 [{}/{}]: {}", retryCount + 1, MAX_RETRY_COUNT, messageId);
rabbitTemplate.send(
originalMessage.getMessageProperties().getReceivedExchange(),
originalMessage.getMessageProperties().getReceivedRoutingKey(),
originalMessage,
correlationData
);
}
} else {
log.error("消息超过最大重试次数,放弃: {}", messageId);
// 记录到数据库,人工介入
saveToDeadLetter(correlationData);
}
}
private void saveToDeadLetter(CorrelationData correlationData) {
// 实现持久化逻辑
}
} * 高可靠性生产者`
`#/**
* 高可靠性生产者
*
* 特性:
* 1. 异步Confirm
* 2. 自动重试
* 3. 消息持久化
* 4. 唯一ID生成
*/
@Service
@Slf4j
public class ReliableProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String RETRY_KEY_PREFIX = "message:retry:";
private static final int MAX_RETRY_COUNT = 3;
@PostConstruct
public void init() {
// 设置异步Confirm回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
log.info("消息发送成功: {}", correlationData);
// 清除重试缓存
String messageId = correlationData.getId();
redisTemplate.delete(RETRY_KEY_PREFIX + messageId);
} else {
log.error("消息发送失败: {}, 原因: {}", correlationData, cause);
// 触发重试
retryMessage(correlationData);
}
});
}
/**
* 发送消息(自动重试)
*/
public void sendWithRetry(String exchange, String routingKey, Object message) {
String messageId = UUID.randomUUID().toString();
// 记录重试次数
redisTemplate.opsForValue().set(
RETRY_KEY_PREFIX + messageId,
0,
24,
TimeUnit.HOURS
);
// 构建消息
MessageBuilder builder = MessageBuilder.withBody(JSON.toJSONString(message).getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_JSON)
.setDeliveryMode(MessageDeliveryMode.PERSISTENT)
.setMessageId(messageId);
// 发送消息
rabbitTemplate.send(
exchange,
routingKey,
builder.build(),
new CorrelationData(messageId)
);
}
/**
* 重试消息
*/
private void retryMessage(CorrelationData correlationData) {
String messageId = correlationData.getId();
String retryKey = RETRY_KEY_PREFIX + messageId;
Integer retryCount = (Integer) redisTemplate.opsForValue().get(retryKey);
if (retryCount == null) {
retryCount = 0;
}
if (retryCount < MAX_RETRY_COUNT) {
// 增加重试次数
redisTemplate.opsForValue().increment(retryKey);
// 从缓存中获取原始消息
String messageKey = "message:content:" + messageId;
Message originalMessage = (Message) redisTemplate.opsForValue().get(messageKey);
if (originalMessage != null) {
log.warn("消息重试 [{}/{}]: {}", retryCount + 1, MAX_RETRY_COUNT, messageId);
rabbitTemplate.send(
originalMessage.getMessageProperties().getReceivedExchange(),
originalMessage.getMessageProperties().getReceivedRoutingKey(),
originalMessage,
correlationData
);
}
} else {
log.error("消息超过最大重试次数,放弃: {}", messageId);
// 记录到数据库,人工介入
saveToDeadLetter(correlationData);
}
}
private void saveToDeadLetter(CorrelationData correlationData) {
// 实现持久化逻辑
}
} * `
`#/**
* 高可靠性生产者
*
* 特性:
* 1. 异步Confirm
* 2. 自动重试
* 3. 消息持久化
* 4. 唯一ID生成
*/
@Service
@Slf4j
public class ReliableProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String RETRY_KEY_PREFIX = "message:retry:";
private static final int MAX_RETRY_COUNT = 3;
@PostConstruct
public void init() {
// 设置异步Confirm回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
log.info("消息发送成功: {}", correlationData);
// 清除重试缓存
String messageId = correlationData.getId();
redisTemplate.delete(RETRY_KEY_PREFIX + messageId);
} else {
log.error("消息发送失败: {}, 原因: {}", correlationData, cause);
// 触发重试
retryMessage(correlationData);
}
});
}
/**
* 发送消息(自动重试)
*/
public void sendWithRetry(String exchange, String routingKey, Object message) {
String messageId = UUID.randomUUID().toString();
// 记录重试次数
redisTemplate.opsForValue().set(
RETRY_KEY_PREFIX + messageId,
0,
24,
TimeUnit.HOURS
);
// 构建消息
MessageBuilder builder = MessageBuilder.withBody(JSON.toJSONString(message).getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_JSON)
.setDeliveryMode(MessageDeliveryMode.PERSISTENT)
.setMessageId(messageId);
// 发送消息
rabbitTemplate.send(
exchange,
routingKey,
builder.build(),
new CorrelationData(messageId)
);
}
/**
* 重试消息
*/
private void retryMessage(CorrelationData correlationData) {
String messageId = correlationData.getId();
String retryKey = RETRY_KEY_PREFIX + messageId;
Integer retryCount = (Integer) redisTemplate.opsForValue().get(retryKey);
if (retryCount == null) {
retryCount = 0;
}
if (retryCount < MAX_RETRY_COUNT) {
// 增加重试次数
redisTemplate.opsForValue().increment(retryKey);
// 从缓存中获取原始消息
String messageKey = "message:content:" + messageId;
Message originalMessage = (Message) redisTemplate.opsForValue().get(messageKey);
if (originalMessage != null) {
log.warn("消息重试 [{}/{}]: {}", retryCount + 1, MAX_RETRY_COUNT, messageId);
rabbitTemplate.send(
originalMessage.getMessageProperties().getReceivedExchange(),
originalMessage.getMessageProperties().getReceivedRoutingKey(),
originalMessage,
correlationData
);
}
} else {
log.error("消息超过最大重试次数,放弃: {}", messageId);
// 记录到数据库,人工介入
saveToDeadLetter(correlationData);
}
}
private void saveToDeadLetter(CorrelationData correlationData) {
// 实现持久化逻辑
}
} * 特性:`
`#/**
* 高可靠性生产者
*
* 特性:
* 1. 异步Confirm
* 2. 自动重试
* 3. 消息持久化
* 4. 唯一ID生成
*/
@Service
@Slf4j
public class ReliableProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String RETRY_KEY_PREFIX = "message:retry:";
private static final int MAX_RETRY_COUNT = 3;
@PostConstruct
public void init() {
// 设置异步Confirm回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
log.info("消息发送成功: {}", correlationData);
// 清除重试缓存
String messageId = correlationData.getId();
redisTemplate.delete(RETRY_KEY_PREFIX + messageId);
} else {
log.error("消息发送失败: {}, 原因: {}", correlationData, cause);
// 触发重试
retryMessage(correlationData);
}
});
}
/**
* 发送消息(自动重试)
*/
public void sendWithRetry(String exchange, String routingKey, Object message) {
String messageId = UUID.randomUUID().toString();
// 记录重试次数
redisTemplate.opsForValue().set(
RETRY_KEY_PREFIX + messageId,
0,
24,
TimeUnit.HOURS
);
// 构建消息
MessageBuilder builder = MessageBuilder.withBody(JSON.toJSONString(message).getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_JSON)
.setDeliveryMode(MessageDeliveryMode.PERSISTENT)
.setMessageId(messageId);
// 发送消息
rabbitTemplate.send(
exchange,
routingKey,
builder.build(),
new CorrelationData(messageId)
);
}
/**
* 重试消息
*/
private void retryMessage(CorrelationData correlationData) {
String messageId = correlationData.getId();
String retryKey = RETRY_KEY_PREFIX + messageId;
Integer retryCount = (Integer) redisTemplate.opsForValue().get(retryKey);
if (retryCount == null) {
retryCount = 0;
}
if (retryCount < MAX_RETRY_COUNT) {
// 增加重试次数
redisTemplate.opsForValue().increment(retryKey);
// 从缓存中获取原始消息
String messageKey = "message:content:" + messageId;
Message originalMessage = (Message) redisTemplate.opsForValue().get(messageKey);
if (originalMessage != null) {
log.warn("消息重试 [{}/{}]: {}", retryCount + 1, MAX_RETRY_COUNT, messageId);
rabbitTemplate.send(
originalMessage.getMessageProperties().getReceivedExchange(),
originalMessage.getMessageProperties().getReceivedRoutingKey(),
originalMessage,
correlationData
);
}
} else {
log.error("消息超过最大重试次数,放弃: {}", messageId);
// 记录到数据库,人工介入
saveToDeadLetter(correlationData);
}
}
private void saveToDeadLetter(CorrelationData correlationData) {
// 实现持久化逻辑
}
} * 1. 异步Confirm`
`#/**
* 高可靠性生产者
*
* 特性:
* 1. 异步Confirm
* 2. 自动重试
* 3. 消息持久化
* 4. 唯一ID生成
*/
@Service
@Slf4j
public class ReliableProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String RETRY_KEY_PREFIX = "message:retry:";
private static final int MAX_RETRY_COUNT = 3;
@PostConstruct
public void init() {
// 设置异步Confirm回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
log.info("消息发送成功: {}", correlationData);
// 清除重试缓存
String messageId = correlationData.getId();
redisTemplate.delete(RETRY_KEY_PREFIX + messageId);
} else {
log.error("消息发送失败: {}, 原因: {}", correlationData, cause);
// 触发重试
retryMessage(correlationData);
}
});
}
/**
* 发送消息(自动重试)
*/
public void sendWithRetry(String exchange, String routingKey, Object message) {
String messageId = UUID.randomUUID().toString();
// 记录重试次数
redisTemplate.opsForValue().set(
RETRY_KEY_PREFIX + messageId,
0,
24,
TimeUnit.HOURS
);
// 构建消息
MessageBuilder builder = MessageBuilder.withBody(JSON.toJSONString(message).getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_JSON)
.setDeliveryMode(MessageDeliveryMode.PERSISTENT)
.setMessageId(messageId);
// 发送消息
rabbitTemplate.send(
exchange,
routingKey,
builder.build(),
new CorrelationData(messageId)
);
}
/**
* 重试消息
*/
private void retryMessage(CorrelationData correlationData) {
String messageId = correlationData.getId();
String retryKey = RETRY_KEY_PREFIX + messageId;
Integer retryCount = (Integer) redisTemplate.opsForValue().get(retryKey);
if (retryCount == null) {
retryCount = 0;
}
if (retryCount < MAX_RETRY_COUNT) {
// 增加重试次数
redisTemplate.opsForValue().increment(retryKey);
// 从缓存中获取原始消息
String messageKey = "message:content:" + messageId;
Message originalMessage = (Message) redisTemplate.opsForValue().get(messageKey);
if (originalMessage != null) {
log.warn("消息重试 [{}/{}]: {}", retryCount + 1, MAX_RETRY_COUNT, messageId);
rabbitTemplate.send(
originalMessage.getMessageProperties().getReceivedExchange(),
originalMessage.getMessageProperties().getReceivedRoutingKey(),
originalMessage,
correlationData
);
}
} else {
log.error("消息超过最大重试次数,放弃: {}", messageId);
// 记录到数据库,人工介入
saveToDeadLetter(correlationData);
}
}
private void saveToDeadLetter(CorrelationData correlationData) {
// 实现持久化逻辑
}
} * 2. 自动重试`
`#/**
* 高可靠性生产者
*
* 特性:
* 1. 异步Confirm
* 2. 自动重试
* 3. 消息持久化
* 4. 唯一ID生成
*/
@Service
@Slf4j
public class ReliableProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String RETRY_KEY_PREFIX = "message:retry:";
private static final int MAX_RETRY_COUNT = 3;
@PostConstruct
public void init() {
// 设置异步Confirm回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
log.info("消息发送成功: {}", correlationData);
// 清除重试缓存
String messageId = correlationData.getId();
redisTemplate.delete(RETRY_KEY_PREFIX + messageId);
} else {
log.error("消息发送失败: {}, 原因: {}", correlationData, cause);
// 触发重试
retryMessage(correlationData);
}
});
}
/**
* 发送消息(自动重试)
*/
public void sendWithRetry(String exchange, String routingKey, Object message) {
String messageId = UUID.randomUUID().toString();
// 记录重试次数
redisTemplate.opsForValue().set(
RETRY_KEY_PREFIX + messageId,
0,
24,
TimeUnit.HOURS
);
// 构建消息
MessageBuilder builder = MessageBuilder.withBody(JSON.toJSONString(message).getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_JSON)
.setDeliveryMode(MessageDeliveryMode.PERSISTENT)
.setMessageId(messageId);
// 发送消息
rabbitTemplate.send(
exchange,
routingKey,
builder.build(),
new CorrelationData(messageId)
);
}
/**
* 重试消息
*/
private void retryMessage(CorrelationData correlationData) {
String messageId = correlationData.getId();
String retryKey = RETRY_KEY_PREFIX + messageId;
Integer retryCount = (Integer) redisTemplate.opsForValue().get(retryKey);
if (retryCount == null) {
retryCount = 0;
}
if (retryCount < MAX_RETRY_COUNT) {
// 增加重试次数
redisTemplate.opsForValue().increment(retryKey);
// 从缓存中获取原始消息
String messageKey = "message:content:" + messageId;
Message originalMessage = (Message) redisTemplate.opsForValue().get(messageKey);
if (originalMessage != null) {
log.warn("消息重试 [{}/{}]: {}", retryCount + 1, MAX_RETRY_COUNT, messageId);
rabbitTemplate.send(
originalMessage.getMessageProperties().getReceivedExchange(),
originalMessage.getMessageProperties().getReceivedRoutingKey(),
originalMessage,
correlationData
);
}
} else {
log.error("消息超过最大重试次数,放弃: {}", messageId);
// 记录到数据库,人工介入
saveToDeadLetter(correlationData);
}
}
private void saveToDeadLetter(CorrelationData correlationData) {
// 实现持久化逻辑
}
} * 3. 消息持久化`
`#/**
* 高可靠性生产者
*
* 特性:
* 1. 异步Confirm
* 2. 自动重试
* 3. 消息持久化
* 4. 唯一ID生成
*/
@Service
@Slf4j
public class ReliableProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String RETRY_KEY_PREFIX = "message:retry:";
private static final int MAX_RETRY_COUNT = 3;
@PostConstruct
public void init() {
// 设置异步Confirm回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
log.info("消息发送成功: {}", correlationData);
// 清除重试缓存
String messageId = correlationData.getId();
redisTemplate.delete(RETRY_KEY_PREFIX + messageId);
} else {
log.error("消息发送失败: {}, 原因: {}", correlationData, cause);
// 触发重试
retryMessage(correlationData);
}
});
}
/**
* 发送消息(自动重试)
*/
public void sendWithRetry(String exchange, String routingKey, Object message) {
String messageId = UUID.randomUUID().toString();
// 记录重试次数
redisTemplate.opsForValue().set(
RETRY_KEY_PREFIX + messageId,
0,
24,
TimeUnit.HOURS
);
// 构建消息
MessageBuilder builder = MessageBuilder.withBody(JSON.toJSONString(message).getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_JSON)
.setDeliveryMode(MessageDeliveryMode.PERSISTENT)
.setMessageId(messageId);
// 发送消息
rabbitTemplate.send(
exchange,
routingKey,
builder.build(),
new CorrelationData(messageId)
);
}
/**
* 重试消息
*/
private void retryMessage(CorrelationData correlationData) {
String messageId = correlationData.getId();
String retryKey = RETRY_KEY_PREFIX + messageId;
Integer retryCount = (Integer) redisTemplate.opsForValue().get(retryKey);
if (retryCount == null) {
retryCount = 0;
}
if (retryCount < MAX_RETRY_COUNT) {
// 增加重试次数
redisTemplate.opsForValue().increment(retryKey);
// 从缓存中获取原始消息
String messageKey = "message:content:" + messageId;
Message originalMessage = (Message) redisTemplate.opsForValue().get(messageKey);
if (originalMessage != null) {
log.warn("消息重试 [{}/{}]: {}", retryCount + 1, MAX_RETRY_COUNT, messageId);
rabbitTemplate.send(
originalMessage.getMessageProperties().getReceivedExchange(),
originalMessage.getMessageProperties().getReceivedRoutingKey(),
originalMessage,
correlationData
);
}
} else {
log.error("消息超过最大重试次数,放弃: {}", messageId);
// 记录到数据库,人工介入
saveToDeadLetter(correlationData);
}
}
private void saveToDeadLetter(CorrelationData correlationData) {
// 实现持久化逻辑
}
} * 4. 唯一ID生成`
`#/**
* 高可靠性生产者
*
* 特性:
* 1. 异步Confirm
* 2. 自动重试
* 3. 消息持久化
* 4. 唯一ID生成
*/
@Service
@Slf4j
public class ReliableProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String RETRY_KEY_PREFIX = "message:retry:";
private static final int MAX_RETRY_COUNT = 3;
@PostConstruct
public void init() {
// 设置异步Confirm回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
log.info("消息发送成功: {}", correlationData);
// 清除重试缓存
String messageId = correlationData.getId();
redisTemplate.delete(RETRY_KEY_PREFIX + messageId);
} else {
log.error("消息发送失败: {}, 原因: {}", correlationData, cause);
// 触发重试
retryMessage(correlationData);
}
});
}
/**
* 发送消息(自动重试)
*/
public void sendWithRetry(String exchange, String routingKey, Object message) {
String messageId = UUID.randomUUID().toString();
// 记录重试次数
redisTemplate.opsForValue().set(
RETRY_KEY_PREFIX + messageId,
0,
24,
TimeUnit.HOURS
);
// 构建消息
MessageBuilder builder = MessageBuilder.withBody(JSON.toJSONString(message).getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_JSON)
.setDeliveryMode(MessageDeliveryMode.PERSISTENT)
.setMessageId(messageId);
// 发送消息
rabbitTemplate.send(
exchange,
routingKey,
builder.build(),
new CorrelationData(messageId)
);
}
/**
* 重试消息
*/
private void retryMessage(CorrelationData correlationData) {
String messageId = correlationData.getId();
String retryKey = RETRY_KEY_PREFIX + messageId;
Integer retryCount = (Integer) redisTemplate.opsForValue().get(retryKey);
if (retryCount == null) {
retryCount = 0;
}
if (retryCount < MAX_RETRY_COUNT) {
// 增加重试次数
redisTemplate.opsForValue().increment(retryKey);
// 从缓存中获取原始消息
String messageKey = "message:content:" + messageId;
Message originalMessage = (Message) redisTemplate.opsForValue().get(messageKey);
if (originalMessage != null) {
log.warn("消息重试 [{}/{}]: {}", retryCount + 1, MAX_RETRY_COUNT, messageId);
rabbitTemplate.send(
originalMessage.getMessageProperties().getReceivedExchange(),
originalMessage.getMessageProperties().getReceivedRoutingKey(),
originalMessage,
correlationData
);
}
} else {
log.error("消息超过最大重试次数,放弃: {}", messageId);
// 记录到数据库,人工介入
saveToDeadLetter(correlationData);
}
}
private void saveToDeadLetter(CorrelationData correlationData) {
// 实现持久化逻辑
}
} */`
`#/**
* 高可靠性生产者
*
* 特性:
* 1. 异步Confirm
* 2. 自动重试
* 3. 消息持久化
* 4. 唯一ID生成
*/
@Service
@Slf4j
public class ReliableProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String RETRY_KEY_PREFIX = "message:retry:";
private static final int MAX_RETRY_COUNT = 3;
@PostConstruct
public void init() {
// 设置异步Confirm回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
log.info("消息发送成功: {}", correlationData);
// 清除重试缓存
String messageId = correlationData.getId();
redisTemplate.delete(RETRY_KEY_PREFIX + messageId);
} else {
log.error("消息发送失败: {}, 原因: {}", correlationData, cause);
// 触发重试
retryMessage(correlationData);
}
});
}
/**
* 发送消息(自动重试)
*/
public void sendWithRetry(String exchange, String routingKey, Object message) {
String messageId = UUID.randomUUID().toString();
// 记录重试次数
redisTemplate.opsForValue().set(
RETRY_KEY_PREFIX + messageId,
0,
24,
TimeUnit.HOURS
);
// 构建消息
MessageBuilder builder = MessageBuilder.withBody(JSON.toJSONString(message).getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_JSON)
.setDeliveryMode(MessageDeliveryMode.PERSISTENT)
.setMessageId(messageId);
// 发送消息
rabbitTemplate.send(
exchange,
routingKey,
builder.build(),
new CorrelationData(messageId)
);
}
/**
* 重试消息
*/
private void retryMessage(CorrelationData correlationData) {
String messageId = correlationData.getId();
String retryKey = RETRY_KEY_PREFIX + messageId;
Integer retryCount = (Integer) redisTemplate.opsForValue().get(retryKey);
if (retryCount == null) {
retryCount = 0;
}
if (retryCount < MAX_RETRY_COUNT) {
// 增加重试次数
redisTemplate.opsForValue().increment(retryKey);
// 从缓存中获取原始消息
String messageKey = "message:content:" + messageId;
Message originalMessage = (Message) redisTemplate.opsForValue().get(messageKey);
if (originalMessage != null) {
log.warn("消息重试 [{}/{}]: {}", retryCount + 1, MAX_RETRY_COUNT, messageId);
rabbitTemplate.send(
originalMessage.getMessageProperties().getReceivedExchange(),
originalMessage.getMessageProperties().getReceivedRoutingKey(),
originalMessage,
correlationData
);
}
} else {
log.error("消息超过最大重试次数,放弃: {}", messageId);
// 记录到数据库,人工介入
saveToDeadLetter(correlationData);
}
}
private void saveToDeadLetter(CorrelationData correlationData) {
// 实现持久化逻辑
}
}@Service`
`#/**
* 高可靠性生产者
*
* 特性:
* 1. 异步Confirm
* 2. 自动重试
* 3. 消息持久化
* 4. 唯一ID生成
*/
@Service
@Slf4j
public class ReliableProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String RETRY_KEY_PREFIX = "message:retry:";
private static final int MAX_RETRY_COUNT = 3;
@PostConstruct
public void init() {
// 设置异步Confirm回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
log.info("消息发送成功: {}", correlationData);
// 清除重试缓存
String messageId = correlationData.getId();
redisTemplate.delete(RETRY_KEY_PREFIX + messageId);
} else {
log.error("消息发送失败: {}, 原因: {}", correlationData, cause);
// 触发重试
retryMessage(correlationData);
}
});
}
/**
* 发送消息(自动重试)
*/
public void sendWithRetry(String exchange, String routingKey, Object message) {
String messageId = UUID.randomUUID().toString();
// 记录重试次数
redisTemplate.opsForValue().set(
RETRY_KEY_PREFIX + messageId,
0,
24,
TimeUnit.HOURS
);
// 构建消息
MessageBuilder builder = MessageBuilder.withBody(JSON.toJSONString(message).getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_JSON)
.setDeliveryMode(MessageDeliveryMode.PERSISTENT)
.setMessageId(messageId);
// 发送消息
rabbitTemplate.send(
exchange,
routingKey,
builder.build(),
new CorrelationData(messageId)
);
}
/**
* 重试消息
*/
private void retryMessage(CorrelationData correlationData) {
String messageId = correlationData.getId();
String retryKey = RETRY_KEY_PREFIX + messageId;
Integer retryCount = (Integer) redisTemplate.opsForValue().get(retryKey);
if (retryCount == null) {
retryCount = 0;
}
if (retryCount < MAX_RETRY_COUNT) {
// 增加重试次数
redisTemplate.opsForValue().increment(retryKey);
// 从缓存中获取原始消息
String messageKey = "message:content:" + messageId;
Message originalMessage = (Message) redisTemplate.opsForValue().get(messageKey);
if (originalMessage != null) {
log.warn("消息重试 [{}/{}]: {}", retryCount + 1, MAX_RETRY_COUNT, messageId);
rabbitTemplate.send(
originalMessage.getMessageProperties().getReceivedExchange(),
originalMessage.getMessageProperties().getReceivedRoutingKey(),
originalMessage,
correlationData
);
}
} else {
log.error("消息超过最大重试次数,放弃: {}", messageId);
// 记录到数据库,人工介入
saveToDeadLetter(correlationData);
}
}
private void saveToDeadLetter(CorrelationData correlationData) {
// 实现持久化逻辑
}
}@Slf4j`
`#/**
* 高可靠性生产者
*
* 特性:
* 1. 异步Confirm
* 2. 自动重试
* 3. 消息持久化
* 4. 唯一ID生成
*/
@Service
@Slf4j
public class ReliableProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String RETRY_KEY_PREFIX = "message:retry:";
private static final int MAX_RETRY_COUNT = 3;
@PostConstruct
public void init() {
// 设置异步Confirm回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
log.info("消息发送成功: {}", correlationData);
// 清除重试缓存
String messageId = correlationData.getId();
redisTemplate.delete(RETRY_KEY_PREFIX + messageId);
} else {
log.error("消息发送失败: {}, 原因: {}", correlationData, cause);
// 触发重试
retryMessage(correlationData);
}
});
}
/**
* 发送消息(自动重试)
*/
public void sendWithRetry(String exchange, String routingKey, Object message) {
String messageId = UUID.randomUUID().toString();
// 记录重试次数
redisTemplate.opsForValue().set(
RETRY_KEY_PREFIX + messageId,
0,
24,
TimeUnit.HOURS
);
// 构建消息
MessageBuilder builder = MessageBuilder.withBody(JSON.toJSONString(message).getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_JSON)
.setDeliveryMode(MessageDeliveryMode.PERSISTENT)
.setMessageId(messageId);
// 发送消息
rabbitTemplate.send(
exchange,
routingKey,
builder.build(),
new CorrelationData(messageId)
);
}
/**
* 重试消息
*/
private void retryMessage(CorrelationData correlationData) {
String messageId = correlationData.getId();
String retryKey = RETRY_KEY_PREFIX + messageId;
Integer retryCount = (Integer) redisTemplate.opsForValue().get(retryKey);
if (retryCount == null) {
retryCount = 0;
}
if (retryCount < MAX_RETRY_COUNT) {
// 增加重试次数
redisTemplate.opsForValue().increment(retryKey);
// 从缓存中获取原始消息
String messageKey = "message:content:" + messageId;
Message originalMessage = (Message) redisTemplate.opsForValue().get(messageKey);
if (originalMessage != null) {
log.warn("消息重试 [{}/{}]: {}", retryCount + 1, MAX_RETRY_COUNT, messageId);
rabbitTemplate.send(
originalMessage.getMessageProperties().getReceivedExchange(),
originalMessage.getMessageProperties().getReceivedRoutingKey(),
originalMessage,
correlationData
);
}
} else {
log.error("消息超过最大重试次数,放弃: {}", messageId);
// 记录到数据库,人工介入
saveToDeadLetter(correlationData);
}
}
private void saveToDeadLetter(CorrelationData correlationData) {
// 实现持久化逻辑
}
}public class ReliableProducer {`
`#/**
* 高可靠性生产者
*
* 特性:
* 1. 异步Confirm
* 2. 自动重试
* 3. 消息持久化
* 4. 唯一ID生成
*/
@Service
@Slf4j
public class ReliableProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String RETRY_KEY_PREFIX = "message:retry:";
private static final int MAX_RETRY_COUNT = 3;
@PostConstruct
public void init() {
// 设置异步Confirm回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
log.info("消息发送成功: {}", correlationData);
// 清除重试缓存
String messageId = correlationData.getId();
redisTemplate.delete(RETRY_KEY_PREFIX + messageId);
} else {
log.error("消息发送失败: {}, 原因: {}", correlationData, cause);
// 触发重试
retryMessage(correlationData);
}
});
}
/**
* 发送消息(自动重试)
*/
public void sendWithRetry(String exchange, String routingKey, Object message) {
String messageId = UUID.randomUUID().toString();
// 记录重试次数
redisTemplate.opsForValue().set(
RETRY_KEY_PREFIX + messageId,
0,
24,
TimeUnit.HOURS
);
// 构建消息
MessageBuilder builder = MessageBuilder.withBody(JSON.toJSONString(message).getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_JSON)
.setDeliveryMode(MessageDeliveryMode.PERSISTENT)
.setMessageId(messageId);
// 发送消息
rabbitTemplate.send(
exchange,
routingKey,
builder.build(),
new CorrelationData(messageId)
);
}
/**
* 重试消息
*/
private void retryMessage(CorrelationData correlationData) {
String messageId = correlationData.getId();
String retryKey = RETRY_KEY_PREFIX + messageId;
Integer retryCount = (Integer) redisTemplate.opsForValue().get(retryKey);
if (retryCount == null) {
retryCount = 0;
}
if (retryCount < MAX_RETRY_COUNT) {
// 增加重试次数
redisTemplate.opsForValue().increment(retryKey);
// 从缓存中获取原始消息
String messageKey = "message:content:" + messageId;
Message originalMessage = (Message) redisTemplate.opsForValue().get(messageKey);
if (originalMessage != null) {
log.warn("消息重试 [{}/{}]: {}", retryCount + 1, MAX_RETRY_COUNT, messageId);
rabbitTemplate.send(
originalMessage.getMessageProperties().getReceivedExchange(),
originalMessage.getMessageProperties().getReceivedRoutingKey(),
originalMessage,
correlationData
);
}
} else {
log.error("消息超过最大重试次数,放弃: {}", messageId);
// 记录到数据库,人工介入
saveToDeadLetter(correlationData);
}
}
private void saveToDeadLetter(CorrelationData correlationData) {
// 实现持久化逻辑
}
}`
`#/**
* 高可靠性生产者
*
* 特性:
* 1. 异步Confirm
* 2. 自动重试
* 3. 消息持久化
* 4. 唯一ID生成
*/
@Service
@Slf4j
public class ReliableProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String RETRY_KEY_PREFIX = "message:retry:";
private static final int MAX_RETRY_COUNT = 3;
@PostConstruct
public void init() {
// 设置异步Confirm回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
log.info("消息发送成功: {}", correlationData);
// 清除重试缓存
String messageId = correlationData.getId();
redisTemplate.delete(RETRY_KEY_PREFIX + messageId);
} else {
log.error("消息发送失败: {}, 原因: {}", correlationData, cause);
// 触发重试
retryMessage(correlationData);
}
});
}
/**
* 发送消息(自动重试)
*/
public void sendWithRetry(String exchange, String routingKey, Object message) {
String messageId = UUID.randomUUID().toString();
// 记录重试次数
redisTemplate.opsForValue().set(
RETRY_KEY_PREFIX + messageId,
0,
24,
TimeUnit.HOURS
);
// 构建消息
MessageBuilder builder = MessageBuilder.withBody(JSON.toJSONString(message).getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_JSON)
.setDeliveryMode(MessageDeliveryMode.PERSISTENT)
.setMessageId(messageId);
// 发送消息
rabbitTemplate.send(
exchange,
routingKey,
builder.build(),
new CorrelationData(messageId)
);
}
/**
* 重试消息
*/
private void retryMessage(CorrelationData correlationData) {
String messageId = correlationData.getId();
String retryKey = RETRY_KEY_PREFIX + messageId;
Integer retryCount = (Integer) redisTemplate.opsForValue().get(retryKey);
if (retryCount == null) {
retryCount = 0;
}
if (retryCount < MAX_RETRY_COUNT) {
// 增加重试次数
redisTemplate.opsForValue().increment(retryKey);
// 从缓存中获取原始消息
String messageKey = "message:content:" + messageId;
Message originalMessage = (Message) redisTemplate.opsForValue().get(messageKey);
if (originalMessage != null) {
log.warn("消息重试 [{}/{}]: {}", retryCount + 1, MAX_RETRY_COUNT, messageId);
rabbitTemplate.send(
originalMessage.getMessageProperties().getReceivedExchange(),
originalMessage.getMessageProperties().getReceivedRoutingKey(),
originalMessage,
correlationData
);
}
} else {
log.error("消息超过最大重试次数,放弃: {}", messageId);
// 记录到数据库,人工介入
saveToDeadLetter(correlationData);
}
}
private void saveToDeadLetter(CorrelationData correlationData) {
// 实现持久化逻辑
}
} @Autowired`
`#/**
* 高可靠性生产者
*
* 特性:
* 1. 异步Confirm
* 2. 自动重试
* 3. 消息持久化
* 4. 唯一ID生成
*/
@Service
@Slf4j
public class ReliableProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String RETRY_KEY_PREFIX = "message:retry:";
private static final int MAX_RETRY_COUNT = 3;
@PostConstruct
public void init() {
// 设置异步Confirm回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
log.info("消息发送成功: {}", correlationData);
// 清除重试缓存
String messageId = correlationData.getId();
redisTemplate.delete(RETRY_KEY_PREFIX + messageId);
} else {
log.error("消息发送失败: {}, 原因: {}", correlationData, cause);
// 触发重试
retryMessage(correlationData);
}
});
}
/**
* 发送消息(自动重试)
*/
public void sendWithRetry(String exchange, String routingKey, Object message) {
String messageId = UUID.randomUUID().toString();
// 记录重试次数
redisTemplate.opsForValue().set(
RETRY_KEY_PREFIX + messageId,
0,
24,
TimeUnit.HOURS
);
// 构建消息
MessageBuilder builder = MessageBuilder.withBody(JSON.toJSONString(message).getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_JSON)
.setDeliveryMode(MessageDeliveryMode.PERSISTENT)
.setMessageId(messageId);
// 发送消息
rabbitTemplate.send(
exchange,
routingKey,
builder.build(),
new CorrelationData(messageId)
);
}
/**
* 重试消息
*/
private void retryMessage(CorrelationData correlationData) {
String messageId = correlationData.getId();
String retryKey = RETRY_KEY_PREFIX + messageId;
Integer retryCount = (Integer) redisTemplate.opsForValue().get(retryKey);
if (retryCount == null) {
retryCount = 0;
}
if (retryCount < MAX_RETRY_COUNT) {
// 增加重试次数
redisTemplate.opsForValue().increment(retryKey);
// 从缓存中获取原始消息
String messageKey = "message:content:" + messageId;
Message originalMessage = (Message) redisTemplate.opsForValue().get(messageKey);
if (originalMessage != null) {
log.warn("消息重试 [{}/{}]: {}", retryCount + 1, MAX_RETRY_COUNT, messageId);
rabbitTemplate.send(
originalMessage.getMessageProperties().getReceivedExchange(),
originalMessage.getMessageProperties().getReceivedRoutingKey(),
originalMessage,
correlationData
);
}
} else {
log.error("消息超过最大重试次数,放弃: {}", messageId);
// 记录到数据库,人工介入
saveToDeadLetter(correlationData);
}
}
private void saveToDeadLetter(CorrelationData correlationData) {
// 实现持久化逻辑
}
} private RabbitTemplate rabbitTemplate;`
`#/**
* 高可靠性生产者
*
* 特性:
* 1. 异步Confirm
* 2. 自动重试
* 3. 消息持久化
* 4. 唯一ID生成
*/
@Service
@Slf4j
public class ReliableProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String RETRY_KEY_PREFIX = "message:retry:";
private static final int MAX_RETRY_COUNT = 3;
@PostConstruct
public void init() {
// 设置异步Confirm回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
log.info("消息发送成功: {}", correlationData);
// 清除重试缓存
String messageId = correlationData.getId();
redisTemplate.delete(RETRY_KEY_PREFIX + messageId);
} else {
log.error("消息发送失败: {}, 原因: {}", correlationData, cause);
// 触发重试
retryMessage(correlationData);
}
});
}
/**
* 发送消息(自动重试)
*/
public void sendWithRetry(String exchange, String routingKey, Object message) {
String messageId = UUID.randomUUID().toString();
// 记录重试次数
redisTemplate.opsForValue().set(
RETRY_KEY_PREFIX + messageId,
0,
24,
TimeUnit.HOURS
);
// 构建消息
MessageBuilder builder = MessageBuilder.withBody(JSON.toJSONString(message).getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_JSON)
.setDeliveryMode(MessageDeliveryMode.PERSISTENT)
.setMessageId(messageId);
// 发送消息
rabbitTemplate.send(
exchange,
routingKey,
builder.build(),
new CorrelationData(messageId)
);
}
/**
* 重试消息
*/
private void retryMessage(CorrelationData correlationData) {
String messageId = correlationData.getId();
String retryKey = RETRY_KEY_PREFIX + messageId;
Integer retryCount = (Integer) redisTemplate.opsForValue().get(retryKey);
if (retryCount == null) {
retryCount = 0;
}
if (retryCount < MAX_RETRY_COUNT) {
// 增加重试次数
redisTemplate.opsForValue().increment(retryKey);
// 从缓存中获取原始消息
String messageKey = "message:content:" + messageId;
Message originalMessage = (Message) redisTemplate.opsForValue().get(messageKey);
if (originalMessage != null) {
log.warn("消息重试 [{}/{}]: {}", retryCount + 1, MAX_RETRY_COUNT, messageId);
rabbitTemplate.send(
originalMessage.getMessageProperties().getReceivedExchange(),
originalMessage.getMessageProperties().getReceivedRoutingKey(),
originalMessage,
correlationData
);
}
} else {
log.error("消息超过最大重试次数,放弃: {}", messageId);
// 记录到数据库,人工介入
saveToDeadLetter(correlationData);
}
}
private void saveToDeadLetter(CorrelationData correlationData) {
// 实现持久化逻辑
}
}`
`#/**
* 高可靠性生产者
*
* 特性:
* 1. 异步Confirm
* 2. 自动重试
* 3. 消息持久化
* 4. 唯一ID生成
*/
@Service
@Slf4j
public class ReliableProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String RETRY_KEY_PREFIX = "message:retry:";
private static final int MAX_RETRY_COUNT = 3;
@PostConstruct
public void init() {
// 设置异步Confirm回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
log.info("消息发送成功: {}", correlationData);
// 清除重试缓存
String messageId = correlationData.getId();
redisTemplate.delete(RETRY_KEY_PREFIX + messageId);
} else {
log.error("消息发送失败: {}, 原因: {}", correlationData, cause);
// 触发重试
retryMessage(correlationData);
}
});
}
/**
* 发送消息(自动重试)
*/
public void sendWithRetry(String exchange, String routingKey, Object message) {
String messageId = UUID.randomUUID().toString();
// 记录重试次数
redisTemplate.opsForValue().set(
RETRY_KEY_PREFIX + messageId,
0,
24,
TimeUnit.HOURS
);
// 构建消息
MessageBuilder builder = MessageBuilder.withBody(JSON.toJSONString(message).getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_JSON)
.setDeliveryMode(MessageDeliveryMode.PERSISTENT)
.setMessageId(messageId);
// 发送消息
rabbitTemplate.send(
exchange,
routingKey,
builder.build(),
new CorrelationData(messageId)
);
}
/**
* 重试消息
*/
private void retryMessage(CorrelationData correlationData) {
String messageId = correlationData.getId();
String retryKey = RETRY_KEY_PREFIX + messageId;
Integer retryCount = (Integer) redisTemplate.opsForValue().get(retryKey);
if (retryCount == null) {
retryCount = 0;
}
if (retryCount < MAX_RETRY_COUNT) {
// 增加重试次数
redisTemplate.opsForValue().increment(retryKey);
// 从缓存中获取原始消息
String messageKey = "message:content:" + messageId;
Message originalMessage = (Message) redisTemplate.opsForValue().get(messageKey);
if (originalMessage != null) {
log.warn("消息重试 [{}/{}]: {}", retryCount + 1, MAX_RETRY_COUNT, messageId);
rabbitTemplate.send(
originalMessage.getMessageProperties().getReceivedExchange(),
originalMessage.getMessageProperties().getReceivedRoutingKey(),
originalMessage,
correlationData
);
}
} else {
log.error("消息超过最大重试次数,放弃: {}", messageId);
// 记录到数据库,人工介入
saveToDeadLetter(correlationData);
}
}
private void saveToDeadLetter(CorrelationData correlationData) {
// 实现持久化逻辑
}
} @Autowired`
`#/**
* 高可靠性生产者
*
* 特性:
* 1. 异步Confirm
* 2. 自动重试
* 3. 消息持久化
* 4. 唯一ID生成
*/
@Service
@Slf4j
public class ReliableProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String RETRY_KEY_PREFIX = "message:retry:";
private static final int MAX_RETRY_COUNT = 3;
@PostConstruct
public void init() {
// 设置异步Confirm回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
log.info("消息发送成功: {}", correlationData);
// 清除重试缓存
String messageId = correlationData.getId();
redisTemplate.delete(RETRY_KEY_PREFIX + messageId);
} else {
log.error("消息发送失败: {}, 原因: {}", correlationData, cause);
// 触发重试
retryMessage(correlationData);
}
});
}
/**
* 发送消息(自动重试)
*/
public void sendWithRetry(String exchange, String routingKey, Object message) {
String messageId = UUID.randomUUID().toString();
// 记录重试次数
redisTemplate.opsForValue().set(
RETRY_KEY_PREFIX + messageId,
0,
24,
TimeUnit.HOURS
);
// 构建消息
MessageBuilder builder = MessageBuilder.withBody(JSON.toJSONString(message).getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_JSON)
.setDeliveryMode(MessageDeliveryMode.PERSISTENT)
.setMessageId(messageId);
// 发送消息
rabbitTemplate.send(
exchange,
routingKey,
builder.build(),
new CorrelationData(messageId)
);
}
/**
* 重试消息
*/
private void retryMessage(CorrelationData correlationData) {
String messageId = correlationData.getId();
String retryKey = RETRY_KEY_PREFIX + messageId;
Integer retryCount = (Integer) redisTemplate.opsForValue().get(retryKey);
if (retryCount == null) {
retryCount = 0;
}
if (retryCount < MAX_RETRY_COUNT) {
// 增加重试次数
redisTemplate.opsForValue().increment(retryKey);
// 从缓存中获取原始消息
String messageKey = "message:content:" + messageId;
Message originalMessage = (Message) redisTemplate.opsForValue().get(messageKey);
if (originalMessage != null) {
log.warn("消息重试 [{}/{}]: {}", retryCount + 1, MAX_RETRY_COUNT, messageId);
rabbitTemplate.send(
originalMessage.getMessageProperties().getReceivedExchange(),
originalMessage.getMessageProperties().getReceivedRoutingKey(),
originalMessage,
correlationData
);
}
} else {
log.error("消息超过最大重试次数,放弃: {}", messageId);
// 记录到数据库,人工介入
saveToDeadLetter(correlationData);
}
}
private void saveToDeadLetter(CorrelationData correlationData) {
// 实现持久化逻辑
}
} private RedisTemplate<String, Object> redisTemplate;`
`#/**
* 高可靠性生产者
*
* 特性:
* 1. 异步Confirm
* 2. 自动重试
* 3. 消息持久化
* 4. 唯一ID生成
*/
@Service
@Slf4j
public class ReliableProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String RETRY_KEY_PREFIX = "message:retry:";
private static final int MAX_RETRY_COUNT = 3;
@PostConstruct
public void init() {
// 设置异步Confirm回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
log.info("消息发送成功: {}", correlationData);
// 清除重试缓存
String messageId = correlationData.getId();
redisTemplate.delete(RETRY_KEY_PREFIX + messageId);
} else {
log.error("消息发送失败: {}, 原因: {}", correlationData, cause);
// 触发重试
retryMessage(correlationData);
}
});
}
/**
* 发送消息(自动重试)
*/
public void sendWithRetry(String exchange, String routingKey, Object message) {
String messageId = UUID.randomUUID().toString();
// 记录重试次数
redisTemplate.opsForValue().set(
RETRY_KEY_PREFIX + messageId,
0,
24,
TimeUnit.HOURS
);
// 构建消息
MessageBuilder builder = MessageBuilder.withBody(JSON.toJSONString(message).getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_JSON)
.setDeliveryMode(MessageDeliveryMode.PERSISTENT)
.setMessageId(messageId);
// 发送消息
rabbitTemplate.send(
exchange,
routingKey,
builder.build(),
new CorrelationData(messageId)
);
}
/**
* 重试消息
*/
private void retryMessage(CorrelationData correlationData) {
String messageId = correlationData.getId();
String retryKey = RETRY_KEY_PREFIX + messageId;
Integer retryCount = (Integer) redisTemplate.opsForValue().get(retryKey);
if (retryCount == null) {
retryCount = 0;
}
if (retryCount < MAX_RETRY_COUNT) {
// 增加重试次数
redisTemplate.opsForValue().increment(retryKey);
// 从缓存中获取原始消息
String messageKey = "message:content:" + messageId;
Message originalMessage = (Message) redisTemplate.opsForValue().get(messageKey);
if (originalMessage != null) {
log.warn("消息重试 [{}/{}]: {}", retryCount + 1, MAX_RETRY_COUNT, messageId);
rabbitTemplate.send(
originalMessage.getMessageProperties().getReceivedExchange(),
originalMessage.getMessageProperties().getReceivedRoutingKey(),
originalMessage,
correlationData
);
}
} else {
log.error("消息超过最大重试次数,放弃: {}", messageId);
// 记录到数据库,人工介入
saveToDeadLetter(correlationData);
}
}
private void saveToDeadLetter(CorrelationData correlationData) {
// 实现持久化逻辑
}
}`
`#/**
* 高可靠性生产者
*
* 特性:
* 1. 异步Confirm
* 2. 自动重试
* 3. 消息持久化
* 4. 唯一ID生成
*/
@Service
@Slf4j
public class ReliableProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String RETRY_KEY_PREFIX = "message:retry:";
private static final int MAX_RETRY_COUNT = 3;
@PostConstruct
public void init() {
// 设置异步Confirm回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
log.info("消息发送成功: {}", correlationData);
// 清除重试缓存
String messageId = correlationData.getId();
redisTemplate.delete(RETRY_KEY_PREFIX + messageId);
} else {
log.error("消息发送失败: {}, 原因: {}", correlationData, cause);
// 触发重试
retryMessage(correlationData);
}
});
}
/**
* 发送消息(自动重试)
*/
public void sendWithRetry(String exchange, String routingKey, Object message) {
String messageId = UUID.randomUUID().toString();
// 记录重试次数
redisTemplate.opsForValue().set(
RETRY_KEY_PREFIX + messageId,
0,
24,
TimeUnit.HOURS
);
// 构建消息
MessageBuilder builder = MessageBuilder.withBody(JSON.toJSONString(message).getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_JSON)
.setDeliveryMode(MessageDeliveryMode.PERSISTENT)
.setMessageId(messageId);
// 发送消息
rabbitTemplate.send(
exchange,
routingKey,
builder.build(),
new CorrelationData(messageId)
);
}
/**
* 重试消息
*/
private void retryMessage(CorrelationData correlationData) {
String messageId = correlationData.getId();
String retryKey = RETRY_KEY_PREFIX + messageId;
Integer retryCount = (Integer) redisTemplate.opsForValue().get(retryKey);
if (retryCount == null) {
retryCount = 0;
}
if (retryCount < MAX_RETRY_COUNT) {
// 增加重试次数
redisTemplate.opsForValue().increment(retryKey);
// 从缓存中获取原始消息
String messageKey = "message:content:" + messageId;
Message originalMessage = (Message) redisTemplate.opsForValue().get(messageKey);
if (originalMessage != null) {
log.warn("消息重试 [{}/{}]: {}", retryCount + 1, MAX_RETRY_COUNT, messageId);
rabbitTemplate.send(
originalMessage.getMessageProperties().getReceivedExchange(),
originalMessage.getMessageProperties().getReceivedRoutingKey(),
originalMessage,
correlationData
);
}
} else {
log.error("消息超过最大重试次数,放弃: {}", messageId);
// 记录到数据库,人工介入
saveToDeadLetter(correlationData);
}
}
private void saveToDeadLetter(CorrelationData correlationData) {
// 实现持久化逻辑
}
} private static final String RETRY_KEY_PREFIX = "message:retry:";`
`#/**
* 高可靠性生产者
*
* 特性:
* 1. 异步Confirm
* 2. 自动重试
* 3. 消息持久化
* 4. 唯一ID生成
*/
@Service
@Slf4j
public class ReliableProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String RETRY_KEY_PREFIX = "message:retry:";
private static final int MAX_RETRY_COUNT = 3;
@PostConstruct
public void init() {
// 设置异步Confirm回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
log.info("消息发送成功: {}", correlationData);
// 清除重试缓存
String messageId = correlationData.getId();
redisTemplate.delete(RETRY_KEY_PREFIX + messageId);
} else {
log.error("消息发送失败: {}, 原因: {}", correlationData, cause);
// 触发重试
retryMessage(correlationData);
}
});
}
/**
* 发送消息(自动重试)
*/
public void sendWithRetry(String exchange, String routingKey, Object message) {
String messageId = UUID.randomUUID().toString();
// 记录重试次数
redisTemplate.opsForValue().set(
RETRY_KEY_PREFIX + messageId,
0,
24,
TimeUnit.HOURS
);
// 构建消息
MessageBuilder builder = MessageBuilder.withBody(JSON.toJSONString(message).getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_JSON)
.setDeliveryMode(MessageDeliveryMode.PERSISTENT)
.setMessageId(messageId);
// 发送消息
rabbitTemplate.send(
exchange,
routingKey,
builder.build(),
new CorrelationData(messageId)
);
}
/**
* 重试消息
*/
private void retryMessage(CorrelationData correlationData) {
String messageId = correlationData.getId();
String retryKey = RETRY_KEY_PREFIX + messageId;
Integer retryCount = (Integer) redisTemplate.opsForValue().get(retryKey);
if (retryCount == null) {
retryCount = 0;
}
if (retryCount < MAX_RETRY_COUNT) {
// 增加重试次数
redisTemplate.opsForValue().increment(retryKey);
// 从缓存中获取原始消息
String messageKey = "message:content:" + messageId;
Message originalMessage = (Message) redisTemplate.opsForValue().get(messageKey);
if (originalMessage != null) {
log.warn("消息重试 [{}/{}]: {}", retryCount + 1, MAX_RETRY_COUNT, messageId);
rabbitTemplate.send(
originalMessage.getMessageProperties().getReceivedExchange(),
originalMessage.getMessageProperties().getReceivedRoutingKey(),
originalMessage,
correlationData
);
}
} else {
log.error("消息超过最大重试次数,放弃: {}", messageId);
// 记录到数据库,人工介入
saveToDeadLetter(correlationData);
}
}
private void saveToDeadLetter(CorrelationData correlationData) {
// 实现持久化逻辑
}
} private static final int MAX_RETRY_COUNT = 3;`
`#/**
* 高可靠性生产者
*
* 特性:
* 1. 异步Confirm
* 2. 自动重试
* 3. 消息持久化
* 4. 唯一ID生成
*/
@Service
@Slf4j
public class ReliableProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String RETRY_KEY_PREFIX = "message:retry:";
private static final int MAX_RETRY_COUNT = 3;
@PostConstruct
public void init() {
// 设置异步Confirm回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
log.info("消息发送成功: {}", correlationData);
// 清除重试缓存
String messageId = correlationData.getId();
redisTemplate.delete(RETRY_KEY_PREFIX + messageId);
} else {
log.error("消息发送失败: {}, 原因: {}", correlationData, cause);
// 触发重试
retryMessage(correlationData);
}
});
}
/**
* 发送消息(自动重试)
*/
public void sendWithRetry(String exchange, String routingKey, Object message) {
String messageId = UUID.randomUUID().toString();
// 记录重试次数
redisTemplate.opsForValue().set(
RETRY_KEY_PREFIX + messageId,
0,
24,
TimeUnit.HOURS
);
// 构建消息
MessageBuilder builder = MessageBuilder.withBody(JSON.toJSONString(message).getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_JSON)
.setDeliveryMode(MessageDeliveryMode.PERSISTENT)
.setMessageId(messageId);
// 发送消息
rabbitTemplate.send(
exchange,
routingKey,
builder.build(),
new CorrelationData(messageId)
);
}
/**
* 重试消息
*/
private void retryMessage(CorrelationData correlationData) {
String messageId = correlationData.getId();
String retryKey = RETRY_KEY_PREFIX + messageId;
Integer retryCount = (Integer) redisTemplate.opsForValue().get(retryKey);
if (retryCount == null) {
retryCount = 0;
}
if (retryCount < MAX_RETRY_COUNT) {
// 增加重试次数
redisTemplate.opsForValue().increment(retryKey);
// 从缓存中获取原始消息
String messageKey = "message:content:" + messageId;
Message originalMessage = (Message) redisTemplate.opsForValue().get(messageKey);
if (originalMessage != null) {
log.warn("消息重试 [{}/{}]: {}", retryCount + 1, MAX_RETRY_COUNT, messageId);
rabbitTemplate.send(
originalMessage.getMessageProperties().getReceivedExchange(),
originalMessage.getMessageProperties().getReceivedRoutingKey(),
originalMessage,
correlationData
);
}
} else {
log.error("消息超过最大重试次数,放弃: {}", messageId);
// 记录到数据库,人工介入
saveToDeadLetter(correlationData);
}
}
private void saveToDeadLetter(CorrelationData correlationData) {
// 实现持久化逻辑
}
}`
`#/**
* 高可靠性生产者
*
* 特性:
* 1. 异步Confirm
* 2. 自动重试
* 3. 消息持久化
* 4. 唯一ID生成
*/
@Service
@Slf4j
public class ReliableProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String RETRY_KEY_PREFIX = "message:retry:";
private static final int MAX_RETRY_COUNT = 3;
@PostConstruct
public void init() {
// 设置异步Confirm回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
log.info("消息发送成功: {}", correlationData);
// 清除重试缓存
String messageId = correlationData.getId();
redisTemplate.delete(RETRY_KEY_PREFIX + messageId);
} else {
log.error("消息发送失败: {}, 原因: {}", correlationData, cause);
// 触发重试
retryMessage(correlationData);
}
});
}
/**
* 发送消息(自动重试)
*/
public void sendWithRetry(String exchange, String routingKey, Object message) {
String messageId = UUID.randomUUID().toString();
// 记录重试次数
redisTemplate.opsForValue().set(
RETRY_KEY_PREFIX + messageId,
0,
24,
TimeUnit.HOURS
);
// 构建消息
MessageBuilder builder = MessageBuilder.withBody(JSON.toJSONString(message).getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_JSON)
.setDeliveryMode(MessageDeliveryMode.PERSISTENT)
.setMessageId(messageId);
// 发送消息
rabbitTemplate.send(
exchange,
routingKey,
builder.build(),
new CorrelationData(messageId)
);
}
/**
* 重试消息
*/
private void retryMessage(CorrelationData correlationData) {
String messageId = correlationData.getId();
String retryKey = RETRY_KEY_PREFIX + messageId;
Integer retryCount = (Integer) redisTemplate.opsForValue().get(retryKey);
if (retryCount == null) {
retryCount = 0;
}
if (retryCount < MAX_RETRY_COUNT) {
// 增加重试次数
redisTemplate.opsForValue().increment(retryKey);
// 从缓存中获取原始消息
String messageKey = "message:content:" + messageId;
Message originalMessage = (Message) redisTemplate.opsForValue().get(messageKey);
if (originalMessage != null) {
log.warn("消息重试 [{}/{}]: {}", retryCount + 1, MAX_RETRY_COUNT, messageId);
rabbitTemplate.send(
originalMessage.getMessageProperties().getReceivedExchange(),
originalMessage.getMessageProperties().getReceivedRoutingKey(),
originalMessage,
correlationData
);
}
} else {
log.error("消息超过最大重试次数,放弃: {}", messageId);
// 记录到数据库,人工介入
saveToDeadLetter(correlationData);
}
}
private void saveToDeadLetter(CorrelationData correlationData) {
// 实现持久化逻辑
}
} @PostConstruct`
`#/**
* 高可靠性生产者
*
* 特性:
* 1. 异步Confirm
* 2. 自动重试
* 3. 消息持久化
* 4. 唯一ID生成
*/
@Service
@Slf4j
public class ReliableProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String RETRY_KEY_PREFIX = "message:retry:";
private static final int MAX_RETRY_COUNT = 3;
@PostConstruct
public void init() {
// 设置异步Confirm回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
log.info("消息发送成功: {}", correlationData);
// 清除重试缓存
String messageId = correlationData.getId();
redisTemplate.delete(RETRY_KEY_PREFIX + messageId);
} else {
log.error("消息发送失败: {}, 原因: {}", correlationData, cause);
// 触发重试
retryMessage(correlationData);
}
});
}
/**
* 发送消息(自动重试)
*/
public void sendWithRetry(String exchange, String routingKey, Object message) {
String messageId = UUID.randomUUID().toString();
// 记录重试次数
redisTemplate.opsForValue().set(
RETRY_KEY_PREFIX + messageId,
0,
24,
TimeUnit.HOURS
);
// 构建消息
MessageBuilder builder = MessageBuilder.withBody(JSON.toJSONString(message).getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_JSON)
.setDeliveryMode(MessageDeliveryMode.PERSISTENT)
.setMessageId(messageId);
// 发送消息
rabbitTemplate.send(
exchange,
routingKey,
builder.build(),
new CorrelationData(messageId)
);
}
/**
* 重试消息
*/
private void retryMessage(CorrelationData correlationData) {
String messageId = correlationData.getId();
String retryKey = RETRY_KEY_PREFIX + messageId;
Integer retryCount = (Integer) redisTemplate.opsForValue().get(retryKey);
if (retryCount == null) {
retryCount = 0;
}
if (retryCount < MAX_RETRY_COUNT) {
// 增加重试次数
redisTemplate.opsForValue().increment(retryKey);
// 从缓存中获取原始消息
String messageKey = "message:content:" + messageId;
Message originalMessage = (Message) redisTemplate.opsForValue().get(messageKey);
if (originalMessage != null) {
log.warn("消息重试 [{}/{}]: {}", retryCount + 1, MAX_RETRY_COUNT, messageId);
rabbitTemplate.send(
originalMessage.getMessageProperties().getReceivedExchange(),
originalMessage.getMessageProperties().getReceivedRoutingKey(),
originalMessage,
correlationData
);
}
} else {
log.error("消息超过最大重试次数,放弃: {}", messageId);
// 记录到数据库,人工介入
saveToDeadLetter(correlationData);
}
}
private void saveToDeadLetter(CorrelationData correlationData) {
// 实现持久化逻辑
}
} public void init() {`
`#/**
* 高可靠性生产者
*
* 特性:
* 1. 异步Confirm
* 2. 自动重试
* 3. 消息持久化
* 4. 唯一ID生成
*/
@Service
@Slf4j
public class ReliableProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String RETRY_KEY_PREFIX = "message:retry:";
private static final int MAX_RETRY_COUNT = 3;
@PostConstruct
public void init() {
// 设置异步Confirm回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
log.info("消息发送成功: {}", correlationData);
// 清除重试缓存
String messageId = correlationData.getId();
redisTemplate.delete(RETRY_KEY_PREFIX + messageId);
} else {
log.error("消息发送失败: {}, 原因: {}", correlationData, cause);
// 触发重试
retryMessage(correlationData);
}
});
}
/**
* 发送消息(自动重试)
*/
public void sendWithRetry(String exchange, String routingKey, Object message) {
String messageId = UUID.randomUUID().toString();
// 记录重试次数
redisTemplate.opsForValue().set(
RETRY_KEY_PREFIX + messageId,
0,
24,
TimeUnit.HOURS
);
// 构建消息
MessageBuilder builder = MessageBuilder.withBody(JSON.toJSONString(message).getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_JSON)
.setDeliveryMode(MessageDeliveryMode.PERSISTENT)
.setMessageId(messageId);
// 发送消息
rabbitTemplate.send(
exchange,
routingKey,
builder.build(),
new CorrelationData(messageId)
);
}
/**
* 重试消息
*/
private void retryMessage(CorrelationData correlationData) {
String messageId = correlationData.getId();
String retryKey = RETRY_KEY_PREFIX + messageId;
Integer retryCount = (Integer) redisTemplate.opsForValue().get(retryKey);
if (retryCount == null) {
retryCount = 0;
}
if (retryCount < MAX_RETRY_COUNT) {
// 增加重试次数
redisTemplate.opsForValue().increment(retryKey);
// 从缓存中获取原始消息
String messageKey = "message:content:" + messageId;
Message originalMessage = (Message) redisTemplate.opsForValue().get(messageKey);
if (originalMessage != null) {
log.warn("消息重试 [{}/{}]: {}", retryCount + 1, MAX_RETRY_COUNT, messageId);
rabbitTemplate.send(
originalMessage.getMessageProperties().getReceivedExchange(),
originalMessage.getMessageProperties().getReceivedRoutingKey(),
originalMessage,
correlationData
);
}
} else {
log.error("消息超过最大重试次数,放弃: {}", messageId);
// 记录到数据库,人工介入
saveToDeadLetter(correlationData);
}
}
private void saveToDeadLetter(CorrelationData correlationData) {
// 实现持久化逻辑
}
} // 设置异步Confirm回调`
`#/**
* 高可靠性生产者
*
* 特性:
* 1. 异步Confirm
* 2. 自动重试
* 3. 消息持久化
* 4. 唯一ID生成
*/
@Service
@Slf4j
public class ReliableProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String RETRY_KEY_PREFIX = "message:retry:";
private static final int MAX_RETRY_COUNT = 3;
@PostConstruct
public void init() {
// 设置异步Confirm回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
log.info("消息发送成功: {}", correlationData);
// 清除重试缓存
String messageId = correlationData.getId();
redisTemplate.delete(RETRY_KEY_PREFIX + messageId);
} else {
log.error("消息发送失败: {}, 原因: {}", correlationData, cause);
// 触发重试
retryMessage(correlationData);
}
});
}
/**
* 发送消息(自动重试)
*/
public void sendWithRetry(String exchange, String routingKey, Object message) {
String messageId = UUID.randomUUID().toString();
// 记录重试次数
redisTemplate.opsForValue().set(
RETRY_KEY_PREFIX + messageId,
0,
24,
TimeUnit.HOURS
);
// 构建消息
MessageBuilder builder = MessageBuilder.withBody(JSON.toJSONString(message).getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_JSON)
.setDeliveryMode(MessageDeliveryMode.PERSISTENT)
.setMessageId(messageId);
// 发送消息
rabbitTemplate.send(
exchange,
routingKey,
builder.build(),
new CorrelationData(messageId)
);
}
/**
* 重试消息
*/
private void retryMessage(CorrelationData correlationData) {
String messageId = correlationData.getId();
String retryKey = RETRY_KEY_PREFIX + messageId;
Integer retryCount = (Integer) redisTemplate.opsForValue().get(retryKey);
if (retryCount == null) {
retryCount = 0;
}
if (retryCount < MAX_RETRY_COUNT) {
// 增加重试次数
redisTemplate.opsForValue().increment(retryKey);
// 从缓存中获取原始消息
String messageKey = "message:content:" + messageId;
Message originalMessage = (Message) redisTemplate.opsForValue().get(messageKey);
if (originalMessage != null) {
log.warn("消息重试 [{}/{}]: {}", retryCount + 1, MAX_RETRY_COUNT, messageId);
rabbitTemplate.send(
originalMessage.getMessageProperties().getReceivedExchange(),
originalMessage.getMessageProperties().getReceivedRoutingKey(),
originalMessage,
correlationData
);
}
} else {
log.error("消息超过最大重试次数,放弃: {}", messageId);
// 记录到数据库,人工介入
saveToDeadLetter(correlationData);
}
}
private void saveToDeadLetter(CorrelationData correlationData) {
// 实现持久化逻辑
}
} rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {`
`#/**
* 高可靠性生产者
*
* 特性:
* 1. 异步Confirm
* 2. 自动重试
* 3. 消息持久化
* 4. 唯一ID生成
*/
@Service
@Slf4j
public class ReliableProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String RETRY_KEY_PREFIX = "message:retry:";
private static final int MAX_RETRY_COUNT = 3;
@PostConstruct
public void init() {
// 设置异步Confirm回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
log.info("消息发送成功: {}", correlationData);
// 清除重试缓存
String messageId = correlationData.getId();
redisTemplate.delete(RETRY_KEY_PREFIX + messageId);
} else {
log.error("消息发送失败: {}, 原因: {}", correlationData, cause);
// 触发重试
retryMessage(correlationData);
}
});
}
/**
* 发送消息(自动重试)
*/
public void sendWithRetry(String exchange, String routingKey, Object message) {
String messageId = UUID.randomUUID().toString();
// 记录重试次数
redisTemplate.opsForValue().set(
RETRY_KEY_PREFIX + messageId,
0,
24,
TimeUnit.HOURS
);
// 构建消息
MessageBuilder builder = MessageBuilder.withBody(JSON.toJSONString(message).getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_JSON)
.setDeliveryMode(MessageDeliveryMode.PERSISTENT)
.setMessageId(messageId);
// 发送消息
rabbitTemplate.send(
exchange,
routingKey,
builder.build(),
new CorrelationData(messageId)
);
}
/**
* 重试消息
*/
private void retryMessage(CorrelationData correlationData) {
String messageId = correlationData.getId();
String retryKey = RETRY_KEY_PREFIX + messageId;
Integer retryCount = (Integer) redisTemplate.opsForValue().get(retryKey);
if (retryCount == null) {
retryCount = 0;
}
if (retryCount < MAX_RETRY_COUNT) {
// 增加重试次数
redisTemplate.opsForValue().increment(retryKey);
// 从缓存中获取原始消息
String messageKey = "message:content:" + messageId;
Message originalMessage = (Message) redisTemplate.opsForValue().get(messageKey);
if (originalMessage != null) {
log.warn("消息重试 [{}/{}]: {}", retryCount + 1, MAX_RETRY_COUNT, messageId);
rabbitTemplate.send(
originalMessage.getMessageProperties().getReceivedExchange(),
originalMessage.getMessageProperties().getReceivedRoutingKey(),
originalMessage,
correlationData
);
}
} else {
log.error("消息超过最大重试次数,放弃: {}", messageId);
// 记录到数据库,人工介入
saveToDeadLetter(correlationData);
}
}
private void saveToDeadLetter(CorrelationData correlationData) {
// 实现持久化逻辑
}
} if (ack) {`
`#/**
* 高可靠性生产者
*
* 特性:
* 1. 异步Confirm
* 2. 自动重试
* 3. 消息持久化
* 4. 唯一ID生成
*/
@Service
@Slf4j
public class ReliableProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String RETRY_KEY_PREFIX = "message:retry:";
private static final int MAX_RETRY_COUNT = 3;
@PostConstruct
public void init() {
// 设置异步Confirm回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
log.info("消息发送成功: {}", correlationData);
// 清除重试缓存
String messageId = correlationData.getId();
redisTemplate.delete(RETRY_KEY_PREFIX + messageId);
} else {
log.error("消息发送失败: {}, 原因: {}", correlationData, cause);
// 触发重试
retryMessage(correlationData);
}
});
}
/**
* 发送消息(自动重试)
*/
public void sendWithRetry(String exchange, String routingKey, Object message) {
String messageId = UUID.randomUUID().toString();
// 记录重试次数
redisTemplate.opsForValue().set(
RETRY_KEY_PREFIX + messageId,
0,
24,
TimeUnit.HOURS
);
// 构建消息
MessageBuilder builder = MessageBuilder.withBody(JSON.toJSONString(message).getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_JSON)
.setDeliveryMode(MessageDeliveryMode.PERSISTENT)
.setMessageId(messageId);
// 发送消息
rabbitTemplate.send(
exchange,
routingKey,
builder.build(),
new CorrelationData(messageId)
);
}
/**
* 重试消息
*/
private void retryMessage(CorrelationData correlationData) {
String messageId = correlationData.getId();
String retryKey = RETRY_KEY_PREFIX + messageId;
Integer retryCount = (Integer) redisTemplate.opsForValue().get(retryKey);
if (retryCount == null) {
retryCount = 0;
}
if (retryCount < MAX_RETRY_COUNT) {
// 增加重试次数
redisTemplate.opsForValue().increment(retryKey);
// 从缓存中获取原始消息
String messageKey = "message:content:" + messageId;
Message originalMessage = (Message) redisTemplate.opsForValue().get(messageKey);
if (originalMessage != null) {
log.warn("消息重试 [{}/{}]: {}", retryCount + 1, MAX_RETRY_COUNT, messageId);
rabbitTemplate.send(
originalMessage.getMessageProperties().getReceivedExchange(),
originalMessage.getMessageProperties().getReceivedRoutingKey(),
originalMessage,
correlationData
);
}
} else {
log.error("消息超过最大重试次数,放弃: {}", messageId);
// 记录到数据库,人工介入
saveToDeadLetter(correlationData);
}
}
private void saveToDeadLetter(CorrelationData correlationData) {
// 实现持久化逻辑
}
} log.info("消息发送成功: {}", correlationData);`
`#/**
* 高可靠性生产者
*
* 特性:
* 1. 异步Confirm
* 2. 自动重试
* 3. 消息持久化
* 4. 唯一ID生成
*/
@Service
@Slf4j
public class ReliableProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String RETRY_KEY_PREFIX = "message:retry:";
private static final int MAX_RETRY_COUNT = 3;
@PostConstruct
public void init() {
// 设置异步Confirm回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
log.info("消息发送成功: {}", correlationData);
// 清除重试缓存
String messageId = correlationData.getId();
redisTemplate.delete(RETRY_KEY_PREFIX + messageId);
} else {
log.error("消息发送失败: {}, 原因: {}", correlationData, cause);
// 触发重试
retryMessage(correlationData);
}
});
}
/**
* 发送消息(自动重试)
*/
public void sendWithRetry(String exchange, String routingKey, Object message) {
String messageId = UUID.randomUUID().toString();
// 记录重试次数
redisTemplate.opsForValue().set(
RETRY_KEY_PREFIX + messageId,
0,
24,
TimeUnit.HOURS
);
// 构建消息
MessageBuilder builder = MessageBuilder.withBody(JSON.toJSONString(message).getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_JSON)
.setDeliveryMode(MessageDeliveryMode.PERSISTENT)
.setMessageId(messageId);
// 发送消息
rabbitTemplate.send(
exchange,
routingKey,
builder.build(),
new CorrelationData(messageId)
);
}
/**
* 重试消息
*/
private void retryMessage(CorrelationData correlationData) {
String messageId = correlationData.getId();
String retryKey = RETRY_KEY_PREFIX + messageId;
Integer retryCount = (Integer) redisTemplate.opsForValue().get(retryKey);
if (retryCount == null) {
retryCount = 0;
}
if (retryCount < MAX_RETRY_COUNT) {
// 增加重试次数
redisTemplate.opsForValue().increment(retryKey);
// 从缓存中获取原始消息
String messageKey = "message:content:" + messageId;
Message originalMessage = (Message) redisTemplate.opsForValue().get(messageKey);
if (originalMessage != null) {
log.warn("消息重试 [{}/{}]: {}", retryCount + 1, MAX_RETRY_COUNT, messageId);
rabbitTemplate.send(
originalMessage.getMessageProperties().getReceivedExchange(),
originalMessage.getMessageProperties().getReceivedRoutingKey(),
originalMessage,
correlationData
);
}
} else {
log.error("消息超过最大重试次数,放弃: {}", messageId);
// 记录到数据库,人工介入
saveToDeadLetter(correlationData);
}
}
private void saveToDeadLetter(CorrelationData correlationData) {
// 实现持久化逻辑
}
} // 清除重试缓存`
`#/**
* 高可靠性生产者
*
* 特性:
* 1. 异步Confirm
* 2. 自动重试
* 3. 消息持久化
* 4. 唯一ID生成
*/
@Service
@Slf4j
public class ReliableProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String RETRY_KEY_PREFIX = "message:retry:";
private static final int MAX_RETRY_COUNT = 3;
@PostConstruct
public void init() {
// 设置异步Confirm回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
log.info("消息发送成功: {}", correlationData);
// 清除重试缓存
String messageId = correlationData.getId();
redisTemplate.delete(RETRY_KEY_PREFIX + messageId);
} else {
log.error("消息发送失败: {}, 原因: {}", correlationData, cause);
// 触发重试
retryMessage(correlationData);
}
});
}
/**
* 发送消息(自动重试)
*/
public void sendWithRetry(String exchange, String routingKey, Object message) {
String messageId = UUID.randomUUID().toString();
// 记录重试次数
redisTemplate.opsForValue().set(
RETRY_KEY_PREFIX + messageId,
0,
24,
TimeUnit.HOURS
);
// 构建消息
MessageBuilder builder = MessageBuilder.withBody(JSON.toJSONString(message).getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_JSON)
.setDeliveryMode(MessageDeliveryMode.PERSISTENT)
.setMessageId(messageId);
// 发送消息
rabbitTemplate.send(
exchange,
routingKey,
builder.build(),
new CorrelationData(messageId)
);
}
/**
* 重试消息
*/
private void retryMessage(CorrelationData correlationData) {
String messageId = correlationData.getId();
String retryKey = RETRY_KEY_PREFIX + messageId;
Integer retryCount = (Integer) redisTemplate.opsForValue().get(retryKey);
if (retryCount == null) {
retryCount = 0;
}
if (retryCount < MAX_RETRY_COUNT) {
// 增加重试次数
redisTemplate.opsForValue().increment(retryKey);
// 从缓存中获取原始消息
String messageKey = "message:content:" + messageId;
Message originalMessage = (Message) redisTemplate.opsForValue().get(messageKey);
if (originalMessage != null) {
log.warn("消息重试 [{}/{}]: {}", retryCount + 1, MAX_RETRY_COUNT, messageId);
rabbitTemplate.send(
originalMessage.getMessageProperties().getReceivedExchange(),
originalMessage.getMessageProperties().getReceivedRoutingKey(),
originalMessage,
correlationData
);
}
} else {
log.error("消息超过最大重试次数,放弃: {}", messageId);
// 记录到数据库,人工介入
saveToDeadLetter(correlationData);
}
}
private void saveToDeadLetter(CorrelationData correlationData) {
// 实现持久化逻辑
}
} String messageId = correlationData.getId();`
`#/**
* 高可靠性生产者
*
* 特性:
* 1. 异步Confirm
* 2. 自动重试
* 3. 消息持久化
* 4. 唯一ID生成
*/
@Service
@Slf4j
public class ReliableProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String RETRY_KEY_PREFIX = "message:retry:";
private static final int MAX_RETRY_COUNT = 3;
@PostConstruct
public void init() {
// 设置异步Confirm回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
log.info("消息发送成功: {}", correlationData);
// 清除重试缓存
String messageId = correlationData.getId();
redisTemplate.delete(RETRY_KEY_PREFIX + messageId);
} else {
log.error("消息发送失败: {}, 原因: {}", correlationData, cause);
// 触发重试
retryMessage(correlationData);
}
});
}
/**
* 发送消息(自动重试)
*/
public void sendWithRetry(String exchange, String routingKey, Object message) {
String messageId = UUID.randomUUID().toString();
// 记录重试次数
redisTemplate.opsForValue().set(
RETRY_KEY_PREFIX + messageId,
0,
24,
TimeUnit.HOURS
);
// 构建消息
MessageBuilder builder = MessageBuilder.withBody(JSON.toJSONString(message).getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_JSON)
.setDeliveryMode(MessageDeliveryMode.PERSISTENT)
.setMessageId(messageId);
// 发送消息
rabbitTemplate.send(
exchange,
routingKey,
builder.build(),
new CorrelationData(messageId)
);
}
/**
* 重试消息
*/
private void retryMessage(CorrelationData correlationData) {
String messageId = correlationData.getId();
String retryKey = RETRY_KEY_PREFIX + messageId;
Integer retryCount = (Integer) redisTemplate.opsForValue().get(retryKey);
if (retryCount == null) {
retryCount = 0;
}
if (retryCount < MAX_RETRY_COUNT) {
// 增加重试次数
redisTemplate.opsForValue().increment(retryKey);
// 从缓存中获取原始消息
String messageKey = "message:content:" + messageId;
Message originalMessage = (Message) redisTemplate.opsForValue().get(messageKey);
if (originalMessage != null) {
log.warn("消息重试 [{}/{}]: {}", retryCount + 1, MAX_RETRY_COUNT, messageId);
rabbitTemplate.send(
originalMessage.getMessageProperties().getReceivedExchange(),
originalMessage.getMessageProperties().getReceivedRoutingKey(),
originalMessage,
correlationData
);
}
} else {
log.error("消息超过最大重试次数,放弃: {}", messageId);
// 记录到数据库,人工介入
saveToDeadLetter(correlationData);
}
}
private void saveToDeadLetter(CorrelationData correlationData) {
// 实现持久化逻辑
}
} redisTemplate.delete(RETRY_KEY_PREFIX + messageId);`
`#/**
* 高可靠性生产者
*
* 特性:
* 1. 异步Confirm
* 2. 自动重试
* 3. 消息持久化
* 4. 唯一ID生成
*/
@Service
@Slf4j
public class ReliableProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String RETRY_KEY_PREFIX = "message:retry:";
private static final int MAX_RETRY_COUNT = 3;
@PostConstruct
public void init() {
// 设置异步Confirm回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
log.info("消息发送成功: {}", correlationData);
// 清除重试缓存
String messageId = correlationData.getId();
redisTemplate.delete(RETRY_KEY_PREFIX + messageId);
} else {
log.error("消息发送失败: {}, 原因: {}", correlationData, cause);
// 触发重试
retryMessage(correlationData);
}
});
}
/**
* 发送消息(自动重试)
*/
public void sendWithRetry(String exchange, String routingKey, Object message) {
String messageId = UUID.randomUUID().toString();
// 记录重试次数
redisTemplate.opsForValue().set(
RETRY_KEY_PREFIX + messageId,
0,
24,
TimeUnit.HOURS
);
// 构建消息
MessageBuilder builder = MessageBuilder.withBody(JSON.toJSONString(message).getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_JSON)
.setDeliveryMode(MessageDeliveryMode.PERSISTENT)
.setMessageId(messageId);
// 发送消息
rabbitTemplate.send(
exchange,
routingKey,
builder.build(),
new CorrelationData(messageId)
);
}
/**
* 重试消息
*/
private void retryMessage(CorrelationData correlationData) {
String messageId = correlationData.getId();
String retryKey = RETRY_KEY_PREFIX + messageId;
Integer retryCount = (Integer) redisTemplate.opsForValue().get(retryKey);
if (retryCount == null) {
retryCount = 0;
}
if (retryCount < MAX_RETRY_COUNT) {
// 增加重试次数
redisTemplate.opsForValue().increment(retryKey);
// 从缓存中获取原始消息
String messageKey = "message:content:" + messageId;
Message originalMessage = (Message) redisTemplate.opsForValue().get(messageKey);
if (originalMessage != null) {
log.warn("消息重试 [{}/{}]: {}", retryCount + 1, MAX_RETRY_COUNT, messageId);
rabbitTemplate.send(
originalMessage.getMessageProperties().getReceivedExchange(),
originalMessage.getMessageProperties().getReceivedRoutingKey(),
originalMessage,
correlationData
);
}
} else {
log.error("消息超过最大重试次数,放弃: {}", messageId);
// 记录到数据库,人工介入
saveToDeadLetter(correlationData);
}
}
private void saveToDeadLetter(CorrelationData correlationData) {
// 实现持久化逻辑
}
} } else {`
`#/**
* 高可靠性生产者
*
* 特性:
* 1. 异步Confirm
* 2. 自动重试
* 3. 消息持久化
* 4. 唯一ID生成
*/
@Service
@Slf4j
public class ReliableProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String RETRY_KEY_PREFIX = "message:retry:";
private static final int MAX_RETRY_COUNT = 3;
@PostConstruct
public void init() {
// 设置异步Confirm回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
log.info("消息发送成功: {}", correlationData);
// 清除重试缓存
String messageId = correlationData.getId();
redisTemplate.delete(RETRY_KEY_PREFIX + messageId);
} else {
log.error("消息发送失败: {}, 原因: {}", correlationData, cause);
// 触发重试
retryMessage(correlationData);
}
});
}
/**
* 发送消息(自动重试)
*/
public void sendWithRetry(String exchange, String routingKey, Object message) {
String messageId = UUID.randomUUID().toString();
// 记录重试次数
redisTemplate.opsForValue().set(
RETRY_KEY_PREFIX + messageId,
0,
24,
TimeUnit.HOURS
);
// 构建消息
MessageBuilder builder = MessageBuilder.withBody(JSON.toJSONString(message).getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_JSON)
.setDeliveryMode(MessageDeliveryMode.PERSISTENT)
.setMessageId(messageId);
// 发送消息
rabbitTemplate.send(
exchange,
routingKey,
builder.build(),
new CorrelationData(messageId)
);
}
/**
* 重试消息
*/
private void retryMessage(CorrelationData correlationData) {
String messageId = correlationData.getId();
String retryKey = RETRY_KEY_PREFIX + messageId;
Integer retryCount = (Integer) redisTemplate.opsForValue().get(retryKey);
if (retryCount == null) {
retryCount = 0;
}
if (retryCount < MAX_RETRY_COUNT) {
// 增加重试次数
redisTemplate.opsForValue().increment(retryKey);
// 从缓存中获取原始消息
String messageKey = "message:content:" + messageId;
Message originalMessage = (Message) redisTemplate.opsForValue().get(messageKey);
if (originalMessage != null) {
log.warn("消息重试 [{}/{}]: {}", retryCount + 1, MAX_RETRY_COUNT, messageId);
rabbitTemplate.send(
originalMessage.getMessageProperties().getReceivedExchange(),
originalMessage.getMessageProperties().getReceivedRoutingKey(),
originalMessage,
correlationData
);
}
} else {
log.error("消息超过最大重试次数,放弃: {}", messageId);
// 记录到数据库,人工介入
saveToDeadLetter(correlationData);
}
}
private void saveToDeadLetter(CorrelationData correlationData) {
// 实现持久化逻辑
}
} log.error("消息发送失败: {}, 原因: {}", correlationData, cause);`
`#/**
* 高可靠性生产者
*
* 特性:
* 1. 异步Confirm
* 2. 自动重试
* 3. 消息持久化
* 4. 唯一ID生成
*/
@Service
@Slf4j
public class ReliableProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String RETRY_KEY_PREFIX = "message:retry:";
private static final int MAX_RETRY_COUNT = 3;
@PostConstruct
public void init() {
// 设置异步Confirm回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
log.info("消息发送成功: {}", correlationData);
// 清除重试缓存
String messageId = correlationData.getId();
redisTemplate.delete(RETRY_KEY_PREFIX + messageId);
} else {
log.error("消息发送失败: {}, 原因: {}", correlationData, cause);
// 触发重试
retryMessage(correlationData);
}
});
}
/**
* 发送消息(自动重试)
*/
public void sendWithRetry(String exchange, String routingKey, Object message) {
String messageId = UUID.randomUUID().toString();
// 记录重试次数
redisTemplate.opsForValue().set(
RETRY_KEY_PREFIX + messageId,
0,
24,
TimeUnit.HOURS
);
// 构建消息
MessageBuilder builder = MessageBuilder.withBody(JSON.toJSONString(message).getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_JSON)
.setDeliveryMode(MessageDeliveryMode.PERSISTENT)
.setMessageId(messageId);
// 发送消息
rabbitTemplate.send(
exchange,
routingKey,
builder.build(),
new CorrelationData(messageId)
);
}
/**
* 重试消息
*/
private void retryMessage(CorrelationData correlationData) {
String messageId = correlationData.getId();
String retryKey = RETRY_KEY_PREFIX + messageId;
Integer retryCount = (Integer) redisTemplate.opsForValue().get(retryKey);
if (retryCount == null) {
retryCount = 0;
}
if (retryCount < MAX_RETRY_COUNT) {
// 增加重试次数
redisTemplate.opsForValue().increment(retryKey);
// 从缓存中获取原始消息
String messageKey = "message:content:" + messageId;
Message originalMessage = (Message) redisTemplate.opsForValue().get(messageKey);
if (originalMessage != null) {
log.warn("消息重试 [{}/{}]: {}", retryCount + 1, MAX_RETRY_COUNT, messageId);
rabbitTemplate.send(
originalMessage.getMessageProperties().getReceivedExchange(),
originalMessage.getMessageProperties().getReceivedRoutingKey(),
originalMessage,
correlationData
);
}
} else {
log.error("消息超过最大重试次数,放弃: {}", messageId);
// 记录到数据库,人工介入
saveToDeadLetter(correlationData);
}
}
private void saveToDeadLetter(CorrelationData correlationData) {
// 实现持久化逻辑
}
} // 触发重试`
`#/**
* 高可靠性生产者
*
* 特性:
* 1. 异步Confirm
* 2. 自动重试
* 3. 消息持久化
* 4. 唯一ID生成
*/
@Service
@Slf4j
public class ReliableProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String RETRY_KEY_PREFIX = "message:retry:";
private static final int MAX_RETRY_COUNT = 3;
@PostConstruct
public void init() {
// 设置异步Confirm回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
log.info("消息发送成功: {}", correlationData);
// 清除重试缓存
String messageId = correlationData.getId();
redisTemplate.delete(RETRY_KEY_PREFIX + messageId);
} else {
log.error("消息发送失败: {}, 原因: {}", correlationData, cause);
// 触发重试
retryMessage(correlationData);
}
});
}
/**
* 发送消息(自动重试)
*/
public void sendWithRetry(String exchange, String routingKey, Object message) {
String messageId = UUID.randomUUID().toString();
// 记录重试次数
redisTemplate.opsForValue().set(
RETRY_KEY_PREFIX + messageId,
0,
24,
TimeUnit.HOURS
);
// 构建消息
MessageBuilder builder = MessageBuilder.withBody(JSON.toJSONString(message).getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_JSON)
.setDeliveryMode(MessageDeliveryMode.PERSISTENT)
.setMessageId(messageId);
// 发送消息
rabbitTemplate.send(
exchange,
routingKey,
builder.build(),
new CorrelationData(messageId)
);
}
/**
* 重试消息
*/
private void retryMessage(CorrelationData correlationData) {
String messageId = correlationData.getId();
String retryKey = RETRY_KEY_PREFIX + messageId;
Integer retryCount = (Integer) redisTemplate.opsForValue().get(retryKey);
if (retryCount == null) {
retryCount = 0;
}
if (retryCount < MAX_RETRY_COUNT) {
// 增加重试次数
redisTemplate.opsForValue().increment(retryKey);
// 从缓存中获取原始消息
String messageKey = "message:content:" + messageId;
Message originalMessage = (Message) redisTemplate.opsForValue().get(messageKey);
if (originalMessage != null) {
log.warn("消息重试 [{}/{}]: {}", retryCount + 1, MAX_RETRY_COUNT, messageId);
rabbitTemplate.send(
originalMessage.getMessageProperties().getReceivedExchange(),
originalMessage.getMessageProperties().getReceivedRoutingKey(),
originalMessage,
correlationData
);
}
} else {
log.error("消息超过最大重试次数,放弃: {}", messageId);
// 记录到数据库,人工介入
saveToDeadLetter(correlationData);
}
}
private void saveToDeadLetter(CorrelationData correlationData) {
// 实现持久化逻辑
}
} retryMessage(correlationData);`
`#/**
* 高可靠性生产者
*
* 特性:
* 1. 异步Confirm
* 2. 自动重试
* 3. 消息持久化
* 4. 唯一ID生成
*/
@Service
@Slf4j
public class ReliableProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String RETRY_KEY_PREFIX = "message:retry:";
private static final int MAX_RETRY_COUNT = 3;
@PostConstruct
public void init() {
// 设置异步Confirm回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
log.info("消息发送成功: {}", correlationData);
// 清除重试缓存
String messageId = correlationData.getId();
redisTemplate.delete(RETRY_KEY_PREFIX + messageId);
} else {
log.error("消息发送失败: {}, 原因: {}", correlationData, cause);
// 触发重试
retryMessage(correlationData);
}
});
}
/**
* 发送消息(自动重试)
*/
public void sendWithRetry(String exchange, String routingKey, Object message) {
String messageId = UUID.randomUUID().toString();
// 记录重试次数
redisTemplate.opsForValue().set(
RETRY_KEY_PREFIX + messageId,
0,
24,
TimeUnit.HOURS
);
// 构建消息
MessageBuilder builder = MessageBuilder.withBody(JSON.toJSONString(message).getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_JSON)
.setDeliveryMode(MessageDeliveryMode.PERSISTENT)
.setMessageId(messageId);
// 发送消息
rabbitTemplate.send(
exchange,
routingKey,
builder.build(),
new CorrelationData(messageId)
);
}
/**
* 重试消息
*/
private void retryMessage(CorrelationData correlationData) {
String messageId = correlationData.getId();
String retryKey = RETRY_KEY_PREFIX + messageId;
Integer retryCount = (Integer) redisTemplate.opsForValue().get(retryKey);
if (retryCount == null) {
retryCount = 0;
}
if (retryCount < MAX_RETRY_COUNT) {
// 增加重试次数
redisTemplate.opsForValue().increment(retryKey);
// 从缓存中获取原始消息
String messageKey = "message:content:" + messageId;
Message originalMessage = (Message) redisTemplate.opsForValue().get(messageKey);
if (originalMessage != null) {
log.warn("消息重试 [{}/{}]: {}", retryCount + 1, MAX_RETRY_COUNT, messageId);
rabbitTemplate.send(
originalMessage.getMessageProperties().getReceivedExchange(),
originalMessage.getMessageProperties().getReceivedRoutingKey(),
originalMessage,
correlationData
);
}
} else {
log.error("消息超过最大重试次数,放弃: {}", messageId);
// 记录到数据库,人工介入
saveToDeadLetter(correlationData);
}
}
private void saveToDeadLetter(CorrelationData correlationData) {
// 实现持久化逻辑
}
} }`
`#/**
* 高可靠性生产者
*
* 特性:
* 1. 异步Confirm
* 2. 自动重试
* 3. 消息持久化
* 4. 唯一ID生成
*/
@Service
@Slf4j
public class ReliableProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String RETRY_KEY_PREFIX = "message:retry:";
private static final int MAX_RETRY_COUNT = 3;
@PostConstruct
public void init() {
// 设置异步Confirm回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
log.info("消息发送成功: {}", correlationData);
// 清除重试缓存
String messageId = correlationData.getId();
redisTemplate.delete(RETRY_KEY_PREFIX + messageId);
} else {
log.error("消息发送失败: {}, 原因: {}", correlationData, cause);
// 触发重试
retryMessage(correlationData);
}
});
}
/**
* 发送消息(自动重试)
*/
public void sendWithRetry(String exchange, String routingKey, Object message) {
String messageId = UUID.randomUUID().toString();
// 记录重试次数
redisTemplate.opsForValue().set(
RETRY_KEY_PREFIX + messageId,
0,
24,
TimeUnit.HOURS
);
// 构建消息
MessageBuilder builder = MessageBuilder.withBody(JSON.toJSONString(message).getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_JSON)
.setDeliveryMode(MessageDeliveryMode.PERSISTENT)
.setMessageId(messageId);
// 发送消息
rabbitTemplate.send(
exchange,
routingKey,
builder.build(),
new CorrelationData(messageId)
);
}
/**
* 重试消息
*/
private void retryMessage(CorrelationData correlationData) {
String messageId = correlationData.getId();
String retryKey = RETRY_KEY_PREFIX + messageId;
Integer retryCount = (Integer) redisTemplate.opsForValue().get(retryKey);
if (retryCount == null) {
retryCount = 0;
}
if (retryCount < MAX_RETRY_COUNT) {
// 增加重试次数
redisTemplate.opsForValue().increment(retryKey);
// 从缓存中获取原始消息
String messageKey = "message:content:" + messageId;
Message originalMessage = (Message) redisTemplate.opsForValue().get(messageKey);
if (originalMessage != null) {
log.warn("消息重试 [{}/{}]: {}", retryCount + 1, MAX_RETRY_COUNT, messageId);
rabbitTemplate.send(
originalMessage.getMessageProperties().getReceivedExchange(),
originalMessage.getMessageProperties().getReceivedRoutingKey(),
originalMessage,
correlationData
);
}
} else {
log.error("消息超过最大重试次数,放弃: {}", messageId);
// 记录到数据库,人工介入
saveToDeadLetter(correlationData);
}
}
private void saveToDeadLetter(CorrelationData correlationData) {
// 实现持久化逻辑
}
} });`
`#/**
* 高可靠性生产者
*
* 特性:
* 1. 异步Confirm
* 2. 自动重试
* 3. 消息持久化
* 4. 唯一ID生成
*/
@Service
@Slf4j
public class ReliableProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String RETRY_KEY_PREFIX = "message:retry:";
private static final int MAX_RETRY_COUNT = 3;
@PostConstruct
public void init() {
// 设置异步Confirm回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
log.info("消息发送成功: {}", correlationData);
// 清除重试缓存
String messageId = correlationData.getId();
redisTemplate.delete(RETRY_KEY_PREFIX + messageId);
} else {
log.error("消息发送失败: {}, 原因: {}", correlationData, cause);
// 触发重试
retryMessage(correlationData);
}
});
}
/**
* 发送消息(自动重试)
*/
public void sendWithRetry(String exchange, String routingKey, Object message) {
String messageId = UUID.randomUUID().toString();
// 记录重试次数
redisTemplate.opsForValue().set(
RETRY_KEY_PREFIX + messageId,
0,
24,
TimeUnit.HOURS
);
// 构建消息
MessageBuilder builder = MessageBuilder.withBody(JSON.toJSONString(message).getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_JSON)
.setDeliveryMode(MessageDeliveryMode.PERSISTENT)
.setMessageId(messageId);
// 发送消息
rabbitTemplate.send(
exchange,
routingKey,
builder.build(),
new CorrelationData(messageId)
);
}
/**
* 重试消息
*/
private void retryMessage(CorrelationData correlationData) {
String messageId = correlationData.getId();
String retryKey = RETRY_KEY_PREFIX + messageId;
Integer retryCount = (Integer) redisTemplate.opsForValue().get(retryKey);
if (retryCount == null) {
retryCount = 0;
}
if (retryCount < MAX_RETRY_COUNT) {
// 增加重试次数
redisTemplate.opsForValue().increment(retryKey);
// 从缓存中获取原始消息
String messageKey = "message:content:" + messageId;
Message originalMessage = (Message) redisTemplate.opsForValue().get(messageKey);
if (originalMessage != null) {
log.warn("消息重试 [{}/{}]: {}", retryCount + 1, MAX_RETRY_COUNT, messageId);
rabbitTemplate.send(
originalMessage.getMessageProperties().getReceivedExchange(),
originalMessage.getMessageProperties().getReceivedRoutingKey(),
originalMessage,
correlationData
);
}
} else {
log.error("消息超过最大重试次数,放弃: {}", messageId);
// 记录到数据库,人工介入
saveToDeadLetter(correlationData);
}
}
private void saveToDeadLetter(CorrelationData correlationData) {
// 实现持久化逻辑
}
} }`
`#/**
* 高可靠性生产者
*
* 特性:
* 1. 异步Confirm
* 2. 自动重试
* 3. 消息持久化
* 4. 唯一ID生成
*/
@Service
@Slf4j
public class ReliableProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String RETRY_KEY_PREFIX = "message:retry:";
private static final int MAX_RETRY_COUNT = 3;
@PostConstruct
public void init() {
// 设置异步Confirm回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
log.info("消息发送成功: {}", correlationData);
// 清除重试缓存
String messageId = correlationData.getId();
redisTemplate.delete(RETRY_KEY_PREFIX + messageId);
} else {
log.error("消息发送失败: {}, 原因: {}", correlationData, cause);
// 触发重试
retryMessage(correlationData);
}
});
}
/**
* 发送消息(自动重试)
*/
public void sendWithRetry(String exchange, String routingKey, Object message) {
String messageId = UUID.randomUUID().toString();
// 记录重试次数
redisTemplate.opsForValue().set(
RETRY_KEY_PREFIX + messageId,
0,
24,
TimeUnit.HOURS
);
// 构建消息
MessageBuilder builder = MessageBuilder.withBody(JSON.toJSONString(message).getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_JSON)
.setDeliveryMode(MessageDeliveryMode.PERSISTENT)
.setMessageId(messageId);
// 发送消息
rabbitTemplate.send(
exchange,
routingKey,
builder.build(),
new CorrelationData(messageId)
);
}
/**
* 重试消息
*/
private void retryMessage(CorrelationData correlationData) {
String messageId = correlationData.getId();
String retryKey = RETRY_KEY_PREFIX + messageId;
Integer retryCount = (Integer) redisTemplate.opsForValue().get(retryKey);
if (retryCount == null) {
retryCount = 0;
}
if (retryCount < MAX_RETRY_COUNT) {
// 增加重试次数
redisTemplate.opsForValue().increment(retryKey);
// 从缓存中获取原始消息
String messageKey = "message:content:" + messageId;
Message originalMessage = (Message) redisTemplate.opsForValue().get(messageKey);
if (originalMessage != null) {
log.warn("消息重试 [{}/{}]: {}", retryCount + 1, MAX_RETRY_COUNT, messageId);
rabbitTemplate.send(
originalMessage.getMessageProperties().getReceivedExchange(),
originalMessage.getMessageProperties().getReceivedRoutingKey(),
originalMessage,
correlationData
);
}
} else {
log.error("消息超过最大重试次数,放弃: {}", messageId);
// 记录到数据库,人工介入
saveToDeadLetter(correlationData);
}
}
private void saveToDeadLetter(CorrelationData correlationData) {
// 实现持久化逻辑
}
}`
`#/**
* 高可靠性生产者
*
* 特性:
* 1. 异步Confirm
* 2. 自动重试
* 3. 消息持久化
* 4. 唯一ID生成
*/
@Service
@Slf4j
public class ReliableProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String RETRY_KEY_PREFIX = "message:retry:";
private static final int MAX_RETRY_COUNT = 3;
@PostConstruct
public void init() {
// 设置异步Confirm回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
log.info("消息发送成功: {}", correlationData);
// 清除重试缓存
String messageId = correlationData.getId();
redisTemplate.delete(RETRY_KEY_PREFIX + messageId);
} else {
log.error("消息发送失败: {}, 原因: {}", correlationData, cause);
// 触发重试
retryMessage(correlationData);
}
});
}
/**
* 发送消息(自动重试)
*/
public void sendWithRetry(String exchange, String routingKey, Object message) {
String messageId = UUID.randomUUID().toString();
// 记录重试次数
redisTemplate.opsForValue().set(
RETRY_KEY_PREFIX + messageId,
0,
24,
TimeUnit.HOURS
);
// 构建消息
MessageBuilder builder = MessageBuilder.withBody(JSON.toJSONString(message).getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_JSON)
.setDeliveryMode(MessageDeliveryMode.PERSISTENT)
.setMessageId(messageId);
// 发送消息
rabbitTemplate.send(
exchange,
routingKey,
builder.build(),
new CorrelationData(messageId)
);
}
/**
* 重试消息
*/
private void retryMessage(CorrelationData correlationData) {
String messageId = correlationData.getId();
String retryKey = RETRY_KEY_PREFIX + messageId;
Integer retryCount = (Integer) redisTemplate.opsForValue().get(retryKey);
if (retryCount == null) {
retryCount = 0;
}
if (retryCount < MAX_RETRY_COUNT) {
// 增加重试次数
redisTemplate.opsForValue().increment(retryKey);
// 从缓存中获取原始消息
String messageKey = "message:content:" + messageId;
Message originalMessage = (Message) redisTemplate.opsForValue().get(messageKey);
if (originalMessage != null) {
log.warn("消息重试 [{}/{}]: {}", retryCount + 1, MAX_RETRY_COUNT, messageId);
rabbitTemplate.send(
originalMessage.getMessageProperties().getReceivedExchange(),
originalMessage.getMessageProperties().getReceivedRoutingKey(),
originalMessage,
correlationData
);
}
} else {
log.error("消息超过最大重试次数,放弃: {}", messageId);
// 记录到数据库,人工介入
saveToDeadLetter(correlationData);
}
}
private void saveToDeadLetter(CorrelationData correlationData) {
// 实现持久化逻辑
}
} /**`
`#/**
* 高可靠性生产者
*
* 特性:
* 1. 异步Confirm
* 2. 自动重试
* 3. 消息持久化
* 4. 唯一ID生成
*/
@Service
@Slf4j
public class ReliableProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String RETRY_KEY_PREFIX = "message:retry:";
private static final int MAX_RETRY_COUNT = 3;
@PostConstruct
public void init() {
// 设置异步Confirm回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
log.info("消息发送成功: {}", correlationData);
// 清除重试缓存
String messageId = correlationData.getId();
redisTemplate.delete(RETRY_KEY_PREFIX + messageId);
} else {
log.error("消息发送失败: {}, 原因: {}", correlationData, cause);
// 触发重试
retryMessage(correlationData);
}
});
}
/**
* 发送消息(自动重试)
*/
public void sendWithRetry(String exchange, String routingKey, Object message) {
String messageId = UUID.randomUUID().toString();
// 记录重试次数
redisTemplate.opsForValue().set(
RETRY_KEY_PREFIX + messageId,
0,
24,
TimeUnit.HOURS
);
// 构建消息
MessageBuilder builder = MessageBuilder.withBody(JSON.toJSONString(message).getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_JSON)
.setDeliveryMode(MessageDeliveryMode.PERSISTENT)
.setMessageId(messageId);
// 发送消息
rabbitTemplate.send(
exchange,
routingKey,
builder.build(),
new CorrelationData(messageId)
);
}
/**
* 重试消息
*/
private void retryMessage(CorrelationData correlationData) {
String messageId = correlationData.getId();
String retryKey = RETRY_KEY_PREFIX + messageId;
Integer retryCount = (Integer) redisTemplate.opsForValue().get(retryKey);
if (retryCount == null) {
retryCount = 0;
}
if (retryCount < MAX_RETRY_COUNT) {
// 增加重试次数
redisTemplate.opsForValue().increment(retryKey);
// 从缓存中获取原始消息
String messageKey = "message:content:" + messageId;
Message originalMessage = (Message) redisTemplate.opsForValue().get(messageKey);
if (originalMessage != null) {
log.warn("消息重试 [{}/{}]: {}", retryCount + 1, MAX_RETRY_COUNT, messageId);
rabbitTemplate.send(
originalMessage.getMessageProperties().getReceivedExchange(),
originalMessage.getMessageProperties().getReceivedRoutingKey(),
originalMessage,
correlationData
);
}
} else {
log.error("消息超过最大重试次数,放弃: {}", messageId);
// 记录到数据库,人工介入
saveToDeadLetter(correlationData);
}
}
private void saveToDeadLetter(CorrelationData correlationData) {
// 实现持久化逻辑
}
} * 发送消息(自动重试)`
`#/**
* 高可靠性生产者
*
* 特性:
* 1. 异步Confirm
* 2. 自动重试
* 3. 消息持久化
* 4. 唯一ID生成
*/
@Service
@Slf4j
public class ReliableProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String RETRY_KEY_PREFIX = "message:retry:";
private static final int MAX_RETRY_COUNT = 3;
@PostConstruct
public void init() {
// 设置异步Confirm回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
log.info("消息发送成功: {}", correlationData);
// 清除重试缓存
String messageId = correlationData.getId();
redisTemplate.delete(RETRY_KEY_PREFIX + messageId);
} else {
log.error("消息发送失败: {}, 原因: {}", correlationData, cause);
// 触发重试
retryMessage(correlationData);
}
});
}
/**
* 发送消息(自动重试)
*/
public void sendWithRetry(String exchange, String routingKey, Object message) {
String messageId = UUID.randomUUID().toString();
// 记录重试次数
redisTemplate.opsForValue().set(
RETRY_KEY_PREFIX + messageId,
0,
24,
TimeUnit.HOURS
);
// 构建消息
MessageBuilder builder = MessageBuilder.withBody(JSON.toJSONString(message).getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_JSON)
.setDeliveryMode(MessageDeliveryMode.PERSISTENT)
.setMessageId(messageId);
// 发送消息
rabbitTemplate.send(
exchange,
routingKey,
builder.build(),
new CorrelationData(messageId)
);
}
/**
* 重试消息
*/
private void retryMessage(CorrelationData correlationData) {
String messageId = correlationData.getId();
String retryKey = RETRY_KEY_PREFIX + messageId;
Integer retryCount = (Integer) redisTemplate.opsForValue().get(retryKey);
if (retryCount == null) {
retryCount = 0;
}
if (retryCount < MAX_RETRY_COUNT) {
// 增加重试次数
redisTemplate.opsForValue().increment(retryKey);
// 从缓存中获取原始消息
String messageKey = "message:content:" + messageId;
Message originalMessage = (Message) redisTemplate.opsForValue().get(messageKey);
if (originalMessage != null) {
log.warn("消息重试 [{}/{}]: {}", retryCount + 1, MAX_RETRY_COUNT, messageId);
rabbitTemplate.send(
originalMessage.getMessageProperties().getReceivedExchange(),
originalMessage.getMessageProperties().getReceivedRoutingKey(),
originalMessage,
correlationData
);
}
} else {
log.error("消息超过最大重试次数,放弃: {}", messageId);
// 记录到数据库,人工介入
saveToDeadLetter(correlationData);
}
}
private void saveToDeadLetter(CorrelationData correlationData) {
// 实现持久化逻辑
}
} */`
`#/**
* 高可靠性生产者
*
* 特性:
* 1. 异步Confirm
* 2. 自动重试
* 3. 消息持久化
* 4. 唯一ID生成
*/
@Service
@Slf4j
public class ReliableProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String RETRY_KEY_PREFIX = "message:retry:";
private static final int MAX_RETRY_COUNT = 3;
@PostConstruct
public void init() {
// 设置异步Confirm回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
log.info("消息发送成功: {}", correlationData);
// 清除重试缓存
String messageId = correlationData.getId();
redisTemplate.delete(RETRY_KEY_PREFIX + messageId);
} else {
log.error("消息发送失败: {}, 原因: {}", correlationData, cause);
// 触发重试
retryMessage(correlationData);
}
});
}
/**
* 发送消息(自动重试)
*/
public void sendWithRetry(String exchange, String routingKey, Object message) {
String messageId = UUID.randomUUID().toString();
// 记录重试次数
redisTemplate.opsForValue().set(
RETRY_KEY_PREFIX + messageId,
0,
24,
TimeUnit.HOURS
);
// 构建消息
MessageBuilder builder = MessageBuilder.withBody(JSON.toJSONString(message).getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_JSON)
.setDeliveryMode(MessageDeliveryMode.PERSISTENT)
.setMessageId(messageId);
// 发送消息
rabbitTemplate.send(
exchange,
routingKey,
builder.build(),
new CorrelationData(messageId)
);
}
/**
* 重试消息
*/
private void retryMessage(CorrelationData correlationData) {
String messageId = correlationData.getId();
String retryKey = RETRY_KEY_PREFIX + messageId;
Integer retryCount = (Integer) redisTemplate.opsForValue().get(retryKey);
if (retryCount == null) {
retryCount = 0;
}
if (retryCount < MAX_RETRY_COUNT) {
// 增加重试次数
redisTemplate.opsForValue().increment(retryKey);
// 从缓存中获取原始消息
String messageKey = "message:content:" + messageId;
Message originalMessage = (Message) redisTemplate.opsForValue().get(messageKey);
if (originalMessage != null) {
log.warn("消息重试 [{}/{}]: {}", retryCount + 1, MAX_RETRY_COUNT, messageId);
rabbitTemplate.send(
originalMessage.getMessageProperties().getReceivedExchange(),
originalMessage.getMessageProperties().getReceivedRoutingKey(),
originalMessage,
correlationData
);
}
} else {
log.error("消息超过最大重试次数,放弃: {}", messageId);
// 记录到数据库,人工介入
saveToDeadLetter(correlationData);
}
}
private void saveToDeadLetter(CorrelationData correlationData) {
// 实现持久化逻辑
}
} public void sendWithRetry(String exchange, String routingKey, Object message) {`
`#/**
* 高可靠性生产者
*
* 特性:
* 1. 异步Confirm
* 2. 自动重试
* 3. 消息持久化
* 4. 唯一ID生成
*/
@Service
@Slf4j
public class ReliableProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String RETRY_KEY_PREFIX = "message:retry:";
private static final int MAX_RETRY_COUNT = 3;
@PostConstruct
public void init() {
// 设置异步Confirm回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
log.info("消息发送成功: {}", correlationData);
// 清除重试缓存
String messageId = correlationData.getId();
redisTemplate.delete(RETRY_KEY_PREFIX + messageId);
} else {
log.error("消息发送失败: {}, 原因: {}", correlationData, cause);
// 触发重试
retryMessage(correlationData);
}
});
}
/**
* 发送消息(自动重试)
*/
public void sendWithRetry(String exchange, String routingKey, Object message) {
String messageId = UUID.randomUUID().toString();
// 记录重试次数
redisTemplate.opsForValue().set(
RETRY_KEY_PREFIX + messageId,
0,
24,
TimeUnit.HOURS
);
// 构建消息
MessageBuilder builder = MessageBuilder.withBody(JSON.toJSONString(message).getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_JSON)
.setDeliveryMode(MessageDeliveryMode.PERSISTENT)
.setMessageId(messageId);
// 发送消息
rabbitTemplate.send(
exchange,
routingKey,
builder.build(),
new CorrelationData(messageId)
);
}
/**
* 重试消息
*/
private void retryMessage(CorrelationData correlationData) {
String messageId = correlationData.getId();
String retryKey = RETRY_KEY_PREFIX + messageId;
Integer retryCount = (Integer) redisTemplate.opsForValue().get(retryKey);
if (retryCount == null) {
retryCount = 0;
}
if (retryCount < MAX_RETRY_COUNT) {
// 增加重试次数
redisTemplate.opsForValue().increment(retryKey);
// 从缓存中获取原始消息
String messageKey = "message:content:" + messageId;
Message originalMessage = (Message) redisTemplate.opsForValue().get(messageKey);
if (originalMessage != null) {
log.warn("消息重试 [{}/{}]: {}", retryCount + 1, MAX_RETRY_COUNT, messageId);
rabbitTemplate.send(
originalMessage.getMessageProperties().getReceivedExchange(),
originalMessage.getMessageProperties().getReceivedRoutingKey(),
originalMessage,
correlationData
);
}
} else {
log.error("消息超过最大重试次数,放弃: {}", messageId);
// 记录到数据库,人工介入
saveToDeadLetter(correlationData);
}
}
private void saveToDeadLetter(CorrelationData correlationData) {
// 实现持久化逻辑
}
} String messageId = UUID.randomUUID().toString();`
`#/**
* 高可靠性生产者
*
* 特性:
* 1. 异步Confirm
* 2. 自动重试
* 3. 消息持久化
* 4. 唯一ID生成
*/
@Service
@Slf4j
public class ReliableProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String RETRY_KEY_PREFIX = "message:retry:";
private static final int MAX_RETRY_COUNT = 3;
@PostConstruct
public void init() {
// 设置异步Confirm回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
log.info("消息发送成功: {}", correlationData);
// 清除重试缓存
String messageId = correlationData.getId();
redisTemplate.delete(RETRY_KEY_PREFIX + messageId);
} else {
log.error("消息发送失败: {}, 原因: {}", correlationData, cause);
// 触发重试
retryMessage(correlationData);
}
});
}
/**
* 发送消息(自动重试)
*/
public void sendWithRetry(String exchange, String routingKey, Object message) {
String messageId = UUID.randomUUID().toString();
// 记录重试次数
redisTemplate.opsForValue().set(
RETRY_KEY_PREFIX + messageId,
0,
24,
TimeUnit.HOURS
);
// 构建消息
MessageBuilder builder = MessageBuilder.withBody(JSON.toJSONString(message).getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_JSON)
.setDeliveryMode(MessageDeliveryMode.PERSISTENT)
.setMessageId(messageId);
// 发送消息
rabbitTemplate.send(
exchange,
routingKey,
builder.build(),
new CorrelationData(messageId)
);
}
/**
* 重试消息
*/
private void retryMessage(CorrelationData correlationData) {
String messageId = correlationData.getId();
String retryKey = RETRY_KEY_PREFIX + messageId;
Integer retryCount = (Integer) redisTemplate.opsForValue().get(retryKey);
if (retryCount == null) {
retryCount = 0;
}
if (retryCount < MAX_RETRY_COUNT) {
// 增加重试次数
redisTemplate.opsForValue().increment(retryKey);
// 从缓存中获取原始消息
String messageKey = "message:content:" + messageId;
Message originalMessage = (Message) redisTemplate.opsForValue().get(messageKey);
if (originalMessage != null) {
log.warn("消息重试 [{}/{}]: {}", retryCount + 1, MAX_RETRY_COUNT, messageId);
rabbitTemplate.send(
originalMessage.getMessageProperties().getReceivedExchange(),
originalMessage.getMessageProperties().getReceivedRoutingKey(),
originalMessage,
correlationData
);
}
} else {
log.error("消息超过最大重试次数,放弃: {}", messageId);
// 记录到数据库,人工介入
saveToDeadLetter(correlationData);
}
}
private void saveToDeadLetter(CorrelationData correlationData) {
// 实现持久化逻辑
}
} `
`#/**
* 高可靠性生产者
*
* 特性:
* 1. 异步Confirm
* 2. 自动重试
* 3. 消息持久化
* 4. 唯一ID生成
*/
@Service
@Slf4j
public class ReliableProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String RETRY_KEY_PREFIX = "message:retry:";
private static final int MAX_RETRY_COUNT = 3;
@PostConstruct
public void init() {
// 设置异步Confirm回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
log.info("消息发送成功: {}", correlationData);
// 清除重试缓存
String messageId = correlationData.getId();
redisTemplate.delete(RETRY_KEY_PREFIX + messageId);
} else {
log.error("消息发送失败: {}, 原因: {}", correlationData, cause);
// 触发重试
retryMessage(correlationData);
}
});
}
/**
* 发送消息(自动重试)
*/
public void sendWithRetry(String exchange, String routingKey, Object message) {
String messageId = UUID.randomUUID().toString();
// 记录重试次数
redisTemplate.opsForValue().set(
RETRY_KEY_PREFIX + messageId,
0,
24,
TimeUnit.HOURS
);
// 构建消息
MessageBuilder builder = MessageBuilder.withBody(JSON.toJSONString(message).getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_JSON)
.setDeliveryMode(MessageDeliveryMode.PERSISTENT)
.setMessageId(messageId);
// 发送消息
rabbitTemplate.send(
exchange,
routingKey,
builder.build(),
new CorrelationData(messageId)
);
}
/**
* 重试消息
*/
private void retryMessage(CorrelationData correlationData) {
String messageId = correlationData.getId();
String retryKey = RETRY_KEY_PREFIX + messageId;
Integer retryCount = (Integer) redisTemplate.opsForValue().get(retryKey);
if (retryCount == null) {
retryCount = 0;
}
if (retryCount < MAX_RETRY_COUNT) {
// 增加重试次数
redisTemplate.opsForValue().increment(retryKey);
// 从缓存中获取原始消息
String messageKey = "message:content:" + messageId;
Message originalMessage = (Message) redisTemplate.opsForValue().get(messageKey);
if (originalMessage != null) {
log.warn("消息重试 [{}/{}]: {}", retryCount + 1, MAX_RETRY_COUNT, messageId);
rabbitTemplate.send(
originalMessage.getMessageProperties().getReceivedExchange(),
originalMessage.getMessageProperties().getReceivedRoutingKey(),
originalMessage,
correlationData
);
}
} else {
log.error("消息超过最大重试次数,放弃: {}", messageId);
// 记录到数据库,人工介入
saveToDeadLetter(correlationData);
}
}
private void saveToDeadLetter(CorrelationData correlationData) {
// 实现持久化逻辑
}
} // 记录重试次数`
`#/**
* 高可靠性生产者
*
* 特性:
* 1. 异步Confirm
* 2. 自动重试
* 3. 消息持久化
* 4. 唯一ID生成
*/
@Service
@Slf4j
public class ReliableProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String RETRY_KEY_PREFIX = "message:retry:";
private static final int MAX_RETRY_COUNT = 3;
@PostConstruct
public void init() {
// 设置异步Confirm回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
log.info("消息发送成功: {}", correlationData);
// 清除重试缓存
String messageId = correlationData.getId();
redisTemplate.delete(RETRY_KEY_PREFIX + messageId);
} else {
log.error("消息发送失败: {}, 原因: {}", correlationData, cause);
// 触发重试
retryMessage(correlationData);
}
});
}
/**
* 发送消息(自动重试)
*/
public void sendWithRetry(String exchange, String routingKey, Object message) {
String messageId = UUID.randomUUID().toString();
// 记录重试次数
redisTemplate.opsForValue().set(
RETRY_KEY_PREFIX + messageId,
0,
24,
TimeUnit.HOURS
);
// 构建消息
MessageBuilder builder = MessageBuilder.withBody(JSON.toJSONString(message).getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_JSON)
.setDeliveryMode(MessageDeliveryMode.PERSISTENT)
.setMessageId(messageId);
// 发送消息
rabbitTemplate.send(
exchange,
routingKey,
builder.build(),
new CorrelationData(messageId)
);
}
/**
* 重试消息
*/
private void retryMessage(CorrelationData correlationData) {
String messageId = correlationData.getId();
String retryKey = RETRY_KEY_PREFIX + messageId;
Integer retryCount = (Integer) redisTemplate.opsForValue().get(retryKey);
if (retryCount == null) {
retryCount = 0;
}
if (retryCount < MAX_RETRY_COUNT) {
// 增加重试次数
redisTemplate.opsForValue().increment(retryKey);
// 从缓存中获取原始消息
String messageKey = "message:content:" + messageId;
Message originalMessage = (Message) redisTemplate.opsForValue().get(messageKey);
if (originalMessage != null) {
log.warn("消息重试 [{}/{}]: {}", retryCount + 1, MAX_RETRY_COUNT, messageId);
rabbitTemplate.send(
originalMessage.getMessageProperties().getReceivedExchange(),
originalMessage.getMessageProperties().getReceivedRoutingKey(),
originalMessage,
correlationData
);
}
} else {
log.error("消息超过最大重试次数,放弃: {}", messageId);
// 记录到数据库,人工介入
saveToDeadLetter(correlationData);
}
}
private void saveToDeadLetter(CorrelationData correlationData) {
// 实现持久化逻辑
}
} redisTemplate.opsForValue().set(`
`#/**
* 高可靠性生产者
*
* 特性:
* 1. 异步Confirm
* 2. 自动重试
* 3. 消息持久化
* 4. 唯一ID生成
*/
@Service
@Slf4j
public class ReliableProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String RETRY_KEY_PREFIX = "message:retry:";
private static final int MAX_RETRY_COUNT = 3;
@PostConstruct
public void init() {
// 设置异步Confirm回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
log.info("消息发送成功: {}", correlationData);
// 清除重试缓存
String messageId = correlationData.getId();
redisTemplate.delete(RETRY_KEY_PREFIX + messageId);
} else {
log.error("消息发送失败: {}, 原因: {}", correlationData, cause);
// 触发重试
retryMessage(correlationData);
}
});
}
/**
* 发送消息(自动重试)
*/
public void sendWithRetry(String exchange, String routingKey, Object message) {
String messageId = UUID.randomUUID().toString();
// 记录重试次数
redisTemplate.opsForValue().set(
RETRY_KEY_PREFIX + messageId,
0,
24,
TimeUnit.HOURS
);
// 构建消息
MessageBuilder builder = MessageBuilder.withBody(JSON.toJSONString(message).getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_JSON)
.setDeliveryMode(MessageDeliveryMode.PERSISTENT)
.setMessageId(messageId);
// 发送消息
rabbitTemplate.send(
exchange,
routingKey,
builder.build(),
new CorrelationData(messageId)
);
}
/**
* 重试消息
*/
private void retryMessage(CorrelationData correlationData) {
String messageId = correlationData.getId();
String retryKey = RETRY_KEY_PREFIX + messageId;
Integer retryCount = (Integer) redisTemplate.opsForValue().get(retryKey);
if (retryCount == null) {
retryCount = 0;
}
if (retryCount < MAX_RETRY_COUNT) {
// 增加重试次数
redisTemplate.opsForValue().increment(retryKey);
// 从缓存中获取原始消息
String messageKey = "message:content:" + messageId;
Message originalMessage = (Message) redisTemplate.opsForValue().get(messageKey);
if (originalMessage != null) {
log.warn("消息重试 [{}/{}]: {}", retryCount + 1, MAX_RETRY_COUNT, messageId);
rabbitTemplate.send(
originalMessage.getMessageProperties().getReceivedExchange(),
originalMessage.getMessageProperties().getReceivedRoutingKey(),
originalMessage,
correlationData
);
}
} else {
log.error("消息超过最大重试次数,放弃: {}", messageId);
// 记录到数据库,人工介入
saveToDeadLetter(correlationData);
}
}
private void saveToDeadLetter(CorrelationData correlationData) {
// 实现持久化逻辑
}
} RETRY_KEY_PREFIX + messageId, `
`#/**
* 高可靠性生产者
*
* 特性:
* 1. 异步Confirm
* 2. 自动重试
* 3. 消息持久化
* 4. 唯一ID生成
*/
@Service
@Slf4j
public class ReliableProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String RETRY_KEY_PREFIX = "message:retry:";
private static final int MAX_RETRY_COUNT = 3;
@PostConstruct
public void init() {
// 设置异步Confirm回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
log.info("消息发送成功: {}", correlationData);
// 清除重试缓存
String messageId = correlationData.getId();
redisTemplate.delete(RETRY_KEY_PREFIX + messageId);
} else {
log.error("消息发送失败: {}, 原因: {}", correlationData, cause);
// 触发重试
retryMessage(correlationData);
}
});
}
/**
* 发送消息(自动重试)
*/
public void sendWithRetry(String exchange, String routingKey, Object message) {
String messageId = UUID.randomUUID().toString();
// 记录重试次数
redisTemplate.opsForValue().set(
RETRY_KEY_PREFIX + messageId,
0,
24,
TimeUnit.HOURS
);
// 构建消息
MessageBuilder builder = MessageBuilder.withBody(JSON.toJSONString(message).getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_JSON)
.setDeliveryMode(MessageDeliveryMode.PERSISTENT)
.setMessageId(messageId);
// 发送消息
rabbitTemplate.send(
exchange,
routingKey,
builder.build(),
new CorrelationData(messageId)
);
}
/**
* 重试消息
*/
private void retryMessage(CorrelationData correlationData) {
String messageId = correlationData.getId();
String retryKey = RETRY_KEY_PREFIX + messageId;
Integer retryCount = (Integer) redisTemplate.opsForValue().get(retryKey);
if (retryCount == null) {
retryCount = 0;
}
if (retryCount < MAX_RETRY_COUNT) {
// 增加重试次数
redisTemplate.opsForValue().increment(retryKey);
// 从缓存中获取原始消息
String messageKey = "message:content:" + messageId;
Message originalMessage = (Message) redisTemplate.opsForValue().get(messageKey);
if (originalMessage != null) {
log.warn("消息重试 [{}/{}]: {}", retryCount + 1, MAX_RETRY_COUNT, messageId);
rabbitTemplate.send(
originalMessage.getMessageProperties().getReceivedExchange(),
originalMessage.getMessageProperties().getReceivedRoutingKey(),
originalMessage,
correlationData
);
}
} else {
log.error("消息超过最大重试次数,放弃: {}", messageId);
// 记录到数据库,人工介入
saveToDeadLetter(correlationData);
}
}
private void saveToDeadLetter(CorrelationData correlationData) {
// 实现持久化逻辑
}
} 0, `
`#/**
* 高可靠性生产者
*
* 特性:
* 1. 异步Confirm
* 2. 自动重试
* 3. 消息持久化
* 4. 唯一ID生成
*/
@Service
@Slf4j
public class ReliableProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String RETRY_KEY_PREFIX = "message:retry:";
private static final int MAX_RETRY_COUNT = 3;
@PostConstruct
public void init() {
// 设置异步Confirm回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
log.info("消息发送成功: {}", correlationData);
// 清除重试缓存
String messageId = correlationData.getId();
redisTemplate.delete(RETRY_KEY_PREFIX + messageId);
} else {
log.error("消息发送失败: {}, 原因: {}", correlationData, cause);
// 触发重试
retryMessage(correlationData);
}
});
}
/**
* 发送消息(自动重试)
*/
public void sendWithRetry(String exchange, String routingKey, Object message) {
String messageId = UUID.randomUUID().toString();
// 记录重试次数
redisTemplate.opsForValue().set(
RETRY_KEY_PREFIX + messageId,
0,
24,
TimeUnit.HOURS
);
// 构建消息
MessageBuilder builder = MessageBuilder.withBody(JSON.toJSONString(message).getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_JSON)
.setDeliveryMode(MessageDeliveryMode.PERSISTENT)
.setMessageId(messageId);
// 发送消息
rabbitTemplate.send(
exchange,
routingKey,
builder.build(),
new CorrelationData(messageId)
);
}
/**
* 重试消息
*/
private void retryMessage(CorrelationData correlationData) {
String messageId = correlationData.getId();
String retryKey = RETRY_KEY_PREFIX + messageId;
Integer retryCount = (Integer) redisTemplate.opsForValue().get(retryKey);
if (retryCount == null) {
retryCount = 0;
}
if (retryCount < MAX_RETRY_COUNT) {
// 增加重试次数
redisTemplate.opsForValue().increment(retryKey);
// 从缓存中获取原始消息
String messageKey = "message:content:" + messageId;
Message originalMessage = (Message) redisTemplate.opsForValue().get(messageKey);
if (originalMessage != null) {
log.warn("消息重试 [{}/{}]: {}", retryCount + 1, MAX_RETRY_COUNT, messageId);
rabbitTemplate.send(
originalMessage.getMessageProperties().getReceivedExchange(),
originalMessage.getMessageProperties().getReceivedRoutingKey(),
originalMessage,
correlationData
);
}
} else {
log.error("消息超过最大重试次数,放弃: {}", messageId);
// 记录到数据库,人工介入
saveToDeadLetter(correlationData);
}
}
private void saveToDeadLetter(CorrelationData correlationData) {
// 实现持久化逻辑
}
} 24, `
`#/**
* 高可靠性生产者
*
* 特性:
* 1. 异步Confirm
* 2. 自动重试
* 3. 消息持久化
* 4. 唯一ID生成
*/
@Service
@Slf4j
public class ReliableProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String RETRY_KEY_PREFIX = "message:retry:";
private static final int MAX_RETRY_COUNT = 3;
@PostConstruct
public void init() {
// 设置异步Confirm回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
log.info("消息发送成功: {}", correlationData);
// 清除重试缓存
String messageId = correlationData.getId();
redisTemplate.delete(RETRY_KEY_PREFIX + messageId);
} else {
log.error("消息发送失败: {}, 原因: {}", correlationData, cause);
// 触发重试
retryMessage(correlationData);
}
});
}
/**
* 发送消息(自动重试)
*/
public void sendWithRetry(String exchange, String routingKey, Object message) {
String messageId = UUID.randomUUID().toString();
// 记录重试次数
redisTemplate.opsForValue().set(
RETRY_KEY_PREFIX + messageId,
0,
24,
TimeUnit.HOURS
);
// 构建消息
MessageBuilder builder = MessageBuilder.withBody(JSON.toJSONString(message).getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_JSON)
.setDeliveryMode(MessageDeliveryMode.PERSISTENT)
.setMessageId(messageId);
// 发送消息
rabbitTemplate.send(
exchange,
routingKey,
builder.build(),
new CorrelationData(messageId)
);
}
/**
* 重试消息
*/
private void retryMessage(CorrelationData correlationData) {
String messageId = correlationData.getId();
String retryKey = RETRY_KEY_PREFIX + messageId;
Integer retryCount = (Integer) redisTemplate.opsForValue().get(retryKey);
if (retryCount == null) {
retryCount = 0;
}
if (retryCount < MAX_RETRY_COUNT) {
// 增加重试次数
redisTemplate.opsForValue().increment(retryKey);
// 从缓存中获取原始消息
String messageKey = "message:content:" + messageId;
Message originalMessage = (Message) redisTemplate.opsForValue().get(messageKey);
if (originalMessage != null) {
log.warn("消息重试 [{}/{}]: {}", retryCount + 1, MAX_RETRY_COUNT, messageId);
rabbitTemplate.send(
originalMessage.getMessageProperties().getReceivedExchange(),
originalMessage.getMessageProperties().getReceivedRoutingKey(),
originalMessage,
correlationData
);
}
} else {
log.error("消息超过最大重试次数,放弃: {}", messageId);
// 记录到数据库,人工介入
saveToDeadLetter(correlationData);
}
}
private void saveToDeadLetter(CorrelationData correlationData) {
// 实现持久化逻辑
}
} TimeUnit.HOURS`
`#/**
* 高可靠性生产者
*
* 特性:
* 1. 异步Confirm
* 2. 自动重试
* 3. 消息持久化
* 4. 唯一ID生成
*/
@Service
@Slf4j
public class ReliableProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String RETRY_KEY_PREFIX = "message:retry:";
private static final int MAX_RETRY_COUNT = 3;
@PostConstruct
public void init() {
// 设置异步Confirm回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
log.info("消息发送成功: {}", correlationData);
// 清除重试缓存
String messageId = correlationData.getId();
redisTemplate.delete(RETRY_KEY_PREFIX + messageId);
} else {
log.error("消息发送失败: {}, 原因: {}", correlationData, cause);
// 触发重试
retryMessage(correlationData);
}
});
}
/**
* 发送消息(自动重试)
*/
public void sendWithRetry(String exchange, String routingKey, Object message) {
String messageId = UUID.randomUUID().toString();
// 记录重试次数
redisTemplate.opsForValue().set(
RETRY_KEY_PREFIX + messageId,
0,
24,
TimeUnit.HOURS
);
// 构建消息
MessageBuilder builder = MessageBuilder.withBody(JSON.toJSONString(message).getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_JSON)
.setDeliveryMode(MessageDeliveryMode.PERSISTENT)
.setMessageId(messageId);
// 发送消息
rabbitTemplate.send(
exchange,
routingKey,
builder.build(),
new CorrelationData(messageId)
);
}
/**
* 重试消息
*/
private void retryMessage(CorrelationData correlationData) {
String messageId = correlationData.getId();
String retryKey = RETRY_KEY_PREFIX + messageId;
Integer retryCount = (Integer) redisTemplate.opsForValue().get(retryKey);
if (retryCount == null) {
retryCount = 0;
}
if (retryCount < MAX_RETRY_COUNT) {
// 增加重试次数
redisTemplate.opsForValue().increment(retryKey);
// 从缓存中获取原始消息
String messageKey = "message:content:" + messageId;
Message originalMessage = (Message) redisTemplate.opsForValue().get(messageKey);
if (originalMessage != null) {
log.warn("消息重试 [{}/{}]: {}", retryCount + 1, MAX_RETRY_COUNT, messageId);
rabbitTemplate.send(
originalMessage.getMessageProperties().getReceivedExchange(),
originalMessage.getMessageProperties().getReceivedRoutingKey(),
originalMessage,
correlationData
);
}
} else {
log.error("消息超过最大重试次数,放弃: {}", messageId);
// 记录到数据库,人工介入
saveToDeadLetter(correlationData);
}
}
private void saveToDeadLetter(CorrelationData correlationData) {
// 实现持久化逻辑
}
} );`
`#/**
* 高可靠性生产者
*
* 特性:
* 1. 异步Confirm
* 2. 自动重试
* 3. 消息持久化
* 4. 唯一ID生成
*/
@Service
@Slf4j
public class ReliableProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String RETRY_KEY_PREFIX = "message:retry:";
private static final int MAX_RETRY_COUNT = 3;
@PostConstruct
public void init() {
// 设置异步Confirm回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
log.info("消息发送成功: {}", correlationData);
// 清除重试缓存
String messageId = correlationData.getId();
redisTemplate.delete(RETRY_KEY_PREFIX + messageId);
} else {
log.error("消息发送失败: {}, 原因: {}", correlationData, cause);
// 触发重试
retryMessage(correlationData);
}
});
}
/**
* 发送消息(自动重试)
*/
public void sendWithRetry(String exchange, String routingKey, Object message) {
String messageId = UUID.randomUUID().toString();
// 记录重试次数
redisTemplate.opsForValue().set(
RETRY_KEY_PREFIX + messageId,
0,
24,
TimeUnit.HOURS
);
// 构建消息
MessageBuilder builder = MessageBuilder.withBody(JSON.toJSONString(message).getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_JSON)
.setDeliveryMode(MessageDeliveryMode.PERSISTENT)
.setMessageId(messageId);
// 发送消息
rabbitTemplate.send(
exchange,
routingKey,
builder.build(),
new CorrelationData(messageId)
);
}
/**
* 重试消息
*/
private void retryMessage(CorrelationData correlationData) {
String messageId = correlationData.getId();
String retryKey = RETRY_KEY_PREFIX + messageId;
Integer retryCount = (Integer) redisTemplate.opsForValue().get(retryKey);
if (retryCount == null) {
retryCount = 0;
}
if (retryCount < MAX_RETRY_COUNT) {
// 增加重试次数
redisTemplate.opsForValue().increment(retryKey);
// 从缓存中获取原始消息
String messageKey = "message:content:" + messageId;
Message originalMessage = (Message) redisTemplate.opsForValue().get(messageKey);
if (originalMessage != null) {
log.warn("消息重试 [{}/{}]: {}", retryCount + 1, MAX_RETRY_COUNT, messageId);
rabbitTemplate.send(
originalMessage.getMessageProperties().getReceivedExchange(),
originalMessage.getMessageProperties().getReceivedRoutingKey(),
originalMessage,
correlationData
);
}
} else {
log.error("消息超过最大重试次数,放弃: {}", messageId);
// 记录到数据库,人工介入
saveToDeadLetter(correlationData);
}
}
private void saveToDeadLetter(CorrelationData correlationData) {
// 实现持久化逻辑
}
} `
`#/**
* 高可靠性生产者
*
* 特性:
* 1. 异步Confirm
* 2. 自动重试
* 3. 消息持久化
* 4. 唯一ID生成
*/
@Service
@Slf4j
public class ReliableProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String RETRY_KEY_PREFIX = "message:retry:";
private static final int MAX_RETRY_COUNT = 3;
@PostConstruct
public void init() {
// 设置异步Confirm回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
log.info("消息发送成功: {}", correlationData);
// 清除重试缓存
String messageId = correlationData.getId();
redisTemplate.delete(RETRY_KEY_PREFIX + messageId);
} else {
log.error("消息发送失败: {}, 原因: {}", correlationData, cause);
// 触发重试
retryMessage(correlationData);
}
});
}
/**
* 发送消息(自动重试)
*/
public void sendWithRetry(String exchange, String routingKey, Object message) {
String messageId = UUID.randomUUID().toString();
// 记录重试次数
redisTemplate.opsForValue().set(
RETRY_KEY_PREFIX + messageId,
0,
24,
TimeUnit.HOURS
);
// 构建消息
MessageBuilder builder = MessageBuilder.withBody(JSON.toJSONString(message).getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_JSON)
.setDeliveryMode(MessageDeliveryMode.PERSISTENT)
.setMessageId(messageId);
// 发送消息
rabbitTemplate.send(
exchange,
routingKey,
builder.build(),
new CorrelationData(messageId)
);
}
/**
* 重试消息
*/
private void retryMessage(CorrelationData correlationData) {
String messageId = correlationData.getId();
String retryKey = RETRY_KEY_PREFIX + messageId;
Integer retryCount = (Integer) redisTemplate.opsForValue().get(retryKey);
if (retryCount == null) {
retryCount = 0;
}
if (retryCount < MAX_RETRY_COUNT) {
// 增加重试次数
redisTemplate.opsForValue().increment(retryKey);
// 从缓存中获取原始消息
String messageKey = "message:content:" + messageId;
Message originalMessage = (Message) redisTemplate.opsForValue().get(messageKey);
if (originalMessage != null) {
log.warn("消息重试 [{}/{}]: {}", retryCount + 1, MAX_RETRY_COUNT, messageId);
rabbitTemplate.send(
originalMessage.getMessageProperties().getReceivedExchange(),
originalMessage.getMessageProperties().getReceivedRoutingKey(),
originalMessage,
correlationData
);
}
} else {
log.error("消息超过最大重试次数,放弃: {}", messageId);
// 记录到数据库,人工介入
saveToDeadLetter(correlationData);
}
}
private void saveToDeadLetter(CorrelationData correlationData) {
// 实现持久化逻辑
}
} // 构建消息`
`#/**
* 高可靠性生产者
*
* 特性:
* 1. 异步Confirm
* 2. 自动重试
* 3. 消息持久化
* 4. 唯一ID生成
*/
@Service
@Slf4j
public class ReliableProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String RETRY_KEY_PREFIX = "message:retry:";
private static final int MAX_RETRY_COUNT = 3;
@PostConstruct
public void init() {
// 设置异步Confirm回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
log.info("消息发送成功: {}", correlationData);
// 清除重试缓存
String messageId = correlationData.getId();
redisTemplate.delete(RETRY_KEY_PREFIX + messageId);
} else {
log.error("消息发送失败: {}, 原因: {}", correlationData, cause);
// 触发重试
retryMessage(correlationData);
}
});
}
/**
* 发送消息(自动重试)
*/
public void sendWithRetry(String exchange, String routingKey, Object message) {
String messageId = UUID.randomUUID().toString();
// 记录重试次数
redisTemplate.opsForValue().set(
RETRY_KEY_PREFIX + messageId,
0,
24,
TimeUnit.HOURS
);
// 构建消息
MessageBuilder builder = MessageBuilder.withBody(JSON.toJSONString(message).getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_JSON)
.setDeliveryMode(MessageDeliveryMode.PERSISTENT)
.setMessageId(messageId);
// 发送消息
rabbitTemplate.send(
exchange,
routingKey,
builder.build(),
new CorrelationData(messageId)
);
}
/**
* 重试消息
*/
private void retryMessage(CorrelationData correlationData) {
String messageId = correlationData.getId();
String retryKey = RETRY_KEY_PREFIX + messageId;
Integer retryCount = (Integer) redisTemplate.opsForValue().get(retryKey);
if (retryCount == null) {
retryCount = 0;
}
if (retryCount < MAX_RETRY_COUNT) {
// 增加重试次数
redisTemplate.opsForValue().increment(retryKey);
// 从缓存中获取原始消息
String messageKey = "message:content:" + messageId;
Message originalMessage = (Message) redisTemplate.opsForValue().get(messageKey);
if (originalMessage != null) {
log.warn("消息重试 [{}/{}]: {}", retryCount + 1, MAX_RETRY_COUNT, messageId);
rabbitTemplate.send(
originalMessage.getMessageProperties().getReceivedExchange(),
originalMessage.getMessageProperties().getReceivedRoutingKey(),
originalMessage,
correlationData
);
}
} else {
log.error("消息超过最大重试次数,放弃: {}", messageId);
// 记录到数据库,人工介入
saveToDeadLetter(correlationData);
}
}
private void saveToDeadLetter(CorrelationData correlationData) {
// 实现持久化逻辑
}
} MessageBuilder builder = MessageBuilder.withBody(JSON.toJSONString(message).getBytes())`
`#/**
* 高可靠性生产者
*
* 特性:
* 1. 异步Confirm
* 2. 自动重试
* 3. 消息持久化
* 4. 唯一ID生成
*/
@Service
@Slf4j
public class ReliableProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String RETRY_KEY_PREFIX = "message:retry:";
private static final int MAX_RETRY_COUNT = 3;
@PostConstruct
public void init() {
// 设置异步Confirm回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
log.info("消息发送成功: {}", correlationData);
// 清除重试缓存
String messageId = correlationData.getId();
redisTemplate.delete(RETRY_KEY_PREFIX + messageId);
} else {
log.error("消息发送失败: {}, 原因: {}", correlationData, cause);
// 触发重试
retryMessage(correlationData);
}
});
}
/**
* 发送消息(自动重试)
*/
public void sendWithRetry(String exchange, String routingKey, Object message) {
String messageId = UUID.randomUUID().toString();
// 记录重试次数
redisTemplate.opsForValue().set(
RETRY_KEY_PREFIX + messageId,
0,
24,
TimeUnit.HOURS
);
// 构建消息
MessageBuilder builder = MessageBuilder.withBody(JSON.toJSONString(message).getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_JSON)
.setDeliveryMode(MessageDeliveryMode.PERSISTENT)
.setMessageId(messageId);
// 发送消息
rabbitTemplate.send(
exchange,
routingKey,
builder.build(),
new CorrelationData(messageId)
);
}
/**
* 重试消息
*/
private void retryMessage(CorrelationData correlationData) {
String messageId = correlationData.getId();
String retryKey = RETRY_KEY_PREFIX + messageId;
Integer retryCount = (Integer) redisTemplate.opsForValue().get(retryKey);
if (retryCount == null) {
retryCount = 0;
}
if (retryCount < MAX_RETRY_COUNT) {
// 增加重试次数
redisTemplate.opsForValue().increment(retryKey);
// 从缓存中获取原始消息
String messageKey = "message:content:" + messageId;
Message originalMessage = (Message) redisTemplate.opsForValue().get(messageKey);
if (originalMessage != null) {
log.warn("消息重试 [{}/{}]: {}", retryCount + 1, MAX_RETRY_COUNT, messageId);
rabbitTemplate.send(
originalMessage.getMessageProperties().getReceivedExchange(),
originalMessage.getMessageProperties().getReceivedRoutingKey(),
originalMessage,
correlationData
);
}
} else {
log.error("消息超过最大重试次数,放弃: {}", messageId);
// 记录到数据库,人工介入
saveToDeadLetter(correlationData);
}
}
private void saveToDeadLetter(CorrelationData correlationData) {
// 实现持久化逻辑
}
} .setContentType(MessageProperties.CONTENT_TYPE_JSON)`
`#/**
* 高可靠性生产者
*
* 特性:
* 1. 异步Confirm
* 2. 自动重试
* 3. 消息持久化
* 4. 唯一ID生成
*/
@Service
@Slf4j
public class ReliableProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String RETRY_KEY_PREFIX = "message:retry:";
private static final int MAX_RETRY_COUNT = 3;
@PostConstruct
public void init() {
// 设置异步Confirm回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
log.info("消息发送成功: {}", correlationData);
// 清除重试缓存
String messageId = correlationData.getId();
redisTemplate.delete(RETRY_KEY_PREFIX + messageId);
} else {
log.error("消息发送失败: {}, 原因: {}", correlationData, cause);
// 触发重试
retryMessage(correlationData);
}
});
}
/**
* 发送消息(自动重试)
*/
public void sendWithRetry(String exchange, String routingKey, Object message) {
String messageId = UUID.randomUUID().toString();
// 记录重试次数
redisTemplate.opsForValue().set(
RETRY_KEY_PREFIX + messageId,
0,
24,
TimeUnit.HOURS
);
// 构建消息
MessageBuilder builder = MessageBuilder.withBody(JSON.toJSONString(message).getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_JSON)
.setDeliveryMode(MessageDeliveryMode.PERSISTENT)
.setMessageId(messageId);
// 发送消息
rabbitTemplate.send(
exchange,
routingKey,
builder.build(),
new CorrelationData(messageId)
);
}
/**
* 重试消息
*/
private void retryMessage(CorrelationData correlationData) {
String messageId = correlationData.getId();
String retryKey = RETRY_KEY_PREFIX + messageId;
Integer retryCount = (Integer) redisTemplate.opsForValue().get(retryKey);
if (retryCount == null) {
retryCount = 0;
}
if (retryCount < MAX_RETRY_COUNT) {
// 增加重试次数
redisTemplate.opsForValue().increment(retryKey);
// 从缓存中获取原始消息
String messageKey = "message:content:" + messageId;
Message originalMessage = (Message) redisTemplate.opsForValue().get(messageKey);
if (originalMessage != null) {
log.warn("消息重试 [{}/{}]: {}", retryCount + 1, MAX_RETRY_COUNT, messageId);
rabbitTemplate.send(
originalMessage.getMessageProperties().getReceivedExchange(),
originalMessage.getMessageProperties().getReceivedRoutingKey(),
originalMessage,
correlationData
);
}
} else {
log.error("消息超过最大重试次数,放弃: {}", messageId);
// 记录到数据库,人工介入
saveToDeadLetter(correlationData);
}
}
private void saveToDeadLetter(CorrelationData correlationData) {
// 实现持久化逻辑
}
} .setDeliveryMode(MessageDeliveryMode.PERSISTENT)`
`#/**
* 高可靠性生产者
*
* 特性:
* 1. 异步Confirm
* 2. 自动重试
* 3. 消息持久化
* 4. 唯一ID生成
*/
@Service
@Slf4j
public class ReliableProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String RETRY_KEY_PREFIX = "message:retry:";
private static final int MAX_RETRY_COUNT = 3;
@PostConstruct
public void init() {
// 设置异步Confirm回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
log.info("消息发送成功: {}", correlationData);
// 清除重试缓存
String messageId = correlationData.getId();
redisTemplate.delete(RETRY_KEY_PREFIX + messageId);
} else {
log.error("消息发送失败: {}, 原因: {}", correlationData, cause);
// 触发重试
retryMessage(correlationData);
}
});
}
/**
* 发送消息(自动重试)
*/
public void sendWithRetry(String exchange, String routingKey, Object message) {
String messageId = UUID.randomUUID().toString();
// 记录重试次数
redisTemplate.opsForValue().set(
RETRY_KEY_PREFIX + messageId,
0,
24,
TimeUnit.HOURS
);
// 构建消息
MessageBuilder builder = MessageBuilder.withBody(JSON.toJSONString(message).getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_JSON)
.setDeliveryMode(MessageDeliveryMode.PERSISTENT)
.setMessageId(messageId);
// 发送消息
rabbitTemplate.send(
exchange,
routingKey,
builder.build(),
new CorrelationData(messageId)
);
}
/**
* 重试消息
*/
private void retryMessage(CorrelationData correlationData) {
String messageId = correlationData.getId();
String retryKey = RETRY_KEY_PREFIX + messageId;
Integer retryCount = (Integer) redisTemplate.opsForValue().get(retryKey);
if (retryCount == null) {
retryCount = 0;
}
if (retryCount < MAX_RETRY_COUNT) {
// 增加重试次数
redisTemplate.opsForValue().increment(retryKey);
// 从缓存中获取原始消息
String messageKey = "message:content:" + messageId;
Message originalMessage = (Message) redisTemplate.opsForValue().get(messageKey);
if (originalMessage != null) {
log.warn("消息重试 [{}/{}]: {}", retryCount + 1, MAX_RETRY_COUNT, messageId);
rabbitTemplate.send(
originalMessage.getMessageProperties().getReceivedExchange(),
originalMessage.getMessageProperties().getReceivedRoutingKey(),
originalMessage,
correlationData
);
}
} else {
log.error("消息超过最大重试次数,放弃: {}", messageId);
// 记录到数据库,人工介入
saveToDeadLetter(correlationData);
}
}
private void saveToDeadLetter(CorrelationData correlationData) {
// 实现持久化逻辑
}
} .setMessageId(messageId);`
`#/**
* 高可靠性生产者
*
* 特性:
* 1. 异步Confirm
* 2. 自动重试
* 3. 消息持久化
* 4. 唯一ID生成
*/
@Service
@Slf4j
public class ReliableProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String RETRY_KEY_PREFIX = "message:retry:";
private static final int MAX_RETRY_COUNT = 3;
@PostConstruct
public void init() {
// 设置异步Confirm回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
log.info("消息发送成功: {}", correlationData);
// 清除重试缓存
String messageId = correlationData.getId();
redisTemplate.delete(RETRY_KEY_PREFIX + messageId);
} else {
log.error("消息发送失败: {}, 原因: {}", correlationData, cause);
// 触发重试
retryMessage(correlationData);
}
});
}
/**
* 发送消息(自动重试)
*/
public void sendWithRetry(String exchange, String routingKey, Object message) {
String messageId = UUID.randomUUID().toString();
// 记录重试次数
redisTemplate.opsForValue().set(
RETRY_KEY_PREFIX + messageId,
0,
24,
TimeUnit.HOURS
);
// 构建消息
MessageBuilder builder = MessageBuilder.withBody(JSON.toJSONString(message).getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_JSON)
.setDeliveryMode(MessageDeliveryMode.PERSISTENT)
.setMessageId(messageId);
// 发送消息
rabbitTemplate.send(
exchange,
routingKey,
builder.build(),
new CorrelationData(messageId)
);
}
/**
* 重试消息
*/
private void retryMessage(CorrelationData correlationData) {
String messageId = correlationData.getId();
String retryKey = RETRY_KEY_PREFIX + messageId;
Integer retryCount = (Integer) redisTemplate.opsForValue().get(retryKey);
if (retryCount == null) {
retryCount = 0;
}
if (retryCount < MAX_RETRY_COUNT) {
// 增加重试次数
redisTemplate.opsForValue().increment(retryKey);
// 从缓存中获取原始消息
String messageKey = "message:content:" + messageId;
Message originalMessage = (Message) redisTemplate.opsForValue().get(messageKey);
if (originalMessage != null) {
log.warn("消息重试 [{}/{}]: {}", retryCount + 1, MAX_RETRY_COUNT, messageId);
rabbitTemplate.send(
originalMessage.getMessageProperties().getReceivedExchange(),
originalMessage.getMessageProperties().getReceivedRoutingKey(),
originalMessage,
correlationData
);
}
} else {
log.error("消息超过最大重试次数,放弃: {}", messageId);
// 记录到数据库,人工介入
saveToDeadLetter(correlationData);
}
}
private void saveToDeadLetter(CorrelationData correlationData) {
// 实现持久化逻辑
}
} `
`#/**
* 高可靠性生产者
*
* 特性:
* 1. 异步Confirm
* 2. 自动重试
* 3. 消息持久化
* 4. 唯一ID生成
*/
@Service
@Slf4j
public class ReliableProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String RETRY_KEY_PREFIX = "message:retry:";
private static final int MAX_RETRY_COUNT = 3;
@PostConstruct
public void init() {
// 设置异步Confirm回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
log.info("消息发送成功: {}", correlationData);
// 清除重试缓存
String messageId = correlationData.getId();
redisTemplate.delete(RETRY_KEY_PREFIX + messageId);
} else {
log.error("消息发送失败: {}, 原因: {}", correlationData, cause);
// 触发重试
retryMessage(correlationData);
}
});
}
/**
* 发送消息(自动重试)
*/
public void sendWithRetry(String exchange, String routingKey, Object message) {
String messageId = UUID.randomUUID().toString();
// 记录重试次数
redisTemplate.opsForValue().set(
RETRY_KEY_PREFIX + messageId,
0,
24,
TimeUnit.HOURS
);
// 构建消息
MessageBuilder builder = MessageBuilder.withBody(JSON.toJSONString(message).getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_JSON)
.setDeliveryMode(MessageDeliveryMode.PERSISTENT)
.setMessageId(messageId);
// 发送消息
rabbitTemplate.send(
exchange,
routingKey,
builder.build(),
new CorrelationData(messageId)
);
}
/**
* 重试消息
*/
private void retryMessage(CorrelationData correlationData) {
String messageId = correlationData.getId();
String retryKey = RETRY_KEY_PREFIX + messageId;
Integer retryCount = (Integer) redisTemplate.opsForValue().get(retryKey);
if (retryCount == null) {
retryCount = 0;
}
if (retryCount < MAX_RETRY_COUNT) {
// 增加重试次数
redisTemplate.opsForValue().increment(retryKey);
// 从缓存中获取原始消息
String messageKey = "message:content:" + messageId;
Message originalMessage = (Message) redisTemplate.opsForValue().get(messageKey);
if (originalMessage != null) {
log.warn("消息重试 [{}/{}]: {}", retryCount + 1, MAX_RETRY_COUNT, messageId);
rabbitTemplate.send(
originalMessage.getMessageProperties().getReceivedExchange(),
originalMessage.getMessageProperties().getReceivedRoutingKey(),
originalMessage,
correlationData
);
}
} else {
log.error("消息超过最大重试次数,放弃: {}", messageId);
// 记录到数据库,人工介入
saveToDeadLetter(correlationData);
}
}
private void saveToDeadLetter(CorrelationData correlationData) {
// 实现持久化逻辑
}
} // 发送消息`
`#/**
* 高可靠性生产者
*
* 特性:
* 1. 异步Confirm
* 2. 自动重试
* 3. 消息持久化
* 4. 唯一ID生成
*/
@Service
@Slf4j
public class ReliableProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String RETRY_KEY_PREFIX = "message:retry:";
private static final int MAX_RETRY_COUNT = 3;
@PostConstruct
public void init() {
// 设置异步Confirm回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
log.info("消息发送成功: {}", correlationData);
// 清除重试缓存
String messageId = correlationData.getId();
redisTemplate.delete(RETRY_KEY_PREFIX + messageId);
} else {
log.error("消息发送失败: {}, 原因: {}", correlationData, cause);
// 触发重试
retryMessage(correlationData);
}
});
}
/**
* 发送消息(自动重试)
*/
public void sendWithRetry(String exchange, String routingKey, Object message) {
String messageId = UUID.randomUUID().toString();
// 记录重试次数
redisTemplate.opsForValue().set(
RETRY_KEY_PREFIX + messageId,
0,
24,
TimeUnit.HOURS
);
// 构建消息
MessageBuilder builder = MessageBuilder.withBody(JSON.toJSONString(message).getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_JSON)
.setDeliveryMode(MessageDeliveryMode.PERSISTENT)
.setMessageId(messageId);
// 发送消息
rabbitTemplate.send(
exchange,
routingKey,
builder.build(),
new CorrelationData(messageId)
);
}
/**
* 重试消息
*/
private void retryMessage(CorrelationData correlationData) {
String messageId = correlationData.getId();
String retryKey = RETRY_KEY_PREFIX + messageId;
Integer retryCount = (Integer) redisTemplate.opsForValue().get(retryKey);
if (retryCount == null) {
retryCount = 0;
}
if (retryCount < MAX_RETRY_COUNT) {
// 增加重试次数
redisTemplate.opsForValue().increment(retryKey);
// 从缓存中获取原始消息
String messageKey = "message:content:" + messageId;
Message originalMessage = (Message) redisTemplate.opsForValue().get(messageKey);
if (originalMessage != null) {
log.warn("消息重试 [{}/{}]: {}", retryCount + 1, MAX_RETRY_COUNT, messageId);
rabbitTemplate.send(
originalMessage.getMessageProperties().getReceivedExchange(),
originalMessage.getMessageProperties().getReceivedRoutingKey(),
originalMessage,
correlationData
);
}
} else {
log.error("消息超过最大重试次数,放弃: {}", messageId);
// 记录到数据库,人工介入
saveToDeadLetter(correlationData);
}
}
private void saveToDeadLetter(CorrelationData correlationData) {
// 实现持久化逻辑
}
} rabbitTemplate.send(`
`#/**
* 高可靠性生产者
*
* 特性:
* 1. 异步Confirm
* 2. 自动重试
* 3. 消息持久化
* 4. 唯一ID生成
*/
@Service
@Slf4j
public class ReliableProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String RETRY_KEY_PREFIX = "message:retry:";
private static final int MAX_RETRY_COUNT = 3;
@PostConstruct
public void init() {
// 设置异步Confirm回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
log.info("消息发送成功: {}", correlationData);
// 清除重试缓存
String messageId = correlationData.getId();
redisTemplate.delete(RETRY_KEY_PREFIX + messageId);
} else {
log.error("消息发送失败: {}, 原因: {}", correlationData, cause);
// 触发重试
retryMessage(correlationData);
}
});
}
/**
* 发送消息(自动重试)
*/
public void sendWithRetry(String exchange, String routingKey, Object message) {
String messageId = UUID.randomUUID().toString();
// 记录重试次数
redisTemplate.opsForValue().set(
RETRY_KEY_PREFIX + messageId,
0,
24,
TimeUnit.HOURS
);
// 构建消息
MessageBuilder builder = MessageBuilder.withBody(JSON.toJSONString(message).getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_JSON)
.setDeliveryMode(MessageDeliveryMode.PERSISTENT)
.setMessageId(messageId);
// 发送消息
rabbitTemplate.send(
exchange,
routingKey,
builder.build(),
new CorrelationData(messageId)
);
}
/**
* 重试消息
*/
private void retryMessage(CorrelationData correlationData) {
String messageId = correlationData.getId();
String retryKey = RETRY_KEY_PREFIX + messageId;
Integer retryCount = (Integer) redisTemplate.opsForValue().get(retryKey);
if (retryCount == null) {
retryCount = 0;
}
if (retryCount < MAX_RETRY_COUNT) {
// 增加重试次数
redisTemplate.opsForValue().increment(retryKey);
// 从缓存中获取原始消息
String messageKey = "message:content:" + messageId;
Message originalMessage = (Message) redisTemplate.opsForValue().get(messageKey);
if (originalMessage != null) {
log.warn("消息重试 [{}/{}]: {}", retryCount + 1, MAX_RETRY_COUNT, messageId);
rabbitTemplate.send(
originalMessage.getMessageProperties().getReceivedExchange(),
originalMessage.getMessageProperties().getReceivedRoutingKey(),
originalMessage,
correlationData
);
}
} else {
log.error("消息超过最大重试次数,放弃: {}", messageId);
// 记录到数据库,人工介入
saveToDeadLetter(correlationData);
}
}
private void saveToDeadLetter(CorrelationData correlationData) {
// 实现持久化逻辑
}
} exchange,`
`#/**
* 高可靠性生产者
*
* 特性:
* 1. 异步Confirm
* 2. 自动重试
* 3. 消息持久化
* 4. 唯一ID生成
*/
@Service
@Slf4j
public class ReliableProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String RETRY_KEY_PREFIX = "message:retry:";
private static final int MAX_RETRY_COUNT = 3;
@PostConstruct
public void init() {
// 设置异步Confirm回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
log.info("消息发送成功: {}", correlationData);
// 清除重试缓存
String messageId = correlationData.getId();
redisTemplate.delete(RETRY_KEY_PREFIX + messageId);
} else {
log.error("消息发送失败: {}, 原因: {}", correlationData, cause);
// 触发重试
retryMessage(correlationData);
}
});
}
/**
* 发送消息(自动重试)
*/
public void sendWithRetry(String exchange, String routingKey, Object message) {
String messageId = UUID.randomUUID().toString();
// 记录重试次数
redisTemplate.opsForValue().set(
RETRY_KEY_PREFIX + messageId,
0,
24,
TimeUnit.HOURS
);
// 构建消息
MessageBuilder builder = MessageBuilder.withBody(JSON.toJSONString(message).getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_JSON)
.setDeliveryMode(MessageDeliveryMode.PERSISTENT)
.setMessageId(messageId);
// 发送消息
rabbitTemplate.send(
exchange,
routingKey,
builder.build(),
new CorrelationData(messageId)
);
}
/**
* 重试消息
*/
private void retryMessage(CorrelationData correlationData) {
String messageId = correlationData.getId();
String retryKey = RETRY_KEY_PREFIX + messageId;
Integer retryCount = (Integer) redisTemplate.opsForValue().get(retryKey);
if (retryCount == null) {
retryCount = 0;
}
if (retryCount < MAX_RETRY_COUNT) {
// 增加重试次数
redisTemplate.opsForValue().increment(retryKey);
// 从缓存中获取原始消息
String messageKey = "message:content:" + messageId;
Message originalMessage = (Message) redisTemplate.opsForValue().get(messageKey);
if (originalMessage != null) {
log.warn("消息重试 [{}/{}]: {}", retryCount + 1, MAX_RETRY_COUNT, messageId);
rabbitTemplate.send(
originalMessage.getMessageProperties().getReceivedExchange(),
originalMessage.getMessageProperties().getReceivedRoutingKey(),
originalMessage,
correlationData
);
}
} else {
log.error("消息超过最大重试次数,放弃: {}", messageId);
// 记录到数据库,人工介入
saveToDeadLetter(correlationData);
}
}
private void saveToDeadLetter(CorrelationData correlationData) {
// 实现持久化逻辑
}
} routingKey,`
`#/**
* 高可靠性生产者
*
* 特性:
* 1. 异步Confirm
* 2. 自动重试
* 3. 消息持久化
* 4. 唯一ID生成
*/
@Service
@Slf4j
public class ReliableProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String RETRY_KEY_PREFIX = "message:retry:";
private static final int MAX_RETRY_COUNT = 3;
@PostConstruct
public void init() {
// 设置异步Confirm回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
log.info("消息发送成功: {}", correlationData);
// 清除重试缓存
String messageId = correlationData.getId();
redisTemplate.delete(RETRY_KEY_PREFIX + messageId);
} else {
log.error("消息发送失败: {}, 原因: {}", correlationData, cause);
// 触发重试
retryMessage(correlationData);
}
});
}
/**
* 发送消息(自动重试)
*/
public void sendWithRetry(String exchange, String routingKey, Object message) {
String messageId = UUID.randomUUID().toString();
// 记录重试次数
redisTemplate.opsForValue().set(
RETRY_KEY_PREFIX + messageId,
0,
24,
TimeUnit.HOURS
);
// 构建消息
MessageBuilder builder = MessageBuilder.withBody(JSON.toJSONString(message).getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_JSON)
.setDeliveryMode(MessageDeliveryMode.PERSISTENT)
.setMessageId(messageId);
// 发送消息
rabbitTemplate.send(
exchange,
routingKey,
builder.build(),
new CorrelationData(messageId)
);
}
/**
* 重试消息
*/
private void retryMessage(CorrelationData correlationData) {
String messageId = correlationData.getId();
String retryKey = RETRY_KEY_PREFIX + messageId;
Integer retryCount = (Integer) redisTemplate.opsForValue().get(retryKey);
if (retryCount == null) {
retryCount = 0;
}
if (retryCount < MAX_RETRY_COUNT) {
// 增加重试次数
redisTemplate.opsForValue().increment(retryKey);
// 从缓存中获取原始消息
String messageKey = "message:content:" + messageId;
Message originalMessage = (Message) redisTemplate.opsForValue().get(messageKey);
if (originalMessage != null) {
log.warn("消息重试 [{}/{}]: {}", retryCount + 1, MAX_RETRY_COUNT, messageId);
rabbitTemplate.send(
originalMessage.getMessageProperties().getReceivedExchange(),
originalMessage.getMessageProperties().getReceivedRoutingKey(),
originalMessage,
correlationData
);
}
} else {
log.error("消息超过最大重试次数,放弃: {}", messageId);
// 记录到数据库,人工介入
saveToDeadLetter(correlationData);
}
}
private void saveToDeadLetter(CorrelationData correlationData) {
// 实现持久化逻辑
}
} builder.build(),`
`#/**
* 高可靠性生产者
*
* 特性:
* 1. 异步Confirm
* 2. 自动重试
* 3. 消息持久化
* 4. 唯一ID生成
*/
@Service
@Slf4j
public class ReliableProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String RETRY_KEY_PREFIX = "message:retry:";
private static final int MAX_RETRY_COUNT = 3;
@PostConstruct
public void init() {
// 设置异步Confirm回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
log.info("消息发送成功: {}", correlationData);
// 清除重试缓存
String messageId = correlationData.getId();
redisTemplate.delete(RETRY_KEY_PREFIX + messageId);
} else {
log.error("消息发送失败: {}, 原因: {}", correlationData, cause);
// 触发重试
retryMessage(correlationData);
}
});
}
/**
* 发送消息(自动重试)
*/
public void sendWithRetry(String exchange, String routingKey, Object message) {
String messageId = UUID.randomUUID().toString();
// 记录重试次数
redisTemplate.opsForValue().set(
RETRY_KEY_PREFIX + messageId,
0,
24,
TimeUnit.HOURS
);
// 构建消息
MessageBuilder builder = MessageBuilder.withBody(JSON.toJSONString(message).getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_JSON)
.setDeliveryMode(MessageDeliveryMode.PERSISTENT)
.setMessageId(messageId);
// 发送消息
rabbitTemplate.send(
exchange,
routingKey,
builder.build(),
new CorrelationData(messageId)
);
}
/**
* 重试消息
*/
private void retryMessage(CorrelationData correlationData) {
String messageId = correlationData.getId();
String retryKey = RETRY_KEY_PREFIX + messageId;
Integer retryCount = (Integer) redisTemplate.opsForValue().get(retryKey);
if (retryCount == null) {
retryCount = 0;
}
if (retryCount < MAX_RETRY_COUNT) {
// 增加重试次数
redisTemplate.opsForValue().increment(retryKey);
// 从缓存中获取原始消息
String messageKey = "message:content:" + messageId;
Message originalMessage = (Message) redisTemplate.opsForValue().get(messageKey);
if (originalMessage != null) {
log.warn("消息重试 [{}/{}]: {}", retryCount + 1, MAX_RETRY_COUNT, messageId);
rabbitTemplate.send(
originalMessage.getMessageProperties().getReceivedExchange(),
originalMessage.getMessageProperties().getReceivedRoutingKey(),
originalMessage,
correlationData
);
}
} else {
log.error("消息超过最大重试次数,放弃: {}", messageId);
// 记录到数据库,人工介入
saveToDeadLetter(correlationData);
}
}
private void saveToDeadLetter(CorrelationData correlationData) {
// 实现持久化逻辑
}
} new CorrelationData(messageId)`
`#/**
* 高可靠性生产者
*
* 特性:
* 1. 异步Confirm
* 2. 自动重试
* 3. 消息持久化
* 4. 唯一ID生成
*/
@Service
@Slf4j
public class ReliableProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String RETRY_KEY_PREFIX = "message:retry:";
private static final int MAX_RETRY_COUNT = 3;
@PostConstruct
public void init() {
// 设置异步Confirm回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
log.info("消息发送成功: {}", correlationData);
// 清除重试缓存
String messageId = correlationData.getId();
redisTemplate.delete(RETRY_KEY_PREFIX + messageId);
} else {
log.error("消息发送失败: {}, 原因: {}", correlationData, cause);
// 触发重试
retryMessage(correlationData);
}
});
}
/**
* 发送消息(自动重试)
*/
public void sendWithRetry(String exchange, String routingKey, Object message) {
String messageId = UUID.randomUUID().toString();
// 记录重试次数
redisTemplate.opsForValue().set(
RETRY_KEY_PREFIX + messageId,
0,
24,
TimeUnit.HOURS
);
// 构建消息
MessageBuilder builder = MessageBuilder.withBody(JSON.toJSONString(message).getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_JSON)
.setDeliveryMode(MessageDeliveryMode.PERSISTENT)
.setMessageId(messageId);
// 发送消息
rabbitTemplate.send(
exchange,
routingKey,
builder.build(),
new CorrelationData(messageId)
);
}
/**
* 重试消息
*/
private void retryMessage(CorrelationData correlationData) {
String messageId = correlationData.getId();
String retryKey = RETRY_KEY_PREFIX + messageId;
Integer retryCount = (Integer) redisTemplate.opsForValue().get(retryKey);
if (retryCount == null) {
retryCount = 0;
}
if (retryCount < MAX_RETRY_COUNT) {
// 增加重试次数
redisTemplate.opsForValue().increment(retryKey);
// 从缓存中获取原始消息
String messageKey = "message:content:" + messageId;
Message originalMessage = (Message) redisTemplate.opsForValue().get(messageKey);
if (originalMessage != null) {
log.warn("消息重试 [{}/{}]: {}", retryCount + 1, MAX_RETRY_COUNT, messageId);
rabbitTemplate.send(
originalMessage.getMessageProperties().getReceivedExchange(),
originalMessage.getMessageProperties().getReceivedRoutingKey(),
originalMessage,
correlationData
);
}
} else {
log.error("消息超过最大重试次数,放弃: {}", messageId);
// 记录到数据库,人工介入
saveToDeadLetter(correlationData);
}
}
private void saveToDeadLetter(CorrelationData correlationData) {
// 实现持久化逻辑
}
} );`
`#/**
* 高可靠性生产者
*
* 特性:
* 1. 异步Confirm
* 2. 自动重试
* 3. 消息持久化
* 4. 唯一ID生成
*/
@Service
@Slf4j
public class ReliableProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String RETRY_KEY_PREFIX = "message:retry:";
private static final int MAX_RETRY_COUNT = 3;
@PostConstruct
public void init() {
// 设置异步Confirm回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
log.info("消息发送成功: {}", correlationData);
// 清除重试缓存
String messageId = correlationData.getId();
redisTemplate.delete(RETRY_KEY_PREFIX + messageId);
} else {
log.error("消息发送失败: {}, 原因: {}", correlationData, cause);
// 触发重试
retryMessage(correlationData);
}
});
}
/**
* 发送消息(自动重试)
*/
public void sendWithRetry(String exchange, String routingKey, Object message) {
String messageId = UUID.randomUUID().toString();
// 记录重试次数
redisTemplate.opsForValue().set(
RETRY_KEY_PREFIX + messageId,
0,
24,
TimeUnit.HOURS
);
// 构建消息
MessageBuilder builder = MessageBuilder.withBody(JSON.toJSONString(message).getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_JSON)
.setDeliveryMode(MessageDeliveryMode.PERSISTENT)
.setMessageId(messageId);
// 发送消息
rabbitTemplate.send(
exchange,
routingKey,
builder.build(),
new CorrelationData(messageId)
);
}
/**
* 重试消息
*/
private void retryMessage(CorrelationData correlationData) {
String messageId = correlationData.getId();
String retryKey = RETRY_KEY_PREFIX + messageId;
Integer retryCount = (Integer) redisTemplate.opsForValue().get(retryKey);
if (retryCount == null) {
retryCount = 0;
}
if (retryCount < MAX_RETRY_COUNT) {
// 增加重试次数
redisTemplate.opsForValue().increment(retryKey);
// 从缓存中获取原始消息
String messageKey = "message:content:" + messageId;
Message originalMessage = (Message) redisTemplate.opsForValue().get(messageKey);
if (originalMessage != null) {
log.warn("消息重试 [{}/{}]: {}", retryCount + 1, MAX_RETRY_COUNT, messageId);
rabbitTemplate.send(
originalMessage.getMessageProperties().getReceivedExchange(),
originalMessage.getMessageProperties().getReceivedRoutingKey(),
originalMessage,
correlationData
);
}
} else {
log.error("消息超过最大重试次数,放弃: {}", messageId);
// 记录到数据库,人工介入
saveToDeadLetter(correlationData);
}
}
private void saveToDeadLetter(CorrelationData correlationData) {
// 实现持久化逻辑
}
} }`
`#/**
* 高可靠性生产者
*
* 特性:
* 1. 异步Confirm
* 2. 自动重试
* 3. 消息持久化
* 4. 唯一ID生成
*/
@Service
@Slf4j
public class ReliableProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String RETRY_KEY_PREFIX = "message:retry:";
private static final int MAX_RETRY_COUNT = 3;
@PostConstruct
public void init() {
// 设置异步Confirm回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
log.info("消息发送成功: {}", correlationData);
// 清除重试缓存
String messageId = correlationData.getId();
redisTemplate.delete(RETRY_KEY_PREFIX + messageId);
} else {
log.error("消息发送失败: {}, 原因: {}", correlationData, cause);
// 触发重试
retryMessage(correlationData);
}
});
}
/**
* 发送消息(自动重试)
*/
public void sendWithRetry(String exchange, String routingKey, Object message) {
String messageId = UUID.randomUUID().toString();
// 记录重试次数
redisTemplate.opsForValue().set(
RETRY_KEY_PREFIX + messageId,
0,
24,
TimeUnit.HOURS
);
// 构建消息
MessageBuilder builder = MessageBuilder.withBody(JSON.toJSONString(message).getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_JSON)
.setDeliveryMode(MessageDeliveryMode.PERSISTENT)
.setMessageId(messageId);
// 发送消息
rabbitTemplate.send(
exchange,
routingKey,
builder.build(),
new CorrelationData(messageId)
);
}
/**
* 重试消息
*/
private void retryMessage(CorrelationData correlationData) {
String messageId = correlationData.getId();
String retryKey = RETRY_KEY_PREFIX + messageId;
Integer retryCount = (Integer) redisTemplate.opsForValue().get(retryKey);
if (retryCount == null) {
retryCount = 0;
}
if (retryCount < MAX_RETRY_COUNT) {
// 增加重试次数
redisTemplate.opsForValue().increment(retryKey);
// 从缓存中获取原始消息
String messageKey = "message:content:" + messageId;
Message originalMessage = (Message) redisTemplate.opsForValue().get(messageKey);
if (originalMessage != null) {
log.warn("消息重试 [{}/{}]: {}", retryCount + 1, MAX_RETRY_COUNT, messageId);
rabbitTemplate.send(
originalMessage.getMessageProperties().getReceivedExchange(),
originalMessage.getMessageProperties().getReceivedRoutingKey(),
originalMessage,
correlationData
);
}
} else {
log.error("消息超过最大重试次数,放弃: {}", messageId);
// 记录到数据库,人工介入
saveToDeadLetter(correlationData);
}
}
private void saveToDeadLetter(CorrelationData correlationData) {
// 实现持久化逻辑
}
}`
`#/**
* 高可靠性生产者
*
* 特性:
* 1. 异步Confirm
* 2. 自动重试
* 3. 消息持久化
* 4. 唯一ID生成
*/
@Service
@Slf4j
public class ReliableProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String RETRY_KEY_PREFIX = "message:retry:";
private static final int MAX_RETRY_COUNT = 3;
@PostConstruct
public void init() {
// 设置异步Confirm回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
log.info("消息发送成功: {}", correlationData);
// 清除重试缓存
String messageId = correlationData.getId();
redisTemplate.delete(RETRY_KEY_PREFIX + messageId);
} else {
log.error("消息发送失败: {}, 原因: {}", correlationData, cause);
// 触发重试
retryMessage(correlationData);
}
});
}
/**
* 发送消息(自动重试)
*/
public void sendWithRetry(String exchange, String routingKey, Object message) {
String messageId = UUID.randomUUID().toString();
// 记录重试次数
redisTemplate.opsForValue().set(
RETRY_KEY_PREFIX + messageId,
0,
24,
TimeUnit.HOURS
);
// 构建消息
MessageBuilder builder = MessageBuilder.withBody(JSON.toJSONString(message).getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_JSON)
.setDeliveryMode(MessageDeliveryMode.PERSISTENT)
.setMessageId(messageId);
// 发送消息
rabbitTemplate.send(
exchange,
routingKey,
builder.build(),
new CorrelationData(messageId)
);
}
/**
* 重试消息
*/
private void retryMessage(CorrelationData correlationData) {
String messageId = correlationData.getId();
String retryKey = RETRY_KEY_PREFIX + messageId;
Integer retryCount = (Integer) redisTemplate.opsForValue().get(retryKey);
if (retryCount == null) {
retryCount = 0;
}
if (retryCount < MAX_RETRY_COUNT) {
// 增加重试次数
redisTemplate.opsForValue().increment(retryKey);
// 从缓存中获取原始消息
String messageKey = "message:content:" + messageId;
Message originalMessage = (Message) redisTemplate.opsForValue().get(messageKey);
if (originalMessage != null) {
log.warn("消息重试 [{}/{}]: {}", retryCount + 1, MAX_RETRY_COUNT, messageId);
rabbitTemplate.send(
originalMessage.getMessageProperties().getReceivedExchange(),
originalMessage.getMessageProperties().getReceivedRoutingKey(),
originalMessage,
correlationData
);
}
} else {
log.error("消息超过最大重试次数,放弃: {}", messageId);
// 记录到数据库,人工介入
saveToDeadLetter(correlationData);
}
}
private void saveToDeadLetter(CorrelationData correlationData) {
// 实现持久化逻辑
}
} /**`
`#/**
* 高可靠性生产者
*
* 特性:
* 1. 异步Confirm
* 2. 自动重试
* 3. 消息持久化
* 4. 唯一ID生成
*/
@Service
@Slf4j
public class ReliableProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String RETRY_KEY_PREFIX = "message:retry:";
private static final int MAX_RETRY_COUNT = 3;
@PostConstruct
public void init() {
// 设置异步Confirm回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
log.info("消息发送成功: {}", correlationData);
// 清除重试缓存
String messageId = correlationData.getId();
redisTemplate.delete(RETRY_KEY_PREFIX + messageId);
} else {
log.error("消息发送失败: {}, 原因: {}", correlationData, cause);
// 触发重试
retryMessage(correlationData);
}
});
}
/**
* 发送消息(自动重试)
*/
public void sendWithRetry(String exchange, String routingKey, Object message) {
String messageId = UUID.randomUUID().toString();
// 记录重试次数
redisTemplate.opsForValue().set(
RETRY_KEY_PREFIX + messageId,
0,
24,
TimeUnit.HOURS
);
// 构建消息
MessageBuilder builder = MessageBuilder.withBody(JSON.toJSONString(message).getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_JSON)
.setDeliveryMode(MessageDeliveryMode.PERSISTENT)
.setMessageId(messageId);
// 发送消息
rabbitTemplate.send(
exchange,
routingKey,
builder.build(),
new CorrelationData(messageId)
);
}
/**
* 重试消息
*/
private void retryMessage(CorrelationData correlationData) {
String messageId = correlationData.getId();
String retryKey = RETRY_KEY_PREFIX + messageId;
Integer retryCount = (Integer) redisTemplate.opsForValue().get(retryKey);
if (retryCount == null) {
retryCount = 0;
}
if (retryCount < MAX_RETRY_COUNT) {
// 增加重试次数
redisTemplate.opsForValue().increment(retryKey);
// 从缓存中获取原始消息
String messageKey = "message:content:" + messageId;
Message originalMessage = (Message) redisTemplate.opsForValue().get(messageKey);
if (originalMessage != null) {
log.warn("消息重试 [{}/{}]: {}", retryCount + 1, MAX_RETRY_COUNT, messageId);
rabbitTemplate.send(
originalMessage.getMessageProperties().getReceivedExchange(),
originalMessage.getMessageProperties().getReceivedRoutingKey(),
originalMessage,
correlationData
);
}
} else {
log.error("消息超过最大重试次数,放弃: {}", messageId);
// 记录到数据库,人工介入
saveToDeadLetter(correlationData);
}
}
private void saveToDeadLetter(CorrelationData correlationData) {
// 实现持久化逻辑
}
} * 重试消息`
`#/**
* 高可靠性生产者
*
* 特性:
* 1. 异步Confirm
* 2. 自动重试
* 3. 消息持久化
* 4. 唯一ID生成
*/
@Service
@Slf4j
public class ReliableProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String RETRY_KEY_PREFIX = "message:retry:";
private static final int MAX_RETRY_COUNT = 3;
@PostConstruct
public void init() {
// 设置异步Confirm回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
log.info("消息发送成功: {}", correlationData);
// 清除重试缓存
String messageId = correlationData.getId();
redisTemplate.delete(RETRY_KEY_PREFIX + messageId);
} else {
log.error("消息发送失败: {}, 原因: {}", correlationData, cause);
// 触发重试
retryMessage(correlationData);
}
});
}
/**
* 发送消息(自动重试)
*/
public void sendWithRetry(String exchange, String routingKey, Object message) {
String messageId = UUID.randomUUID().toString();
// 记录重试次数
redisTemplate.opsForValue().set(
RETRY_KEY_PREFIX + messageId,
0,
24,
TimeUnit.HOURS
);
// 构建消息
MessageBuilder builder = MessageBuilder.withBody(JSON.toJSONString(message).getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_JSON)
.setDeliveryMode(MessageDeliveryMode.PERSISTENT)
.setMessageId(messageId);
// 发送消息
rabbitTemplate.send(
exchange,
routingKey,
builder.build(),
new CorrelationData(messageId)
);
}
/**
* 重试消息
*/
private void retryMessage(CorrelationData correlationData) {
String messageId = correlationData.getId();
String retryKey = RETRY_KEY_PREFIX + messageId;
Integer retryCount = (Integer) redisTemplate.opsForValue().get(retryKey);
if (retryCount == null) {
retryCount = 0;
}
if (retryCount < MAX_RETRY_COUNT) {
// 增加重试次数
redisTemplate.opsForValue().increment(retryKey);
// 从缓存中获取原始消息
String messageKey = "message:content:" + messageId;
Message originalMessage = (Message) redisTemplate.opsForValue().get(messageKey);
if (originalMessage != null) {
log.warn("消息重试 [{}/{}]: {}", retryCount + 1, MAX_RETRY_COUNT, messageId);
rabbitTemplate.send(
originalMessage.getMessageProperties().getReceivedExchange(),
originalMessage.getMessageProperties().getReceivedRoutingKey(),
originalMessage,
correlationData
);
}
} else {
log.error("消息超过最大重试次数,放弃: {}", messageId);
// 记录到数据库,人工介入
saveToDeadLetter(correlationData);
}
}
private void saveToDeadLetter(CorrelationData correlationData) {
// 实现持久化逻辑
}
} */`
`#/**
* 高可靠性生产者
*
* 特性:
* 1. 异步Confirm
* 2. 自动重试
* 3. 消息持久化
* 4. 唯一ID生成
*/
@Service
@Slf4j
public class ReliableProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String RETRY_KEY_PREFIX = "message:retry:";
private static final int MAX_RETRY_COUNT = 3;
@PostConstruct
public void init() {
// 设置异步Confirm回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
log.info("消息发送成功: {}", correlationData);
// 清除重试缓存
String messageId = correlationData.getId();
redisTemplate.delete(RETRY_KEY_PREFIX + messageId);
} else {
log.error("消息发送失败: {}, 原因: {}", correlationData, cause);
// 触发重试
retryMessage(correlationData);
}
});
}
/**
* 发送消息(自动重试)
*/
public void sendWithRetry(String exchange, String routingKey, Object message) {
String messageId = UUID.randomUUID().toString();
// 记录重试次数
redisTemplate.opsForValue().set(
RETRY_KEY_PREFIX + messageId,
0,
24,
TimeUnit.HOURS
);
// 构建消息
MessageBuilder builder = MessageBuilder.withBody(JSON.toJSONString(message).getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_JSON)
.setDeliveryMode(MessageDeliveryMode.PERSISTENT)
.setMessageId(messageId);
// 发送消息
rabbitTemplate.send(
exchange,
routingKey,
builder.build(),
new CorrelationData(messageId)
);
}
/**
* 重试消息
*/
private void retryMessage(CorrelationData correlationData) {
String messageId = correlationData.getId();
String retryKey = RETRY_KEY_PREFIX + messageId;
Integer retryCount = (Integer) redisTemplate.opsForValue().get(retryKey);
if (retryCount == null) {
retryCount = 0;
}
if (retryCount < MAX_RETRY_COUNT) {
// 增加重试次数
redisTemplate.opsForValue().increment(retryKey);
// 从缓存中获取原始消息
String messageKey = "message:content:" + messageId;
Message originalMessage = (Message) redisTemplate.opsForValue().get(messageKey);
if (originalMessage != null) {
log.warn("消息重试 [{}/{}]: {}", retryCount + 1, MAX_RETRY_COUNT, messageId);
rabbitTemplate.send(
originalMessage.getMessageProperties().getReceivedExchange(),
originalMessage.getMessageProperties().getReceivedRoutingKey(),
originalMessage,
correlationData
);
}
} else {
log.error("消息超过最大重试次数,放弃: {}", messageId);
// 记录到数据库,人工介入
saveToDeadLetter(correlationData);
}
}
private void saveToDeadLetter(CorrelationData correlationData) {
// 实现持久化逻辑
}
} private void retryMessage(CorrelationData correlationData) {`
`#/**
* 高可靠性生产者
*
* 特性:
* 1. 异步Confirm
* 2. 自动重试
* 3. 消息持久化
* 4. 唯一ID生成
*/
@Service
@Slf4j
public class ReliableProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String RETRY_KEY_PREFIX = "message:retry:";
private static final int MAX_RETRY_COUNT = 3;
@PostConstruct
public void init() {
// 设置异步Confirm回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
log.info("消息发送成功: {}", correlationData);
// 清除重试缓存
String messageId = correlationData.getId();
redisTemplate.delete(RETRY_KEY_PREFIX + messageId);
} else {
log.error("消息发送失败: {}, 原因: {}", correlationData, cause);
// 触发重试
retryMessage(correlationData);
}
});
}
/**
* 发送消息(自动重试)
*/
public void sendWithRetry(String exchange, String routingKey, Object message) {
String messageId = UUID.randomUUID().toString();
// 记录重试次数
redisTemplate.opsForValue().set(
RETRY_KEY_PREFIX + messageId,
0,
24,
TimeUnit.HOURS
);
// 构建消息
MessageBuilder builder = MessageBuilder.withBody(JSON.toJSONString(message).getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_JSON)
.setDeliveryMode(MessageDeliveryMode.PERSISTENT)
.setMessageId(messageId);
// 发送消息
rabbitTemplate.send(
exchange,
routingKey,
builder.build(),
new CorrelationData(messageId)
);
}
/**
* 重试消息
*/
private void retryMessage(CorrelationData correlationData) {
String messageId = correlationData.getId();
String retryKey = RETRY_KEY_PREFIX + messageId;
Integer retryCount = (Integer) redisTemplate.opsForValue().get(retryKey);
if (retryCount == null) {
retryCount = 0;
}
if (retryCount < MAX_RETRY_COUNT) {
// 增加重试次数
redisTemplate.opsForValue().increment(retryKey);
// 从缓存中获取原始消息
String messageKey = "message:content:" + messageId;
Message originalMessage = (Message) redisTemplate.opsForValue().get(messageKey);
if (originalMessage != null) {
log.warn("消息重试 [{}/{}]: {}", retryCount + 1, MAX_RETRY_COUNT, messageId);
rabbitTemplate.send(
originalMessage.getMessageProperties().getReceivedExchange(),
originalMessage.getMessageProperties().getReceivedRoutingKey(),
originalMessage,
correlationData
);
}
} else {
log.error("消息超过最大重试次数,放弃: {}", messageId);
// 记录到数据库,人工介入
saveToDeadLetter(correlationData);
}
}
private void saveToDeadLetter(CorrelationData correlationData) {
// 实现持久化逻辑
}
} String messageId = correlationData.getId();`
`#/**
* 高可靠性生产者
*
* 特性:
* 1. 异步Confirm
* 2. 自动重试
* 3. 消息持久化
* 4. 唯一ID生成
*/
@Service
@Slf4j
public class ReliableProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String RETRY_KEY_PREFIX = "message:retry:";
private static final int MAX_RETRY_COUNT = 3;
@PostConstruct
public void init() {
// 设置异步Confirm回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
log.info("消息发送成功: {}", correlationData);
// 清除重试缓存
String messageId = correlationData.getId();
redisTemplate.delete(RETRY_KEY_PREFIX + messageId);
} else {
log.error("消息发送失败: {}, 原因: {}", correlationData, cause);
// 触发重试
retryMessage(correlationData);
}
});
}
/**
* 发送消息(自动重试)
*/
public void sendWithRetry(String exchange, String routingKey, Object message) {
String messageId = UUID.randomUUID().toString();
// 记录重试次数
redisTemplate.opsForValue().set(
RETRY_KEY_PREFIX + messageId,
0,
24,
TimeUnit.HOURS
);
// 构建消息
MessageBuilder builder = MessageBuilder.withBody(JSON.toJSONString(message).getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_JSON)
.setDeliveryMode(MessageDeliveryMode.PERSISTENT)
.setMessageId(messageId);
// 发送消息
rabbitTemplate.send(
exchange,
routingKey,
builder.build(),
new CorrelationData(messageId)
);
}
/**
* 重试消息
*/
private void retryMessage(CorrelationData correlationData) {
String messageId = correlationData.getId();
String retryKey = RETRY_KEY_PREFIX + messageId;
Integer retryCount = (Integer) redisTemplate.opsForValue().get(retryKey);
if (retryCount == null) {
retryCount = 0;
}
if (retryCount < MAX_RETRY_COUNT) {
// 增加重试次数
redisTemplate.opsForValue().increment(retryKey);
// 从缓存中获取原始消息
String messageKey = "message:content:" + messageId;
Message originalMessage = (Message) redisTemplate.opsForValue().get(messageKey);
if (originalMessage != null) {
log.warn("消息重试 [{}/{}]: {}", retryCount + 1, MAX_RETRY_COUNT, messageId);
rabbitTemplate.send(
originalMessage.getMessageProperties().getReceivedExchange(),
originalMessage.getMessageProperties().getReceivedRoutingKey(),
originalMessage,
correlationData
);
}
} else {
log.error("消息超过最大重试次数,放弃: {}", messageId);
// 记录到数据库,人工介入
saveToDeadLetter(correlationData);
}
}
private void saveToDeadLetter(CorrelationData correlationData) {
// 实现持久化逻辑
}
} String retryKey = RETRY_KEY_PREFIX + messageId;`
`#/**
* 高可靠性生产者
*
* 特性:
* 1. 异步Confirm
* 2. 自动重试
* 3. 消息持久化
* 4. 唯一ID生成
*/
@Service
@Slf4j
public class ReliableProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String RETRY_KEY_PREFIX = "message:retry:";
private static final int MAX_RETRY_COUNT = 3;
@PostConstruct
public void init() {
// 设置异步Confirm回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
log.info("消息发送成功: {}", correlationData);
// 清除重试缓存
String messageId = correlationData.getId();
redisTemplate.delete(RETRY_KEY_PREFIX + messageId);
} else {
log.error("消息发送失败: {}, 原因: {}", correlationData, cause);
// 触发重试
retryMessage(correlationData);
}
});
}
/**
* 发送消息(自动重试)
*/
public void sendWithRetry(String exchange, String routingKey, Object message) {
String messageId = UUID.randomUUID().toString();
// 记录重试次数
redisTemplate.opsForValue().set(
RETRY_KEY_PREFIX + messageId,
0,
24,
TimeUnit.HOURS
);
// 构建消息
MessageBuilder builder = MessageBuilder.withBody(JSON.toJSONString(message).getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_JSON)
.setDeliveryMode(MessageDeliveryMode.PERSISTENT)
.setMessageId(messageId);
// 发送消息
rabbitTemplate.send(
exchange,
routingKey,
builder.build(),
new CorrelationData(messageId)
);
}
/**
* 重试消息
*/
private void retryMessage(CorrelationData correlationData) {
String messageId = correlationData.getId();
String retryKey = RETRY_KEY_PREFIX + messageId;
Integer retryCount = (Integer) redisTemplate.opsForValue().get(retryKey);
if (retryCount == null) {
retryCount = 0;
}
if (retryCount < MAX_RETRY_COUNT) {
// 增加重试次数
redisTemplate.opsForValue().increment(retryKey);
// 从缓存中获取原始消息
String messageKey = "message:content:" + messageId;
Message originalMessage = (Message) redisTemplate.opsForValue().get(messageKey);
if (originalMessage != null) {
log.warn("消息重试 [{}/{}]: {}", retryCount + 1, MAX_RETRY_COUNT, messageId);
rabbitTemplate.send(
originalMessage.getMessageProperties().getReceivedExchange(),
originalMessage.getMessageProperties().getReceivedRoutingKey(),
originalMessage,
correlationData
);
}
} else {
log.error("消息超过最大重试次数,放弃: {}", messageId);
// 记录到数据库,人工介入
saveToDeadLetter(correlationData);
}
}
private void saveToDeadLetter(CorrelationData correlationData) {
// 实现持久化逻辑
}
} `
`#/**
* 高可靠性生产者
*
* 特性:
* 1. 异步Confirm
* 2. 自动重试
* 3. 消息持久化
* 4. 唯一ID生成
*/
@Service
@Slf4j
public class ReliableProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String RETRY_KEY_PREFIX = "message:retry:";
private static final int MAX_RETRY_COUNT = 3;
@PostConstruct
public void init() {
// 设置异步Confirm回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
log.info("消息发送成功: {}", correlationData);
// 清除重试缓存
String messageId = correlationData.getId();
redisTemplate.delete(RETRY_KEY_PREFIX + messageId);
} else {
log.error("消息发送失败: {}, 原因: {}", correlationData, cause);
// 触发重试
retryMessage(correlationData);
}
});
}
/**
* 发送消息(自动重试)
*/
public void sendWithRetry(String exchange, String routingKey, Object message) {
String messageId = UUID.randomUUID().toString();
// 记录重试次数
redisTemplate.opsForValue().set(
RETRY_KEY_PREFIX + messageId,
0,
24,
TimeUnit.HOURS
);
// 构建消息
MessageBuilder builder = MessageBuilder.withBody(JSON.toJSONString(message).getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_JSON)
.setDeliveryMode(MessageDeliveryMode.PERSISTENT)
.setMessageId(messageId);
// 发送消息
rabbitTemplate.send(
exchange,
routingKey,
builder.build(),
new CorrelationData(messageId)
);
}
/**
* 重试消息
*/
private void retryMessage(CorrelationData correlationData) {
String messageId = correlationData.getId();
String retryKey = RETRY_KEY_PREFIX + messageId;
Integer retryCount = (Integer) redisTemplate.opsForValue().get(retryKey);
if (retryCount == null) {
retryCount = 0;
}
if (retryCount < MAX_RETRY_COUNT) {
// 增加重试次数
redisTemplate.opsForValue().increment(retryKey);
// 从缓存中获取原始消息
String messageKey = "message:content:" + messageId;
Message originalMessage = (Message) redisTemplate.opsForValue().get(messageKey);
if (originalMessage != null) {
log.warn("消息重试 [{}/{}]: {}", retryCount + 1, MAX_RETRY_COUNT, messageId);
rabbitTemplate.send(
originalMessage.getMessageProperties().getReceivedExchange(),
originalMessage.getMessageProperties().getReceivedRoutingKey(),
originalMessage,
correlationData
);
}
} else {
log.error("消息超过最大重试次数,放弃: {}", messageId);
// 记录到数据库,人工介入
saveToDeadLetter(correlationData);
}
}
private void saveToDeadLetter(CorrelationData correlationData) {
// 实现持久化逻辑
}
} Integer retryCount = (Integer) redisTemplate.opsForValue().get(retryKey);`
`#/**
* 高可靠性生产者
*
* 特性:
* 1. 异步Confirm
* 2. 自动重试
* 3. 消息持久化
* 4. 唯一ID生成
*/
@Service
@Slf4j
public class ReliableProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String RETRY_KEY_PREFIX = "message:retry:";
private static final int MAX_RETRY_COUNT = 3;
@PostConstruct
public void init() {
// 设置异步Confirm回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
log.info("消息发送成功: {}", correlationData);
// 清除重试缓存
String messageId = correlationData.getId();
redisTemplate.delete(RETRY_KEY_PREFIX + messageId);
} else {
log.error("消息发送失败: {}, 原因: {}", correlationData, cause);
// 触发重试
retryMessage(correlationData);
}
});
}
/**
* 发送消息(自动重试)
*/
public void sendWithRetry(String exchange, String routingKey, Object message) {
String messageId = UUID.randomUUID().toString();
// 记录重试次数
redisTemplate.opsForValue().set(
RETRY_KEY_PREFIX + messageId,
0,
24,
TimeUnit.HOURS
);
// 构建消息
MessageBuilder builder = MessageBuilder.withBody(JSON.toJSONString(message).getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_JSON)
.setDeliveryMode(MessageDeliveryMode.PERSISTENT)
.setMessageId(messageId);
// 发送消息
rabbitTemplate.send(
exchange,
routingKey,
builder.build(),
new CorrelationData(messageId)
);
}
/**
* 重试消息
*/
private void retryMessage(CorrelationData correlationData) {
String messageId = correlationData.getId();
String retryKey = RETRY_KEY_PREFIX + messageId;
Integer retryCount = (Integer) redisTemplate.opsForValue().get(retryKey);
if (retryCount == null) {
retryCount = 0;
}
if (retryCount < MAX_RETRY_COUNT) {
// 增加重试次数
redisTemplate.opsForValue().increment(retryKey);
// 从缓存中获取原始消息
String messageKey = "message:content:" + messageId;
Message originalMessage = (Message) redisTemplate.opsForValue().get(messageKey);
if (originalMessage != null) {
log.warn("消息重试 [{}/{}]: {}", retryCount + 1, MAX_RETRY_COUNT, messageId);
rabbitTemplate.send(
originalMessage.getMessageProperties().getReceivedExchange(),
originalMessage.getMessageProperties().getReceivedRoutingKey(),
originalMessage,
correlationData
);
}
} else {
log.error("消息超过最大重试次数,放弃: {}", messageId);
// 记录到数据库,人工介入
saveToDeadLetter(correlationData);
}
}
private void saveToDeadLetter(CorrelationData correlationData) {
// 实现持久化逻辑
}
} if (retryCount == null) {`
`#/**
* 高可靠性生产者
*
* 特性:
* 1. 异步Confirm
* 2. 自动重试
* 3. 消息持久化
* 4. 唯一ID生成
*/
@Service
@Slf4j
public class ReliableProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String RETRY_KEY_PREFIX = "message:retry:";
private static final int MAX_RETRY_COUNT = 3;
@PostConstruct
public void init() {
// 设置异步Confirm回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
log.info("消息发送成功: {}", correlationData);
// 清除重试缓存
String messageId = correlationData.getId();
redisTemplate.delete(RETRY_KEY_PREFIX + messageId);
} else {
log.error("消息发送失败: {}, 原因: {}", correlationData, cause);
// 触发重试
retryMessage(correlationData);
}
});
}
/**
* 发送消息(自动重试)
*/
public void sendWithRetry(String exchange, String routingKey, Object message) {
String messageId = UUID.randomUUID().toString();
// 记录重试次数
redisTemplate.opsForValue().set(
RETRY_KEY_PREFIX + messageId,
0,
24,
TimeUnit.HOURS
);
// 构建消息
MessageBuilder builder = MessageBuilder.withBody(JSON.toJSONString(message).getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_JSON)
.setDeliveryMode(MessageDeliveryMode.PERSISTENT)
.setMessageId(messageId);
// 发送消息
rabbitTemplate.send(
exchange,
routingKey,
builder.build(),
new CorrelationData(messageId)
);
}
/**
* 重试消息
*/
private void retryMessage(CorrelationData correlationData) {
String messageId = correlationData.getId();
String retryKey = RETRY_KEY_PREFIX + messageId;
Integer retryCount = (Integer) redisTemplate.opsForValue().get(retryKey);
if (retryCount == null) {
retryCount = 0;
}
if (retryCount < MAX_RETRY_COUNT) {
// 增加重试次数
redisTemplate.opsForValue().increment(retryKey);
// 从缓存中获取原始消息
String messageKey = "message:content:" + messageId;
Message originalMessage = (Message) redisTemplate.opsForValue().get(messageKey);
if (originalMessage != null) {
log.warn("消息重试 [{}/{}]: {}", retryCount + 1, MAX_RETRY_COUNT, messageId);
rabbitTemplate.send(
originalMessage.getMessageProperties().getReceivedExchange(),
originalMessage.getMessageProperties().getReceivedRoutingKey(),
originalMessage,
correlationData
);
}
} else {
log.error("消息超过最大重试次数,放弃: {}", messageId);
// 记录到数据库,人工介入
saveToDeadLetter(correlationData);
}
}
private void saveToDeadLetter(CorrelationData correlationData) {
// 实现持久化逻辑
}
} retryCount = 0;`
`#/**
* 高可靠性生产者
*
* 特性:
* 1. 异步Confirm
* 2. 自动重试
* 3. 消息持久化
* 4. 唯一ID生成
*/
@Service
@Slf4j
public class ReliableProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String RETRY_KEY_PREFIX = "message:retry:";
private static final int MAX_RETRY_COUNT = 3;
@PostConstruct
public void init() {
// 设置异步Confirm回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
log.info("消息发送成功: {}", correlationData);
// 清除重试缓存
String messageId = correlationData.getId();
redisTemplate.delete(RETRY_KEY_PREFIX + messageId);
} else {
log.error("消息发送失败: {}, 原因: {}", correlationData, cause);
// 触发重试
retryMessage(correlationData);
}
});
}
/**
* 发送消息(自动重试)
*/
public void sendWithRetry(String exchange, String routingKey, Object message) {
String messageId = UUID.randomUUID().toString();
// 记录重试次数
redisTemplate.opsForValue().set(
RETRY_KEY_PREFIX + messageId,
0,
24,
TimeUnit.HOURS
);
// 构建消息
MessageBuilder builder = MessageBuilder.withBody(JSON.toJSONString(message).getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_JSON)
.setDeliveryMode(MessageDeliveryMode.PERSISTENT)
.setMessageId(messageId);
// 发送消息
rabbitTemplate.send(
exchange,
routingKey,
builder.build(),
new CorrelationData(messageId)
);
}
/**
* 重试消息
*/
private void retryMessage(CorrelationData correlationData) {
String messageId = correlationData.getId();
String retryKey = RETRY_KEY_PREFIX + messageId;
Integer retryCount = (Integer) redisTemplate.opsForValue().get(retryKey);
if (retryCount == null) {
retryCount = 0;
}
if (retryCount < MAX_RETRY_COUNT) {
// 增加重试次数
redisTemplate.opsForValue().increment(retryKey);
// 从缓存中获取原始消息
String messageKey = "message:content:" + messageId;
Message originalMessage = (Message) redisTemplate.opsForValue().get(messageKey);
if (originalMessage != null) {
log.warn("消息重试 [{}/{}]: {}", retryCount + 1, MAX_RETRY_COUNT, messageId);
rabbitTemplate.send(
originalMessage.getMessageProperties().getReceivedExchange(),
originalMessage.getMessageProperties().getReceivedRoutingKey(),
originalMessage,
correlationData
);
}
} else {
log.error("消息超过最大重试次数,放弃: {}", messageId);
// 记录到数据库,人工介入
saveToDeadLetter(correlationData);
}
}
private void saveToDeadLetter(CorrelationData correlationData) {
// 实现持久化逻辑
}
} }`
`#/**
* 高可靠性生产者
*
* 特性:
* 1. 异步Confirm
* 2. 自动重试
* 3. 消息持久化
* 4. 唯一ID生成
*/
@Service
@Slf4j
public class ReliableProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String RETRY_KEY_PREFIX = "message:retry:";
private static final int MAX_RETRY_COUNT = 3;
@PostConstruct
public void init() {
// 设置异步Confirm回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
log.info("消息发送成功: {}", correlationData);
// 清除重试缓存
String messageId = correlationData.getId();
redisTemplate.delete(RETRY_KEY_PREFIX + messageId);
} else {
log.error("消息发送失败: {}, 原因: {}", correlationData, cause);
// 触发重试
retryMessage(correlationData);
}
});
}
/**
* 发送消息(自动重试)
*/
public void sendWithRetry(String exchange, String routingKey, Object message) {
String messageId = UUID.randomUUID().toString();
// 记录重试次数
redisTemplate.opsForValue().set(
RETRY_KEY_PREFIX + messageId,
0,
24,
TimeUnit.HOURS
);
// 构建消息
MessageBuilder builder = MessageBuilder.withBody(JSON.toJSONString(message).getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_JSON)
.setDeliveryMode(MessageDeliveryMode.PERSISTENT)
.setMessageId(messageId);
// 发送消息
rabbitTemplate.send(
exchange,
routingKey,
builder.build(),
new CorrelationData(messageId)
);
}
/**
* 重试消息
*/
private void retryMessage(CorrelationData correlationData) {
String messageId = correlationData.getId();
String retryKey = RETRY_KEY_PREFIX + messageId;
Integer retryCount = (Integer) redisTemplate.opsForValue().get(retryKey);
if (retryCount == null) {
retryCount = 0;
}
if (retryCount < MAX_RETRY_COUNT) {
// 增加重试次数
redisTemplate.opsForValue().increment(retryKey);
// 从缓存中获取原始消息
String messageKey = "message:content:" + messageId;
Message originalMessage = (Message) redisTemplate.opsForValue().get(messageKey);
if (originalMessage != null) {
log.warn("消息重试 [{}/{}]: {}", retryCount + 1, MAX_RETRY_COUNT, messageId);
rabbitTemplate.send(
originalMessage.getMessageProperties().getReceivedExchange(),
originalMessage.getMessageProperties().getReceivedRoutingKey(),
originalMessage,
correlationData
);
}
} else {
log.error("消息超过最大重试次数,放弃: {}", messageId);
// 记录到数据库,人工介入
saveToDeadLetter(correlationData);
}
}
private void saveToDeadLetter(CorrelationData correlationData) {
// 实现持久化逻辑
}
} `
`#/**
* 高可靠性生产者
*
* 特性:
* 1. 异步Confirm
* 2. 自动重试
* 3. 消息持久化
* 4. 唯一ID生成
*/
@Service
@Slf4j
public class ReliableProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String RETRY_KEY_PREFIX = "message:retry:";
private static final int MAX_RETRY_COUNT = 3;
@PostConstruct
public void init() {
// 设置异步Confirm回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
log.info("消息发送成功: {}", correlationData);
// 清除重试缓存
String messageId = correlationData.getId();
redisTemplate.delete(RETRY_KEY_PREFIX + messageId);
} else {
log.error("消息发送失败: {}, 原因: {}", correlationData, cause);
// 触发重试
retryMessage(correlationData);
}
});
}
/**
* 发送消息(自动重试)
*/
public void sendWithRetry(String exchange, String routingKey, Object message) {
String messageId = UUID.randomUUID().toString();
// 记录重试次数
redisTemplate.opsForValue().set(
RETRY_KEY_PREFIX + messageId,
0,
24,
TimeUnit.HOURS
);
// 构建消息
MessageBuilder builder = MessageBuilder.withBody(JSON.toJSONString(message).getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_JSON)
.setDeliveryMode(MessageDeliveryMode.PERSISTENT)
.setMessageId(messageId);
// 发送消息
rabbitTemplate.send(
exchange,
routingKey,
builder.build(),
new CorrelationData(messageId)
);
}
/**
* 重试消息
*/
private void retryMessage(CorrelationData correlationData) {
String messageId = correlationData.getId();
String retryKey = RETRY_KEY_PREFIX + messageId;
Integer retryCount = (Integer) redisTemplate.opsForValue().get(retryKey);
if (retryCount == null) {
retryCount = 0;
}
if (retryCount < MAX_RETRY_COUNT) {
// 增加重试次数
redisTemplate.opsForValue().increment(retryKey);
// 从缓存中获取原始消息
String messageKey = "message:content:" + messageId;
Message originalMessage = (Message) redisTemplate.opsForValue().get(messageKey);
if (originalMessage != null) {
log.warn("消息重试 [{}/{}]: {}", retryCount + 1, MAX_RETRY_COUNT, messageId);
rabbitTemplate.send(
originalMessage.getMessageProperties().getReceivedExchange(),
originalMessage.getMessageProperties().getReceivedRoutingKey(),
originalMessage,
correlationData
);
}
} else {
log.error("消息超过最大重试次数,放弃: {}", messageId);
// 记录到数据库,人工介入
saveToDeadLetter(correlationData);
}
}
private void saveToDeadLetter(CorrelationData correlationData) {
// 实现持久化逻辑
}
} if (retryCount < MAX_RETRY_COUNT) {`
`#/**
* 高可靠性生产者
*
* 特性:
* 1. 异步Confirm
* 2. 自动重试
* 3. 消息持久化
* 4. 唯一ID生成
*/
@Service
@Slf4j
public class ReliableProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String RETRY_KEY_PREFIX = "message:retry:";
private static final int MAX_RETRY_COUNT = 3;
@PostConstruct
public void init() {
// 设置异步Confirm回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
log.info("消息发送成功: {}", correlationData);
// 清除重试缓存
String messageId = correlationData.getId();
redisTemplate.delete(RETRY_KEY_PREFIX + messageId);
} else {
log.error("消息发送失败: {}, 原因: {}", correlationData, cause);
// 触发重试
retryMessage(correlationData);
}
});
}
/**
* 发送消息(自动重试)
*/
public void sendWithRetry(String exchange, String routingKey, Object message) {
String messageId = UUID.randomUUID().toString();
// 记录重试次数
redisTemplate.opsForValue().set(
RETRY_KEY_PREFIX + messageId,
0,
24,
TimeUnit.HOURS
);
// 构建消息
MessageBuilder builder = MessageBuilder.withBody(JSON.toJSONString(message).getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_JSON)
.setDeliveryMode(MessageDeliveryMode.PERSISTENT)
.setMessageId(messageId);
// 发送消息
rabbitTemplate.send(
exchange,
routingKey,
builder.build(),
new CorrelationData(messageId)
);
}
/**
* 重试消息
*/
private void retryMessage(CorrelationData correlationData) {
String messageId = correlationData.getId();
String retryKey = RETRY_KEY_PREFIX + messageId;
Integer retryCount = (Integer) redisTemplate.opsForValue().get(retryKey);
if (retryCount == null) {
retryCount = 0;
}
if (retryCount < MAX_RETRY_COUNT) {
// 增加重试次数
redisTemplate.opsForValue().increment(retryKey);
// 从缓存中获取原始消息
String messageKey = "message:content:" + messageId;
Message originalMessage = (Message) redisTemplate.opsForValue().get(messageKey);
if (originalMessage != null) {
log.warn("消息重试 [{}/{}]: {}", retryCount + 1, MAX_RETRY_COUNT, messageId);
rabbitTemplate.send(
originalMessage.getMessageProperties().getReceivedExchange(),
originalMessage.getMessageProperties().getReceivedRoutingKey(),
originalMessage,
correlationData
);
}
} else {
log.error("消息超过最大重试次数,放弃: {}", messageId);
// 记录到数据库,人工介入
saveToDeadLetter(correlationData);
}
}
private void saveToDeadLetter(CorrelationData correlationData) {
// 实现持久化逻辑
}
} // 增加重试次数`
`#/**
* 高可靠性生产者
*
* 特性:
* 1. 异步Confirm
* 2. 自动重试
* 3. 消息持久化
* 4. 唯一ID生成
*/
@Service
@Slf4j
public class ReliableProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String RETRY_KEY_PREFIX = "message:retry:";
private static final int MAX_RETRY_COUNT = 3;
@PostConstruct
public void init() {
// 设置异步Confirm回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
log.info("消息发送成功: {}", correlationData);
// 清除重试缓存
String messageId = correlationData.getId();
redisTemplate.delete(RETRY_KEY_PREFIX + messageId);
} else {
log.error("消息发送失败: {}, 原因: {}", correlationData, cause);
// 触发重试
retryMessage(correlationData);
}
});
}
/**
* 发送消息(自动重试)
*/
public void sendWithRetry(String exchange, String routingKey, Object message) {
String messageId = UUID.randomUUID().toString();
// 记录重试次数
redisTemplate.opsForValue().set(
RETRY_KEY_PREFIX + messageId,
0,
24,
TimeUnit.HOURS
);
// 构建消息
MessageBuilder builder = MessageBuilder.withBody(JSON.toJSONString(message).getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_JSON)
.setDeliveryMode(MessageDeliveryMode.PERSISTENT)
.setMessageId(messageId);
// 发送消息
rabbitTemplate.send(
exchange,
routingKey,
builder.build(),
new CorrelationData(messageId)
);
}
/**
* 重试消息
*/
private void retryMessage(CorrelationData correlationData) {
String messageId = correlationData.getId();
String retryKey = RETRY_KEY_PREFIX + messageId;
Integer retryCount = (Integer) redisTemplate.opsForValue().get(retryKey);
if (retryCount == null) {
retryCount = 0;
}
if (retryCount < MAX_RETRY_COUNT) {
// 增加重试次数
redisTemplate.opsForValue().increment(retryKey);
// 从缓存中获取原始消息
String messageKey = "message:content:" + messageId;
Message originalMessage = (Message) redisTemplate.opsForValue().get(messageKey);
if (originalMessage != null) {
log.warn("消息重试 [{}/{}]: {}", retryCount + 1, MAX_RETRY_COUNT, messageId);
rabbitTemplate.send(
originalMessage.getMessageProperties().getReceivedExchange(),
originalMessage.getMessageProperties().getReceivedRoutingKey(),
originalMessage,
correlationData
);
}
} else {
log.error("消息超过最大重试次数,放弃: {}", messageId);
// 记录到数据库,人工介入
saveToDeadLetter(correlationData);
}
}
private void saveToDeadLetter(CorrelationData correlationData) {
// 实现持久化逻辑
}
} redisTemplate.opsForValue().increment(retryKey);`
`#/**
* 高可靠性生产者
*
* 特性:
* 1. 异步Confirm
* 2. 自动重试
* 3. 消息持久化
* 4. 唯一ID生成
*/
@Service
@Slf4j
public class ReliableProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String RETRY_KEY_PREFIX = "message:retry:";
private static final int MAX_RETRY_COUNT = 3;
@PostConstruct
public void init() {
// 设置异步Confirm回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
log.info("消息发送成功: {}", correlationData);
// 清除重试缓存
String messageId = correlationData.getId();
redisTemplate.delete(RETRY_KEY_PREFIX + messageId);
} else {
log.error("消息发送失败: {}, 原因: {}", correlationData, cause);
// 触发重试
retryMessage(correlationData);
}
});
}
/**
* 发送消息(自动重试)
*/
public void sendWithRetry(String exchange, String routingKey, Object message) {
String messageId = UUID.randomUUID().toString();
// 记录重试次数
redisTemplate.opsForValue().set(
RETRY_KEY_PREFIX + messageId,
0,
24,
TimeUnit.HOURS
);
// 构建消息
MessageBuilder builder = MessageBuilder.withBody(JSON.toJSONString(message).getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_JSON)
.setDeliveryMode(MessageDeliveryMode.PERSISTENT)
.setMessageId(messageId);
// 发送消息
rabbitTemplate.send(
exchange,
routingKey,
builder.build(),
new CorrelationData(messageId)
);
}
/**
* 重试消息
*/
private void retryMessage(CorrelationData correlationData) {
String messageId = correlationData.getId();
String retryKey = RETRY_KEY_PREFIX + messageId;
Integer retryCount = (Integer) redisTemplate.opsForValue().get(retryKey);
if (retryCount == null) {
retryCount = 0;
}
if (retryCount < MAX_RETRY_COUNT) {
// 增加重试次数
redisTemplate.opsForValue().increment(retryKey);
// 从缓存中获取原始消息
String messageKey = "message:content:" + messageId;
Message originalMessage = (Message) redisTemplate.opsForValue().get(messageKey);
if (originalMessage != null) {
log.warn("消息重试 [{}/{}]: {}", retryCount + 1, MAX_RETRY_COUNT, messageId);
rabbitTemplate.send(
originalMessage.getMessageProperties().getReceivedExchange(),
originalMessage.getMessageProperties().getReceivedRoutingKey(),
originalMessage,
correlationData
);
}
} else {
log.error("消息超过最大重试次数,放弃: {}", messageId);
// 记录到数据库,人工介入
saveToDeadLetter(correlationData);
}
}
private void saveToDeadLetter(CorrelationData correlationData) {
// 实现持久化逻辑
}
} `
`#/**
* 高可靠性生产者
*
* 特性:
* 1. 异步Confirm
* 2. 自动重试
* 3. 消息持久化
* 4. 唯一ID生成
*/
@Service
@Slf4j
public class ReliableProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String RETRY_KEY_PREFIX = "message:retry:";
private static final int MAX_RETRY_COUNT = 3;
@PostConstruct
public void init() {
// 设置异步Confirm回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
log.info("消息发送成功: {}", correlationData);
// 清除重试缓存
String messageId = correlationData.getId();
redisTemplate.delete(RETRY_KEY_PREFIX + messageId);
} else {
log.error("消息发送失败: {}, 原因: {}", correlationData, cause);
// 触发重试
retryMessage(correlationData);
}
});
}
/**
* 发送消息(自动重试)
*/
public void sendWithRetry(String exchange, String routingKey, Object message) {
String messageId = UUID.randomUUID().toString();
// 记录重试次数
redisTemplate.opsForValue().set(
RETRY_KEY_PREFIX + messageId,
0,
24,
TimeUnit.HOURS
);
// 构建消息
MessageBuilder builder = MessageBuilder.withBody(JSON.toJSONString(message).getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_JSON)
.setDeliveryMode(MessageDeliveryMode.PERSISTENT)
.setMessageId(messageId);
// 发送消息
rabbitTemplate.send(
exchange,
routingKey,
builder.build(),
new CorrelationData(messageId)
);
}
/**
* 重试消息
*/
private void retryMessage(CorrelationData correlationData) {
String messageId = correlationData.getId();
String retryKey = RETRY_KEY_PREFIX + messageId;
Integer retryCount = (Integer) redisTemplate.opsForValue().get(retryKey);
if (retryCount == null) {
retryCount = 0;
}
if (retryCount < MAX_RETRY_COUNT) {
// 增加重试次数
redisTemplate.opsForValue().increment(retryKey);
// 从缓存中获取原始消息
String messageKey = "message:content:" + messageId;
Message originalMessage = (Message) redisTemplate.opsForValue().get(messageKey);
if (originalMessage != null) {
log.warn("消息重试 [{}/{}]: {}", retryCount + 1, MAX_RETRY_COUNT, messageId);
rabbitTemplate.send(
originalMessage.getMessageProperties().getReceivedExchange(),
originalMessage.getMessageProperties().getReceivedRoutingKey(),
originalMessage,
correlationData
);
}
} else {
log.error("消息超过最大重试次数,放弃: {}", messageId);
// 记录到数据库,人工介入
saveToDeadLetter(correlationData);
}
}
private void saveToDeadLetter(CorrelationData correlationData) {
// 实现持久化逻辑
}
} // 从缓存中获取原始消息`
`#/**
* 高可靠性生产者
*
* 特性:
* 1. 异步Confirm
* 2. 自动重试
* 3. 消息持久化
* 4. 唯一ID生成
*/
@Service
@Slf4j
public class ReliableProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String RETRY_KEY_PREFIX = "message:retry:";
private static final int MAX_RETRY_COUNT = 3;
@PostConstruct
public void init() {
// 设置异步Confirm回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
log.info("消息发送成功: {}", correlationData);
// 清除重试缓存
String messageId = correlationData.getId();
redisTemplate.delete(RETRY_KEY_PREFIX + messageId);
} else {
log.error("消息发送失败: {}, 原因: {}", correlationData, cause);
// 触发重试
retryMessage(correlationData);
}
});
}
/**
* 发送消息(自动重试)
*/
public void sendWithRetry(String exchange, String routingKey, Object message) {
String messageId = UUID.randomUUID().toString();
// 记录重试次数
redisTemplate.opsForValue().set(
RETRY_KEY_PREFIX + messageId,
0,
24,
TimeUnit.HOURS
);
// 构建消息
MessageBuilder builder = MessageBuilder.withBody(JSON.toJSONString(message).getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_JSON)
.setDeliveryMode(MessageDeliveryMode.PERSISTENT)
.setMessageId(messageId);
// 发送消息
rabbitTemplate.send(
exchange,
routingKey,
builder.build(),
new CorrelationData(messageId)
);
}
/**
* 重试消息
*/
private void retryMessage(CorrelationData correlationData) {
String messageId = correlationData.getId();
String retryKey = RETRY_KEY_PREFIX + messageId;
Integer retryCount = (Integer) redisTemplate.opsForValue().get(retryKey);
if (retryCount == null) {
retryCount = 0;
}
if (retryCount < MAX_RETRY_COUNT) {
// 增加重试次数
redisTemplate.opsForValue().increment(retryKey);
// 从缓存中获取原始消息
String messageKey = "message:content:" + messageId;
Message originalMessage = (Message) redisTemplate.opsForValue().get(messageKey);
if (originalMessage != null) {
log.warn("消息重试 [{}/{}]: {}", retryCount + 1, MAX_RETRY_COUNT, messageId);
rabbitTemplate.send(
originalMessage.getMessageProperties().getReceivedExchange(),
originalMessage.getMessageProperties().getReceivedRoutingKey(),
originalMessage,
correlationData
);
}
} else {
log.error("消息超过最大重试次数,放弃: {}", messageId);
// 记录到数据库,人工介入
saveToDeadLetter(correlationData);
}
}
private void saveToDeadLetter(CorrelationData correlationData) {
// 实现持久化逻辑
}
} String messageKey = "message:content:" + messageId;`
`#/**
* 高可靠性生产者
*
* 特性:
* 1. 异步Confirm
* 2. 自动重试
* 3. 消息持久化
* 4. 唯一ID生成
*/
@Service
@Slf4j
public class ReliableProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String RETRY_KEY_PREFIX = "message:retry:";
private static final int MAX_RETRY_COUNT = 3;
@PostConstruct
public void init() {
// 设置异步Confirm回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
log.info("消息发送成功: {}", correlationData);
// 清除重试缓存
String messageId = correlationData.getId();
redisTemplate.delete(RETRY_KEY_PREFIX + messageId);
} else {
log.error("消息发送失败: {}, 原因: {}", correlationData, cause);
// 触发重试
retryMessage(correlationData);
}
});
}
/**
* 发送消息(自动重试)
*/
public void sendWithRetry(String exchange, String routingKey, Object message) {
String messageId = UUID.randomUUID().toString();
// 记录重试次数
redisTemplate.opsForValue().set(
RETRY_KEY_PREFIX + messageId,
0,
24,
TimeUnit.HOURS
);
// 构建消息
MessageBuilder builder = MessageBuilder.withBody(JSON.toJSONString(message).getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_JSON)
.setDeliveryMode(MessageDeliveryMode.PERSISTENT)
.setMessageId(messageId);
// 发送消息
rabbitTemplate.send(
exchange,
routingKey,
builder.build(),
new CorrelationData(messageId)
);
}
/**
* 重试消息
*/
private void retryMessage(CorrelationData correlationData) {
String messageId = correlationData.getId();
String retryKey = RETRY_KEY_PREFIX + messageId;
Integer retryCount = (Integer) redisTemplate.opsForValue().get(retryKey);
if (retryCount == null) {
retryCount = 0;
}
if (retryCount < MAX_RETRY_COUNT) {
// 增加重试次数
redisTemplate.opsForValue().increment(retryKey);
// 从缓存中获取原始消息
String messageKey = "message:content:" + messageId;
Message originalMessage = (Message) redisTemplate.opsForValue().get(messageKey);
if (originalMessage != null) {
log.warn("消息重试 [{}/{}]: {}", retryCount + 1, MAX_RETRY_COUNT, messageId);
rabbitTemplate.send(
originalMessage.getMessageProperties().getReceivedExchange(),
originalMessage.getMessageProperties().getReceivedRoutingKey(),
originalMessage,
correlationData
);
}
} else {
log.error("消息超过最大重试次数,放弃: {}", messageId);
// 记录到数据库,人工介入
saveToDeadLetter(correlationData);
}
}
private void saveToDeadLetter(CorrelationData correlationData) {
// 实现持久化逻辑
}
} Message originalMessage = (Message) redisTemplate.opsForValue().get(messageKey);`
`#/**
* 高可靠性生产者
*
* 特性:
* 1. 异步Confirm
* 2. 自动重试
* 3. 消息持久化
* 4. 唯一ID生成
*/
@Service
@Slf4j
public class ReliableProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String RETRY_KEY_PREFIX = "message:retry:";
private static final int MAX_RETRY_COUNT = 3;
@PostConstruct
public void init() {
// 设置异步Confirm回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
log.info("消息发送成功: {}", correlationData);
// 清除重试缓存
String messageId = correlationData.getId();
redisTemplate.delete(RETRY_KEY_PREFIX + messageId);
} else {
log.error("消息发送失败: {}, 原因: {}", correlationData, cause);
// 触发重试
retryMessage(correlationData);
}
});
}
/**
* 发送消息(自动重试)
*/
public void sendWithRetry(String exchange, String routingKey, Object message) {
String messageId = UUID.randomUUID().toString();
// 记录重试次数
redisTemplate.opsForValue().set(
RETRY_KEY_PREFIX + messageId,
0,
24,
TimeUnit.HOURS
);
// 构建消息
MessageBuilder builder = MessageBuilder.withBody(JSON.toJSONString(message).getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_JSON)
.setDeliveryMode(MessageDeliveryMode.PERSISTENT)
.setMessageId(messageId);
// 发送消息
rabbitTemplate.send(
exchange,
routingKey,
builder.build(),
new CorrelationData(messageId)
);
}
/**
* 重试消息
*/
private void retryMessage(CorrelationData correlationData) {
String messageId = correlationData.getId();
String retryKey = RETRY_KEY_PREFIX + messageId;
Integer retryCount = (Integer) redisTemplate.opsForValue().get(retryKey);
if (retryCount == null) {
retryCount = 0;
}
if (retryCount < MAX_RETRY_COUNT) {
// 增加重试次数
redisTemplate.opsForValue().increment(retryKey);
// 从缓存中获取原始消息
String messageKey = "message:content:" + messageId;
Message originalMessage = (Message) redisTemplate.opsForValue().get(messageKey);
if (originalMessage != null) {
log.warn("消息重试 [{}/{}]: {}", retryCount + 1, MAX_RETRY_COUNT, messageId);
rabbitTemplate.send(
originalMessage.getMessageProperties().getReceivedExchange(),
originalMessage.getMessageProperties().getReceivedRoutingKey(),
originalMessage,
correlationData
);
}
} else {
log.error("消息超过最大重试次数,放弃: {}", messageId);
// 记录到数据库,人工介入
saveToDeadLetter(correlationData);
}
}
private void saveToDeadLetter(CorrelationData correlationData) {
// 实现持久化逻辑
}
} `
`#/**
* 高可靠性生产者
*
* 特性:
* 1. 异步Confirm
* 2. 自动重试
* 3. 消息持久化
* 4. 唯一ID生成
*/
@Service
@Slf4j
public class ReliableProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String RETRY_KEY_PREFIX = "message:retry:";
private static final int MAX_RETRY_COUNT = 3;
@PostConstruct
public void init() {
// 设置异步Confirm回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
log.info("消息发送成功: {}", correlationData);
// 清除重试缓存
String messageId = correlationData.getId();
redisTemplate.delete(RETRY_KEY_PREFIX + messageId);
} else {
log.error("消息发送失败: {}, 原因: {}", correlationData, cause);
// 触发重试
retryMessage(correlationData);
}
});
}
/**
* 发送消息(自动重试)
*/
public void sendWithRetry(String exchange, String routingKey, Object message) {
String messageId = UUID.randomUUID().toString();
// 记录重试次数
redisTemplate.opsForValue().set(
RETRY_KEY_PREFIX + messageId,
0,
24,
TimeUnit.HOURS
);
// 构建消息
MessageBuilder builder = MessageBuilder.withBody(JSON.toJSONString(message).getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_JSON)
.setDeliveryMode(MessageDeliveryMode.PERSISTENT)
.setMessageId(messageId);
// 发送消息
rabbitTemplate.send(
exchange,
routingKey,
builder.build(),
new CorrelationData(messageId)
);
}
/**
* 重试消息
*/
private void retryMessage(CorrelationData correlationData) {
String messageId = correlationData.getId();
String retryKey = RETRY_KEY_PREFIX + messageId;
Integer retryCount = (Integer) redisTemplate.opsForValue().get(retryKey);
if (retryCount == null) {
retryCount = 0;
}
if (retryCount < MAX_RETRY_COUNT) {
// 增加重试次数
redisTemplate.opsForValue().increment(retryKey);
// 从缓存中获取原始消息
String messageKey = "message:content:" + messageId;
Message originalMessage = (Message) redisTemplate.opsForValue().get(messageKey);
if (originalMessage != null) {
log.warn("消息重试 [{}/{}]: {}", retryCount + 1, MAX_RETRY_COUNT, messageId);
rabbitTemplate.send(
originalMessage.getMessageProperties().getReceivedExchange(),
originalMessage.getMessageProperties().getReceivedRoutingKey(),
originalMessage,
correlationData
);
}
} else {
log.error("消息超过最大重试次数,放弃: {}", messageId);
// 记录到数据库,人工介入
saveToDeadLetter(correlationData);
}
}
private void saveToDeadLetter(CorrelationData correlationData) {
// 实现持久化逻辑
}
} if (originalMessage != null) {`
`#/**
* 高可靠性生产者
*
* 特性:
* 1. 异步Confirm
* 2. 自动重试
* 3. 消息持久化
* 4. 唯一ID生成
*/
@Service
@Slf4j
public class ReliableProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String RETRY_KEY_PREFIX = "message:retry:";
private static final int MAX_RETRY_COUNT = 3;
@PostConstruct
public void init() {
// 设置异步Confirm回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
log.info("消息发送成功: {}", correlationData);
// 清除重试缓存
String messageId = correlationData.getId();
redisTemplate.delete(RETRY_KEY_PREFIX + messageId);
} else {
log.error("消息发送失败: {}, 原因: {}", correlationData, cause);
// 触发重试
retryMessage(correlationData);
}
});
}
/**
* 发送消息(自动重试)
*/
public void sendWithRetry(String exchange, String routingKey, Object message) {
String messageId = UUID.randomUUID().toString();
// 记录重试次数
redisTemplate.opsForValue().set(
RETRY_KEY_PREFIX + messageId,
0,
24,
TimeUnit.HOURS
);
// 构建消息
MessageBuilder builder = MessageBuilder.withBody(JSON.toJSONString(message).getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_JSON)
.setDeliveryMode(MessageDeliveryMode.PERSISTENT)
.setMessageId(messageId);
// 发送消息
rabbitTemplate.send(
exchange,
routingKey,
builder.build(),
new CorrelationData(messageId)
);
}
/**
* 重试消息
*/
private void retryMessage(CorrelationData correlationData) {
String messageId = correlationData.getId();
String retryKey = RETRY_KEY_PREFIX + messageId;
Integer retryCount = (Integer) redisTemplate.opsForValue().get(retryKey);
if (retryCount == null) {
retryCount = 0;
}
if (retryCount < MAX_RETRY_COUNT) {
// 增加重试次数
redisTemplate.opsForValue().increment(retryKey);
// 从缓存中获取原始消息
String messageKey = "message:content:" + messageId;
Message originalMessage = (Message) redisTemplate.opsForValue().get(messageKey);
if (originalMessage != null) {
log.warn("消息重试 [{}/{}]: {}", retryCount + 1, MAX_RETRY_COUNT, messageId);
rabbitTemplate.send(
originalMessage.getMessageProperties().getReceivedExchange(),
originalMessage.getMessageProperties().getReceivedRoutingKey(),
originalMessage,
correlationData
);
}
} else {
log.error("消息超过最大重试次数,放弃: {}", messageId);
// 记录到数据库,人工介入
saveToDeadLetter(correlationData);
}
}
private void saveToDeadLetter(CorrelationData correlationData) {
// 实现持久化逻辑
}
} log.warn("消息重试 [{}/{}]: {}", retryCount + 1, MAX_RETRY_COUNT, messageId);`
`#/**
* 高可靠性生产者
*
* 特性:
* 1. 异步Confirm
* 2. 自动重试
* 3. 消息持久化
* 4. 唯一ID生成
*/
@Service
@Slf4j
public class ReliableProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String RETRY_KEY_PREFIX = "message:retry:";
private static final int MAX_RETRY_COUNT = 3;
@PostConstruct
public void init() {
// 设置异步Confirm回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
log.info("消息发送成功: {}", correlationData);
// 清除重试缓存
String messageId = correlationData.getId();
redisTemplate.delete(RETRY_KEY_PREFIX + messageId);
} else {
log.error("消息发送失败: {}, 原因: {}", correlationData, cause);
// 触发重试
retryMessage(correlationData);
}
});
}
/**
* 发送消息(自动重试)
*/
public void sendWithRetry(String exchange, String routingKey, Object message) {
String messageId = UUID.randomUUID().toString();
// 记录重试次数
redisTemplate.opsForValue().set(
RETRY_KEY_PREFIX + messageId,
0,
24,
TimeUnit.HOURS
);
// 构建消息
MessageBuilder builder = MessageBuilder.withBody(JSON.toJSONString(message).getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_JSON)
.setDeliveryMode(MessageDeliveryMode.PERSISTENT)
.setMessageId(messageId);
// 发送消息
rabbitTemplate.send(
exchange,
routingKey,
builder.build(),
new CorrelationData(messageId)
);
}
/**
* 重试消息
*/
private void retryMessage(CorrelationData correlationData) {
String messageId = correlationData.getId();
String retryKey = RETRY_KEY_PREFIX + messageId;
Integer retryCount = (Integer) redisTemplate.opsForValue().get(retryKey);
if (retryCount == null) {
retryCount = 0;
}
if (retryCount < MAX_RETRY_COUNT) {
// 增加重试次数
redisTemplate.opsForValue().increment(retryKey);
// 从缓存中获取原始消息
String messageKey = "message:content:" + messageId;
Message originalMessage = (Message) redisTemplate.opsForValue().get(messageKey);
if (originalMessage != null) {
log.warn("消息重试 [{}/{}]: {}", retryCount + 1, MAX_RETRY_COUNT, messageId);
rabbitTemplate.send(
originalMessage.getMessageProperties().getReceivedExchange(),
originalMessage.getMessageProperties().getReceivedRoutingKey(),
originalMessage,
correlationData
);
}
} else {
log.error("消息超过最大重试次数,放弃: {}", messageId);
// 记录到数据库,人工介入
saveToDeadLetter(correlationData);
}
}
private void saveToDeadLetter(CorrelationData correlationData) {
// 实现持久化逻辑
}
} rabbitTemplate.send(`
`#/**
* 高可靠性生产者
*
* 特性:
* 1. 异步Confirm
* 2. 自动重试
* 3. 消息持久化
* 4. 唯一ID生成
*/
@Service
@Slf4j
public class ReliableProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String RETRY_KEY_PREFIX = "message:retry:";
private static final int MAX_RETRY_COUNT = 3;
@PostConstruct
public void init() {
// 设置异步Confirm回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
log.info("消息发送成功: {}", correlationData);
// 清除重试缓存
String messageId = correlationData.getId();
redisTemplate.delete(RETRY_KEY_PREFIX + messageId);
} else {
log.error("消息发送失败: {}, 原因: {}", correlationData, cause);
// 触发重试
retryMessage(correlationData);
}
});
}
/**
* 发送消息(自动重试)
*/
public void sendWithRetry(String exchange, String routingKey, Object message) {
String messageId = UUID.randomUUID().toString();
// 记录重试次数
redisTemplate.opsForValue().set(
RETRY_KEY_PREFIX + messageId,
0,
24,
TimeUnit.HOURS
);
// 构建消息
MessageBuilder builder = MessageBuilder.withBody(JSON.toJSONString(message).getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_JSON)
.setDeliveryMode(MessageDeliveryMode.PERSISTENT)
.setMessageId(messageId);
// 发送消息
rabbitTemplate.send(
exchange,
routingKey,
builder.build(),
new CorrelationData(messageId)
);
}
/**
* 重试消息
*/
private void retryMessage(CorrelationData correlationData) {
String messageId = correlationData.getId();
String retryKey = RETRY_KEY_PREFIX + messageId;
Integer retryCount = (Integer) redisTemplate.opsForValue().get(retryKey);
if (retryCount == null) {
retryCount = 0;
}
if (retryCount < MAX_RETRY_COUNT) {
// 增加重试次数
redisTemplate.opsForValue().increment(retryKey);
// 从缓存中获取原始消息
String messageKey = "message:content:" + messageId;
Message originalMessage = (Message) redisTemplate.opsForValue().get(messageKey);
if (originalMessage != null) {
log.warn("消息重试 [{}/{}]: {}", retryCount + 1, MAX_RETRY_COUNT, messageId);
rabbitTemplate.send(
originalMessage.getMessageProperties().getReceivedExchange(),
originalMessage.getMessageProperties().getReceivedRoutingKey(),
originalMessage,
correlationData
);
}
} else {
log.error("消息超过最大重试次数,放弃: {}", messageId);
// 记录到数据库,人工介入
saveToDeadLetter(correlationData);
}
}
private void saveToDeadLetter(CorrelationData correlationData) {
// 实现持久化逻辑
}
} originalMessage.getMessageProperties().getReceivedExchange(),`
`#/**
* 高可靠性生产者
*
* 特性:
* 1. 异步Confirm
* 2. 自动重试
* 3. 消息持久化
* 4. 唯一ID生成
*/
@Service
@Slf4j
public class ReliableProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String RETRY_KEY_PREFIX = "message:retry:";
private static final int MAX_RETRY_COUNT = 3;
@PostConstruct
public void init() {
// 设置异步Confirm回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
log.info("消息发送成功: {}", correlationData);
// 清除重试缓存
String messageId = correlationData.getId();
redisTemplate.delete(RETRY_KEY_PREFIX + messageId);
} else {
log.error("消息发送失败: {}, 原因: {}", correlationData, cause);
// 触发重试
retryMessage(correlationData);
}
});
}
/**
* 发送消息(自动重试)
*/
public void sendWithRetry(String exchange, String routingKey, Object message) {
String messageId = UUID.randomUUID().toString();
// 记录重试次数
redisTemplate.opsForValue().set(
RETRY_KEY_PREFIX + messageId,
0,
24,
TimeUnit.HOURS
);
// 构建消息
MessageBuilder builder = MessageBuilder.withBody(JSON.toJSONString(message).getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_JSON)
.setDeliveryMode(MessageDeliveryMode.PERSISTENT)
.setMessageId(messageId);
// 发送消息
rabbitTemplate.send(
exchange,
routingKey,
builder.build(),
new CorrelationData(messageId)
);
}
/**
* 重试消息
*/
private void retryMessage(CorrelationData correlationData) {
String messageId = correlationData.getId();
String retryKey = RETRY_KEY_PREFIX + messageId;
Integer retryCount = (Integer) redisTemplate.opsForValue().get(retryKey);
if (retryCount == null) {
retryCount = 0;
}
if (retryCount < MAX_RETRY_COUNT) {
// 增加重试次数
redisTemplate.opsForValue().increment(retryKey);
// 从缓存中获取原始消息
String messageKey = "message:content:" + messageId;
Message originalMessage = (Message) redisTemplate.opsForValue().get(messageKey);
if (originalMessage != null) {
log.warn("消息重试 [{}/{}]: {}", retryCount + 1, MAX_RETRY_COUNT, messageId);
rabbitTemplate.send(
originalMessage.getMessageProperties().getReceivedExchange(),
originalMessage.getMessageProperties().getReceivedRoutingKey(),
originalMessage,
correlationData
);
}
} else {
log.error("消息超过最大重试次数,放弃: {}", messageId);
// 记录到数据库,人工介入
saveToDeadLetter(correlationData);
}
}
private void saveToDeadLetter(CorrelationData correlationData) {
// 实现持久化逻辑
}
} originalMessage.getMessageProperties().getReceivedRoutingKey(),`
`#/**
* 高可靠性生产者
*
* 特性:
* 1. 异步Confirm
* 2. 自动重试
* 3. 消息持久化
* 4. 唯一ID生成
*/
@Service
@Slf4j
public class ReliableProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String RETRY_KEY_PREFIX = "message:retry:";
private static final int MAX_RETRY_COUNT = 3;
@PostConstruct
public void init() {
// 设置异步Confirm回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
log.info("消息发送成功: {}", correlationData);
// 清除重试缓存
String messageId = correlationData.getId();
redisTemplate.delete(RETRY_KEY_PREFIX + messageId);
} else {
log.error("消息发送失败: {}, 原因: {}", correlationData, cause);
// 触发重试
retryMessage(correlationData);
}
});
}
/**
* 发送消息(自动重试)
*/
public void sendWithRetry(String exchange, String routingKey, Object message) {
String messageId = UUID.randomUUID().toString();
// 记录重试次数
redisTemplate.opsForValue().set(
RETRY_KEY_PREFIX + messageId,
0,
24,
TimeUnit.HOURS
);
// 构建消息
MessageBuilder builder = MessageBuilder.withBody(JSON.toJSONString(message).getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_JSON)
.setDeliveryMode(MessageDeliveryMode.PERSISTENT)
.setMessageId(messageId);
// 发送消息
rabbitTemplate.send(
exchange,
routingKey,
builder.build(),
new CorrelationData(messageId)
);
}
/**
* 重试消息
*/
private void retryMessage(CorrelationData correlationData) {
String messageId = correlationData.getId();
String retryKey = RETRY_KEY_PREFIX + messageId;
Integer retryCount = (Integer) redisTemplate.opsForValue().get(retryKey);
if (retryCount == null) {
retryCount = 0;
}
if (retryCount < MAX_RETRY_COUNT) {
// 增加重试次数
redisTemplate.opsForValue().increment(retryKey);
// 从缓存中获取原始消息
String messageKey = "message:content:" + messageId;
Message originalMessage = (Message) redisTemplate.opsForValue().get(messageKey);
if (originalMessage != null) {
log.warn("消息重试 [{}/{}]: {}", retryCount + 1, MAX_RETRY_COUNT, messageId);
rabbitTemplate.send(
originalMessage.getMessageProperties().getReceivedExchange(),
originalMessage.getMessageProperties().getReceivedRoutingKey(),
originalMessage,
correlationData
);
}
} else {
log.error("消息超过最大重试次数,放弃: {}", messageId);
// 记录到数据库,人工介入
saveToDeadLetter(correlationData);
}
}
private void saveToDeadLetter(CorrelationData correlationData) {
// 实现持久化逻辑
}
} originalMessage,`
`#/**
* 高可靠性生产者
*
* 特性:
* 1. 异步Confirm
* 2. 自动重试
* 3. 消息持久化
* 4. 唯一ID生成
*/
@Service
@Slf4j
public class ReliableProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String RETRY_KEY_PREFIX = "message:retry:";
private static final int MAX_RETRY_COUNT = 3;
@PostConstruct
public void init() {
// 设置异步Confirm回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
log.info("消息发送成功: {}", correlationData);
// 清除重试缓存
String messageId = correlationData.getId();
redisTemplate.delete(RETRY_KEY_PREFIX + messageId);
} else {
log.error("消息发送失败: {}, 原因: {}", correlationData, cause);
// 触发重试
retryMessage(correlationData);
}
});
}
/**
* 发送消息(自动重试)
*/
public void sendWithRetry(String exchange, String routingKey, Object message) {
String messageId = UUID.randomUUID().toString();
// 记录重试次数
redisTemplate.opsForValue().set(
RETRY_KEY_PREFIX + messageId,
0,
24,
TimeUnit.HOURS
);
// 构建消息
MessageBuilder builder = MessageBuilder.withBody(JSON.toJSONString(message).getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_JSON)
.setDeliveryMode(MessageDeliveryMode.PERSISTENT)
.setMessageId(messageId);
// 发送消息
rabbitTemplate.send(
exchange,
routingKey,
builder.build(),
new CorrelationData(messageId)
);
}
/**
* 重试消息
*/
private void retryMessage(CorrelationData correlationData) {
String messageId = correlationData.getId();
String retryKey = RETRY_KEY_PREFIX + messageId;
Integer retryCount = (Integer) redisTemplate.opsForValue().get(retryKey);
if (retryCount == null) {
retryCount = 0;
}
if (retryCount < MAX_RETRY_COUNT) {
// 增加重试次数
redisTemplate.opsForValue().increment(retryKey);
// 从缓存中获取原始消息
String messageKey = "message:content:" + messageId;
Message originalMessage = (Message) redisTemplate.opsForValue().get(messageKey);
if (originalMessage != null) {
log.warn("消息重试 [{}/{}]: {}", retryCount + 1, MAX_RETRY_COUNT, messageId);
rabbitTemplate.send(
originalMessage.getMessageProperties().getReceivedExchange(),
originalMessage.getMessageProperties().getReceivedRoutingKey(),
originalMessage,
correlationData
);
}
} else {
log.error("消息超过最大重试次数,放弃: {}", messageId);
// 记录到数据库,人工介入
saveToDeadLetter(correlationData);
}
}
private void saveToDeadLetter(CorrelationData correlationData) {
// 实现持久化逻辑
}
} correlationData`
`#/**
* 高可靠性生产者
*
* 特性:
* 1. 异步Confirm
* 2. 自动重试
* 3. 消息持久化
* 4. 唯一ID生成
*/
@Service
@Slf4j
public class ReliableProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String RETRY_KEY_PREFIX = "message:retry:";
private static final int MAX_RETRY_COUNT = 3;
@PostConstruct
public void init() {
// 设置异步Confirm回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
log.info("消息发送成功: {}", correlationData);
// 清除重试缓存
String messageId = correlationData.getId();
redisTemplate.delete(RETRY_KEY_PREFIX + messageId);
} else {
log.error("消息发送失败: {}, 原因: {}", correlationData, cause);
// 触发重试
retryMessage(correlationData);
}
});
}
/**
* 发送消息(自动重试)
*/
public void sendWithRetry(String exchange, String routingKey, Object message) {
String messageId = UUID.randomUUID().toString();
// 记录重试次数
redisTemplate.opsForValue().set(
RETRY_KEY_PREFIX + messageId,
0,
24,
TimeUnit.HOURS
);
// 构建消息
MessageBuilder builder = MessageBuilder.withBody(JSON.toJSONString(message).getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_JSON)
.setDeliveryMode(MessageDeliveryMode.PERSISTENT)
.setMessageId(messageId);
// 发送消息
rabbitTemplate.send(
exchange,
routingKey,
builder.build(),
new CorrelationData(messageId)
);
}
/**
* 重试消息
*/
private void retryMessage(CorrelationData correlationData) {
String messageId = correlationData.getId();
String retryKey = RETRY_KEY_PREFIX + messageId;
Integer retryCount = (Integer) redisTemplate.opsForValue().get(retryKey);
if (retryCount == null) {
retryCount = 0;
}
if (retryCount < MAX_RETRY_COUNT) {
// 增加重试次数
redisTemplate.opsForValue().increment(retryKey);
// 从缓存中获取原始消息
String messageKey = "message:content:" + messageId;
Message originalMessage = (Message) redisTemplate.opsForValue().get(messageKey);
if (originalMessage != null) {
log.warn("消息重试 [{}/{}]: {}", retryCount + 1, MAX_RETRY_COUNT, messageId);
rabbitTemplate.send(
originalMessage.getMessageProperties().getReceivedExchange(),
originalMessage.getMessageProperties().getReceivedRoutingKey(),
originalMessage,
correlationData
);
}
} else {
log.error("消息超过最大重试次数,放弃: {}", messageId);
// 记录到数据库,人工介入
saveToDeadLetter(correlationData);
}
}
private void saveToDeadLetter(CorrelationData correlationData) {
// 实现持久化逻辑
}
} );`
`#/**
* 高可靠性生产者
*
* 特性:
* 1. 异步Confirm
* 2. 自动重试
* 3. 消息持久化
* 4. 唯一ID生成
*/
@Service
@Slf4j
public class ReliableProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String RETRY_KEY_PREFIX = "message:retry:";
private static final int MAX_RETRY_COUNT = 3;
@PostConstruct
public void init() {
// 设置异步Confirm回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
log.info("消息发送成功: {}", correlationData);
// 清除重试缓存
String messageId = correlationData.getId();
redisTemplate.delete(RETRY_KEY_PREFIX + messageId);
} else {
log.error("消息发送失败: {}, 原因: {}", correlationData, cause);
// 触发重试
retryMessage(correlationData);
}
});
}
/**
* 发送消息(自动重试)
*/
public void sendWithRetry(String exchange, String routingKey, Object message) {
String messageId = UUID.randomUUID().toString();
// 记录重试次数
redisTemplate.opsForValue().set(
RETRY_KEY_PREFIX + messageId,
0,
24,
TimeUnit.HOURS
);
// 构建消息
MessageBuilder builder = MessageBuilder.withBody(JSON.toJSONString(message).getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_JSON)
.setDeliveryMode(MessageDeliveryMode.PERSISTENT)
.setMessageId(messageId);
// 发送消息
rabbitTemplate.send(
exchange,
routingKey,
builder.build(),
new CorrelationData(messageId)
);
}
/**
* 重试消息
*/
private void retryMessage(CorrelationData correlationData) {
String messageId = correlationData.getId();
String retryKey = RETRY_KEY_PREFIX + messageId;
Integer retryCount = (Integer) redisTemplate.opsForValue().get(retryKey);
if (retryCount == null) {
retryCount = 0;
}
if (retryCount < MAX_RETRY_COUNT) {
// 增加重试次数
redisTemplate.opsForValue().increment(retryKey);
// 从缓存中获取原始消息
String messageKey = "message:content:" + messageId;
Message originalMessage = (Message) redisTemplate.opsForValue().get(messageKey);
if (originalMessage != null) {
log.warn("消息重试 [{}/{}]: {}", retryCount + 1, MAX_RETRY_COUNT, messageId);
rabbitTemplate.send(
originalMessage.getMessageProperties().getReceivedExchange(),
originalMessage.getMessageProperties().getReceivedRoutingKey(),
originalMessage,
correlationData
);
}
} else {
log.error("消息超过最大重试次数,放弃: {}", messageId);
// 记录到数据库,人工介入
saveToDeadLetter(correlationData);
}
}
private void saveToDeadLetter(CorrelationData correlationData) {
// 实现持久化逻辑
}
} }`
`#/**
* 高可靠性生产者
*
* 特性:
* 1. 异步Confirm
* 2. 自动重试
* 3. 消息持久化
* 4. 唯一ID生成
*/
@Service
@Slf4j
public class ReliableProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String RETRY_KEY_PREFIX = "message:retry:";
private static final int MAX_RETRY_COUNT = 3;
@PostConstruct
public void init() {
// 设置异步Confirm回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
log.info("消息发送成功: {}", correlationData);
// 清除重试缓存
String messageId = correlationData.getId();
redisTemplate.delete(RETRY_KEY_PREFIX + messageId);
} else {
log.error("消息发送失败: {}, 原因: {}", correlationData, cause);
// 触发重试
retryMessage(correlationData);
}
});
}
/**
* 发送消息(自动重试)
*/
public void sendWithRetry(String exchange, String routingKey, Object message) {
String messageId = UUID.randomUUID().toString();
// 记录重试次数
redisTemplate.opsForValue().set(
RETRY_KEY_PREFIX + messageId,
0,
24,
TimeUnit.HOURS
);
// 构建消息
MessageBuilder builder = MessageBuilder.withBody(JSON.toJSONString(message).getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_JSON)
.setDeliveryMode(MessageDeliveryMode.PERSISTENT)
.setMessageId(messageId);
// 发送消息
rabbitTemplate.send(
exchange,
routingKey,
builder.build(),
new CorrelationData(messageId)
);
}
/**
* 重试消息
*/
private void retryMessage(CorrelationData correlationData) {
String messageId = correlationData.getId();
String retryKey = RETRY_KEY_PREFIX + messageId;
Integer retryCount = (Integer) redisTemplate.opsForValue().get(retryKey);
if (retryCount == null) {
retryCount = 0;
}
if (retryCount < MAX_RETRY_COUNT) {
// 增加重试次数
redisTemplate.opsForValue().increment(retryKey);
// 从缓存中获取原始消息
String messageKey = "message:content:" + messageId;
Message originalMessage = (Message) redisTemplate.opsForValue().get(messageKey);
if (originalMessage != null) {
log.warn("消息重试 [{}/{}]: {}", retryCount + 1, MAX_RETRY_COUNT, messageId);
rabbitTemplate.send(
originalMessage.getMessageProperties().getReceivedExchange(),
originalMessage.getMessageProperties().getReceivedRoutingKey(),
originalMessage,
correlationData
);
}
} else {
log.error("消息超过最大重试次数,放弃: {}", messageId);
// 记录到数据库,人工介入
saveToDeadLetter(correlationData);
}
}
private void saveToDeadLetter(CorrelationData correlationData) {
// 实现持久化逻辑
}
} } else {`
`#/**
* 高可靠性生产者
*
* 特性:
* 1. 异步Confirm
* 2. 自动重试
* 3. 消息持久化
* 4. 唯一ID生成
*/
@Service
@Slf4j
public class ReliableProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String RETRY_KEY_PREFIX = "message:retry:";
private static final int MAX_RETRY_COUNT = 3;
@PostConstruct
public void init() {
// 设置异步Confirm回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
log.info("消息发送成功: {}", correlationData);
// 清除重试缓存
String messageId = correlationData.getId();
redisTemplate.delete(RETRY_KEY_PREFIX + messageId);
} else {
log.error("消息发送失败: {}, 原因: {}", correlationData, cause);
// 触发重试
retryMessage(correlationData);
}
});
}
/**
* 发送消息(自动重试)
*/
public void sendWithRetry(String exchange, String routingKey, Object message) {
String messageId = UUID.randomUUID().toString();
// 记录重试次数
redisTemplate.opsForValue().set(
RETRY_KEY_PREFIX + messageId,
0,
24,
TimeUnit.HOURS
);
// 构建消息
MessageBuilder builder = MessageBuilder.withBody(JSON.toJSONString(message).getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_JSON)
.setDeliveryMode(MessageDeliveryMode.PERSISTENT)
.setMessageId(messageId);
// 发送消息
rabbitTemplate.send(
exchange,
routingKey,
builder.build(),
new CorrelationData(messageId)
);
}
/**
* 重试消息
*/
private void retryMessage(CorrelationData correlationData) {
String messageId = correlationData.getId();
String retryKey = RETRY_KEY_PREFIX + messageId;
Integer retryCount = (Integer) redisTemplate.opsForValue().get(retryKey);
if (retryCount == null) {
retryCount = 0;
}
if (retryCount < MAX_RETRY_COUNT) {
// 增加重试次数
redisTemplate.opsForValue().increment(retryKey);
// 从缓存中获取原始消息
String messageKey = "message:content:" + messageId;
Message originalMessage = (Message) redisTemplate.opsForValue().get(messageKey);
if (originalMessage != null) {
log.warn("消息重试 [{}/{}]: {}", retryCount + 1, MAX_RETRY_COUNT, messageId);
rabbitTemplate.send(
originalMessage.getMessageProperties().getReceivedExchange(),
originalMessage.getMessageProperties().getReceivedRoutingKey(),
originalMessage,
correlationData
);
}
} else {
log.error("消息超过最大重试次数,放弃: {}", messageId);
// 记录到数据库,人工介入
saveToDeadLetter(correlationData);
}
}
private void saveToDeadLetter(CorrelationData correlationData) {
// 实现持久化逻辑
}
} log.error("消息超过最大重试次数,放弃: {}", messageId);`
`#/**
* 高可靠性生产者
*
* 特性:
* 1. 异步Confirm
* 2. 自动重试
* 3. 消息持久化
* 4. 唯一ID生成
*/
@Service
@Slf4j
public class ReliableProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String RETRY_KEY_PREFIX = "message:retry:";
private static final int MAX_RETRY_COUNT = 3;
@PostConstruct
public void init() {
// 设置异步Confirm回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
log.info("消息发送成功: {}", correlationData);
// 清除重试缓存
String messageId = correlationData.getId();
redisTemplate.delete(RETRY_KEY_PREFIX + messageId);
} else {
log.error("消息发送失败: {}, 原因: {}", correlationData, cause);
// 触发重试
retryMessage(correlationData);
}
});
}
/**
* 发送消息(自动重试)
*/
public void sendWithRetry(String exchange, String routingKey, Object message) {
String messageId = UUID.randomUUID().toString();
// 记录重试次数
redisTemplate.opsForValue().set(
RETRY_KEY_PREFIX + messageId,
0,
24,
TimeUnit.HOURS
);
// 构建消息
MessageBuilder builder = MessageBuilder.withBody(JSON.toJSONString(message).getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_JSON)
.setDeliveryMode(MessageDeliveryMode.PERSISTENT)
.setMessageId(messageId);
// 发送消息
rabbitTemplate.send(
exchange,
routingKey,
builder.build(),
new CorrelationData(messageId)
);
}
/**
* 重试消息
*/
private void retryMessage(CorrelationData correlationData) {
String messageId = correlationData.getId();
String retryKey = RETRY_KEY_PREFIX + messageId;
Integer retryCount = (Integer) redisTemplate.opsForValue().get(retryKey);
if (retryCount == null) {
retryCount = 0;
}
if (retryCount < MAX_RETRY_COUNT) {
// 增加重试次数
redisTemplate.opsForValue().increment(retryKey);
// 从缓存中获取原始消息
String messageKey = "message:content:" + messageId;
Message originalMessage = (Message) redisTemplate.opsForValue().get(messageKey);
if (originalMessage != null) {
log.warn("消息重试 [{}/{}]: {}", retryCount + 1, MAX_RETRY_COUNT, messageId);
rabbitTemplate.send(
originalMessage.getMessageProperties().getReceivedExchange(),
originalMessage.getMessageProperties().getReceivedRoutingKey(),
originalMessage,
correlationData
);
}
} else {
log.error("消息超过最大重试次数,放弃: {}", messageId);
// 记录到数据库,人工介入
saveToDeadLetter(correlationData);
}
}
private void saveToDeadLetter(CorrelationData correlationData) {
// 实现持久化逻辑
}
} // 记录到数据库,人工介入`
`#/**
* 高可靠性生产者
*
* 特性:
* 1. 异步Confirm
* 2. 自动重试
* 3. 消息持久化
* 4. 唯一ID生成
*/
@Service
@Slf4j
public class ReliableProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String RETRY_KEY_PREFIX = "message:retry:";
private static final int MAX_RETRY_COUNT = 3;
@PostConstruct
public void init() {
// 设置异步Confirm回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
log.info("消息发送成功: {}", correlationData);
// 清除重试缓存
String messageId = correlationData.getId();
redisTemplate.delete(RETRY_KEY_PREFIX + messageId);
} else {
log.error("消息发送失败: {}, 原因: {}", correlationData, cause);
// 触发重试
retryMessage(correlationData);
}
});
}
/**
* 发送消息(自动重试)
*/
public void sendWithRetry(String exchange, String routingKey, Object message) {
String messageId = UUID.randomUUID().toString();
// 记录重试次数
redisTemplate.opsForValue().set(
RETRY_KEY_PREFIX + messageId,
0,
24,
TimeUnit.HOURS
);
// 构建消息
MessageBuilder builder = MessageBuilder.withBody(JSON.toJSONString(message).getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_JSON)
.setDeliveryMode(MessageDeliveryMode.PERSISTENT)
.setMessageId(messageId);
// 发送消息
rabbitTemplate.send(
exchange,
routingKey,
builder.build(),
new CorrelationData(messageId)
);
}
/**
* 重试消息
*/
private void retryMessage(CorrelationData correlationData) {
String messageId = correlationData.getId();
String retryKey = RETRY_KEY_PREFIX + messageId;
Integer retryCount = (Integer) redisTemplate.opsForValue().get(retryKey);
if (retryCount == null) {
retryCount = 0;
}
if (retryCount < MAX_RETRY_COUNT) {
// 增加重试次数
redisTemplate.opsForValue().increment(retryKey);
// 从缓存中获取原始消息
String messageKey = "message:content:" + messageId;
Message originalMessage = (Message) redisTemplate.opsForValue().get(messageKey);
if (originalMessage != null) {
log.warn("消息重试 [{}/{}]: {}", retryCount + 1, MAX_RETRY_COUNT, messageId);
rabbitTemplate.send(
originalMessage.getMessageProperties().getReceivedExchange(),
originalMessage.getMessageProperties().getReceivedRoutingKey(),
originalMessage,
correlationData
);
}
} else {
log.error("消息超过最大重试次数,放弃: {}", messageId);
// 记录到数据库,人工介入
saveToDeadLetter(correlationData);
}
}
private void saveToDeadLetter(CorrelationData correlationData) {
// 实现持久化逻辑
}
} saveToDeadLetter(correlationData);`
`#/**
* 高可靠性生产者
*
* 特性:
* 1. 异步Confirm
* 2. 自动重试
* 3. 消息持久化
* 4. 唯一ID生成
*/
@Service
@Slf4j
public class ReliableProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String RETRY_KEY_PREFIX = "message:retry:";
private static final int MAX_RETRY_COUNT = 3;
@PostConstruct
public void init() {
// 设置异步Confirm回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
log.info("消息发送成功: {}", correlationData);
// 清除重试缓存
String messageId = correlationData.getId();
redisTemplate.delete(RETRY_KEY_PREFIX + messageId);
} else {
log.error("消息发送失败: {}, 原因: {}", correlationData, cause);
// 触发重试
retryMessage(correlationData);
}
});
}
/**
* 发送消息(自动重试)
*/
public void sendWithRetry(String exchange, String routingKey, Object message) {
String messageId = UUID.randomUUID().toString();
// 记录重试次数
redisTemplate.opsForValue().set(
RETRY_KEY_PREFIX + messageId,
0,
24,
TimeUnit.HOURS
);
// 构建消息
MessageBuilder builder = MessageBuilder.withBody(JSON.toJSONString(message).getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_JSON)
.setDeliveryMode(MessageDeliveryMode.PERSISTENT)
.setMessageId(messageId);
// 发送消息
rabbitTemplate.send(
exchange,
routingKey,
builder.build(),
new CorrelationData(messageId)
);
}
/**
* 重试消息
*/
private void retryMessage(CorrelationData correlationData) {
String messageId = correlationData.getId();
String retryKey = RETRY_KEY_PREFIX + messageId;
Integer retryCount = (Integer) redisTemplate.opsForValue().get(retryKey);
if (retryCount == null) {
retryCount = 0;
}
if (retryCount < MAX_RETRY_COUNT) {
// 增加重试次数
redisTemplate.opsForValue().increment(retryKey);
// 从缓存中获取原始消息
String messageKey = "message:content:" + messageId;
Message originalMessage = (Message) redisTemplate.opsForValue().get(messageKey);
if (originalMessage != null) {
log.warn("消息重试 [{}/{}]: {}", retryCount + 1, MAX_RETRY_COUNT, messageId);
rabbitTemplate.send(
originalMessage.getMessageProperties().getReceivedExchange(),
originalMessage.getMessageProperties().getReceivedRoutingKey(),
originalMessage,
correlationData
);
}
} else {
log.error("消息超过最大重试次数,放弃: {}", messageId);
// 记录到数据库,人工介入
saveToDeadLetter(correlationData);
}
}
private void saveToDeadLetter(CorrelationData correlationData) {
// 实现持久化逻辑
}
} }`
`#/**
* 高可靠性生产者
*
* 特性:
* 1. 异步Confirm
* 2. 自动重试
* 3. 消息持久化
* 4. 唯一ID生成
*/
@Service
@Slf4j
public class ReliableProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String RETRY_KEY_PREFIX = "message:retry:";
private static final int MAX_RETRY_COUNT = 3;
@PostConstruct
public void init() {
// 设置异步Confirm回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
log.info("消息发送成功: {}", correlationData);
// 清除重试缓存
String messageId = correlationData.getId();
redisTemplate.delete(RETRY_KEY_PREFIX + messageId);
} else {
log.error("消息发送失败: {}, 原因: {}", correlationData, cause);
// 触发重试
retryMessage(correlationData);
}
});
}
/**
* 发送消息(自动重试)
*/
public void sendWithRetry(String exchange, String routingKey, Object message) {
String messageId = UUID.randomUUID().toString();
// 记录重试次数
redisTemplate.opsForValue().set(
RETRY_KEY_PREFIX + messageId,
0,
24,
TimeUnit.HOURS
);
// 构建消息
MessageBuilder builder = MessageBuilder.withBody(JSON.toJSONString(message).getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_JSON)
.setDeliveryMode(MessageDeliveryMode.PERSISTENT)
.setMessageId(messageId);
// 发送消息
rabbitTemplate.send(
exchange,
routingKey,
builder.build(),
new CorrelationData(messageId)
);
}
/**
* 重试消息
*/
private void retryMessage(CorrelationData correlationData) {
String messageId = correlationData.getId();
String retryKey = RETRY_KEY_PREFIX + messageId;
Integer retryCount = (Integer) redisTemplate.opsForValue().get(retryKey);
if (retryCount == null) {
retryCount = 0;
}
if (retryCount < MAX_RETRY_COUNT) {
// 增加重试次数
redisTemplate.opsForValue().increment(retryKey);
// 从缓存中获取原始消息
String messageKey = "message:content:" + messageId;
Message originalMessage = (Message) redisTemplate.opsForValue().get(messageKey);
if (originalMessage != null) {
log.warn("消息重试 [{}/{}]: {}", retryCount + 1, MAX_RETRY_COUNT, messageId);
rabbitTemplate.send(
originalMessage.getMessageProperties().getReceivedExchange(),
originalMessage.getMessageProperties().getReceivedRoutingKey(),
originalMessage,
correlationData
);
}
} else {
log.error("消息超过最大重试次数,放弃: {}", messageId);
// 记录到数据库,人工介入
saveToDeadLetter(correlationData);
}
}
private void saveToDeadLetter(CorrelationData correlationData) {
// 实现持久化逻辑
}
} }`
`#/**
* 高可靠性生产者
*
* 特性:
* 1. 异步Confirm
* 2. 自动重试
* 3. 消息持久化
* 4. 唯一ID生成
*/
@Service
@Slf4j
public class ReliableProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String RETRY_KEY_PREFIX = "message:retry:";
private static final int MAX_RETRY_COUNT = 3;
@PostConstruct
public void init() {
// 设置异步Confirm回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
log.info("消息发送成功: {}", correlationData);
// 清除重试缓存
String messageId = correlationData.getId();
redisTemplate.delete(RETRY_KEY_PREFIX + messageId);
} else {
log.error("消息发送失败: {}, 原因: {}", correlationData, cause);
// 触发重试
retryMessage(correlationData);
}
});
}
/**
* 发送消息(自动重试)
*/
public void sendWithRetry(String exchange, String routingKey, Object message) {
String messageId = UUID.randomUUID().toString();
// 记录重试次数
redisTemplate.opsForValue().set(
RETRY_KEY_PREFIX + messageId,
0,
24,
TimeUnit.HOURS
);
// 构建消息
MessageBuilder builder = MessageBuilder.withBody(JSON.toJSONString(message).getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_JSON)
.setDeliveryMode(MessageDeliveryMode.PERSISTENT)
.setMessageId(messageId);
// 发送消息
rabbitTemplate.send(
exchange,
routingKey,
builder.build(),
new CorrelationData(messageId)
);
}
/**
* 重试消息
*/
private void retryMessage(CorrelationData correlationData) {
String messageId = correlationData.getId();
String retryKey = RETRY_KEY_PREFIX + messageId;
Integer retryCount = (Integer) redisTemplate.opsForValue().get(retryKey);
if (retryCount == null) {
retryCount = 0;
}
if (retryCount < MAX_RETRY_COUNT) {
// 增加重试次数
redisTemplate.opsForValue().increment(retryKey);
// 从缓存中获取原始消息
String messageKey = "message:content:" + messageId;
Message originalMessage = (Message) redisTemplate.opsForValue().get(messageKey);
if (originalMessage != null) {
log.warn("消息重试 [{}/{}]: {}", retryCount + 1, MAX_RETRY_COUNT, messageId);
rabbitTemplate.send(
originalMessage.getMessageProperties().getReceivedExchange(),
originalMessage.getMessageProperties().getReceivedRoutingKey(),
originalMessage,
correlationData
);
}
} else {
log.error("消息超过最大重试次数,放弃: {}", messageId);
// 记录到数据库,人工介入
saveToDeadLetter(correlationData);
}
}
private void saveToDeadLetter(CorrelationData correlationData) {
// 实现持久化逻辑
}
}`
`#/**
* 高可靠性生产者
*
* 特性:
* 1. 异步Confirm
* 2. 自动重试
* 3. 消息持久化
* 4. 唯一ID生成
*/
@Service
@Slf4j
public class ReliableProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String RETRY_KEY_PREFIX = "message:retry:";
private static final int MAX_RETRY_COUNT = 3;
@PostConstruct
public void init() {
// 设置异步Confirm回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
log.info("消息发送成功: {}", correlationData);
// 清除重试缓存
String messageId = correlationData.getId();
redisTemplate.delete(RETRY_KEY_PREFIX + messageId);
} else {
log.error("消息发送失败: {}, 原因: {}", correlationData, cause);
// 触发重试
retryMessage(correlationData);
}
});
}
/**
* 发送消息(自动重试)
*/
public void sendWithRetry(String exchange, String routingKey, Object message) {
String messageId = UUID.randomUUID().toString();
// 记录重试次数
redisTemplate.opsForValue().set(
RETRY_KEY_PREFIX + messageId,
0,
24,
TimeUnit.HOURS
);
// 构建消息
MessageBuilder builder = MessageBuilder.withBody(JSON.toJSONString(message).getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_JSON)
.setDeliveryMode(MessageDeliveryMode.PERSISTENT)
.setMessageId(messageId);
// 发送消息
rabbitTemplate.send(
exchange,
routingKey,
builder.build(),
new CorrelationData(messageId)
);
}
/**
* 重试消息
*/
private void retryMessage(CorrelationData correlationData) {
String messageId = correlationData.getId();
String retryKey = RETRY_KEY_PREFIX + messageId;
Integer retryCount = (Integer) redisTemplate.opsForValue().get(retryKey);
if (retryCount == null) {
retryCount = 0;
}
if (retryCount < MAX_RETRY_COUNT) {
// 增加重试次数
redisTemplate.opsForValue().increment(retryKey);
// 从缓存中获取原始消息
String messageKey = "message:content:" + messageId;
Message originalMessage = (Message) redisTemplate.opsForValue().get(messageKey);
if (originalMessage != null) {
log.warn("消息重试 [{}/{}]: {}", retryCount + 1, MAX_RETRY_COUNT, messageId);
rabbitTemplate.send(
originalMessage.getMessageProperties().getReceivedExchange(),
originalMessage.getMessageProperties().getReceivedRoutingKey(),
originalMessage,
correlationData
);
}
} else {
log.error("消息超过最大重试次数,放弃: {}", messageId);
// 记录到数据库,人工介入
saveToDeadLetter(correlationData);
}
}
private void saveToDeadLetter(CorrelationData correlationData) {
// 实现持久化逻辑
}
} private void saveToDeadLetter(CorrelationData correlationData) {`
`#/**
* 高可靠性生产者
*
* 特性:
* 1. 异步Confirm
* 2. 自动重试
* 3. 消息持久化
* 4. 唯一ID生成
*/
@Service
@Slf4j
public class ReliableProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String RETRY_KEY_PREFIX = "message:retry:";
private static final int MAX_RETRY_COUNT = 3;
@PostConstruct
public void init() {
// 设置异步Confirm回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
log.info("消息发送成功: {}", correlationData);
// 清除重试缓存
String messageId = correlationData.getId();
redisTemplate.delete(RETRY_KEY_PREFIX + messageId);
} else {
log.error("消息发送失败: {}, 原因: {}", correlationData, cause);
// 触发重试
retryMessage(correlationData);
}
});
}
/**
* 发送消息(自动重试)
*/
public void sendWithRetry(String exchange, String routingKey, Object message) {
String messageId = UUID.randomUUID().toString();
// 记录重试次数
redisTemplate.opsForValue().set(
RETRY_KEY_PREFIX + messageId,
0,
24,
TimeUnit.HOURS
);
// 构建消息
MessageBuilder builder = MessageBuilder.withBody(JSON.toJSONString(message).getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_JSON)
.setDeliveryMode(MessageDeliveryMode.PERSISTENT)
.setMessageId(messageId);
// 发送消息
rabbitTemplate.send(
exchange,
routingKey,
builder.build(),
new CorrelationData(messageId)
);
}
/**
* 重试消息
*/
private void retryMessage(CorrelationData correlationData) {
String messageId = correlationData.getId();
String retryKey = RETRY_KEY_PREFIX + messageId;
Integer retryCount = (Integer) redisTemplate.opsForValue().get(retryKey);
if (retryCount == null) {
retryCount = 0;
}
if (retryCount < MAX_RETRY_COUNT) {
// 增加重试次数
redisTemplate.opsForValue().increment(retryKey);
// 从缓存中获取原始消息
String messageKey = "message:content:" + messageId;
Message originalMessage = (Message) redisTemplate.opsForValue().get(messageKey);
if (originalMessage != null) {
log.warn("消息重试 [{}/{}]: {}", retryCount + 1, MAX_RETRY_COUNT, messageId);
rabbitTemplate.send(
originalMessage.getMessageProperties().getReceivedExchange(),
originalMessage.getMessageProperties().getReceivedRoutingKey(),
originalMessage,
correlationData
);
}
} else {
log.error("消息超过最大重试次数,放弃: {}", messageId);
// 记录到数据库,人工介入
saveToDeadLetter(correlationData);
}
}
private void saveToDeadLetter(CorrelationData correlationData) {
// 实现持久化逻辑
}
} // 实现持久化逻辑`
`#/**
* 高可靠性生产者
*
* 特性:
* 1. 异步Confirm
* 2. 自动重试
* 3. 消息持久化
* 4. 唯一ID生成
*/
@Service
@Slf4j
public class ReliableProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String RETRY_KEY_PREFIX = "message:retry:";
private static final int MAX_RETRY_COUNT = 3;
@PostConstruct
public void init() {
// 设置异步Confirm回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
log.info("消息发送成功: {}", correlationData);
// 清除重试缓存
String messageId = correlationData.getId();
redisTemplate.delete(RETRY_KEY_PREFIX + messageId);
} else {
log.error("消息发送失败: {}, 原因: {}", correlationData, cause);
// 触发重试
retryMessage(correlationData);
}
});
}
/**
* 发送消息(自动重试)
*/
public void sendWithRetry(String exchange, String routingKey, Object message) {
String messageId = UUID.randomUUID().toString();
// 记录重试次数
redisTemplate.opsForValue().set(
RETRY_KEY_PREFIX + messageId,
0,
24,
TimeUnit.HOURS
);
// 构建消息
MessageBuilder builder = MessageBuilder.withBody(JSON.toJSONString(message).getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_JSON)
.setDeliveryMode(MessageDeliveryMode.PERSISTENT)
.setMessageId(messageId);
// 发送消息
rabbitTemplate.send(
exchange,
routingKey,
builder.build(),
new CorrelationData(messageId)
);
}
/**
* 重试消息
*/
private void retryMessage(CorrelationData correlationData) {
String messageId = correlationData.getId();
String retryKey = RETRY_KEY_PREFIX + messageId;
Integer retryCount = (Integer) redisTemplate.opsForValue().get(retryKey);
if (retryCount == null) {
retryCount = 0;
}
if (retryCount < MAX_RETRY_COUNT) {
// 增加重试次数
redisTemplate.opsForValue().increment(retryKey);
// 从缓存中获取原始消息
String messageKey = "message:content:" + messageId;
Message originalMessage = (Message) redisTemplate.opsForValue().get(messageKey);
if (originalMessage != null) {
log.warn("消息重试 [{}/{}]: {}", retryCount + 1, MAX_RETRY_COUNT, messageId);
rabbitTemplate.send(
originalMessage.getMessageProperties().getReceivedExchange(),
originalMessage.getMessageProperties().getReceivedRoutingKey(),
originalMessage,
correlationData
);
}
} else {
log.error("消息超过最大重试次数,放弃: {}", messageId);
// 记录到数据库,人工介入
saveToDeadLetter(correlationData);
}
}
private void saveToDeadLetter(CorrelationData correlationData) {
// 实现持久化逻辑
}
} }`
`#/**
* 高可靠性生产者
*
* 特性:
* 1. 异步Confirm
* 2. 自动重试
* 3. 消息持久化
* 4. 唯一ID生成
*/
@Service
@Slf4j
public class ReliableProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String RETRY_KEY_PREFIX = "message:retry:";
private static final int MAX_RETRY_COUNT = 3;
@PostConstruct
public void init() {
// 设置异步Confirm回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
log.info("消息发送成功: {}", correlationData);
// 清除重试缓存
String messageId = correlationData.getId();
redisTemplate.delete(RETRY_KEY_PREFIX + messageId);
} else {
log.error("消息发送失败: {}, 原因: {}", correlationData, cause);
// 触发重试
retryMessage(correlationData);
}
});
}
/**
* 发送消息(自动重试)
*/
public void sendWithRetry(String exchange, String routingKey, Object message) {
String messageId = UUID.randomUUID().toString();
// 记录重试次数
redisTemplate.opsForValue().set(
RETRY_KEY_PREFIX + messageId,
0,
24,
TimeUnit.HOURS
);
// 构建消息
MessageBuilder builder = MessageBuilder.withBody(JSON.toJSONString(message).getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_JSON)
.setDeliveryMode(MessageDeliveryMode.PERSISTENT)
.setMessageId(messageId);
// 发送消息
rabbitTemplate.send(
exchange,
routingKey,
builder.build(),
new CorrelationData(messageId)
);
}
/**
* 重试消息
*/
private void retryMessage(CorrelationData correlationData) {
String messageId = correlationData.getId();
String retryKey = RETRY_KEY_PREFIX + messageId;
Integer retryCount = (Integer) redisTemplate.opsForValue().get(retryKey);
if (retryCount == null) {
retryCount = 0;
}
if (retryCount < MAX_RETRY_COUNT) {
// 增加重试次数
redisTemplate.opsForValue().increment(retryKey);
// 从缓存中获取原始消息
String messageKey = "message:content:" + messageId;
Message originalMessage = (Message) redisTemplate.opsForValue().get(messageKey);
if (originalMessage != null) {
log.warn("消息重试 [{}/{}]: {}", retryCount + 1, MAX_RETRY_COUNT, messageId);
rabbitTemplate.send(
originalMessage.getMessageProperties().getReceivedExchange(),
originalMessage.getMessageProperties().getReceivedRoutingKey(),
originalMessage,
correlationData
);
}
} else {
log.error("消息超过最大重试次数,放弃: {}", messageId);
// 记录到数据库,人工介入
saveToDeadLetter(correlationData);
}
}
private void saveToDeadLetter(CorrelationData correlationData) {
// 实现持久化逻辑
}
}}
5.2.2 消费者:带幂等和死信的可靠消费
java
#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
}/**`
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
} * 高可靠性消费者`
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
} * `
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
} * 特性:`
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
} * 1. 手动ACK`
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
} * 2. 幂等性检查`
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
} * 3. 死信处理`
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
} * 4. 异常分类`
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
} */`
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
}@Component`
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
}@Slf4j`
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
}public class ReliableConsumer {`
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
}`
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
} @Autowired`
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
} private RedisTemplate<String, String> redisTemplate;`
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
}`
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
} @Autowired`
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
} private MessageProcessor messageProcessor;`
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
}`
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
} private static final String IDEMPOTENT_PREFIX = "message:processed:";`
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
}`
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
} @RabbitListener(`
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
} queues = "business.queue",`
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
} containerFactory = "manualAckContainerFactory"`
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
} )`
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
} public void handle(`
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
} Message message,`
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
} Channel channel,`
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
} @Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {`
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
} `
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
} String messageId = message.getMessageProperties().getMessageId();`
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
} String idempotentKey = IDEMPOTENT_PREFIX + messageId;`
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
} `
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
} try {`
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
} // 1. 幂等性检查`
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
} Boolean isFirstTime = redisTemplate.opsForValue()`
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
} .setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);`
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
} `
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
} if (Boolean.FALSE.equals(isFirstTime)) {`
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
} // 重复消息,直接确认`
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
} log.info("消息重复,直接ACK: {}", messageId);`
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
} channel.basicAck(deliveryTag, false);`
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
} return;`
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
} }`
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
} `
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
} // 2. 处理消息`
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
} String messageBody = new String(message.getBody());`
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
} messageProcessor.process(messageBody);`
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
} `
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
} // 3. 处理成功,确认消息`
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
} channel.basicAck(deliveryTag, false);`
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
} log.info("消息处理成功: {}", messageId);`
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
} `
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
} } catch (TemporaryFailureException e) {`
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
} // 临时异常:NACK并重新入队`
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
} try {`
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
} // 删除幂等标记,允许重试`
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
} redisTemplate.delete(idempotentKey);`
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
} channel.basicNack(deliveryTag, false, true);`
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
} log.warn("临时异常,消息重新入队: {}", e.getMessage());`
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
} } catch (IOException ex) {`
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
} log.error("NACK失败", ex);`
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
} }`
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
} `
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
} } catch (PermanentFailureException e) {`
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
} // 永久异常:NACK不重新入队(进入死信队列)`
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
} try {`
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
} channel.basicNack(deliveryTag, false, false);`
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
} log.error("永久异常,消息进入死信队列: {}", e.getMessage());`
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
} } catch (IOException ex) {`
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
} log.error("NACK失败", ex);`
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
} }`
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
} `
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
} } catch (Exception e) {`
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
} // 未知异常:进入死信队列`
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
} try {`
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
} redisTemplate.delete(idempotentKey);`
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
} channel.basicNack(deliveryTag, false, false);`
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
} log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);`
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
} } catch (IOException ex) {`
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
} log.error("NACK失败", ex);`
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
} }`
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
} }`
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
} }`
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
}}`
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
}`
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
}/**`
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
} * 消息处理器`
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
} */`
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
}@Service`
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
}public class MessageProcessor {`
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
} `
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
} public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {`
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
} // 实际业务逻辑`
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
} JSONObject json = JSON.parseObject(messageBody);`
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
} `
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
} // 模拟业务处理`
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
} if (json.containsKey("errorType")) {`
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
} String errorType = json.getString("errorType");`
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
} `
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
} if ("temporary".equals(errorType)) {`
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
} throw new TemporaryFailureException("临时性失败:外部服务不可用");`
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
} } else if ("permanent".equals(errorType)) {`
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
} throw new PermanentFailureException("永久性失败:数据格式错误");`
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
} }`
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
} }`
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
} `
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
} // 正常处理`
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
} log.info("业务逻辑执行成功: {}", messageBody);`
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
} }`
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
}}`
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
}`
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
}// 自定义异常`
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
}class TemporaryFailureException extends Exception {`
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
} public TemporaryFailureException(String message) {`
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
} super(message);`
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
} }`
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
}}`
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
}`
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
}class PermanentFailureException extends Exception {`
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
} public PermanentFailureException(String message) {`
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
} super(message);`
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
} }`
`#/**
* 高可靠性消费者
*
* 特性:
* 1. 手动ACK
* 2. 幂等性检查
* 3. 死信处理
* 4. 异常分类
*/
@Component
@Slf4j
public class ReliableConsumer {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private MessageProcessor messageProcessor;
private static final String IDEMPOTENT_PREFIX = "message:processed:";
@RabbitListener(
queues = "business.queue",
containerFactory = "manualAckContainerFactory"
)
public void handle(
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
String messageId = message.getMessageProperties().getMessageId();
String idempotentKey = IDEMPOTENT_PREFIX + messageId;
try {
// 1. 幂等性检查
Boolean isFirstTime = redisTemplate.opsForValue()
.setIfAbsent(idempotentKey, "1", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isFirstTime)) {
// 重复消息,直接确认
log.info("消息重复,直接ACK: {}", messageId);
channel.basicAck(deliveryTag, false);
return;
}
// 2. 处理消息
String messageBody = new String(message.getBody());
messageProcessor.process(messageBody);
// 3. 处理成功,确认消息
channel.basicAck(deliveryTag, false);
log.info("消息处理成功: {}", messageId);
} catch (TemporaryFailureException e) {
// 临时异常:NACK并重新入队
try {
// 删除幂等标记,允许重试
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, true);
log.warn("临时异常,消息重新入队: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (PermanentFailureException e) {
// 永久异常:NACK不重新入队(进入死信队列)
try {
channel.basicNack(deliveryTag, false, false);
log.error("永久异常,消息进入死信队列: {}", e.getMessage());
} catch (IOException ex) {
log.error("NACK失败", ex);
}
} catch (Exception e) {
// 未知异常:进入死信队列
try {
redisTemplate.delete(idempotentKey);
channel.basicNack(deliveryTag, false, false);
log.error("未知异常,消息进入死信队列: {}", e.getMessage(), e);
} catch (IOException ex) {
log.error("NACK失败", ex);
}
}
}
}
/**
* 消息处理器
*/
@Service
public class MessageProcessor {
public void process(String messageBody) throws TemporaryFailureException, PermanentFailureException {
// 实际业务逻辑
JSONObject json = JSON.parseObject(messageBody);
// 模拟业务处理
if (json.containsKey("errorType")) {
String errorType = json.getString("errorType");
if ("temporary".equals(errorType)) {
throw new TemporaryFailureException("临时性失败:外部服务不可用");
} else if ("permanent".equals(errorType)) {
throw new PermanentFailureException("永久性失败:数据格式错误");
}
}
// 正常处理
log.info("业务逻辑执行成功: {}", messageBody);
}
}
// 自定义异常
class TemporaryFailureException extends Exception {
public TemporaryFailureException(String message) {
super(message);
}
}
class PermanentFailureException extends Exception {
public PermanentFailureException(String message) {
super(message);
}
}}
5.3 可靠性方案对比
| 方案 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| 仅持久化 | 实现简单 | 无法处理消费者失败 | 日志收集、监控数据 |
| 持久化+ACK | 可靠性高 | 需要手动处理异常 | 订单处理、支付系统 |
| 完整方案(持久化+ACK+DLQ+幂等) | 最高可靠性 | 实现复杂,性能损耗 | 金融交易、核心业务 |
6. 性能优化与权衡
6.1 可靠性与性能的权衡
graph LR
A[可靠性需求] --> B{选择策略}
B -->|最高可靠性| C[同步持久化<br/>手动ACK<br/>死信队列]
B -->|平衡| D[异步持久化<br/>批量ACK<br/>有限重试]
B -->|高性能| E[内存模式<br/>自动ACK<br/>快速失败]
C --> F[吞吐量: 低<br/>延迟: 高]
D --> G[吞吐量: 中<br/>延迟: 中]
E --> H[吞吐量: 高<br/>延迟: 低]
style C fill:#ffe1e1
style D fill:#fff4e1
style E fill:#e1ffe1
6.2 性能优化技巧
6.2.1 批量确认优化
java
#/**
* 批量Confirm优化
*
* 通过批量确认减少网络往返次数,提升吞吐量
*/
@Service
public class BatchConfirmProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
private static final int BATCH_SIZE = 100;
public void sendBatch(List<String> messages) throws IOException, InterruptedException {
Channel channel = rabbitTemplate.getConnectionFactory().createConnection().createChannel();
channel.confirmSelect();
// 发送批量消息
for (String message : messages) {
long seqNo = channel.getNextPublishSeqNo();
unconfirmedSet.add(seqNo);
channel.basicPublish("exchange", "routing.key", null, message.getBytes());
}
// 批量等待确认
channel.waitForConfirmsOrDie();
unconfirmedSet.clear();
}
}/**`
`#/**
* 批量Confirm优化
*
* 通过批量确认减少网络往返次数,提升吞吐量
*/
@Service
public class BatchConfirmProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
private static final int BATCH_SIZE = 100;
public void sendBatch(List<String> messages) throws IOException, InterruptedException {
Channel channel = rabbitTemplate.getConnectionFactory().createConnection().createChannel();
channel.confirmSelect();
// 发送批量消息
for (String message : messages) {
long seqNo = channel.getNextPublishSeqNo();
unconfirmedSet.add(seqNo);
channel.basicPublish("exchange", "routing.key", null, message.getBytes());
}
// 批量等待确认
channel.waitForConfirmsOrDie();
unconfirmedSet.clear();
}
} * 批量Confirm优化`
`#/**
* 批量Confirm优化
*
* 通过批量确认减少网络往返次数,提升吞吐量
*/
@Service
public class BatchConfirmProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
private static final int BATCH_SIZE = 100;
public void sendBatch(List<String> messages) throws IOException, InterruptedException {
Channel channel = rabbitTemplate.getConnectionFactory().createConnection().createChannel();
channel.confirmSelect();
// 发送批量消息
for (String message : messages) {
long seqNo = channel.getNextPublishSeqNo();
unconfirmedSet.add(seqNo);
channel.basicPublish("exchange", "routing.key", null, message.getBytes());
}
// 批量等待确认
channel.waitForConfirmsOrDie();
unconfirmedSet.clear();
}
} * `
`#/**
* 批量Confirm优化
*
* 通过批量确认减少网络往返次数,提升吞吐量
*/
@Service
public class BatchConfirmProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
private static final int BATCH_SIZE = 100;
public void sendBatch(List<String> messages) throws IOException, InterruptedException {
Channel channel = rabbitTemplate.getConnectionFactory().createConnection().createChannel();
channel.confirmSelect();
// 发送批量消息
for (String message : messages) {
long seqNo = channel.getNextPublishSeqNo();
unconfirmedSet.add(seqNo);
channel.basicPublish("exchange", "routing.key", null, message.getBytes());
}
// 批量等待确认
channel.waitForConfirmsOrDie();
unconfirmedSet.clear();
}
} * 通过批量确认减少网络往返次数,提升吞吐量`
`#/**
* 批量Confirm优化
*
* 通过批量确认减少网络往返次数,提升吞吐量
*/
@Service
public class BatchConfirmProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
private static final int BATCH_SIZE = 100;
public void sendBatch(List<String> messages) throws IOException, InterruptedException {
Channel channel = rabbitTemplate.getConnectionFactory().createConnection().createChannel();
channel.confirmSelect();
// 发送批量消息
for (String message : messages) {
long seqNo = channel.getNextPublishSeqNo();
unconfirmedSet.add(seqNo);
channel.basicPublish("exchange", "routing.key", null, message.getBytes());
}
// 批量等待确认
channel.waitForConfirmsOrDie();
unconfirmedSet.clear();
}
} */`
`#/**
* 批量Confirm优化
*
* 通过批量确认减少网络往返次数,提升吞吐量
*/
@Service
public class BatchConfirmProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
private static final int BATCH_SIZE = 100;
public void sendBatch(List<String> messages) throws IOException, InterruptedException {
Channel channel = rabbitTemplate.getConnectionFactory().createConnection().createChannel();
channel.confirmSelect();
// 发送批量消息
for (String message : messages) {
long seqNo = channel.getNextPublishSeqNo();
unconfirmedSet.add(seqNo);
channel.basicPublish("exchange", "routing.key", null, message.getBytes());
}
// 批量等待确认
channel.waitForConfirmsOrDie();
unconfirmedSet.clear();
}
}@Service`
`#/**
* 批量Confirm优化
*
* 通过批量确认减少网络往返次数,提升吞吐量
*/
@Service
public class BatchConfirmProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
private static final int BATCH_SIZE = 100;
public void sendBatch(List<String> messages) throws IOException, InterruptedException {
Channel channel = rabbitTemplate.getConnectionFactory().createConnection().createChannel();
channel.confirmSelect();
// 发送批量消息
for (String message : messages) {
long seqNo = channel.getNextPublishSeqNo();
unconfirmedSet.add(seqNo);
channel.basicPublish("exchange", "routing.key", null, message.getBytes());
}
// 批量等待确认
channel.waitForConfirmsOrDie();
unconfirmedSet.clear();
}
}public class BatchConfirmProducer {`
`#/**
* 批量Confirm优化
*
* 通过批量确认减少网络往返次数,提升吞吐量
*/
@Service
public class BatchConfirmProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
private static final int BATCH_SIZE = 100;
public void sendBatch(List<String> messages) throws IOException, InterruptedException {
Channel channel = rabbitTemplate.getConnectionFactory().createConnection().createChannel();
channel.confirmSelect();
// 发送批量消息
for (String message : messages) {
long seqNo = channel.getNextPublishSeqNo();
unconfirmedSet.add(seqNo);
channel.basicPublish("exchange", "routing.key", null, message.getBytes());
}
// 批量等待确认
channel.waitForConfirmsOrDie();
unconfirmedSet.clear();
}
}`
`#/**
* 批量Confirm优化
*
* 通过批量确认减少网络往返次数,提升吞吐量
*/
@Service
public class BatchConfirmProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
private static final int BATCH_SIZE = 100;
public void sendBatch(List<String> messages) throws IOException, InterruptedException {
Channel channel = rabbitTemplate.getConnectionFactory().createConnection().createChannel();
channel.confirmSelect();
// 发送批量消息
for (String message : messages) {
long seqNo = channel.getNextPublishSeqNo();
unconfirmedSet.add(seqNo);
channel.basicPublish("exchange", "routing.key", null, message.getBytes());
}
// 批量等待确认
channel.waitForConfirmsOrDie();
unconfirmedSet.clear();
}
} @Autowired`
`#/**
* 批量Confirm优化
*
* 通过批量确认减少网络往返次数,提升吞吐量
*/
@Service
public class BatchConfirmProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
private static final int BATCH_SIZE = 100;
public void sendBatch(List<String> messages) throws IOException, InterruptedException {
Channel channel = rabbitTemplate.getConnectionFactory().createConnection().createChannel();
channel.confirmSelect();
// 发送批量消息
for (String message : messages) {
long seqNo = channel.getNextPublishSeqNo();
unconfirmedSet.add(seqNo);
channel.basicPublish("exchange", "routing.key", null, message.getBytes());
}
// 批量等待确认
channel.waitForConfirmsOrDie();
unconfirmedSet.clear();
}
} private RabbitTemplate rabbitTemplate;`
`#/**
* 批量Confirm优化
*
* 通过批量确认减少网络往返次数,提升吞吐量
*/
@Service
public class BatchConfirmProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
private static final int BATCH_SIZE = 100;
public void sendBatch(List<String> messages) throws IOException, InterruptedException {
Channel channel = rabbitTemplate.getConnectionFactory().createConnection().createChannel();
channel.confirmSelect();
// 发送批量消息
for (String message : messages) {
long seqNo = channel.getNextPublishSeqNo();
unconfirmedSet.add(seqNo);
channel.basicPublish("exchange", "routing.key", null, message.getBytes());
}
// 批量等待确认
channel.waitForConfirmsOrDie();
unconfirmedSet.clear();
}
}`
`#/**
* 批量Confirm优化
*
* 通过批量确认减少网络往返次数,提升吞吐量
*/
@Service
public class BatchConfirmProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
private static final int BATCH_SIZE = 100;
public void sendBatch(List<String> messages) throws IOException, InterruptedException {
Channel channel = rabbitTemplate.getConnectionFactory().createConnection().createChannel();
channel.confirmSelect();
// 发送批量消息
for (String message : messages) {
long seqNo = channel.getNextPublishSeqNo();
unconfirmedSet.add(seqNo);
channel.basicPublish("exchange", "routing.key", null, message.getBytes());
}
// 批量等待确认
channel.waitForConfirmsOrDie();
unconfirmedSet.clear();
}
} private final SortedSet<Long> unconfirmedSet = `
`#/**
* 批量Confirm优化
*
* 通过批量确认减少网络往返次数,提升吞吐量
*/
@Service
public class BatchConfirmProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
private static final int BATCH_SIZE = 100;
public void sendBatch(List<String> messages) throws IOException, InterruptedException {
Channel channel = rabbitTemplate.getConnectionFactory().createConnection().createChannel();
channel.confirmSelect();
// 发送批量消息
for (String message : messages) {
long seqNo = channel.getNextPublishSeqNo();
unconfirmedSet.add(seqNo);
channel.basicPublish("exchange", "routing.key", null, message.getBytes());
}
// 批量等待确认
channel.waitForConfirmsOrDie();
unconfirmedSet.clear();
}
} Collections.synchronizedSortedSet(new TreeSet<>());`
`#/**
* 批量Confirm优化
*
* 通过批量确认减少网络往返次数,提升吞吐量
*/
@Service
public class BatchConfirmProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
private static final int BATCH_SIZE = 100;
public void sendBatch(List<String> messages) throws IOException, InterruptedException {
Channel channel = rabbitTemplate.getConnectionFactory().createConnection().createChannel();
channel.confirmSelect();
// 发送批量消息
for (String message : messages) {
long seqNo = channel.getNextPublishSeqNo();
unconfirmedSet.add(seqNo);
channel.basicPublish("exchange", "routing.key", null, message.getBytes());
}
// 批量等待确认
channel.waitForConfirmsOrDie();
unconfirmedSet.clear();
}
} `
`#/**
* 批量Confirm优化
*
* 通过批量确认减少网络往返次数,提升吞吐量
*/
@Service
public class BatchConfirmProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
private static final int BATCH_SIZE = 100;
public void sendBatch(List<String> messages) throws IOException, InterruptedException {
Channel channel = rabbitTemplate.getConnectionFactory().createConnection().createChannel();
channel.confirmSelect();
// 发送批量消息
for (String message : messages) {
long seqNo = channel.getNextPublishSeqNo();
unconfirmedSet.add(seqNo);
channel.basicPublish("exchange", "routing.key", null, message.getBytes());
}
// 批量等待确认
channel.waitForConfirmsOrDie();
unconfirmedSet.clear();
}
} private static final int BATCH_SIZE = 100;`
`#/**
* 批量Confirm优化
*
* 通过批量确认减少网络往返次数,提升吞吐量
*/
@Service
public class BatchConfirmProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
private static final int BATCH_SIZE = 100;
public void sendBatch(List<String> messages) throws IOException, InterruptedException {
Channel channel = rabbitTemplate.getConnectionFactory().createConnection().createChannel();
channel.confirmSelect();
// 发送批量消息
for (String message : messages) {
long seqNo = channel.getNextPublishSeqNo();
unconfirmedSet.add(seqNo);
channel.basicPublish("exchange", "routing.key", null, message.getBytes());
}
// 批量等待确认
channel.waitForConfirmsOrDie();
unconfirmedSet.clear();
}
}`
`#/**
* 批量Confirm优化
*
* 通过批量确认减少网络往返次数,提升吞吐量
*/
@Service
public class BatchConfirmProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
private static final int BATCH_SIZE = 100;
public void sendBatch(List<String> messages) throws IOException, InterruptedException {
Channel channel = rabbitTemplate.getConnectionFactory().createConnection().createChannel();
channel.confirmSelect();
// 发送批量消息
for (String message : messages) {
long seqNo = channel.getNextPublishSeqNo();
unconfirmedSet.add(seqNo);
channel.basicPublish("exchange", "routing.key", null, message.getBytes());
}
// 批量等待确认
channel.waitForConfirmsOrDie();
unconfirmedSet.clear();
}
} public void sendBatch(List<String> messages) throws IOException, InterruptedException {`
`#/**
* 批量Confirm优化
*
* 通过批量确认减少网络往返次数,提升吞吐量
*/
@Service
public class BatchConfirmProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
private static final int BATCH_SIZE = 100;
public void sendBatch(List<String> messages) throws IOException, InterruptedException {
Channel channel = rabbitTemplate.getConnectionFactory().createConnection().createChannel();
channel.confirmSelect();
// 发送批量消息
for (String message : messages) {
long seqNo = channel.getNextPublishSeqNo();
unconfirmedSet.add(seqNo);
channel.basicPublish("exchange", "routing.key", null, message.getBytes());
}
// 批量等待确认
channel.waitForConfirmsOrDie();
unconfirmedSet.clear();
}
} Channel channel = rabbitTemplate.getConnectionFactory().createConnection().createChannel();`
`#/**
* 批量Confirm优化
*
* 通过批量确认减少网络往返次数,提升吞吐量
*/
@Service
public class BatchConfirmProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
private static final int BATCH_SIZE = 100;
public void sendBatch(List<String> messages) throws IOException, InterruptedException {
Channel channel = rabbitTemplate.getConnectionFactory().createConnection().createChannel();
channel.confirmSelect();
// 发送批量消息
for (String message : messages) {
long seqNo = channel.getNextPublishSeqNo();
unconfirmedSet.add(seqNo);
channel.basicPublish("exchange", "routing.key", null, message.getBytes());
}
// 批量等待确认
channel.waitForConfirmsOrDie();
unconfirmedSet.clear();
}
} channel.confirmSelect();`
`#/**
* 批量Confirm优化
*
* 通过批量确认减少网络往返次数,提升吞吐量
*/
@Service
public class BatchConfirmProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
private static final int BATCH_SIZE = 100;
public void sendBatch(List<String> messages) throws IOException, InterruptedException {
Channel channel = rabbitTemplate.getConnectionFactory().createConnection().createChannel();
channel.confirmSelect();
// 发送批量消息
for (String message : messages) {
long seqNo = channel.getNextPublishSeqNo();
unconfirmedSet.add(seqNo);
channel.basicPublish("exchange", "routing.key", null, message.getBytes());
}
// 批量等待确认
channel.waitForConfirmsOrDie();
unconfirmedSet.clear();
}
}`
`#/**
* 批量Confirm优化
*
* 通过批量确认减少网络往返次数,提升吞吐量
*/
@Service
public class BatchConfirmProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
private static final int BATCH_SIZE = 100;
public void sendBatch(List<String> messages) throws IOException, InterruptedException {
Channel channel = rabbitTemplate.getConnectionFactory().createConnection().createChannel();
channel.confirmSelect();
// 发送批量消息
for (String message : messages) {
long seqNo = channel.getNextPublishSeqNo();
unconfirmedSet.add(seqNo);
channel.basicPublish("exchange", "routing.key", null, message.getBytes());
}
// 批量等待确认
channel.waitForConfirmsOrDie();
unconfirmedSet.clear();
}
} // 发送批量消息`
`#/**
* 批量Confirm优化
*
* 通过批量确认减少网络往返次数,提升吞吐量
*/
@Service
public class BatchConfirmProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
private static final int BATCH_SIZE = 100;
public void sendBatch(List<String> messages) throws IOException, InterruptedException {
Channel channel = rabbitTemplate.getConnectionFactory().createConnection().createChannel();
channel.confirmSelect();
// 发送批量消息
for (String message : messages) {
long seqNo = channel.getNextPublishSeqNo();
unconfirmedSet.add(seqNo);
channel.basicPublish("exchange", "routing.key", null, message.getBytes());
}
// 批量等待确认
channel.waitForConfirmsOrDie();
unconfirmedSet.clear();
}
} for (String message : messages) {`
`#/**
* 批量Confirm优化
*
* 通过批量确认减少网络往返次数,提升吞吐量
*/
@Service
public class BatchConfirmProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
private static final int BATCH_SIZE = 100;
public void sendBatch(List<String> messages) throws IOException, InterruptedException {
Channel channel = rabbitTemplate.getConnectionFactory().createConnection().createChannel();
channel.confirmSelect();
// 发送批量消息
for (String message : messages) {
long seqNo = channel.getNextPublishSeqNo();
unconfirmedSet.add(seqNo);
channel.basicPublish("exchange", "routing.key", null, message.getBytes());
}
// 批量等待确认
channel.waitForConfirmsOrDie();
unconfirmedSet.clear();
}
} long seqNo = channel.getNextPublishSeqNo();`
`#/**
* 批量Confirm优化
*
* 通过批量确认减少网络往返次数,提升吞吐量
*/
@Service
public class BatchConfirmProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
private static final int BATCH_SIZE = 100;
public void sendBatch(List<String> messages) throws IOException, InterruptedException {
Channel channel = rabbitTemplate.getConnectionFactory().createConnection().createChannel();
channel.confirmSelect();
// 发送批量消息
for (String message : messages) {
long seqNo = channel.getNextPublishSeqNo();
unconfirmedSet.add(seqNo);
channel.basicPublish("exchange", "routing.key", null, message.getBytes());
}
// 批量等待确认
channel.waitForConfirmsOrDie();
unconfirmedSet.clear();
}
} unconfirmedSet.add(seqNo);`
`#/**
* 批量Confirm优化
*
* 通过批量确认减少网络往返次数,提升吞吐量
*/
@Service
public class BatchConfirmProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
private static final int BATCH_SIZE = 100;
public void sendBatch(List<String> messages) throws IOException, InterruptedException {
Channel channel = rabbitTemplate.getConnectionFactory().createConnection().createChannel();
channel.confirmSelect();
// 发送批量消息
for (String message : messages) {
long seqNo = channel.getNextPublishSeqNo();
unconfirmedSet.add(seqNo);
channel.basicPublish("exchange", "routing.key", null, message.getBytes());
}
// 批量等待确认
channel.waitForConfirmsOrDie();
unconfirmedSet.clear();
}
} channel.basicPublish("exchange", "routing.key", null, message.getBytes());`
`#/**
* 批量Confirm优化
*
* 通过批量确认减少网络往返次数,提升吞吐量
*/
@Service
public class BatchConfirmProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
private static final int BATCH_SIZE = 100;
public void sendBatch(List<String> messages) throws IOException, InterruptedException {
Channel channel = rabbitTemplate.getConnectionFactory().createConnection().createChannel();
channel.confirmSelect();
// 发送批量消息
for (String message : messages) {
long seqNo = channel.getNextPublishSeqNo();
unconfirmedSet.add(seqNo);
channel.basicPublish("exchange", "routing.key", null, message.getBytes());
}
// 批量等待确认
channel.waitForConfirmsOrDie();
unconfirmedSet.clear();
}
} }`
`#/**
* 批量Confirm优化
*
* 通过批量确认减少网络往返次数,提升吞吐量
*/
@Service
public class BatchConfirmProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
private static final int BATCH_SIZE = 100;
public void sendBatch(List<String> messages) throws IOException, InterruptedException {
Channel channel = rabbitTemplate.getConnectionFactory().createConnection().createChannel();
channel.confirmSelect();
// 发送批量消息
for (String message : messages) {
long seqNo = channel.getNextPublishSeqNo();
unconfirmedSet.add(seqNo);
channel.basicPublish("exchange", "routing.key", null, message.getBytes());
}
// 批量等待确认
channel.waitForConfirmsOrDie();
unconfirmedSet.clear();
}
}`
`#/**
* 批量Confirm优化
*
* 通过批量确认减少网络往返次数,提升吞吐量
*/
@Service
public class BatchConfirmProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
private static final int BATCH_SIZE = 100;
public void sendBatch(List<String> messages) throws IOException, InterruptedException {
Channel channel = rabbitTemplate.getConnectionFactory().createConnection().createChannel();
channel.confirmSelect();
// 发送批量消息
for (String message : messages) {
long seqNo = channel.getNextPublishSeqNo();
unconfirmedSet.add(seqNo);
channel.basicPublish("exchange", "routing.key", null, message.getBytes());
}
// 批量等待确认
channel.waitForConfirmsOrDie();
unconfirmedSet.clear();
}
} // 批量等待确认`
`#/**
* 批量Confirm优化
*
* 通过批量确认减少网络往返次数,提升吞吐量
*/
@Service
public class BatchConfirmProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
private static final int BATCH_SIZE = 100;
public void sendBatch(List<String> messages) throws IOException, InterruptedException {
Channel channel = rabbitTemplate.getConnectionFactory().createConnection().createChannel();
channel.confirmSelect();
// 发送批量消息
for (String message : messages) {
long seqNo = channel.getNextPublishSeqNo();
unconfirmedSet.add(seqNo);
channel.basicPublish("exchange", "routing.key", null, message.getBytes());
}
// 批量等待确认
channel.waitForConfirmsOrDie();
unconfirmedSet.clear();
}
} channel.waitForConfirmsOrDie();`
`#/**
* 批量Confirm优化
*
* 通过批量确认减少网络往返次数,提升吞吐量
*/
@Service
public class BatchConfirmProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
private static final int BATCH_SIZE = 100;
public void sendBatch(List<String> messages) throws IOException, InterruptedException {
Channel channel = rabbitTemplate.getConnectionFactory().createConnection().createChannel();
channel.confirmSelect();
// 发送批量消息
for (String message : messages) {
long seqNo = channel.getNextPublishSeqNo();
unconfirmedSet.add(seqNo);
channel.basicPublish("exchange", "routing.key", null, message.getBytes());
}
// 批量等待确认
channel.waitForConfirmsOrDie();
unconfirmedSet.clear();
}
} unconfirmedSet.clear();`
`#/**
* 批量Confirm优化
*
* 通过批量确认减少网络往返次数,提升吞吐量
*/
@Service
public class BatchConfirmProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
private static final int BATCH_SIZE = 100;
public void sendBatch(List<String> messages) throws IOException, InterruptedException {
Channel channel = rabbitTemplate.getConnectionFactory().createConnection().createChannel();
channel.confirmSelect();
// 发送批量消息
for (String message : messages) {
long seqNo = channel.getNextPublishSeqNo();
unconfirmedSet.add(seqNo);
channel.basicPublish("exchange", "routing.key", null, message.getBytes());
}
// 批量等待确认
channel.waitForConfirmsOrDie();
unconfirmedSet.clear();
}
} }`
`#/**
* 批量Confirm优化
*
* 通过批量确认减少网络往返次数,提升吞吐量
*/
@Service
public class BatchConfirmProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
private final SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet<>());
private static final int BATCH_SIZE = 100;
public void sendBatch(List<String> messages) throws IOException, InterruptedException {
Channel channel = rabbitTemplate.getConnectionFactory().createConnection().createChannel();
channel.confirmSelect();
// 发送批量消息
for (String message : messages) {
long seqNo = channel.getNextPublishSeqNo();
unconfirmedSet.add(seqNo);
channel.basicPublish("exchange", "routing.key", null, message.getBytes());
}
// 批量等待确认
channel.waitForConfirmsOrDie();
unconfirmedSet.clear();
}
}}
6.2.2 消费者批量消费
java
#/**
* 批量消费优化
*
* 通过批量拉取消息减少网络开销
*/
@Component
public class BatchConsumer {
@RabbitListener(
queues = "business.queue",
containerFactory = "batchContainerFactory"
)
public void handleBatch(List<Message> messages, Channel channel) {
List<Long> deliveryTags = new ArrayList<>();
try {
// 批量处理消息
for (Message message : messages) {
processMessage(message);
deliveryTags.add(message.getMessageProperties().getDeliveryTag());
}
// 批量确认
if (!deliveryTags.isEmpty()) {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicAck(lastTag, true); // multiple=true
}
} catch (Exception e) {
// 批量失败,全部重新入队
try {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicNack(lastTag, true, true);
} catch (IOException ex) {
log.error("批量NACK失败", ex);
}
}
}
private void processMessage(Message message) {
// 处理逻辑
}
}
/**
* 批量消费配置
*/
@Configuration
public class BatchConsumerConfig {
@Bean
public SimpleRabbitListenerContainerFactory batchContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
factory.setBatchListener(true); // 启用批量监听
factory.setBatchSize(50); // 批量大小
factory.setConsumerBatchEnabled(true);
factory.setReceiveTimeout(5000L); // 批量等待超时
return factory;
}
}/**`
`#/**
* 批量消费优化
*
* 通过批量拉取消息减少网络开销
*/
@Component
public class BatchConsumer {
@RabbitListener(
queues = "business.queue",
containerFactory = "batchContainerFactory"
)
public void handleBatch(List<Message> messages, Channel channel) {
List<Long> deliveryTags = new ArrayList<>();
try {
// 批量处理消息
for (Message message : messages) {
processMessage(message);
deliveryTags.add(message.getMessageProperties().getDeliveryTag());
}
// 批量确认
if (!deliveryTags.isEmpty()) {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicAck(lastTag, true); // multiple=true
}
} catch (Exception e) {
// 批量失败,全部重新入队
try {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicNack(lastTag, true, true);
} catch (IOException ex) {
log.error("批量NACK失败", ex);
}
}
}
private void processMessage(Message message) {
// 处理逻辑
}
}
/**
* 批量消费配置
*/
@Configuration
public class BatchConsumerConfig {
@Bean
public SimpleRabbitListenerContainerFactory batchContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
factory.setBatchListener(true); // 启用批量监听
factory.setBatchSize(50); // 批量大小
factory.setConsumerBatchEnabled(true);
factory.setReceiveTimeout(5000L); // 批量等待超时
return factory;
}
} * 批量消费优化`
`#/**
* 批量消费优化
*
* 通过批量拉取消息减少网络开销
*/
@Component
public class BatchConsumer {
@RabbitListener(
queues = "business.queue",
containerFactory = "batchContainerFactory"
)
public void handleBatch(List<Message> messages, Channel channel) {
List<Long> deliveryTags = new ArrayList<>();
try {
// 批量处理消息
for (Message message : messages) {
processMessage(message);
deliveryTags.add(message.getMessageProperties().getDeliveryTag());
}
// 批量确认
if (!deliveryTags.isEmpty()) {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicAck(lastTag, true); // multiple=true
}
} catch (Exception e) {
// 批量失败,全部重新入队
try {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicNack(lastTag, true, true);
} catch (IOException ex) {
log.error("批量NACK失败", ex);
}
}
}
private void processMessage(Message message) {
// 处理逻辑
}
}
/**
* 批量消费配置
*/
@Configuration
public class BatchConsumerConfig {
@Bean
public SimpleRabbitListenerContainerFactory batchContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
factory.setBatchListener(true); // 启用批量监听
factory.setBatchSize(50); // 批量大小
factory.setConsumerBatchEnabled(true);
factory.setReceiveTimeout(5000L); // 批量等待超时
return factory;
}
} * `
`#/**
* 批量消费优化
*
* 通过批量拉取消息减少网络开销
*/
@Component
public class BatchConsumer {
@RabbitListener(
queues = "business.queue",
containerFactory = "batchContainerFactory"
)
public void handleBatch(List<Message> messages, Channel channel) {
List<Long> deliveryTags = new ArrayList<>();
try {
// 批量处理消息
for (Message message : messages) {
processMessage(message);
deliveryTags.add(message.getMessageProperties().getDeliveryTag());
}
// 批量确认
if (!deliveryTags.isEmpty()) {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicAck(lastTag, true); // multiple=true
}
} catch (Exception e) {
// 批量失败,全部重新入队
try {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicNack(lastTag, true, true);
} catch (IOException ex) {
log.error("批量NACK失败", ex);
}
}
}
private void processMessage(Message message) {
// 处理逻辑
}
}
/**
* 批量消费配置
*/
@Configuration
public class BatchConsumerConfig {
@Bean
public SimpleRabbitListenerContainerFactory batchContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
factory.setBatchListener(true); // 启用批量监听
factory.setBatchSize(50); // 批量大小
factory.setConsumerBatchEnabled(true);
factory.setReceiveTimeout(5000L); // 批量等待超时
return factory;
}
} * 通过批量拉取消息减少网络开销`
`#/**
* 批量消费优化
*
* 通过批量拉取消息减少网络开销
*/
@Component
public class BatchConsumer {
@RabbitListener(
queues = "business.queue",
containerFactory = "batchContainerFactory"
)
public void handleBatch(List<Message> messages, Channel channel) {
List<Long> deliveryTags = new ArrayList<>();
try {
// 批量处理消息
for (Message message : messages) {
processMessage(message);
deliveryTags.add(message.getMessageProperties().getDeliveryTag());
}
// 批量确认
if (!deliveryTags.isEmpty()) {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicAck(lastTag, true); // multiple=true
}
} catch (Exception e) {
// 批量失败,全部重新入队
try {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicNack(lastTag, true, true);
} catch (IOException ex) {
log.error("批量NACK失败", ex);
}
}
}
private void processMessage(Message message) {
// 处理逻辑
}
}
/**
* 批量消费配置
*/
@Configuration
public class BatchConsumerConfig {
@Bean
public SimpleRabbitListenerContainerFactory batchContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
factory.setBatchListener(true); // 启用批量监听
factory.setBatchSize(50); // 批量大小
factory.setConsumerBatchEnabled(true);
factory.setReceiveTimeout(5000L); // 批量等待超时
return factory;
}
} */`
`#/**
* 批量消费优化
*
* 通过批量拉取消息减少网络开销
*/
@Component
public class BatchConsumer {
@RabbitListener(
queues = "business.queue",
containerFactory = "batchContainerFactory"
)
public void handleBatch(List<Message> messages, Channel channel) {
List<Long> deliveryTags = new ArrayList<>();
try {
// 批量处理消息
for (Message message : messages) {
processMessage(message);
deliveryTags.add(message.getMessageProperties().getDeliveryTag());
}
// 批量确认
if (!deliveryTags.isEmpty()) {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicAck(lastTag, true); // multiple=true
}
} catch (Exception e) {
// 批量失败,全部重新入队
try {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicNack(lastTag, true, true);
} catch (IOException ex) {
log.error("批量NACK失败", ex);
}
}
}
private void processMessage(Message message) {
// 处理逻辑
}
}
/**
* 批量消费配置
*/
@Configuration
public class BatchConsumerConfig {
@Bean
public SimpleRabbitListenerContainerFactory batchContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
factory.setBatchListener(true); // 启用批量监听
factory.setBatchSize(50); // 批量大小
factory.setConsumerBatchEnabled(true);
factory.setReceiveTimeout(5000L); // 批量等待超时
return factory;
}
}@Component`
`#/**
* 批量消费优化
*
* 通过批量拉取消息减少网络开销
*/
@Component
public class BatchConsumer {
@RabbitListener(
queues = "business.queue",
containerFactory = "batchContainerFactory"
)
public void handleBatch(List<Message> messages, Channel channel) {
List<Long> deliveryTags = new ArrayList<>();
try {
// 批量处理消息
for (Message message : messages) {
processMessage(message);
deliveryTags.add(message.getMessageProperties().getDeliveryTag());
}
// 批量确认
if (!deliveryTags.isEmpty()) {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicAck(lastTag, true); // multiple=true
}
} catch (Exception e) {
// 批量失败,全部重新入队
try {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicNack(lastTag, true, true);
} catch (IOException ex) {
log.error("批量NACK失败", ex);
}
}
}
private void processMessage(Message message) {
// 处理逻辑
}
}
/**
* 批量消费配置
*/
@Configuration
public class BatchConsumerConfig {
@Bean
public SimpleRabbitListenerContainerFactory batchContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
factory.setBatchListener(true); // 启用批量监听
factory.setBatchSize(50); // 批量大小
factory.setConsumerBatchEnabled(true);
factory.setReceiveTimeout(5000L); // 批量等待超时
return factory;
}
}public class BatchConsumer {`
`#/**
* 批量消费优化
*
* 通过批量拉取消息减少网络开销
*/
@Component
public class BatchConsumer {
@RabbitListener(
queues = "business.queue",
containerFactory = "batchContainerFactory"
)
public void handleBatch(List<Message> messages, Channel channel) {
List<Long> deliveryTags = new ArrayList<>();
try {
// 批量处理消息
for (Message message : messages) {
processMessage(message);
deliveryTags.add(message.getMessageProperties().getDeliveryTag());
}
// 批量确认
if (!deliveryTags.isEmpty()) {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicAck(lastTag, true); // multiple=true
}
} catch (Exception e) {
// 批量失败,全部重新入队
try {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicNack(lastTag, true, true);
} catch (IOException ex) {
log.error("批量NACK失败", ex);
}
}
}
private void processMessage(Message message) {
// 处理逻辑
}
}
/**
* 批量消费配置
*/
@Configuration
public class BatchConsumerConfig {
@Bean
public SimpleRabbitListenerContainerFactory batchContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
factory.setBatchListener(true); // 启用批量监听
factory.setBatchSize(50); // 批量大小
factory.setConsumerBatchEnabled(true);
factory.setReceiveTimeout(5000L); // 批量等待超时
return factory;
}
}`
`#/**
* 批量消费优化
*
* 通过批量拉取消息减少网络开销
*/
@Component
public class BatchConsumer {
@RabbitListener(
queues = "business.queue",
containerFactory = "batchContainerFactory"
)
public void handleBatch(List<Message> messages, Channel channel) {
List<Long> deliveryTags = new ArrayList<>();
try {
// 批量处理消息
for (Message message : messages) {
processMessage(message);
deliveryTags.add(message.getMessageProperties().getDeliveryTag());
}
// 批量确认
if (!deliveryTags.isEmpty()) {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicAck(lastTag, true); // multiple=true
}
} catch (Exception e) {
// 批量失败,全部重新入队
try {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicNack(lastTag, true, true);
} catch (IOException ex) {
log.error("批量NACK失败", ex);
}
}
}
private void processMessage(Message message) {
// 处理逻辑
}
}
/**
* 批量消费配置
*/
@Configuration
public class BatchConsumerConfig {
@Bean
public SimpleRabbitListenerContainerFactory batchContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
factory.setBatchListener(true); // 启用批量监听
factory.setBatchSize(50); // 批量大小
factory.setConsumerBatchEnabled(true);
factory.setReceiveTimeout(5000L); // 批量等待超时
return factory;
}
} @RabbitListener(`
`#/**
* 批量消费优化
*
* 通过批量拉取消息减少网络开销
*/
@Component
public class BatchConsumer {
@RabbitListener(
queues = "business.queue",
containerFactory = "batchContainerFactory"
)
public void handleBatch(List<Message> messages, Channel channel) {
List<Long> deliveryTags = new ArrayList<>();
try {
// 批量处理消息
for (Message message : messages) {
processMessage(message);
deliveryTags.add(message.getMessageProperties().getDeliveryTag());
}
// 批量确认
if (!deliveryTags.isEmpty()) {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicAck(lastTag, true); // multiple=true
}
} catch (Exception e) {
// 批量失败,全部重新入队
try {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicNack(lastTag, true, true);
} catch (IOException ex) {
log.error("批量NACK失败", ex);
}
}
}
private void processMessage(Message message) {
// 处理逻辑
}
}
/**
* 批量消费配置
*/
@Configuration
public class BatchConsumerConfig {
@Bean
public SimpleRabbitListenerContainerFactory batchContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
factory.setBatchListener(true); // 启用批量监听
factory.setBatchSize(50); // 批量大小
factory.setConsumerBatchEnabled(true);
factory.setReceiveTimeout(5000L); // 批量等待超时
return factory;
}
} queues = "business.queue",`
`#/**
* 批量消费优化
*
* 通过批量拉取消息减少网络开销
*/
@Component
public class BatchConsumer {
@RabbitListener(
queues = "business.queue",
containerFactory = "batchContainerFactory"
)
public void handleBatch(List<Message> messages, Channel channel) {
List<Long> deliveryTags = new ArrayList<>();
try {
// 批量处理消息
for (Message message : messages) {
processMessage(message);
deliveryTags.add(message.getMessageProperties().getDeliveryTag());
}
// 批量确认
if (!deliveryTags.isEmpty()) {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicAck(lastTag, true); // multiple=true
}
} catch (Exception e) {
// 批量失败,全部重新入队
try {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicNack(lastTag, true, true);
} catch (IOException ex) {
log.error("批量NACK失败", ex);
}
}
}
private void processMessage(Message message) {
// 处理逻辑
}
}
/**
* 批量消费配置
*/
@Configuration
public class BatchConsumerConfig {
@Bean
public SimpleRabbitListenerContainerFactory batchContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
factory.setBatchListener(true); // 启用批量监听
factory.setBatchSize(50); // 批量大小
factory.setConsumerBatchEnabled(true);
factory.setReceiveTimeout(5000L); // 批量等待超时
return factory;
}
} containerFactory = "batchContainerFactory"`
`#/**
* 批量消费优化
*
* 通过批量拉取消息减少网络开销
*/
@Component
public class BatchConsumer {
@RabbitListener(
queues = "business.queue",
containerFactory = "batchContainerFactory"
)
public void handleBatch(List<Message> messages, Channel channel) {
List<Long> deliveryTags = new ArrayList<>();
try {
// 批量处理消息
for (Message message : messages) {
processMessage(message);
deliveryTags.add(message.getMessageProperties().getDeliveryTag());
}
// 批量确认
if (!deliveryTags.isEmpty()) {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicAck(lastTag, true); // multiple=true
}
} catch (Exception e) {
// 批量失败,全部重新入队
try {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicNack(lastTag, true, true);
} catch (IOException ex) {
log.error("批量NACK失败", ex);
}
}
}
private void processMessage(Message message) {
// 处理逻辑
}
}
/**
* 批量消费配置
*/
@Configuration
public class BatchConsumerConfig {
@Bean
public SimpleRabbitListenerContainerFactory batchContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
factory.setBatchListener(true); // 启用批量监听
factory.setBatchSize(50); // 批量大小
factory.setConsumerBatchEnabled(true);
factory.setReceiveTimeout(5000L); // 批量等待超时
return factory;
}
} )`
`#/**
* 批量消费优化
*
* 通过批量拉取消息减少网络开销
*/
@Component
public class BatchConsumer {
@RabbitListener(
queues = "business.queue",
containerFactory = "batchContainerFactory"
)
public void handleBatch(List<Message> messages, Channel channel) {
List<Long> deliveryTags = new ArrayList<>();
try {
// 批量处理消息
for (Message message : messages) {
processMessage(message);
deliveryTags.add(message.getMessageProperties().getDeliveryTag());
}
// 批量确认
if (!deliveryTags.isEmpty()) {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicAck(lastTag, true); // multiple=true
}
} catch (Exception e) {
// 批量失败,全部重新入队
try {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicNack(lastTag, true, true);
} catch (IOException ex) {
log.error("批量NACK失败", ex);
}
}
}
private void processMessage(Message message) {
// 处理逻辑
}
}
/**
* 批量消费配置
*/
@Configuration
public class BatchConsumerConfig {
@Bean
public SimpleRabbitListenerContainerFactory batchContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
factory.setBatchListener(true); // 启用批量监听
factory.setBatchSize(50); // 批量大小
factory.setConsumerBatchEnabled(true);
factory.setReceiveTimeout(5000L); // 批量等待超时
return factory;
}
} public void handleBatch(List<Message> messages, Channel channel) {`
`#/**
* 批量消费优化
*
* 通过批量拉取消息减少网络开销
*/
@Component
public class BatchConsumer {
@RabbitListener(
queues = "business.queue",
containerFactory = "batchContainerFactory"
)
public void handleBatch(List<Message> messages, Channel channel) {
List<Long> deliveryTags = new ArrayList<>();
try {
// 批量处理消息
for (Message message : messages) {
processMessage(message);
deliveryTags.add(message.getMessageProperties().getDeliveryTag());
}
// 批量确认
if (!deliveryTags.isEmpty()) {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicAck(lastTag, true); // multiple=true
}
} catch (Exception e) {
// 批量失败,全部重新入队
try {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicNack(lastTag, true, true);
} catch (IOException ex) {
log.error("批量NACK失败", ex);
}
}
}
private void processMessage(Message message) {
// 处理逻辑
}
}
/**
* 批量消费配置
*/
@Configuration
public class BatchConsumerConfig {
@Bean
public SimpleRabbitListenerContainerFactory batchContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
factory.setBatchListener(true); // 启用批量监听
factory.setBatchSize(50); // 批量大小
factory.setConsumerBatchEnabled(true);
factory.setReceiveTimeout(5000L); // 批量等待超时
return factory;
}
} List<Long> deliveryTags = new ArrayList<>();`
`#/**
* 批量消费优化
*
* 通过批量拉取消息减少网络开销
*/
@Component
public class BatchConsumer {
@RabbitListener(
queues = "business.queue",
containerFactory = "batchContainerFactory"
)
public void handleBatch(List<Message> messages, Channel channel) {
List<Long> deliveryTags = new ArrayList<>();
try {
// 批量处理消息
for (Message message : messages) {
processMessage(message);
deliveryTags.add(message.getMessageProperties().getDeliveryTag());
}
// 批量确认
if (!deliveryTags.isEmpty()) {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicAck(lastTag, true); // multiple=true
}
} catch (Exception e) {
// 批量失败,全部重新入队
try {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicNack(lastTag, true, true);
} catch (IOException ex) {
log.error("批量NACK失败", ex);
}
}
}
private void processMessage(Message message) {
// 处理逻辑
}
}
/**
* 批量消费配置
*/
@Configuration
public class BatchConsumerConfig {
@Bean
public SimpleRabbitListenerContainerFactory batchContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
factory.setBatchListener(true); // 启用批量监听
factory.setBatchSize(50); // 批量大小
factory.setConsumerBatchEnabled(true);
factory.setReceiveTimeout(5000L); // 批量等待超时
return factory;
}
} `
`#/**
* 批量消费优化
*
* 通过批量拉取消息减少网络开销
*/
@Component
public class BatchConsumer {
@RabbitListener(
queues = "business.queue",
containerFactory = "batchContainerFactory"
)
public void handleBatch(List<Message> messages, Channel channel) {
List<Long> deliveryTags = new ArrayList<>();
try {
// 批量处理消息
for (Message message : messages) {
processMessage(message);
deliveryTags.add(message.getMessageProperties().getDeliveryTag());
}
// 批量确认
if (!deliveryTags.isEmpty()) {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicAck(lastTag, true); // multiple=true
}
} catch (Exception e) {
// 批量失败,全部重新入队
try {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicNack(lastTag, true, true);
} catch (IOException ex) {
log.error("批量NACK失败", ex);
}
}
}
private void processMessage(Message message) {
// 处理逻辑
}
}
/**
* 批量消费配置
*/
@Configuration
public class BatchConsumerConfig {
@Bean
public SimpleRabbitListenerContainerFactory batchContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
factory.setBatchListener(true); // 启用批量监听
factory.setBatchSize(50); // 批量大小
factory.setConsumerBatchEnabled(true);
factory.setReceiveTimeout(5000L); // 批量等待超时
return factory;
}
} try {`
`#/**
* 批量消费优化
*
* 通过批量拉取消息减少网络开销
*/
@Component
public class BatchConsumer {
@RabbitListener(
queues = "business.queue",
containerFactory = "batchContainerFactory"
)
public void handleBatch(List<Message> messages, Channel channel) {
List<Long> deliveryTags = new ArrayList<>();
try {
// 批量处理消息
for (Message message : messages) {
processMessage(message);
deliveryTags.add(message.getMessageProperties().getDeliveryTag());
}
// 批量确认
if (!deliveryTags.isEmpty()) {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicAck(lastTag, true); // multiple=true
}
} catch (Exception e) {
// 批量失败,全部重新入队
try {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicNack(lastTag, true, true);
} catch (IOException ex) {
log.error("批量NACK失败", ex);
}
}
}
private void processMessage(Message message) {
// 处理逻辑
}
}
/**
* 批量消费配置
*/
@Configuration
public class BatchConsumerConfig {
@Bean
public SimpleRabbitListenerContainerFactory batchContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
factory.setBatchListener(true); // 启用批量监听
factory.setBatchSize(50); // 批量大小
factory.setConsumerBatchEnabled(true);
factory.setReceiveTimeout(5000L); // 批量等待超时
return factory;
}
} // 批量处理消息`
`#/**
* 批量消费优化
*
* 通过批量拉取消息减少网络开销
*/
@Component
public class BatchConsumer {
@RabbitListener(
queues = "business.queue",
containerFactory = "batchContainerFactory"
)
public void handleBatch(List<Message> messages, Channel channel) {
List<Long> deliveryTags = new ArrayList<>();
try {
// 批量处理消息
for (Message message : messages) {
processMessage(message);
deliveryTags.add(message.getMessageProperties().getDeliveryTag());
}
// 批量确认
if (!deliveryTags.isEmpty()) {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicAck(lastTag, true); // multiple=true
}
} catch (Exception e) {
// 批量失败,全部重新入队
try {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicNack(lastTag, true, true);
} catch (IOException ex) {
log.error("批量NACK失败", ex);
}
}
}
private void processMessage(Message message) {
// 处理逻辑
}
}
/**
* 批量消费配置
*/
@Configuration
public class BatchConsumerConfig {
@Bean
public SimpleRabbitListenerContainerFactory batchContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
factory.setBatchListener(true); // 启用批量监听
factory.setBatchSize(50); // 批量大小
factory.setConsumerBatchEnabled(true);
factory.setReceiveTimeout(5000L); // 批量等待超时
return factory;
}
} for (Message message : messages) {`
`#/**
* 批量消费优化
*
* 通过批量拉取消息减少网络开销
*/
@Component
public class BatchConsumer {
@RabbitListener(
queues = "business.queue",
containerFactory = "batchContainerFactory"
)
public void handleBatch(List<Message> messages, Channel channel) {
List<Long> deliveryTags = new ArrayList<>();
try {
// 批量处理消息
for (Message message : messages) {
processMessage(message);
deliveryTags.add(message.getMessageProperties().getDeliveryTag());
}
// 批量确认
if (!deliveryTags.isEmpty()) {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicAck(lastTag, true); // multiple=true
}
} catch (Exception e) {
// 批量失败,全部重新入队
try {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicNack(lastTag, true, true);
} catch (IOException ex) {
log.error("批量NACK失败", ex);
}
}
}
private void processMessage(Message message) {
// 处理逻辑
}
}
/**
* 批量消费配置
*/
@Configuration
public class BatchConsumerConfig {
@Bean
public SimpleRabbitListenerContainerFactory batchContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
factory.setBatchListener(true); // 启用批量监听
factory.setBatchSize(50); // 批量大小
factory.setConsumerBatchEnabled(true);
factory.setReceiveTimeout(5000L); // 批量等待超时
return factory;
}
} processMessage(message);`
`#/**
* 批量消费优化
*
* 通过批量拉取消息减少网络开销
*/
@Component
public class BatchConsumer {
@RabbitListener(
queues = "business.queue",
containerFactory = "batchContainerFactory"
)
public void handleBatch(List<Message> messages, Channel channel) {
List<Long> deliveryTags = new ArrayList<>();
try {
// 批量处理消息
for (Message message : messages) {
processMessage(message);
deliveryTags.add(message.getMessageProperties().getDeliveryTag());
}
// 批量确认
if (!deliveryTags.isEmpty()) {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicAck(lastTag, true); // multiple=true
}
} catch (Exception e) {
// 批量失败,全部重新入队
try {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicNack(lastTag, true, true);
} catch (IOException ex) {
log.error("批量NACK失败", ex);
}
}
}
private void processMessage(Message message) {
// 处理逻辑
}
}
/**
* 批量消费配置
*/
@Configuration
public class BatchConsumerConfig {
@Bean
public SimpleRabbitListenerContainerFactory batchContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
factory.setBatchListener(true); // 启用批量监听
factory.setBatchSize(50); // 批量大小
factory.setConsumerBatchEnabled(true);
factory.setReceiveTimeout(5000L); // 批量等待超时
return factory;
}
} deliveryTags.add(message.getMessageProperties().getDeliveryTag());`
`#/**
* 批量消费优化
*
* 通过批量拉取消息减少网络开销
*/
@Component
public class BatchConsumer {
@RabbitListener(
queues = "business.queue",
containerFactory = "batchContainerFactory"
)
public void handleBatch(List<Message> messages, Channel channel) {
List<Long> deliveryTags = new ArrayList<>();
try {
// 批量处理消息
for (Message message : messages) {
processMessage(message);
deliveryTags.add(message.getMessageProperties().getDeliveryTag());
}
// 批量确认
if (!deliveryTags.isEmpty()) {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicAck(lastTag, true); // multiple=true
}
} catch (Exception e) {
// 批量失败,全部重新入队
try {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicNack(lastTag, true, true);
} catch (IOException ex) {
log.error("批量NACK失败", ex);
}
}
}
private void processMessage(Message message) {
// 处理逻辑
}
}
/**
* 批量消费配置
*/
@Configuration
public class BatchConsumerConfig {
@Bean
public SimpleRabbitListenerContainerFactory batchContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
factory.setBatchListener(true); // 启用批量监听
factory.setBatchSize(50); // 批量大小
factory.setConsumerBatchEnabled(true);
factory.setReceiveTimeout(5000L); // 批量等待超时
return factory;
}
} }`
`#/**
* 批量消费优化
*
* 通过批量拉取消息减少网络开销
*/
@Component
public class BatchConsumer {
@RabbitListener(
queues = "business.queue",
containerFactory = "batchContainerFactory"
)
public void handleBatch(List<Message> messages, Channel channel) {
List<Long> deliveryTags = new ArrayList<>();
try {
// 批量处理消息
for (Message message : messages) {
processMessage(message);
deliveryTags.add(message.getMessageProperties().getDeliveryTag());
}
// 批量确认
if (!deliveryTags.isEmpty()) {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicAck(lastTag, true); // multiple=true
}
} catch (Exception e) {
// 批量失败,全部重新入队
try {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicNack(lastTag, true, true);
} catch (IOException ex) {
log.error("批量NACK失败", ex);
}
}
}
private void processMessage(Message message) {
// 处理逻辑
}
}
/**
* 批量消费配置
*/
@Configuration
public class BatchConsumerConfig {
@Bean
public SimpleRabbitListenerContainerFactory batchContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
factory.setBatchListener(true); // 启用批量监听
factory.setBatchSize(50); // 批量大小
factory.setConsumerBatchEnabled(true);
factory.setReceiveTimeout(5000L); // 批量等待超时
return factory;
}
} `
`#/**
* 批量消费优化
*
* 通过批量拉取消息减少网络开销
*/
@Component
public class BatchConsumer {
@RabbitListener(
queues = "business.queue",
containerFactory = "batchContainerFactory"
)
public void handleBatch(List<Message> messages, Channel channel) {
List<Long> deliveryTags = new ArrayList<>();
try {
// 批量处理消息
for (Message message : messages) {
processMessage(message);
deliveryTags.add(message.getMessageProperties().getDeliveryTag());
}
// 批量确认
if (!deliveryTags.isEmpty()) {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicAck(lastTag, true); // multiple=true
}
} catch (Exception e) {
// 批量失败,全部重新入队
try {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicNack(lastTag, true, true);
} catch (IOException ex) {
log.error("批量NACK失败", ex);
}
}
}
private void processMessage(Message message) {
// 处理逻辑
}
}
/**
* 批量消费配置
*/
@Configuration
public class BatchConsumerConfig {
@Bean
public SimpleRabbitListenerContainerFactory batchContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
factory.setBatchListener(true); // 启用批量监听
factory.setBatchSize(50); // 批量大小
factory.setConsumerBatchEnabled(true);
factory.setReceiveTimeout(5000L); // 批量等待超时
return factory;
}
} // 批量确认`
`#/**
* 批量消费优化
*
* 通过批量拉取消息减少网络开销
*/
@Component
public class BatchConsumer {
@RabbitListener(
queues = "business.queue",
containerFactory = "batchContainerFactory"
)
public void handleBatch(List<Message> messages, Channel channel) {
List<Long> deliveryTags = new ArrayList<>();
try {
// 批量处理消息
for (Message message : messages) {
processMessage(message);
deliveryTags.add(message.getMessageProperties().getDeliveryTag());
}
// 批量确认
if (!deliveryTags.isEmpty()) {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicAck(lastTag, true); // multiple=true
}
} catch (Exception e) {
// 批量失败,全部重新入队
try {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicNack(lastTag, true, true);
} catch (IOException ex) {
log.error("批量NACK失败", ex);
}
}
}
private void processMessage(Message message) {
// 处理逻辑
}
}
/**
* 批量消费配置
*/
@Configuration
public class BatchConsumerConfig {
@Bean
public SimpleRabbitListenerContainerFactory batchContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
factory.setBatchListener(true); // 启用批量监听
factory.setBatchSize(50); // 批量大小
factory.setConsumerBatchEnabled(true);
factory.setReceiveTimeout(5000L); // 批量等待超时
return factory;
}
} if (!deliveryTags.isEmpty()) {`
`#/**
* 批量消费优化
*
* 通过批量拉取消息减少网络开销
*/
@Component
public class BatchConsumer {
@RabbitListener(
queues = "business.queue",
containerFactory = "batchContainerFactory"
)
public void handleBatch(List<Message> messages, Channel channel) {
List<Long> deliveryTags = new ArrayList<>();
try {
// 批量处理消息
for (Message message : messages) {
processMessage(message);
deliveryTags.add(message.getMessageProperties().getDeliveryTag());
}
// 批量确认
if (!deliveryTags.isEmpty()) {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicAck(lastTag, true); // multiple=true
}
} catch (Exception e) {
// 批量失败,全部重新入队
try {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicNack(lastTag, true, true);
} catch (IOException ex) {
log.error("批量NACK失败", ex);
}
}
}
private void processMessage(Message message) {
// 处理逻辑
}
}
/**
* 批量消费配置
*/
@Configuration
public class BatchConsumerConfig {
@Bean
public SimpleRabbitListenerContainerFactory batchContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
factory.setBatchListener(true); // 启用批量监听
factory.setBatchSize(50); // 批量大小
factory.setConsumerBatchEnabled(true);
factory.setReceiveTimeout(5000L); // 批量等待超时
return factory;
}
} Long lastTag = deliveryTags.get(deliveryTags.size() - 1);`
`#/**
* 批量消费优化
*
* 通过批量拉取消息减少网络开销
*/
@Component
public class BatchConsumer {
@RabbitListener(
queues = "business.queue",
containerFactory = "batchContainerFactory"
)
public void handleBatch(List<Message> messages, Channel channel) {
List<Long> deliveryTags = new ArrayList<>();
try {
// 批量处理消息
for (Message message : messages) {
processMessage(message);
deliveryTags.add(message.getMessageProperties().getDeliveryTag());
}
// 批量确认
if (!deliveryTags.isEmpty()) {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicAck(lastTag, true); // multiple=true
}
} catch (Exception e) {
// 批量失败,全部重新入队
try {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicNack(lastTag, true, true);
} catch (IOException ex) {
log.error("批量NACK失败", ex);
}
}
}
private void processMessage(Message message) {
// 处理逻辑
}
}
/**
* 批量消费配置
*/
@Configuration
public class BatchConsumerConfig {
@Bean
public SimpleRabbitListenerContainerFactory batchContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
factory.setBatchListener(true); // 启用批量监听
factory.setBatchSize(50); // 批量大小
factory.setConsumerBatchEnabled(true);
factory.setReceiveTimeout(5000L); // 批量等待超时
return factory;
}
} channel.basicAck(lastTag, true); // multiple=true`
`#/**
* 批量消费优化
*
* 通过批量拉取消息减少网络开销
*/
@Component
public class BatchConsumer {
@RabbitListener(
queues = "business.queue",
containerFactory = "batchContainerFactory"
)
public void handleBatch(List<Message> messages, Channel channel) {
List<Long> deliveryTags = new ArrayList<>();
try {
// 批量处理消息
for (Message message : messages) {
processMessage(message);
deliveryTags.add(message.getMessageProperties().getDeliveryTag());
}
// 批量确认
if (!deliveryTags.isEmpty()) {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicAck(lastTag, true); // multiple=true
}
} catch (Exception e) {
// 批量失败,全部重新入队
try {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicNack(lastTag, true, true);
} catch (IOException ex) {
log.error("批量NACK失败", ex);
}
}
}
private void processMessage(Message message) {
// 处理逻辑
}
}
/**
* 批量消费配置
*/
@Configuration
public class BatchConsumerConfig {
@Bean
public SimpleRabbitListenerContainerFactory batchContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
factory.setBatchListener(true); // 启用批量监听
factory.setBatchSize(50); // 批量大小
factory.setConsumerBatchEnabled(true);
factory.setReceiveTimeout(5000L); // 批量等待超时
return factory;
}
} }`
`#/**
* 批量消费优化
*
* 通过批量拉取消息减少网络开销
*/
@Component
public class BatchConsumer {
@RabbitListener(
queues = "business.queue",
containerFactory = "batchContainerFactory"
)
public void handleBatch(List<Message> messages, Channel channel) {
List<Long> deliveryTags = new ArrayList<>();
try {
// 批量处理消息
for (Message message : messages) {
processMessage(message);
deliveryTags.add(message.getMessageProperties().getDeliveryTag());
}
// 批量确认
if (!deliveryTags.isEmpty()) {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicAck(lastTag, true); // multiple=true
}
} catch (Exception e) {
// 批量失败,全部重新入队
try {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicNack(lastTag, true, true);
} catch (IOException ex) {
log.error("批量NACK失败", ex);
}
}
}
private void processMessage(Message message) {
// 处理逻辑
}
}
/**
* 批量消费配置
*/
@Configuration
public class BatchConsumerConfig {
@Bean
public SimpleRabbitListenerContainerFactory batchContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
factory.setBatchListener(true); // 启用批量监听
factory.setBatchSize(50); // 批量大小
factory.setConsumerBatchEnabled(true);
factory.setReceiveTimeout(5000L); // 批量等待超时
return factory;
}
} `
`#/**
* 批量消费优化
*
* 通过批量拉取消息减少网络开销
*/
@Component
public class BatchConsumer {
@RabbitListener(
queues = "business.queue",
containerFactory = "batchContainerFactory"
)
public void handleBatch(List<Message> messages, Channel channel) {
List<Long> deliveryTags = new ArrayList<>();
try {
// 批量处理消息
for (Message message : messages) {
processMessage(message);
deliveryTags.add(message.getMessageProperties().getDeliveryTag());
}
// 批量确认
if (!deliveryTags.isEmpty()) {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicAck(lastTag, true); // multiple=true
}
} catch (Exception e) {
// 批量失败,全部重新入队
try {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicNack(lastTag, true, true);
} catch (IOException ex) {
log.error("批量NACK失败", ex);
}
}
}
private void processMessage(Message message) {
// 处理逻辑
}
}
/**
* 批量消费配置
*/
@Configuration
public class BatchConsumerConfig {
@Bean
public SimpleRabbitListenerContainerFactory batchContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
factory.setBatchListener(true); // 启用批量监听
factory.setBatchSize(50); // 批量大小
factory.setConsumerBatchEnabled(true);
factory.setReceiveTimeout(5000L); // 批量等待超时
return factory;
}
} } catch (Exception e) {`
`#/**
* 批量消费优化
*
* 通过批量拉取消息减少网络开销
*/
@Component
public class BatchConsumer {
@RabbitListener(
queues = "business.queue",
containerFactory = "batchContainerFactory"
)
public void handleBatch(List<Message> messages, Channel channel) {
List<Long> deliveryTags = new ArrayList<>();
try {
// 批量处理消息
for (Message message : messages) {
processMessage(message);
deliveryTags.add(message.getMessageProperties().getDeliveryTag());
}
// 批量确认
if (!deliveryTags.isEmpty()) {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicAck(lastTag, true); // multiple=true
}
} catch (Exception e) {
// 批量失败,全部重新入队
try {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicNack(lastTag, true, true);
} catch (IOException ex) {
log.error("批量NACK失败", ex);
}
}
}
private void processMessage(Message message) {
// 处理逻辑
}
}
/**
* 批量消费配置
*/
@Configuration
public class BatchConsumerConfig {
@Bean
public SimpleRabbitListenerContainerFactory batchContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
factory.setBatchListener(true); // 启用批量监听
factory.setBatchSize(50); // 批量大小
factory.setConsumerBatchEnabled(true);
factory.setReceiveTimeout(5000L); // 批量等待超时
return factory;
}
} // 批量失败,全部重新入队`
`#/**
* 批量消费优化
*
* 通过批量拉取消息减少网络开销
*/
@Component
public class BatchConsumer {
@RabbitListener(
queues = "business.queue",
containerFactory = "batchContainerFactory"
)
public void handleBatch(List<Message> messages, Channel channel) {
List<Long> deliveryTags = new ArrayList<>();
try {
// 批量处理消息
for (Message message : messages) {
processMessage(message);
deliveryTags.add(message.getMessageProperties().getDeliveryTag());
}
// 批量确认
if (!deliveryTags.isEmpty()) {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicAck(lastTag, true); // multiple=true
}
} catch (Exception e) {
// 批量失败,全部重新入队
try {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicNack(lastTag, true, true);
} catch (IOException ex) {
log.error("批量NACK失败", ex);
}
}
}
private void processMessage(Message message) {
// 处理逻辑
}
}
/**
* 批量消费配置
*/
@Configuration
public class BatchConsumerConfig {
@Bean
public SimpleRabbitListenerContainerFactory batchContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
factory.setBatchListener(true); // 启用批量监听
factory.setBatchSize(50); // 批量大小
factory.setConsumerBatchEnabled(true);
factory.setReceiveTimeout(5000L); // 批量等待超时
return factory;
}
} try {`
`#/**
* 批量消费优化
*
* 通过批量拉取消息减少网络开销
*/
@Component
public class BatchConsumer {
@RabbitListener(
queues = "business.queue",
containerFactory = "batchContainerFactory"
)
public void handleBatch(List<Message> messages, Channel channel) {
List<Long> deliveryTags = new ArrayList<>();
try {
// 批量处理消息
for (Message message : messages) {
processMessage(message);
deliveryTags.add(message.getMessageProperties().getDeliveryTag());
}
// 批量确认
if (!deliveryTags.isEmpty()) {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicAck(lastTag, true); // multiple=true
}
} catch (Exception e) {
// 批量失败,全部重新入队
try {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicNack(lastTag, true, true);
} catch (IOException ex) {
log.error("批量NACK失败", ex);
}
}
}
private void processMessage(Message message) {
// 处理逻辑
}
}
/**
* 批量消费配置
*/
@Configuration
public class BatchConsumerConfig {
@Bean
public SimpleRabbitListenerContainerFactory batchContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
factory.setBatchListener(true); // 启用批量监听
factory.setBatchSize(50); // 批量大小
factory.setConsumerBatchEnabled(true);
factory.setReceiveTimeout(5000L); // 批量等待超时
return factory;
}
} Long lastTag = deliveryTags.get(deliveryTags.size() - 1);`
`#/**
* 批量消费优化
*
* 通过批量拉取消息减少网络开销
*/
@Component
public class BatchConsumer {
@RabbitListener(
queues = "business.queue",
containerFactory = "batchContainerFactory"
)
public void handleBatch(List<Message> messages, Channel channel) {
List<Long> deliveryTags = new ArrayList<>();
try {
// 批量处理消息
for (Message message : messages) {
processMessage(message);
deliveryTags.add(message.getMessageProperties().getDeliveryTag());
}
// 批量确认
if (!deliveryTags.isEmpty()) {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicAck(lastTag, true); // multiple=true
}
} catch (Exception e) {
// 批量失败,全部重新入队
try {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicNack(lastTag, true, true);
} catch (IOException ex) {
log.error("批量NACK失败", ex);
}
}
}
private void processMessage(Message message) {
// 处理逻辑
}
}
/**
* 批量消费配置
*/
@Configuration
public class BatchConsumerConfig {
@Bean
public SimpleRabbitListenerContainerFactory batchContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
factory.setBatchListener(true); // 启用批量监听
factory.setBatchSize(50); // 批量大小
factory.setConsumerBatchEnabled(true);
factory.setReceiveTimeout(5000L); // 批量等待超时
return factory;
}
} channel.basicNack(lastTag, true, true);`
`#/**
* 批量消费优化
*
* 通过批量拉取消息减少网络开销
*/
@Component
public class BatchConsumer {
@RabbitListener(
queues = "business.queue",
containerFactory = "batchContainerFactory"
)
public void handleBatch(List<Message> messages, Channel channel) {
List<Long> deliveryTags = new ArrayList<>();
try {
// 批量处理消息
for (Message message : messages) {
processMessage(message);
deliveryTags.add(message.getMessageProperties().getDeliveryTag());
}
// 批量确认
if (!deliveryTags.isEmpty()) {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicAck(lastTag, true); // multiple=true
}
} catch (Exception e) {
// 批量失败,全部重新入队
try {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicNack(lastTag, true, true);
} catch (IOException ex) {
log.error("批量NACK失败", ex);
}
}
}
private void processMessage(Message message) {
// 处理逻辑
}
}
/**
* 批量消费配置
*/
@Configuration
public class BatchConsumerConfig {
@Bean
public SimpleRabbitListenerContainerFactory batchContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
factory.setBatchListener(true); // 启用批量监听
factory.setBatchSize(50); // 批量大小
factory.setConsumerBatchEnabled(true);
factory.setReceiveTimeout(5000L); // 批量等待超时
return factory;
}
} } catch (IOException ex) {`
`#/**
* 批量消费优化
*
* 通过批量拉取消息减少网络开销
*/
@Component
public class BatchConsumer {
@RabbitListener(
queues = "business.queue",
containerFactory = "batchContainerFactory"
)
public void handleBatch(List<Message> messages, Channel channel) {
List<Long> deliveryTags = new ArrayList<>();
try {
// 批量处理消息
for (Message message : messages) {
processMessage(message);
deliveryTags.add(message.getMessageProperties().getDeliveryTag());
}
// 批量确认
if (!deliveryTags.isEmpty()) {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicAck(lastTag, true); // multiple=true
}
} catch (Exception e) {
// 批量失败,全部重新入队
try {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicNack(lastTag, true, true);
} catch (IOException ex) {
log.error("批量NACK失败", ex);
}
}
}
private void processMessage(Message message) {
// 处理逻辑
}
}
/**
* 批量消费配置
*/
@Configuration
public class BatchConsumerConfig {
@Bean
public SimpleRabbitListenerContainerFactory batchContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
factory.setBatchListener(true); // 启用批量监听
factory.setBatchSize(50); // 批量大小
factory.setConsumerBatchEnabled(true);
factory.setReceiveTimeout(5000L); // 批量等待超时
return factory;
}
} log.error("批量NACK失败", ex);`
`#/**
* 批量消费优化
*
* 通过批量拉取消息减少网络开销
*/
@Component
public class BatchConsumer {
@RabbitListener(
queues = "business.queue",
containerFactory = "batchContainerFactory"
)
public void handleBatch(List<Message> messages, Channel channel) {
List<Long> deliveryTags = new ArrayList<>();
try {
// 批量处理消息
for (Message message : messages) {
processMessage(message);
deliveryTags.add(message.getMessageProperties().getDeliveryTag());
}
// 批量确认
if (!deliveryTags.isEmpty()) {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicAck(lastTag, true); // multiple=true
}
} catch (Exception e) {
// 批量失败,全部重新入队
try {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicNack(lastTag, true, true);
} catch (IOException ex) {
log.error("批量NACK失败", ex);
}
}
}
private void processMessage(Message message) {
// 处理逻辑
}
}
/**
* 批量消费配置
*/
@Configuration
public class BatchConsumerConfig {
@Bean
public SimpleRabbitListenerContainerFactory batchContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
factory.setBatchListener(true); // 启用批量监听
factory.setBatchSize(50); // 批量大小
factory.setConsumerBatchEnabled(true);
factory.setReceiveTimeout(5000L); // 批量等待超时
return factory;
}
} }`
`#/**
* 批量消费优化
*
* 通过批量拉取消息减少网络开销
*/
@Component
public class BatchConsumer {
@RabbitListener(
queues = "business.queue",
containerFactory = "batchContainerFactory"
)
public void handleBatch(List<Message> messages, Channel channel) {
List<Long> deliveryTags = new ArrayList<>();
try {
// 批量处理消息
for (Message message : messages) {
processMessage(message);
deliveryTags.add(message.getMessageProperties().getDeliveryTag());
}
// 批量确认
if (!deliveryTags.isEmpty()) {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicAck(lastTag, true); // multiple=true
}
} catch (Exception e) {
// 批量失败,全部重新入队
try {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicNack(lastTag, true, true);
} catch (IOException ex) {
log.error("批量NACK失败", ex);
}
}
}
private void processMessage(Message message) {
// 处理逻辑
}
}
/**
* 批量消费配置
*/
@Configuration
public class BatchConsumerConfig {
@Bean
public SimpleRabbitListenerContainerFactory batchContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
factory.setBatchListener(true); // 启用批量监听
factory.setBatchSize(50); // 批量大小
factory.setConsumerBatchEnabled(true);
factory.setReceiveTimeout(5000L); // 批量等待超时
return factory;
}
} }`
`#/**
* 批量消费优化
*
* 通过批量拉取消息减少网络开销
*/
@Component
public class BatchConsumer {
@RabbitListener(
queues = "business.queue",
containerFactory = "batchContainerFactory"
)
public void handleBatch(List<Message> messages, Channel channel) {
List<Long> deliveryTags = new ArrayList<>();
try {
// 批量处理消息
for (Message message : messages) {
processMessage(message);
deliveryTags.add(message.getMessageProperties().getDeliveryTag());
}
// 批量确认
if (!deliveryTags.isEmpty()) {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicAck(lastTag, true); // multiple=true
}
} catch (Exception e) {
// 批量失败,全部重新入队
try {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicNack(lastTag, true, true);
} catch (IOException ex) {
log.error("批量NACK失败", ex);
}
}
}
private void processMessage(Message message) {
// 处理逻辑
}
}
/**
* 批量消费配置
*/
@Configuration
public class BatchConsumerConfig {
@Bean
public SimpleRabbitListenerContainerFactory batchContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
factory.setBatchListener(true); // 启用批量监听
factory.setBatchSize(50); // 批量大小
factory.setConsumerBatchEnabled(true);
factory.setReceiveTimeout(5000L); // 批量等待超时
return factory;
}
} }`
`#/**
* 批量消费优化
*
* 通过批量拉取消息减少网络开销
*/
@Component
public class BatchConsumer {
@RabbitListener(
queues = "business.queue",
containerFactory = "batchContainerFactory"
)
public void handleBatch(List<Message> messages, Channel channel) {
List<Long> deliveryTags = new ArrayList<>();
try {
// 批量处理消息
for (Message message : messages) {
processMessage(message);
deliveryTags.add(message.getMessageProperties().getDeliveryTag());
}
// 批量确认
if (!deliveryTags.isEmpty()) {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicAck(lastTag, true); // multiple=true
}
} catch (Exception e) {
// 批量失败,全部重新入队
try {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicNack(lastTag, true, true);
} catch (IOException ex) {
log.error("批量NACK失败", ex);
}
}
}
private void processMessage(Message message) {
// 处理逻辑
}
}
/**
* 批量消费配置
*/
@Configuration
public class BatchConsumerConfig {
@Bean
public SimpleRabbitListenerContainerFactory batchContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
factory.setBatchListener(true); // 启用批量监听
factory.setBatchSize(50); // 批量大小
factory.setConsumerBatchEnabled(true);
factory.setReceiveTimeout(5000L); // 批量等待超时
return factory;
}
}`
`#/**
* 批量消费优化
*
* 通过批量拉取消息减少网络开销
*/
@Component
public class BatchConsumer {
@RabbitListener(
queues = "business.queue",
containerFactory = "batchContainerFactory"
)
public void handleBatch(List<Message> messages, Channel channel) {
List<Long> deliveryTags = new ArrayList<>();
try {
// 批量处理消息
for (Message message : messages) {
processMessage(message);
deliveryTags.add(message.getMessageProperties().getDeliveryTag());
}
// 批量确认
if (!deliveryTags.isEmpty()) {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicAck(lastTag, true); // multiple=true
}
} catch (Exception e) {
// 批量失败,全部重新入队
try {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicNack(lastTag, true, true);
} catch (IOException ex) {
log.error("批量NACK失败", ex);
}
}
}
private void processMessage(Message message) {
// 处理逻辑
}
}
/**
* 批量消费配置
*/
@Configuration
public class BatchConsumerConfig {
@Bean
public SimpleRabbitListenerContainerFactory batchContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
factory.setBatchListener(true); // 启用批量监听
factory.setBatchSize(50); // 批量大小
factory.setConsumerBatchEnabled(true);
factory.setReceiveTimeout(5000L); // 批量等待超时
return factory;
}
} private void processMessage(Message message) {`
`#/**
* 批量消费优化
*
* 通过批量拉取消息减少网络开销
*/
@Component
public class BatchConsumer {
@RabbitListener(
queues = "business.queue",
containerFactory = "batchContainerFactory"
)
public void handleBatch(List<Message> messages, Channel channel) {
List<Long> deliveryTags = new ArrayList<>();
try {
// 批量处理消息
for (Message message : messages) {
processMessage(message);
deliveryTags.add(message.getMessageProperties().getDeliveryTag());
}
// 批量确认
if (!deliveryTags.isEmpty()) {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicAck(lastTag, true); // multiple=true
}
} catch (Exception e) {
// 批量失败,全部重新入队
try {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicNack(lastTag, true, true);
} catch (IOException ex) {
log.error("批量NACK失败", ex);
}
}
}
private void processMessage(Message message) {
// 处理逻辑
}
}
/**
* 批量消费配置
*/
@Configuration
public class BatchConsumerConfig {
@Bean
public SimpleRabbitListenerContainerFactory batchContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
factory.setBatchListener(true); // 启用批量监听
factory.setBatchSize(50); // 批量大小
factory.setConsumerBatchEnabled(true);
factory.setReceiveTimeout(5000L); // 批量等待超时
return factory;
}
} // 处理逻辑`
`#/**
* 批量消费优化
*
* 通过批量拉取消息减少网络开销
*/
@Component
public class BatchConsumer {
@RabbitListener(
queues = "business.queue",
containerFactory = "batchContainerFactory"
)
public void handleBatch(List<Message> messages, Channel channel) {
List<Long> deliveryTags = new ArrayList<>();
try {
// 批量处理消息
for (Message message : messages) {
processMessage(message);
deliveryTags.add(message.getMessageProperties().getDeliveryTag());
}
// 批量确认
if (!deliveryTags.isEmpty()) {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicAck(lastTag, true); // multiple=true
}
} catch (Exception e) {
// 批量失败,全部重新入队
try {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicNack(lastTag, true, true);
} catch (IOException ex) {
log.error("批量NACK失败", ex);
}
}
}
private void processMessage(Message message) {
// 处理逻辑
}
}
/**
* 批量消费配置
*/
@Configuration
public class BatchConsumerConfig {
@Bean
public SimpleRabbitListenerContainerFactory batchContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
factory.setBatchListener(true); // 启用批量监听
factory.setBatchSize(50); // 批量大小
factory.setConsumerBatchEnabled(true);
factory.setReceiveTimeout(5000L); // 批量等待超时
return factory;
}
} }`
`#/**
* 批量消费优化
*
* 通过批量拉取消息减少网络开销
*/
@Component
public class BatchConsumer {
@RabbitListener(
queues = "business.queue",
containerFactory = "batchContainerFactory"
)
public void handleBatch(List<Message> messages, Channel channel) {
List<Long> deliveryTags = new ArrayList<>();
try {
// 批量处理消息
for (Message message : messages) {
processMessage(message);
deliveryTags.add(message.getMessageProperties().getDeliveryTag());
}
// 批量确认
if (!deliveryTags.isEmpty()) {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicAck(lastTag, true); // multiple=true
}
} catch (Exception e) {
// 批量失败,全部重新入队
try {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicNack(lastTag, true, true);
} catch (IOException ex) {
log.error("批量NACK失败", ex);
}
}
}
private void processMessage(Message message) {
// 处理逻辑
}
}
/**
* 批量消费配置
*/
@Configuration
public class BatchConsumerConfig {
@Bean
public SimpleRabbitListenerContainerFactory batchContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
factory.setBatchListener(true); // 启用批量监听
factory.setBatchSize(50); // 批量大小
factory.setConsumerBatchEnabled(true);
factory.setReceiveTimeout(5000L); // 批量等待超时
return factory;
}
}}`
`#/**
* 批量消费优化
*
* 通过批量拉取消息减少网络开销
*/
@Component
public class BatchConsumer {
@RabbitListener(
queues = "business.queue",
containerFactory = "batchContainerFactory"
)
public void handleBatch(List<Message> messages, Channel channel) {
List<Long> deliveryTags = new ArrayList<>();
try {
// 批量处理消息
for (Message message : messages) {
processMessage(message);
deliveryTags.add(message.getMessageProperties().getDeliveryTag());
}
// 批量确认
if (!deliveryTags.isEmpty()) {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicAck(lastTag, true); // multiple=true
}
} catch (Exception e) {
// 批量失败,全部重新入队
try {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicNack(lastTag, true, true);
} catch (IOException ex) {
log.error("批量NACK失败", ex);
}
}
}
private void processMessage(Message message) {
// 处理逻辑
}
}
/**
* 批量消费配置
*/
@Configuration
public class BatchConsumerConfig {
@Bean
public SimpleRabbitListenerContainerFactory batchContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
factory.setBatchListener(true); // 启用批量监听
factory.setBatchSize(50); // 批量大小
factory.setConsumerBatchEnabled(true);
factory.setReceiveTimeout(5000L); // 批量等待超时
return factory;
}
}`
`#/**
* 批量消费优化
*
* 通过批量拉取消息减少网络开销
*/
@Component
public class BatchConsumer {
@RabbitListener(
queues = "business.queue",
containerFactory = "batchContainerFactory"
)
public void handleBatch(List<Message> messages, Channel channel) {
List<Long> deliveryTags = new ArrayList<>();
try {
// 批量处理消息
for (Message message : messages) {
processMessage(message);
deliveryTags.add(message.getMessageProperties().getDeliveryTag());
}
// 批量确认
if (!deliveryTags.isEmpty()) {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicAck(lastTag, true); // multiple=true
}
} catch (Exception e) {
// 批量失败,全部重新入队
try {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicNack(lastTag, true, true);
} catch (IOException ex) {
log.error("批量NACK失败", ex);
}
}
}
private void processMessage(Message message) {
// 处理逻辑
}
}
/**
* 批量消费配置
*/
@Configuration
public class BatchConsumerConfig {
@Bean
public SimpleRabbitListenerContainerFactory batchContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
factory.setBatchListener(true); // 启用批量监听
factory.setBatchSize(50); // 批量大小
factory.setConsumerBatchEnabled(true);
factory.setReceiveTimeout(5000L); // 批量等待超时
return factory;
}
}/**`
`#/**
* 批量消费优化
*
* 通过批量拉取消息减少网络开销
*/
@Component
public class BatchConsumer {
@RabbitListener(
queues = "business.queue",
containerFactory = "batchContainerFactory"
)
public void handleBatch(List<Message> messages, Channel channel) {
List<Long> deliveryTags = new ArrayList<>();
try {
// 批量处理消息
for (Message message : messages) {
processMessage(message);
deliveryTags.add(message.getMessageProperties().getDeliveryTag());
}
// 批量确认
if (!deliveryTags.isEmpty()) {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicAck(lastTag, true); // multiple=true
}
} catch (Exception e) {
// 批量失败,全部重新入队
try {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicNack(lastTag, true, true);
} catch (IOException ex) {
log.error("批量NACK失败", ex);
}
}
}
private void processMessage(Message message) {
// 处理逻辑
}
}
/**
* 批量消费配置
*/
@Configuration
public class BatchConsumerConfig {
@Bean
public SimpleRabbitListenerContainerFactory batchContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
factory.setBatchListener(true); // 启用批量监听
factory.setBatchSize(50); // 批量大小
factory.setConsumerBatchEnabled(true);
factory.setReceiveTimeout(5000L); // 批量等待超时
return factory;
}
} * 批量消费配置`
`#/**
* 批量消费优化
*
* 通过批量拉取消息减少网络开销
*/
@Component
public class BatchConsumer {
@RabbitListener(
queues = "business.queue",
containerFactory = "batchContainerFactory"
)
public void handleBatch(List<Message> messages, Channel channel) {
List<Long> deliveryTags = new ArrayList<>();
try {
// 批量处理消息
for (Message message : messages) {
processMessage(message);
deliveryTags.add(message.getMessageProperties().getDeliveryTag());
}
// 批量确认
if (!deliveryTags.isEmpty()) {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicAck(lastTag, true); // multiple=true
}
} catch (Exception e) {
// 批量失败,全部重新入队
try {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicNack(lastTag, true, true);
} catch (IOException ex) {
log.error("批量NACK失败", ex);
}
}
}
private void processMessage(Message message) {
// 处理逻辑
}
}
/**
* 批量消费配置
*/
@Configuration
public class BatchConsumerConfig {
@Bean
public SimpleRabbitListenerContainerFactory batchContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
factory.setBatchListener(true); // 启用批量监听
factory.setBatchSize(50); // 批量大小
factory.setConsumerBatchEnabled(true);
factory.setReceiveTimeout(5000L); // 批量等待超时
return factory;
}
} */`
`#/**
* 批量消费优化
*
* 通过批量拉取消息减少网络开销
*/
@Component
public class BatchConsumer {
@RabbitListener(
queues = "business.queue",
containerFactory = "batchContainerFactory"
)
public void handleBatch(List<Message> messages, Channel channel) {
List<Long> deliveryTags = new ArrayList<>();
try {
// 批量处理消息
for (Message message : messages) {
processMessage(message);
deliveryTags.add(message.getMessageProperties().getDeliveryTag());
}
// 批量确认
if (!deliveryTags.isEmpty()) {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicAck(lastTag, true); // multiple=true
}
} catch (Exception e) {
// 批量失败,全部重新入队
try {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicNack(lastTag, true, true);
} catch (IOException ex) {
log.error("批量NACK失败", ex);
}
}
}
private void processMessage(Message message) {
// 处理逻辑
}
}
/**
* 批量消费配置
*/
@Configuration
public class BatchConsumerConfig {
@Bean
public SimpleRabbitListenerContainerFactory batchContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
factory.setBatchListener(true); // 启用批量监听
factory.setBatchSize(50); // 批量大小
factory.setConsumerBatchEnabled(true);
factory.setReceiveTimeout(5000L); // 批量等待超时
return factory;
}
}@Configuration`
`#/**
* 批量消费优化
*
* 通过批量拉取消息减少网络开销
*/
@Component
public class BatchConsumer {
@RabbitListener(
queues = "business.queue",
containerFactory = "batchContainerFactory"
)
public void handleBatch(List<Message> messages, Channel channel) {
List<Long> deliveryTags = new ArrayList<>();
try {
// 批量处理消息
for (Message message : messages) {
processMessage(message);
deliveryTags.add(message.getMessageProperties().getDeliveryTag());
}
// 批量确认
if (!deliveryTags.isEmpty()) {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicAck(lastTag, true); // multiple=true
}
} catch (Exception e) {
// 批量失败,全部重新入队
try {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicNack(lastTag, true, true);
} catch (IOException ex) {
log.error("批量NACK失败", ex);
}
}
}
private void processMessage(Message message) {
// 处理逻辑
}
}
/**
* 批量消费配置
*/
@Configuration
public class BatchConsumerConfig {
@Bean
public SimpleRabbitListenerContainerFactory batchContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
factory.setBatchListener(true); // 启用批量监听
factory.setBatchSize(50); // 批量大小
factory.setConsumerBatchEnabled(true);
factory.setReceiveTimeout(5000L); // 批量等待超时
return factory;
}
}public class BatchConsumerConfig {`
`#/**
* 批量消费优化
*
* 通过批量拉取消息减少网络开销
*/
@Component
public class BatchConsumer {
@RabbitListener(
queues = "business.queue",
containerFactory = "batchContainerFactory"
)
public void handleBatch(List<Message> messages, Channel channel) {
List<Long> deliveryTags = new ArrayList<>();
try {
// 批量处理消息
for (Message message : messages) {
processMessage(message);
deliveryTags.add(message.getMessageProperties().getDeliveryTag());
}
// 批量确认
if (!deliveryTags.isEmpty()) {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicAck(lastTag, true); // multiple=true
}
} catch (Exception e) {
// 批量失败,全部重新入队
try {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicNack(lastTag, true, true);
} catch (IOException ex) {
log.error("批量NACK失败", ex);
}
}
}
private void processMessage(Message message) {
// 处理逻辑
}
}
/**
* 批量消费配置
*/
@Configuration
public class BatchConsumerConfig {
@Bean
public SimpleRabbitListenerContainerFactory batchContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
factory.setBatchListener(true); // 启用批量监听
factory.setBatchSize(50); // 批量大小
factory.setConsumerBatchEnabled(true);
factory.setReceiveTimeout(5000L); // 批量等待超时
return factory;
}
}`
`#/**
* 批量消费优化
*
* 通过批量拉取消息减少网络开销
*/
@Component
public class BatchConsumer {
@RabbitListener(
queues = "business.queue",
containerFactory = "batchContainerFactory"
)
public void handleBatch(List<Message> messages, Channel channel) {
List<Long> deliveryTags = new ArrayList<>();
try {
// 批量处理消息
for (Message message : messages) {
processMessage(message);
deliveryTags.add(message.getMessageProperties().getDeliveryTag());
}
// 批量确认
if (!deliveryTags.isEmpty()) {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicAck(lastTag, true); // multiple=true
}
} catch (Exception e) {
// 批量失败,全部重新入队
try {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicNack(lastTag, true, true);
} catch (IOException ex) {
log.error("批量NACK失败", ex);
}
}
}
private void processMessage(Message message) {
// 处理逻辑
}
}
/**
* 批量消费配置
*/
@Configuration
public class BatchConsumerConfig {
@Bean
public SimpleRabbitListenerContainerFactory batchContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
factory.setBatchListener(true); // 启用批量监听
factory.setBatchSize(50); // 批量大小
factory.setConsumerBatchEnabled(true);
factory.setReceiveTimeout(5000L); // 批量等待超时
return factory;
}
} @Bean`
`#/**
* 批量消费优化
*
* 通过批量拉取消息减少网络开销
*/
@Component
public class BatchConsumer {
@RabbitListener(
queues = "business.queue",
containerFactory = "batchContainerFactory"
)
public void handleBatch(List<Message> messages, Channel channel) {
List<Long> deliveryTags = new ArrayList<>();
try {
// 批量处理消息
for (Message message : messages) {
processMessage(message);
deliveryTags.add(message.getMessageProperties().getDeliveryTag());
}
// 批量确认
if (!deliveryTags.isEmpty()) {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicAck(lastTag, true); // multiple=true
}
} catch (Exception e) {
// 批量失败,全部重新入队
try {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicNack(lastTag, true, true);
} catch (IOException ex) {
log.error("批量NACK失败", ex);
}
}
}
private void processMessage(Message message) {
// 处理逻辑
}
}
/**
* 批量消费配置
*/
@Configuration
public class BatchConsumerConfig {
@Bean
public SimpleRabbitListenerContainerFactory batchContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
factory.setBatchListener(true); // 启用批量监听
factory.setBatchSize(50); // 批量大小
factory.setConsumerBatchEnabled(true);
factory.setReceiveTimeout(5000L); // 批量等待超时
return factory;
}
} public SimpleRabbitListenerContainerFactory batchContainerFactory(`
`#/**
* 批量消费优化
*
* 通过批量拉取消息减少网络开销
*/
@Component
public class BatchConsumer {
@RabbitListener(
queues = "business.queue",
containerFactory = "batchContainerFactory"
)
public void handleBatch(List<Message> messages, Channel channel) {
List<Long> deliveryTags = new ArrayList<>();
try {
// 批量处理消息
for (Message message : messages) {
processMessage(message);
deliveryTags.add(message.getMessageProperties().getDeliveryTag());
}
// 批量确认
if (!deliveryTags.isEmpty()) {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicAck(lastTag, true); // multiple=true
}
} catch (Exception e) {
// 批量失败,全部重新入队
try {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicNack(lastTag, true, true);
} catch (IOException ex) {
log.error("批量NACK失败", ex);
}
}
}
private void processMessage(Message message) {
// 处理逻辑
}
}
/**
* 批量消费配置
*/
@Configuration
public class BatchConsumerConfig {
@Bean
public SimpleRabbitListenerContainerFactory batchContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
factory.setBatchListener(true); // 启用批量监听
factory.setBatchSize(50); // 批量大小
factory.setConsumerBatchEnabled(true);
factory.setReceiveTimeout(5000L); // 批量等待超时
return factory;
}
} ConnectionFactory connectionFactory) {`
`#/**
* 批量消费优化
*
* 通过批量拉取消息减少网络开销
*/
@Component
public class BatchConsumer {
@RabbitListener(
queues = "business.queue",
containerFactory = "batchContainerFactory"
)
public void handleBatch(List<Message> messages, Channel channel) {
List<Long> deliveryTags = new ArrayList<>();
try {
// 批量处理消息
for (Message message : messages) {
processMessage(message);
deliveryTags.add(message.getMessageProperties().getDeliveryTag());
}
// 批量确认
if (!deliveryTags.isEmpty()) {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicAck(lastTag, true); // multiple=true
}
} catch (Exception e) {
// 批量失败,全部重新入队
try {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicNack(lastTag, true, true);
} catch (IOException ex) {
log.error("批量NACK失败", ex);
}
}
}
private void processMessage(Message message) {
// 处理逻辑
}
}
/**
* 批量消费配置
*/
@Configuration
public class BatchConsumerConfig {
@Bean
public SimpleRabbitListenerContainerFactory batchContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
factory.setBatchListener(true); // 启用批量监听
factory.setBatchSize(50); // 批量大小
factory.setConsumerBatchEnabled(true);
factory.setReceiveTimeout(5000L); // 批量等待超时
return factory;
}
} SimpleRabbitListenerContainerFactory factory = `
`#/**
* 批量消费优化
*
* 通过批量拉取消息减少网络开销
*/
@Component
public class BatchConsumer {
@RabbitListener(
queues = "business.queue",
containerFactory = "batchContainerFactory"
)
public void handleBatch(List<Message> messages, Channel channel) {
List<Long> deliveryTags = new ArrayList<>();
try {
// 批量处理消息
for (Message message : messages) {
processMessage(message);
deliveryTags.add(message.getMessageProperties().getDeliveryTag());
}
// 批量确认
if (!deliveryTags.isEmpty()) {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicAck(lastTag, true); // multiple=true
}
} catch (Exception e) {
// 批量失败,全部重新入队
try {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicNack(lastTag, true, true);
} catch (IOException ex) {
log.error("批量NACK失败", ex);
}
}
}
private void processMessage(Message message) {
// 处理逻辑
}
}
/**
* 批量消费配置
*/
@Configuration
public class BatchConsumerConfig {
@Bean
public SimpleRabbitListenerContainerFactory batchContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
factory.setBatchListener(true); // 启用批量监听
factory.setBatchSize(50); // 批量大小
factory.setConsumerBatchEnabled(true);
factory.setReceiveTimeout(5000L); // 批量等待超时
return factory;
}
} new SimpleRabbitListenerContainerFactory();`
`#/**
* 批量消费优化
*
* 通过批量拉取消息减少网络开销
*/
@Component
public class BatchConsumer {
@RabbitListener(
queues = "business.queue",
containerFactory = "batchContainerFactory"
)
public void handleBatch(List<Message> messages, Channel channel) {
List<Long> deliveryTags = new ArrayList<>();
try {
// 批量处理消息
for (Message message : messages) {
processMessage(message);
deliveryTags.add(message.getMessageProperties().getDeliveryTag());
}
// 批量确认
if (!deliveryTags.isEmpty()) {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicAck(lastTag, true); // multiple=true
}
} catch (Exception e) {
// 批量失败,全部重新入队
try {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicNack(lastTag, true, true);
} catch (IOException ex) {
log.error("批量NACK失败", ex);
}
}
}
private void processMessage(Message message) {
// 处理逻辑
}
}
/**
* 批量消费配置
*/
@Configuration
public class BatchConsumerConfig {
@Bean
public SimpleRabbitListenerContainerFactory batchContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
factory.setBatchListener(true); // 启用批量监听
factory.setBatchSize(50); // 批量大小
factory.setConsumerBatchEnabled(true);
factory.setReceiveTimeout(5000L); // 批量等待超时
return factory;
}
} factory.setConnectionFactory(connectionFactory);`
`#/**
* 批量消费优化
*
* 通过批量拉取消息减少网络开销
*/
@Component
public class BatchConsumer {
@RabbitListener(
queues = "business.queue",
containerFactory = "batchContainerFactory"
)
public void handleBatch(List<Message> messages, Channel channel) {
List<Long> deliveryTags = new ArrayList<>();
try {
// 批量处理消息
for (Message message : messages) {
processMessage(message);
deliveryTags.add(message.getMessageProperties().getDeliveryTag());
}
// 批量确认
if (!deliveryTags.isEmpty()) {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicAck(lastTag, true); // multiple=true
}
} catch (Exception e) {
// 批量失败,全部重新入队
try {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicNack(lastTag, true, true);
} catch (IOException ex) {
log.error("批量NACK失败", ex);
}
}
}
private void processMessage(Message message) {
// 处理逻辑
}
}
/**
* 批量消费配置
*/
@Configuration
public class BatchConsumerConfig {
@Bean
public SimpleRabbitListenerContainerFactory batchContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
factory.setBatchListener(true); // 启用批量监听
factory.setBatchSize(50); // 批量大小
factory.setConsumerBatchEnabled(true);
factory.setReceiveTimeout(5000L); // 批量等待超时
return factory;
}
} factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);`
`#/**
* 批量消费优化
*
* 通过批量拉取消息减少网络开销
*/
@Component
public class BatchConsumer {
@RabbitListener(
queues = "business.queue",
containerFactory = "batchContainerFactory"
)
public void handleBatch(List<Message> messages, Channel channel) {
List<Long> deliveryTags = new ArrayList<>();
try {
// 批量处理消息
for (Message message : messages) {
processMessage(message);
deliveryTags.add(message.getMessageProperties().getDeliveryTag());
}
// 批量确认
if (!deliveryTags.isEmpty()) {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicAck(lastTag, true); // multiple=true
}
} catch (Exception e) {
// 批量失败,全部重新入队
try {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicNack(lastTag, true, true);
} catch (IOException ex) {
log.error("批量NACK失败", ex);
}
}
}
private void processMessage(Message message) {
// 处理逻辑
}
}
/**
* 批量消费配置
*/
@Configuration
public class BatchConsumerConfig {
@Bean
public SimpleRabbitListenerContainerFactory batchContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
factory.setBatchListener(true); // 启用批量监听
factory.setBatchSize(50); // 批量大小
factory.setConsumerBatchEnabled(true);
factory.setReceiveTimeout(5000L); // 批量等待超时
return factory;
}
} factory.setBatchListener(true); // 启用批量监听`
`#/**
* 批量消费优化
*
* 通过批量拉取消息减少网络开销
*/
@Component
public class BatchConsumer {
@RabbitListener(
queues = "business.queue",
containerFactory = "batchContainerFactory"
)
public void handleBatch(List<Message> messages, Channel channel) {
List<Long> deliveryTags = new ArrayList<>();
try {
// 批量处理消息
for (Message message : messages) {
processMessage(message);
deliveryTags.add(message.getMessageProperties().getDeliveryTag());
}
// 批量确认
if (!deliveryTags.isEmpty()) {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicAck(lastTag, true); // multiple=true
}
} catch (Exception e) {
// 批量失败,全部重新入队
try {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicNack(lastTag, true, true);
} catch (IOException ex) {
log.error("批量NACK失败", ex);
}
}
}
private void processMessage(Message message) {
// 处理逻辑
}
}
/**
* 批量消费配置
*/
@Configuration
public class BatchConsumerConfig {
@Bean
public SimpleRabbitListenerContainerFactory batchContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
factory.setBatchListener(true); // 启用批量监听
factory.setBatchSize(50); // 批量大小
factory.setConsumerBatchEnabled(true);
factory.setReceiveTimeout(5000L); // 批量等待超时
return factory;
}
} factory.setBatchSize(50); // 批量大小`
`#/**
* 批量消费优化
*
* 通过批量拉取消息减少网络开销
*/
@Component
public class BatchConsumer {
@RabbitListener(
queues = "business.queue",
containerFactory = "batchContainerFactory"
)
public void handleBatch(List<Message> messages, Channel channel) {
List<Long> deliveryTags = new ArrayList<>();
try {
// 批量处理消息
for (Message message : messages) {
processMessage(message);
deliveryTags.add(message.getMessageProperties().getDeliveryTag());
}
// 批量确认
if (!deliveryTags.isEmpty()) {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicAck(lastTag, true); // multiple=true
}
} catch (Exception e) {
// 批量失败,全部重新入队
try {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicNack(lastTag, true, true);
} catch (IOException ex) {
log.error("批量NACK失败", ex);
}
}
}
private void processMessage(Message message) {
// 处理逻辑
}
}
/**
* 批量消费配置
*/
@Configuration
public class BatchConsumerConfig {
@Bean
public SimpleRabbitListenerContainerFactory batchContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
factory.setBatchListener(true); // 启用批量监听
factory.setBatchSize(50); // 批量大小
factory.setConsumerBatchEnabled(true);
factory.setReceiveTimeout(5000L); // 批量等待超时
return factory;
}
} factory.setConsumerBatchEnabled(true);`
`#/**
* 批量消费优化
*
* 通过批量拉取消息减少网络开销
*/
@Component
public class BatchConsumer {
@RabbitListener(
queues = "business.queue",
containerFactory = "batchContainerFactory"
)
public void handleBatch(List<Message> messages, Channel channel) {
List<Long> deliveryTags = new ArrayList<>();
try {
// 批量处理消息
for (Message message : messages) {
processMessage(message);
deliveryTags.add(message.getMessageProperties().getDeliveryTag());
}
// 批量确认
if (!deliveryTags.isEmpty()) {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicAck(lastTag, true); // multiple=true
}
} catch (Exception e) {
// 批量失败,全部重新入队
try {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicNack(lastTag, true, true);
} catch (IOException ex) {
log.error("批量NACK失败", ex);
}
}
}
private void processMessage(Message message) {
// 处理逻辑
}
}
/**
* 批量消费配置
*/
@Configuration
public class BatchConsumerConfig {
@Bean
public SimpleRabbitListenerContainerFactory batchContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
factory.setBatchListener(true); // 启用批量监听
factory.setBatchSize(50); // 批量大小
factory.setConsumerBatchEnabled(true);
factory.setReceiveTimeout(5000L); // 批量等待超时
return factory;
}
} factory.setReceiveTimeout(5000L); // 批量等待超时`
`#/**
* 批量消费优化
*
* 通过批量拉取消息减少网络开销
*/
@Component
public class BatchConsumer {
@RabbitListener(
queues = "business.queue",
containerFactory = "batchContainerFactory"
)
public void handleBatch(List<Message> messages, Channel channel) {
List<Long> deliveryTags = new ArrayList<>();
try {
// 批量处理消息
for (Message message : messages) {
processMessage(message);
deliveryTags.add(message.getMessageProperties().getDeliveryTag());
}
// 批量确认
if (!deliveryTags.isEmpty()) {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicAck(lastTag, true); // multiple=true
}
} catch (Exception e) {
// 批量失败,全部重新入队
try {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicNack(lastTag, true, true);
} catch (IOException ex) {
log.error("批量NACK失败", ex);
}
}
}
private void processMessage(Message message) {
// 处理逻辑
}
}
/**
* 批量消费配置
*/
@Configuration
public class BatchConsumerConfig {
@Bean
public SimpleRabbitListenerContainerFactory batchContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
factory.setBatchListener(true); // 启用批量监听
factory.setBatchSize(50); // 批量大小
factory.setConsumerBatchEnabled(true);
factory.setReceiveTimeout(5000L); // 批量等待超时
return factory;
}
} return factory;`
`#/**
* 批量消费优化
*
* 通过批量拉取消息减少网络开销
*/
@Component
public class BatchConsumer {
@RabbitListener(
queues = "business.queue",
containerFactory = "batchContainerFactory"
)
public void handleBatch(List<Message> messages, Channel channel) {
List<Long> deliveryTags = new ArrayList<>();
try {
// 批量处理消息
for (Message message : messages) {
processMessage(message);
deliveryTags.add(message.getMessageProperties().getDeliveryTag());
}
// 批量确认
if (!deliveryTags.isEmpty()) {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicAck(lastTag, true); // multiple=true
}
} catch (Exception e) {
// 批量失败,全部重新入队
try {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicNack(lastTag, true, true);
} catch (IOException ex) {
log.error("批量NACK失败", ex);
}
}
}
private void processMessage(Message message) {
// 处理逻辑
}
}
/**
* 批量消费配置
*/
@Configuration
public class BatchConsumerConfig {
@Bean
public SimpleRabbitListenerContainerFactory batchContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
factory.setBatchListener(true); // 启用批量监听
factory.setBatchSize(50); // 批量大小
factory.setConsumerBatchEnabled(true);
factory.setReceiveTimeout(5000L); // 批量等待超时
return factory;
}
} }`
`#/**
* 批量消费优化
*
* 通过批量拉取消息减少网络开销
*/
@Component
public class BatchConsumer {
@RabbitListener(
queues = "business.queue",
containerFactory = "batchContainerFactory"
)
public void handleBatch(List<Message> messages, Channel channel) {
List<Long> deliveryTags = new ArrayList<>();
try {
// 批量处理消息
for (Message message : messages) {
processMessage(message);
deliveryTags.add(message.getMessageProperties().getDeliveryTag());
}
// 批量确认
if (!deliveryTags.isEmpty()) {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicAck(lastTag, true); // multiple=true
}
} catch (Exception e) {
// 批量失败,全部重新入队
try {
Long lastTag = deliveryTags.get(deliveryTags.size() - 1);
channel.basicNack(lastTag, true, true);
} catch (IOException ex) {
log.error("批量NACK失败", ex);
}
}
}
private void processMessage(Message message) {
// 处理逻辑
}
}
/**
* 批量消费配置
*/
@Configuration
public class BatchConsumerConfig {
@Bean
public SimpleRabbitListenerContainerFactory batchContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
factory.setBatchListener(true); // 启用批量监听
factory.setBatchSize(50); // 批量大小
factory.setConsumerBatchEnabled(true);
factory.setReceiveTimeout(5000L); // 批量等待超时
return factory;
}
}}
6.3 性能对比表
| 配置 | 吞吐量(msg/s) | 平均延迟(ms) | CPU使用率 | 内存使用 |
|---|---|---|---|---|
| 内存+自动ACK | 50,000+ | <5 | 低 | 低 |
| 持久化+自动ACK | 30,000 | 10-20 | 中 | 中 |
| 持久化+手动ACK | 20,000 | 20-50 | 高 | 高 |
| 完整可靠性方案 | 10,000 | 50-100 | 高 | 高 |
7. 最佳实践总结
7.1 可靠性投递检查清单
mindmap
root((RabbitMQ<br/>可靠性投递))
生产者
启用Confirm机制
设置持久化
异步Confirm回调
消息唯一ID
重试机制
Broker
交换机持久化
队列持久化
消息持久化
集群部署
磁盘监控
消费者
手动ACK
幂等性设计
异常分类处理
死信队列配置
重试策略
监控告警
消息堆积告警
死信队列告警
性能监控
日志记录
7.2 常见问题与解决方案
| 问题 | 原因 | 解决方案 |
|---|---|---|
| 消息丢失 | 未持久化或ACK失败 | 启用持久化+手动ACK+Confirm |
| 消息重复 | 网络抖动导致重试 | 实现幂等性(Redis唯一ID) |
| 消息堆积 | 消费速度慢于生产速度 | 增加消费者、优化消费逻辑、批量消费 |
| 死信堆积 | 死信未处理 | 实现死信监控和自动处理 |
| 性能下降 | 过度可靠性配置 | 根据业务场景调整可靠性级别 |
7.3 生产环境配置建议
java
#/**
* 生产环境推荐配置
*
* 适用于:金融、电商等核心业务场景
*/
@Configuration
public class ProductionRabbitMQConfig {
// ========== 生产者配置 ==========
@Bean
public RabbitTemplate productionRabbitTemplate(ConnectionFactory factory) {
RabbitTemplate template = new RabbitTemplate(factory);
// 启用发布确认
template.setConfirmCallback((correlationData, ack, cause) -> {
if (!ack) {
log.error("消息发送失败: {}", cause);
// 触发告警和重试
}
});
// 启用返回确认(消息无法路由时)
template.setReturnsCallback(returned -> {
log.error("消息无法路由: {}", returned.getMessage());
// 记录到死信队列或告警
});
// 启用消息强制回调
template.setMandatory(true);
return template;
}
// ========== 消费者配置 ==========
@Bean
public SimpleRabbitListenerContainerFactory productionContainerFactory(
ConnectionFactory factory) {
SimpleRabbitListenerContainerFactory containerFactory =
new SimpleRabbitListenerContainerFactory();
containerFactory.setConnectionFactory(factory);
// 手动确认
containerFactory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 公平分发
containerFactory.setPrefetch(1);
// 并发消费者数量
containerFactory.setConcurrentConsumers(5);
containerFactory.setMaxConcurrentConsumers(20);
// 重试配置
containerFactory.setAdviceChain(
RetryInterceptorBuilder
.stateless()
.maxAttempts(3)
.backOffOptions(1000, 2, 10000)
.build()
);
return containerFactory;
}
// ========== 队列配置 ==========
@Bean
public Queue productionQueue() {
return QueueBuilder
.durable("production.queue")
// 死信队列
.withArgument("x-dead-letter-exchange", "production.dlx")
.withArgument("x-dead-letter-routing-key", "production.dlq")
// 队列限制(防止内存溢出)
.withArgument("x-max-length", 100000)
.withArgument("x-max-length-bytes", 10737418240) // 10GB
// 惰性分发
.lazy()
// 主节点定位
.withArgument("x-queue-master-locator", "client-local")
.build();
}
}/**`
`#/**
* 生产环境推荐配置
*
* 适用于:金融、电商等核心业务场景
*/
@Configuration
public class ProductionRabbitMQConfig {
// ========== 生产者配置 ==========
@Bean
public RabbitTemplate productionRabbitTemplate(ConnectionFactory factory) {
RabbitTemplate template = new RabbitTemplate(factory);
// 启用发布确认
template.setConfirmCallback((correlationData, ack, cause) -> {
if (!ack) {
log.error("消息发送失败: {}", cause);
// 触发告警和重试
}
});
// 启用返回确认(消息无法路由时)
template.setReturnsCallback(returned -> {
log.error("消息无法路由: {}", returned.getMessage());
// 记录到死信队列或告警
});
// 启用消息强制回调
template.setMandatory(true);
return template;
}
// ========== 消费者配置 ==========
@Bean
public SimpleRabbitListenerContainerFactory productionContainerFactory(
ConnectionFactory factory) {
SimpleRabbitListenerContainerFactory containerFactory =
new SimpleRabbitListenerContainerFactory();
containerFactory.setConnectionFactory(factory);
// 手动确认
containerFactory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 公平分发
containerFactory.setPrefetch(1);
// 并发消费者数量
containerFactory.setConcurrentConsumers(5);
containerFactory.setMaxConcurrentConsumers(20);
// 重试配置
containerFactory.setAdviceChain(
RetryInterceptorBuilder
.stateless()
.maxAttempts(3)
.backOffOptions(1000, 2, 10000)
.build()
);
return containerFactory;
}
// ========== 队列配置 ==========
@Bean
public Queue productionQueue() {
return QueueBuilder
.durable("production.queue")
// 死信队列
.withArgument("x-dead-letter-exchange", "production.dlx")
.withArgument("x-dead-letter-routing-key", "production.dlq")
// 队列限制(防止内存溢出)
.withArgument("x-max-length", 100000)
.withArgument("x-max-length-bytes", 10737418240) // 10GB
// 惰性分发
.lazy()
// 主节点定位
.withArgument("x-queue-master-locator", "client-local")
.build();
}
} * 生产环境推荐配置`
`#/**
* 生产环境推荐配置
*
* 适用于:金融、电商等核心业务场景
*/
@Configuration
public class ProductionRabbitMQConfig {
// ========== 生产者配置 ==========
@Bean
public RabbitTemplate productionRabbitTemplate(ConnectionFactory factory) {
RabbitTemplate template = new RabbitTemplate(factory);
// 启用发布确认
template.setConfirmCallback((correlationData, ack, cause) -> {
if (!ack) {
log.error("消息发送失败: {}", cause);
// 触发告警和重试
}
});
// 启用返回确认(消息无法路由时)
template.setReturnsCallback(returned -> {
log.error("消息无法路由: {}", returned.getMessage());
// 记录到死信队列或告警
});
// 启用消息强制回调
template.setMandatory(true);
return template;
}
// ========== 消费者配置 ==========
@Bean
public SimpleRabbitListenerContainerFactory productionContainerFactory(
ConnectionFactory factory) {
SimpleRabbitListenerContainerFactory containerFactory =
new SimpleRabbitListenerContainerFactory();
containerFactory.setConnectionFactory(factory);
// 手动确认
containerFactory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 公平分发
containerFactory.setPrefetch(1);
// 并发消费者数量
containerFactory.setConcurrentConsumers(5);
containerFactory.setMaxConcurrentConsumers(20);
// 重试配置
containerFactory.setAdviceChain(
RetryInterceptorBuilder
.stateless()
.maxAttempts(3)
.backOffOptions(1000, 2, 10000)
.build()
);
return containerFactory;
}
// ========== 队列配置 ==========
@Bean
public Queue productionQueue() {
return QueueBuilder
.durable("production.queue")
// 死信队列
.withArgument("x-dead-letter-exchange", "production.dlx")
.withArgument("x-dead-letter-routing-key", "production.dlq")
// 队列限制(防止内存溢出)
.withArgument("x-max-length", 100000)
.withArgument("x-max-length-bytes", 10737418240) // 10GB
// 惰性分发
.lazy()
// 主节点定位
.withArgument("x-queue-master-locator", "client-local")
.build();
}
} * `
`#/**
* 生产环境推荐配置
*
* 适用于:金融、电商等核心业务场景
*/
@Configuration
public class ProductionRabbitMQConfig {
// ========== 生产者配置 ==========
@Bean
public RabbitTemplate productionRabbitTemplate(ConnectionFactory factory) {
RabbitTemplate template = new RabbitTemplate(factory);
// 启用发布确认
template.setConfirmCallback((correlationData, ack, cause) -> {
if (!ack) {
log.error("消息发送失败: {}", cause);
// 触发告警和重试
}
});
// 启用返回确认(消息无法路由时)
template.setReturnsCallback(returned -> {
log.error("消息无法路由: {}", returned.getMessage());
// 记录到死信队列或告警
});
// 启用消息强制回调
template.setMandatory(true);
return template;
}
// ========== 消费者配置 ==========
@Bean
public SimpleRabbitListenerContainerFactory productionContainerFactory(
ConnectionFactory factory) {
SimpleRabbitListenerContainerFactory containerFactory =
new SimpleRabbitListenerContainerFactory();
containerFactory.setConnectionFactory(factory);
// 手动确认
containerFactory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 公平分发
containerFactory.setPrefetch(1);
// 并发消费者数量
containerFactory.setConcurrentConsumers(5);
containerFactory.setMaxConcurrentConsumers(20);
// 重试配置
containerFactory.setAdviceChain(
RetryInterceptorBuilder
.stateless()
.maxAttempts(3)
.backOffOptions(1000, 2, 10000)
.build()
);
return containerFactory;
}
// ========== 队列配置 ==========
@Bean
public Queue productionQueue() {
return QueueBuilder
.durable("production.queue")
// 死信队列
.withArgument("x-dead-letter-exchange", "production.dlx")
.withArgument("x-dead-letter-routing-key", "production.dlq")
// 队列限制(防止内存溢出)
.withArgument("x-max-length", 100000)
.withArgument("x-max-length-bytes", 10737418240) // 10GB
// 惰性分发
.lazy()
// 主节点定位
.withArgument("x-queue-master-locator", "client-local")
.build();
}
} * 适用于:金融、电商等核心业务场景`
`#/**
* 生产环境推荐配置
*
* 适用于:金融、电商等核心业务场景
*/
@Configuration
public class ProductionRabbitMQConfig {
// ========== 生产者配置 ==========
@Bean
public RabbitTemplate productionRabbitTemplate(ConnectionFactory factory) {
RabbitTemplate template = new RabbitTemplate(factory);
// 启用发布确认
template.setConfirmCallback((correlationData, ack, cause) -> {
if (!ack) {
log.error("消息发送失败: {}", cause);
// 触发告警和重试
}
});
// 启用返回确认(消息无法路由时)
template.setReturnsCallback(returned -> {
log.error("消息无法路由: {}", returned.getMessage());
// 记录到死信队列或告警
});
// 启用消息强制回调
template.setMandatory(true);
return template;
}
// ========== 消费者配置 ==========
@Bean
public SimpleRabbitListenerContainerFactory productionContainerFactory(
ConnectionFactory factory) {
SimpleRabbitListenerContainerFactory containerFactory =
new SimpleRabbitListenerContainerFactory();
containerFactory.setConnectionFactory(factory);
// 手动确认
containerFactory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 公平分发
containerFactory.setPrefetch(1);
// 并发消费者数量
containerFactory.setConcurrentConsumers(5);
containerFactory.setMaxConcurrentConsumers(20);
// 重试配置
containerFactory.setAdviceChain(
RetryInterceptorBuilder
.stateless()
.maxAttempts(3)
.backOffOptions(1000, 2, 10000)
.build()
);
return containerFactory;
}
// ========== 队列配置 ==========
@Bean
public Queue productionQueue() {
return QueueBuilder
.durable("production.queue")
// 死信队列
.withArgument("x-dead-letter-exchange", "production.dlx")
.withArgument("x-dead-letter-routing-key", "production.dlq")
// 队列限制(防止内存溢出)
.withArgument("x-max-length", 100000)
.withArgument("x-max-length-bytes", 10737418240) // 10GB
// 惰性分发
.lazy()
// 主节点定位
.withArgument("x-queue-master-locator", "client-local")
.build();
}
} */`
`#/**
* 生产环境推荐配置
*
* 适用于:金融、电商等核心业务场景
*/
@Configuration
public class ProductionRabbitMQConfig {
// ========== 生产者配置 ==========
@Bean
public RabbitTemplate productionRabbitTemplate(ConnectionFactory factory) {
RabbitTemplate template = new RabbitTemplate(factory);
// 启用发布确认
template.setConfirmCallback((correlationData, ack, cause) -> {
if (!ack) {
log.error("消息发送失败: {}", cause);
// 触发告警和重试
}
});
// 启用返回确认(消息无法路由时)
template.setReturnsCallback(returned -> {
log.error("消息无法路由: {}", returned.getMessage());
// 记录到死信队列或告警
});
// 启用消息强制回调
template.setMandatory(true);
return template;
}
// ========== 消费者配置 ==========
@Bean
public SimpleRabbitListenerContainerFactory productionContainerFactory(
ConnectionFactory factory) {
SimpleRabbitListenerContainerFactory containerFactory =
new SimpleRabbitListenerContainerFactory();
containerFactory.setConnectionFactory(factory);
// 手动确认
containerFactory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 公平分发
containerFactory.setPrefetch(1);
// 并发消费者数量
containerFactory.setConcurrentConsumers(5);
containerFactory.setMaxConcurrentConsumers(20);
// 重试配置
containerFactory.setAdviceChain(
RetryInterceptorBuilder
.stateless()
.maxAttempts(3)
.backOffOptions(1000, 2, 10000)
.build()
);
return containerFactory;
}
// ========== 队列配置 ==========
@Bean
public Queue productionQueue() {
return QueueBuilder
.durable("production.queue")
// 死信队列
.withArgument("x-dead-letter-exchange", "production.dlx")
.withArgument("x-dead-letter-routing-key", "production.dlq")
// 队列限制(防止内存溢出)
.withArgument("x-max-length", 100000)
.withArgument("x-max-length-bytes", 10737418240) // 10GB
// 惰性分发
.lazy()
// 主节点定位
.withArgument("x-queue-master-locator", "client-local")
.build();
}
}@Configuration`
`#/**
* 生产环境推荐配置
*
* 适用于:金融、电商等核心业务场景
*/
@Configuration
public class ProductionRabbitMQConfig {
// ========== 生产者配置 ==========
@Bean
public RabbitTemplate productionRabbitTemplate(ConnectionFactory factory) {
RabbitTemplate template = new RabbitTemplate(factory);
// 启用发布确认
template.setConfirmCallback((correlationData, ack, cause) -> {
if (!ack) {
log.error("消息发送失败: {}", cause);
// 触发告警和重试
}
});
// 启用返回确认(消息无法路由时)
template.setReturnsCallback(returned -> {
log.error("消息无法路由: {}", returned.getMessage());
// 记录到死信队列或告警
});
// 启用消息强制回调
template.setMandatory(true);
return template;
}
// ========== 消费者配置 ==========
@Bean
public SimpleRabbitListenerContainerFactory productionContainerFactory(
ConnectionFactory factory) {
SimpleRabbitListenerContainerFactory containerFactory =
new SimpleRabbitListenerContainerFactory();
containerFactory.setConnectionFactory(factory);
// 手动确认
containerFactory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 公平分发
containerFactory.setPrefetch(1);
// 并发消费者数量
containerFactory.setConcurrentConsumers(5);
containerFactory.setMaxConcurrentConsumers(20);
// 重试配置
containerFactory.setAdviceChain(
RetryInterceptorBuilder
.stateless()
.maxAttempts(3)
.backOffOptions(1000, 2, 10000)
.build()
);
return containerFactory;
}
// ========== 队列配置 ==========
@Bean
public Queue productionQueue() {
return QueueBuilder
.durable("production.queue")
// 死信队列
.withArgument("x-dead-letter-exchange", "production.dlx")
.withArgument("x-dead-letter-routing-key", "production.dlq")
// 队列限制(防止内存溢出)
.withArgument("x-max-length", 100000)
.withArgument("x-max-length-bytes", 10737418240) // 10GB
// 惰性分发
.lazy()
// 主节点定位
.withArgument("x-queue-master-locator", "client-local")
.build();
}
}public class ProductionRabbitMQConfig {`
`#/**
* 生产环境推荐配置
*
* 适用于:金融、电商等核心业务场景
*/
@Configuration
public class ProductionRabbitMQConfig {
// ========== 生产者配置 ==========
@Bean
public RabbitTemplate productionRabbitTemplate(ConnectionFactory factory) {
RabbitTemplate template = new RabbitTemplate(factory);
// 启用发布确认
template.setConfirmCallback((correlationData, ack, cause) -> {
if (!ack) {
log.error("消息发送失败: {}", cause);
// 触发告警和重试
}
});
// 启用返回确认(消息无法路由时)
template.setReturnsCallback(returned -> {
log.error("消息无法路由: {}", returned.getMessage());
// 记录到死信队列或告警
});
// 启用消息强制回调
template.setMandatory(true);
return template;
}
// ========== 消费者配置 ==========
@Bean
public SimpleRabbitListenerContainerFactory productionContainerFactory(
ConnectionFactory factory) {
SimpleRabbitListenerContainerFactory containerFactory =
new SimpleRabbitListenerContainerFactory();
containerFactory.setConnectionFactory(factory);
// 手动确认
containerFactory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 公平分发
containerFactory.setPrefetch(1);
// 并发消费者数量
containerFactory.setConcurrentConsumers(5);
containerFactory.setMaxConcurrentConsumers(20);
// 重试配置
containerFactory.setAdviceChain(
RetryInterceptorBuilder
.stateless()
.maxAttempts(3)
.backOffOptions(1000, 2, 10000)
.build()
);
return containerFactory;
}
// ========== 队列配置 ==========
@Bean
public Queue productionQueue() {
return QueueBuilder
.durable("production.queue")
// 死信队列
.withArgument("x-dead-letter-exchange", "production.dlx")
.withArgument("x-dead-letter-routing-key", "production.dlq")
// 队列限制(防止内存溢出)
.withArgument("x-max-length", 100000)
.withArgument("x-max-length-bytes", 10737418240) // 10GB
// 惰性分发
.lazy()
// 主节点定位
.withArgument("x-queue-master-locator", "client-local")
.build();
}
}`
`#/**
* 生产环境推荐配置
*
* 适用于:金融、电商等核心业务场景
*/
@Configuration
public class ProductionRabbitMQConfig {
// ========== 生产者配置 ==========
@Bean
public RabbitTemplate productionRabbitTemplate(ConnectionFactory factory) {
RabbitTemplate template = new RabbitTemplate(factory);
// 启用发布确认
template.setConfirmCallback((correlationData, ack, cause) -> {
if (!ack) {
log.error("消息发送失败: {}", cause);
// 触发告警和重试
}
});
// 启用返回确认(消息无法路由时)
template.setReturnsCallback(returned -> {
log.error("消息无法路由: {}", returned.getMessage());
// 记录到死信队列或告警
});
// 启用消息强制回调
template.setMandatory(true);
return template;
}
// ========== 消费者配置 ==========
@Bean
public SimpleRabbitListenerContainerFactory productionContainerFactory(
ConnectionFactory factory) {
SimpleRabbitListenerContainerFactory containerFactory =
new SimpleRabbitListenerContainerFactory();
containerFactory.setConnectionFactory(factory);
// 手动确认
containerFactory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 公平分发
containerFactory.setPrefetch(1);
// 并发消费者数量
containerFactory.setConcurrentConsumers(5);
containerFactory.setMaxConcurrentConsumers(20);
// 重试配置
containerFactory.setAdviceChain(
RetryInterceptorBuilder
.stateless()
.maxAttempts(3)
.backOffOptions(1000, 2, 10000)
.build()
);
return containerFactory;
}
// ========== 队列配置 ==========
@Bean
public Queue productionQueue() {
return QueueBuilder
.durable("production.queue")
// 死信队列
.withArgument("x-dead-letter-exchange", "production.dlx")
.withArgument("x-dead-letter-routing-key", "production.dlq")
// 队列限制(防止内存溢出)
.withArgument("x-max-length", 100000)
.withArgument("x-max-length-bytes", 10737418240) // 10GB
// 惰性分发
.lazy()
// 主节点定位
.withArgument("x-queue-master-locator", "client-local")
.build();
}
} // ========== 生产者配置 ==========`
`#/**
* 生产环境推荐配置
*
* 适用于:金融、电商等核心业务场景
*/
@Configuration
public class ProductionRabbitMQConfig {
// ========== 生产者配置 ==========
@Bean
public RabbitTemplate productionRabbitTemplate(ConnectionFactory factory) {
RabbitTemplate template = new RabbitTemplate(factory);
// 启用发布确认
template.setConfirmCallback((correlationData, ack, cause) -> {
if (!ack) {
log.error("消息发送失败: {}", cause);
// 触发告警和重试
}
});
// 启用返回确认(消息无法路由时)
template.setReturnsCallback(returned -> {
log.error("消息无法路由: {}", returned.getMessage());
// 记录到死信队列或告警
});
// 启用消息强制回调
template.setMandatory(true);
return template;
}
// ========== 消费者配置 ==========
@Bean
public SimpleRabbitListenerContainerFactory productionContainerFactory(
ConnectionFactory factory) {
SimpleRabbitListenerContainerFactory containerFactory =
new SimpleRabbitListenerContainerFactory();
containerFactory.setConnectionFactory(factory);
// 手动确认
containerFactory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 公平分发
containerFactory.setPrefetch(1);
// 并发消费者数量
containerFactory.setConcurrentConsumers(5);
containerFactory.setMaxConcurrentConsumers(20);
// 重试配置
containerFactory.setAdviceChain(
RetryInterceptorBuilder
.stateless()
.maxAttempts(3)
.backOffOptions(1000, 2, 10000)
.build()
);
return containerFactory;
}
// ========== 队列配置 ==========
@Bean
public Queue productionQueue() {
return QueueBuilder
.durable("production.queue")
// 死信队列
.withArgument("x-dead-letter-exchange", "production.dlx")
.withArgument("x-dead-letter-routing-key", "production.dlq")
// 队列限制(防止内存溢出)
.withArgument("x-max-length", 100000)
.withArgument("x-max-length-bytes", 10737418240) // 10GB
// 惰性分发
.lazy()
// 主节点定位
.withArgument("x-queue-master-locator", "client-local")
.build();
}
} `
`#/**
* 生产环境推荐配置
*
* 适用于:金融、电商等核心业务场景
*/
@Configuration
public class ProductionRabbitMQConfig {
// ========== 生产者配置 ==========
@Bean
public RabbitTemplate productionRabbitTemplate(ConnectionFactory factory) {
RabbitTemplate template = new RabbitTemplate(factory);
// 启用发布确认
template.setConfirmCallback((correlationData, ack, cause) -> {
if (!ack) {
log.error("消息发送失败: {}", cause);
// 触发告警和重试
}
});
// 启用返回确认(消息无法路由时)
template.setReturnsCallback(returned -> {
log.error("消息无法路由: {}", returned.getMessage());
// 记录到死信队列或告警
});
// 启用消息强制回调
template.setMandatory(true);
return template;
}
// ========== 消费者配置 ==========
@Bean
public SimpleRabbitListenerContainerFactory productionContainerFactory(
ConnectionFactory factory) {
SimpleRabbitListenerContainerFactory containerFactory =
new SimpleRabbitListenerContainerFactory();
containerFactory.setConnectionFactory(factory);
// 手动确认
containerFactory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 公平分发
containerFactory.setPrefetch(1);
// 并发消费者数量
containerFactory.setConcurrentConsumers(5);
containerFactory.setMaxConcurrentConsumers(20);
// 重试配置
containerFactory.setAdviceChain(
RetryInterceptorBuilder
.stateless()
.maxAttempts(3)
.backOffOptions(1000, 2, 10000)
.build()
);
return containerFactory;
}
// ========== 队列配置 ==========
@Bean
public Queue productionQueue() {
return QueueBuilder
.durable("production.queue")
// 死信队列
.withArgument("x-dead-letter-exchange", "production.dlx")
.withArgument("x-dead-letter-routing-key", "production.dlq")
// 队列限制(防止内存溢出)
.withArgument("x-max-length", 100000)
.withArgument("x-max-length-bytes", 10737418240) // 10GB
// 惰性分发
.lazy()
// 主节点定位
.withArgument("x-queue-master-locator", "client-local")
.build();
}
} @Bean`
`#/**
* 生产环境推荐配置
*
* 适用于:金融、电商等核心业务场景
*/
@Configuration
public class ProductionRabbitMQConfig {
// ========== 生产者配置 ==========
@Bean
public RabbitTemplate productionRabbitTemplate(ConnectionFactory factory) {
RabbitTemplate template = new RabbitTemplate(factory);
// 启用发布确认
template.setConfirmCallback((correlationData, ack, cause) -> {
if (!ack) {
log.error("消息发送失败: {}", cause);
// 触发告警和重试
}
});
// 启用返回确认(消息无法路由时)
template.setReturnsCallback(returned -> {
log.error("消息无法路由: {}", returned.getMessage());
// 记录到死信队列或告警
});
// 启用消息强制回调
template.setMandatory(true);
return template;
}
// ========== 消费者配置 ==========
@Bean
public SimpleRabbitListenerContainerFactory productionContainerFactory(
ConnectionFactory factory) {
SimpleRabbitListenerContainerFactory containerFactory =
new SimpleRabbitListenerContainerFactory();
containerFactory.setConnectionFactory(factory);
// 手动确认
containerFactory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 公平分发
containerFactory.setPrefetch(1);
// 并发消费者数量
containerFactory.setConcurrentConsumers(5);
containerFactory.setMaxConcurrentConsumers(20);
// 重试配置
containerFactory.setAdviceChain(
RetryInterceptorBuilder
.stateless()
.maxAttempts(3)
.backOffOptions(1000, 2, 10000)
.build()
);
return containerFactory;
}
// ========== 队列配置 ==========
@Bean
public Queue productionQueue() {
return QueueBuilder
.durable("production.queue")
// 死信队列
.withArgument("x-dead-letter-exchange", "production.dlx")
.withArgument("x-dead-letter-routing-key", "production.dlq")
// 队列限制(防止内存溢出)
.withArgument("x-max-length", 100000)
.withArgument("x-max-length-bytes", 10737418240) // 10GB
// 惰性分发
.lazy()
// 主节点定位
.withArgument("x-queue-master-locator", "client-local")
.build();
}
} public RabbitTemplate productionRabbitTemplate(ConnectionFactory factory) {`
`#/**
* 生产环境推荐配置
*
* 适用于:金融、电商等核心业务场景
*/
@Configuration
public class ProductionRabbitMQConfig {
// ========== 生产者配置 ==========
@Bean
public RabbitTemplate productionRabbitTemplate(ConnectionFactory factory) {
RabbitTemplate template = new RabbitTemplate(factory);
// 启用发布确认
template.setConfirmCallback((correlationData, ack, cause) -> {
if (!ack) {
log.error("消息发送失败: {}", cause);
// 触发告警和重试
}
});
// 启用返回确认(消息无法路由时)
template.setReturnsCallback(returned -> {
log.error("消息无法路由: {}", returned.getMessage());
// 记录到死信队列或告警
});
// 启用消息强制回调
template.setMandatory(true);
return template;
}
// ========== 消费者配置 ==========
@Bean
public SimpleRabbitListenerContainerFactory productionContainerFactory(
ConnectionFactory factory) {
SimpleRabbitListenerContainerFactory containerFactory =
new SimpleRabbitListenerContainerFactory();
containerFactory.setConnectionFactory(factory);
// 手动确认
containerFactory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 公平分发
containerFactory.setPrefetch(1);
// 并发消费者数量
containerFactory.setConcurrentConsumers(5);
containerFactory.setMaxConcurrentConsumers(20);
// 重试配置
containerFactory.setAdviceChain(
RetryInterceptorBuilder
.stateless()
.maxAttempts(3)
.backOffOptions(1000, 2, 10000)
.build()
);
return containerFactory;
}
// ========== 队列配置 ==========
@Bean
public Queue productionQueue() {
return QueueBuilder
.durable("production.queue")
// 死信队列
.withArgument("x-dead-letter-exchange", "production.dlx")
.withArgument("x-dead-letter-routing-key", "production.dlq")
// 队列限制(防止内存溢出)
.withArgument("x-max-length", 100000)
.withArgument("x-max-length-bytes", 10737418240) // 10GB
// 惰性分发
.lazy()
// 主节点定位
.withArgument("x-queue-master-locator", "client-local")
.build();
}
} RabbitTemplate template = new RabbitTemplate(factory);`
`#/**
* 生产环境推荐配置
*
* 适用于:金融、电商等核心业务场景
*/
@Configuration
public class ProductionRabbitMQConfig {
// ========== 生产者配置 ==========
@Bean
public RabbitTemplate productionRabbitTemplate(ConnectionFactory factory) {
RabbitTemplate template = new RabbitTemplate(factory);
// 启用发布确认
template.setConfirmCallback((correlationData, ack, cause) -> {
if (!ack) {
log.error("消息发送失败: {}", cause);
// 触发告警和重试
}
});
// 启用返回确认(消息无法路由时)
template.setReturnsCallback(returned -> {
log.error("消息无法路由: {}", returned.getMessage());
// 记录到死信队列或告警
});
// 启用消息强制回调
template.setMandatory(true);
return template;
}
// ========== 消费者配置 ==========
@Bean
public SimpleRabbitListenerContainerFactory productionContainerFactory(
ConnectionFactory factory) {
SimpleRabbitListenerContainerFactory containerFactory =
new SimpleRabbitListenerContainerFactory();
containerFactory.setConnectionFactory(factory);
// 手动确认
containerFactory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 公平分发
containerFactory.setPrefetch(1);
// 并发消费者数量
containerFactory.setConcurrentConsumers(5);
containerFactory.setMaxConcurrentConsumers(20);
// 重试配置
containerFactory.setAdviceChain(
RetryInterceptorBuilder
.stateless()
.maxAttempts(3)
.backOffOptions(1000, 2, 10000)
.build()
);
return containerFactory;
}
// ========== 队列配置 ==========
@Bean
public Queue productionQueue() {
return QueueBuilder
.durable("production.queue")
// 死信队列
.withArgument("x-dead-letter-exchange", "production.dlx")
.withArgument("x-dead-letter-routing-key", "production.dlq")
// 队列限制(防止内存溢出)
.withArgument("x-max-length", 100000)
.withArgument("x-max-length-bytes", 10737418240) // 10GB
// 惰性分发
.lazy()
// 主节点定位
.withArgument("x-queue-master-locator", "client-local")
.build();
}
} `
`#/**
* 生产环境推荐配置
*
* 适用于:金融、电商等核心业务场景
*/
@Configuration
public class ProductionRabbitMQConfig {
// ========== 生产者配置 ==========
@Bean
public RabbitTemplate productionRabbitTemplate(ConnectionFactory factory) {
RabbitTemplate template = new RabbitTemplate(factory);
// 启用发布确认
template.setConfirmCallback((correlationData, ack, cause) -> {
if (!ack) {
log.error("消息发送失败: {}", cause);
// 触发告警和重试
}
});
// 启用返回确认(消息无法路由时)
template.setReturnsCallback(returned -> {
log.error("消息无法路由: {}", returned.getMessage());
// 记录到死信队列或告警
});
// 启用消息强制回调
template.setMandatory(true);
return template;
}
// ========== 消费者配置 ==========
@Bean
public SimpleRabbitListenerContainerFactory productionContainerFactory(
ConnectionFactory factory) {
SimpleRabbitListenerContainerFactory containerFactory =
new SimpleRabbitListenerContainerFactory();
containerFactory.setConnectionFactory(factory);
// 手动确认
containerFactory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 公平分发
containerFactory.setPrefetch(1);
// 并发消费者数量
containerFactory.setConcurrentConsumers(5);
containerFactory.setMaxConcurrentConsumers(20);
// 重试配置
containerFactory.setAdviceChain(
RetryInterceptorBuilder
.stateless()
.maxAttempts(3)
.backOffOptions(1000, 2, 10000)
.build()
);
return containerFactory;
}
// ========== 队列配置 ==========
@Bean
public Queue productionQueue() {
return QueueBuilder
.durable("production.queue")
// 死信队列
.withArgument("x-dead-letter-exchange", "production.dlx")
.withArgument("x-dead-letter-routing-key", "production.dlq")
// 队列限制(防止内存溢出)
.withArgument("x-max-length", 100000)
.withArgument("x-max-length-bytes", 10737418240) // 10GB
// 惰性分发
.lazy()
// 主节点定位
.withArgument("x-queue-master-locator", "client-local")
.build();
}
} // 启用发布确认`
`#/**
* 生产环境推荐配置
*
* 适用于:金融、电商等核心业务场景
*/
@Configuration
public class ProductionRabbitMQConfig {
// ========== 生产者配置 ==========
@Bean
public RabbitTemplate productionRabbitTemplate(ConnectionFactory factory) {
RabbitTemplate template = new RabbitTemplate(factory);
// 启用发布确认
template.setConfirmCallback((correlationData, ack, cause) -> {
if (!ack) {
log.error("消息发送失败: {}", cause);
// 触发告警和重试
}
});
// 启用返回确认(消息无法路由时)
template.setReturnsCallback(returned -> {
log.error("消息无法路由: {}", returned.getMessage());
// 记录到死信队列或告警
});
// 启用消息强制回调
template.setMandatory(true);
return template;
}
// ========== 消费者配置 ==========
@Bean
public SimpleRabbitListenerContainerFactory productionContainerFactory(
ConnectionFactory factory) {
SimpleRabbitListenerContainerFactory containerFactory =
new SimpleRabbitListenerContainerFactory();
containerFactory.setConnectionFactory(factory);
// 手动确认
containerFactory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 公平分发
containerFactory.setPrefetch(1);
// 并发消费者数量
containerFactory.setConcurrentConsumers(5);
containerFactory.setMaxConcurrentConsumers(20);
// 重试配置
containerFactory.setAdviceChain(
RetryInterceptorBuilder
.stateless()
.maxAttempts(3)
.backOffOptions(1000, 2, 10000)
.build()
);
return containerFactory;
}
// ========== 队列配置 ==========
@Bean
public Queue productionQueue() {
return QueueBuilder
.durable("production.queue")
// 死信队列
.withArgument("x-dead-letter-exchange", "production.dlx")
.withArgument("x-dead-letter-routing-key", "production.dlq")
// 队列限制(防止内存溢出)
.withArgument("x-max-length", 100000)
.withArgument("x-max-length-bytes", 10737418240) // 10GB
// 惰性分发
.lazy()
// 主节点定位
.withArgument("x-queue-master-locator", "client-local")
.build();
}
} template.setConfirmCallback((correlationData, ack, cause) -> {`
`#/**
* 生产环境推荐配置
*
* 适用于:金融、电商等核心业务场景
*/
@Configuration
public class ProductionRabbitMQConfig {
// ========== 生产者配置 ==========
@Bean
public RabbitTemplate productionRabbitTemplate(ConnectionFactory factory) {
RabbitTemplate template = new RabbitTemplate(factory);
// 启用发布确认
template.setConfirmCallback((correlationData, ack, cause) -> {
if (!ack) {
log.error("消息发送失败: {}", cause);
// 触发告警和重试
}
});
// 启用返回确认(消息无法路由时)
template.setReturnsCallback(returned -> {
log.error("消息无法路由: {}", returned.getMessage());
// 记录到死信队列或告警
});
// 启用消息强制回调
template.setMandatory(true);
return template;
}
// ========== 消费者配置 ==========
@Bean
public SimpleRabbitListenerContainerFactory productionContainerFactory(
ConnectionFactory factory) {
SimpleRabbitListenerContainerFactory containerFactory =
new SimpleRabbitListenerContainerFactory();
containerFactory.setConnectionFactory(factory);
// 手动确认
containerFactory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 公平分发
containerFactory.setPrefetch(1);
// 并发消费者数量
containerFactory.setConcurrentConsumers(5);
containerFactory.setMaxConcurrentConsumers(20);
// 重试配置
containerFactory.setAdviceChain(
RetryInterceptorBuilder
.stateless()
.maxAttempts(3)
.backOffOptions(1000, 2, 10000)
.build()
);
return containerFactory;
}
// ========== 队列配置 ==========
@Bean
public Queue productionQueue() {
return QueueBuilder
.durable("production.queue")
// 死信队列
.withArgument("x-dead-letter-exchange", "production.dlx")
.withArgument("x-dead-letter-routing-key", "production.dlq")
// 队列限制(防止内存溢出)
.withArgument("x-max-length", 100000)
.withArgument("x-max-length-bytes", 10737418240) // 10GB
// 惰性分发
.lazy()
// 主节点定位
.withArgument("x-queue-master-locator", "client-local")
.build();
}
} if (!ack) {`
`#/**
* 生产环境推荐配置
*
* 适用于:金融、电商等核心业务场景
*/
@Configuration
public class ProductionRabbitMQConfig {
// ========== 生产者配置 ==========
@Bean
public RabbitTemplate productionRabbitTemplate(ConnectionFactory factory) {
RabbitTemplate template = new RabbitTemplate(factory);
// 启用发布确认
template.setConfirmCallback((correlationData, ack, cause) -> {
if (!ack) {
log.error("消息发送失败: {}", cause);
// 触发告警和重试
}
});
// 启用返回确认(消息无法路由时)
template.setReturnsCallback(returned -> {
log.error("消息无法路由: {}", returned.getMessage());
// 记录到死信队列或告警
});
// 启用消息强制回调
template.setMandatory(true);
return template;
}
// ========== 消费者配置 ==========
@Bean
public SimpleRabbitListenerContainerFactory productionContainerFactory(
ConnectionFactory factory) {
SimpleRabbitListenerContainerFactory containerFactory =
new SimpleRabbitListenerContainerFactory();
containerFactory.setConnectionFactory(factory);
// 手动确认
containerFactory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 公平分发
containerFactory.setPrefetch(1);
// 并发消费者数量
containerFactory.setConcurrentConsumers(5);
containerFactory.setMaxConcurrentConsumers(20);
// 重试配置
containerFactory.setAdviceChain(
RetryInterceptorBuilder
.stateless()
.maxAttempts(3)
.backOffOptions(1000, 2, 10000)
.build()
);
return containerFactory;
}
// ========== 队列配置 ==========
@Bean
public Queue productionQueue() {
return QueueBuilder
.durable("production.queue")
// 死信队列
.withArgument("x-dead-letter-exchange", "production.dlx")
.withArgument("x-dead-letter-routing-key", "production.dlq")
// 队列限制(防止内存溢出)
.withArgument("x-max-length", 100000)
.withArgument("x-max-length-bytes", 10737418240) // 10GB
// 惰性分发
.lazy()
// 主节点定位
.withArgument("x-queue-master-locator", "client-local")
.build();
}
} log.error("消息发送失败: {}", cause);`
`#/**
* 生产环境推荐配置
*
* 适用于:金融、电商等核心业务场景
*/
@Configuration
public class ProductionRabbitMQConfig {
// ========== 生产者配置 ==========
@Bean
public RabbitTemplate productionRabbitTemplate(ConnectionFactory factory) {
RabbitTemplate template = new RabbitTemplate(factory);
// 启用发布确认
template.setConfirmCallback((correlationData, ack, cause) -> {
if (!ack) {
log.error("消息发送失败: {}", cause);
// 触发告警和重试
}
});
// 启用返回确认(消息无法路由时)
template.setReturnsCallback(returned -> {
log.error("消息无法路由: {}", returned.getMessage());
// 记录到死信队列或告警
});
// 启用消息强制回调
template.setMandatory(true);
return template;
}
// ========== 消费者配置 ==========
@Bean
public SimpleRabbitListenerContainerFactory productionContainerFactory(
ConnectionFactory factory) {
SimpleRabbitListenerContainerFactory containerFactory =
new SimpleRabbitListenerContainerFactory();
containerFactory.setConnectionFactory(factory);
// 手动确认
containerFactory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 公平分发
containerFactory.setPrefetch(1);
// 并发消费者数量
containerFactory.setConcurrentConsumers(5);
containerFactory.setMaxConcurrentConsumers(20);
// 重试配置
containerFactory.setAdviceChain(
RetryInterceptorBuilder
.stateless()
.maxAttempts(3)
.backOffOptions(1000, 2, 10000)
.build()
);
return containerFactory;
}
// ========== 队列配置 ==========
@Bean
public Queue productionQueue() {
return QueueBuilder
.durable("production.queue")
// 死信队列
.withArgument("x-dead-letter-exchange", "production.dlx")
.withArgument("x-dead-letter-routing-key", "production.dlq")
// 队列限制(防止内存溢出)
.withArgument("x-max-length", 100000)
.withArgument("x-max-length-bytes", 10737418240) // 10GB
// 惰性分发
.lazy()
// 主节点定位
.withArgument("x-queue-master-locator", "client-local")
.build();
}
} // 触发告警和重试`
`#/**
* 生产环境推荐配置
*
* 适用于:金融、电商等核心业务场景
*/
@Configuration
public class ProductionRabbitMQConfig {
// ========== 生产者配置 ==========
@Bean
public RabbitTemplate productionRabbitTemplate(ConnectionFactory factory) {
RabbitTemplate template = new RabbitTemplate(factory);
// 启用发布确认
template.setConfirmCallback((correlationData, ack, cause) -> {
if (!ack) {
log.error("消息发送失败: {}", cause);
// 触发告警和重试
}
});
// 启用返回确认(消息无法路由时)
template.setReturnsCallback(returned -> {
log.error("消息无法路由: {}", returned.getMessage());
// 记录到死信队列或告警
});
// 启用消息强制回调
template.setMandatory(true);
return template;
}
// ========== 消费者配置 ==========
@Bean
public SimpleRabbitListenerContainerFactory productionContainerFactory(
ConnectionFactory factory) {
SimpleRabbitListenerContainerFactory containerFactory =
new SimpleRabbitListenerContainerFactory();
containerFactory.setConnectionFactory(factory);
// 手动确认
containerFactory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 公平分发
containerFactory.setPrefetch(1);
// 并发消费者数量
containerFactory.setConcurrentConsumers(5);
containerFactory.setMaxConcurrentConsumers(20);
// 重试配置
containerFactory.setAdviceChain(
RetryInterceptorBuilder
.stateless()
.maxAttempts(3)
.backOffOptions(1000, 2, 10000)
.build()
);
return containerFactory;
}
// ========== 队列配置 ==========
@Bean
public Queue productionQueue() {
return QueueBuilder
.durable("production.queue")
// 死信队列
.withArgument("x-dead-letter-exchange", "production.dlx")
.withArgument("x-dead-letter-routing-key", "production.dlq")
// 队列限制(防止内存溢出)
.withArgument("x-max-length", 100000)
.withArgument("x-max-length-bytes", 10737418240) // 10GB
// 惰性分发
.lazy()
// 主节点定位
.withArgument("x-queue-master-locator", "client-local")
.build();
}
} }`
`#/**
* 生产环境推荐配置
*
* 适用于:金融、电商等核心业务场景
*/
@Configuration
public class ProductionRabbitMQConfig {
// ========== 生产者配置 ==========
@Bean
public RabbitTemplate productionRabbitTemplate(ConnectionFactory factory) {
RabbitTemplate template = new RabbitTemplate(factory);
// 启用发布确认
template.setConfirmCallback((correlationData, ack, cause) -> {
if (!ack) {
log.error("消息发送失败: {}", cause);
// 触发告警和重试
}
});
// 启用返回确认(消息无法路由时)
template.setReturnsCallback(returned -> {
log.error("消息无法路由: {}", returned.getMessage());
// 记录到死信队列或告警
});
// 启用消息强制回调
template.setMandatory(true);
return template;
}
// ========== 消费者配置 ==========
@Bean
public SimpleRabbitListenerContainerFactory productionContainerFactory(
ConnectionFactory factory) {
SimpleRabbitListenerContainerFactory containerFactory =
new SimpleRabbitListenerContainerFactory();
containerFactory.setConnectionFactory(factory);
// 手动确认
containerFactory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 公平分发
containerFactory.setPrefetch(1);
// 并发消费者数量
containerFactory.setConcurrentConsumers(5);
containerFactory.setMaxConcurrentConsumers(20);
// 重试配置
containerFactory.setAdviceChain(
RetryInterceptorBuilder
.stateless()
.maxAttempts(3)
.backOffOptions(1000, 2, 10000)
.build()
);
return containerFactory;
}
// ========== 队列配置 ==========
@Bean
public Queue productionQueue() {
return QueueBuilder
.durable("production.queue")
// 死信队列
.withArgument("x-dead-letter-exchange", "production.dlx")
.withArgument("x-dead-letter-routing-key", "production.dlq")
// 队列限制(防止内存溢出)
.withArgument("x-max-length", 100000)
.withArgument("x-max-length-bytes", 10737418240) // 10GB
// 惰性分发
.lazy()
// 主节点定位
.withArgument("x-queue-master-locator", "client-local")
.build();
}
} });`
`#/**
* 生产环境推荐配置
*
* 适用于:金融、电商等核心业务场景
*/
@Configuration
public class ProductionRabbitMQConfig {
// ========== 生产者配置 ==========
@Bean
public RabbitTemplate productionRabbitTemplate(ConnectionFactory factory) {
RabbitTemplate template = new RabbitTemplate(factory);
// 启用发布确认
template.setConfirmCallback((correlationData, ack, cause) -> {
if (!ack) {
log.error("消息发送失败: {}", cause);
// 触发告警和重试
}
});
// 启用返回确认(消息无法路由时)
template.setReturnsCallback(returned -> {
log.error("消息无法路由: {}", returned.getMessage());
// 记录到死信队列或告警
});
// 启用消息强制回调
template.setMandatory(true);
return template;
}
// ========== 消费者配置 ==========
@Bean
public SimpleRabbitListenerContainerFactory productionContainerFactory(
ConnectionFactory factory) {
SimpleRabbitListenerContainerFactory containerFactory =
new SimpleRabbitListenerContainerFactory();
containerFactory.setConnectionFactory(factory);
// 手动确认
containerFactory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 公平分发
containerFactory.setPrefetch(1);
// 并发消费者数量
containerFactory.setConcurrentConsumers(5);
containerFactory.setMaxConcurrentConsumers(20);
// 重试配置
containerFactory.setAdviceChain(
RetryInterceptorBuilder
.stateless()
.maxAttempts(3)
.backOffOptions(1000, 2, 10000)
.build()
);
return containerFactory;
}
// ========== 队列配置 ==========
@Bean
public Queue productionQueue() {
return QueueBuilder
.durable("production.queue")
// 死信队列
.withArgument("x-dead-letter-exchange", "production.dlx")
.withArgument("x-dead-letter-routing-key", "production.dlq")
// 队列限制(防止内存溢出)
.withArgument("x-max-length", 100000)
.withArgument("x-max-length-bytes", 10737418240) // 10GB
// 惰性分发
.lazy()
// 主节点定位
.withArgument("x-queue-master-locator", "client-local")
.build();
}
} `
`#/**
* 生产环境推荐配置
*
* 适用于:金融、电商等核心业务场景
*/
@Configuration
public class ProductionRabbitMQConfig {
// ========== 生产者配置 ==========
@Bean
public RabbitTemplate productionRabbitTemplate(ConnectionFactory factory) {
RabbitTemplate template = new RabbitTemplate(factory);
// 启用发布确认
template.setConfirmCallback((correlationData, ack, cause) -> {
if (!ack) {
log.error("消息发送失败: {}", cause);
// 触发告警和重试
}
});
// 启用返回确认(消息无法路由时)
template.setReturnsCallback(returned -> {
log.error("消息无法路由: {}", returned.getMessage());
// 记录到死信队列或告警
});
// 启用消息强制回调
template.setMandatory(true);
return template;
}
// ========== 消费者配置 ==========
@Bean
public SimpleRabbitListenerContainerFactory productionContainerFactory(
ConnectionFactory factory) {
SimpleRabbitListenerContainerFactory containerFactory =
new SimpleRabbitListenerContainerFactory();
containerFactory.setConnectionFactory(factory);
// 手动确认
containerFactory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 公平分发
containerFactory.setPrefetch(1);
// 并发消费者数量
containerFactory.setConcurrentConsumers(5);
containerFactory.setMaxConcurrentConsumers(20);
// 重试配置
containerFactory.setAdviceChain(
RetryInterceptorBuilder
.stateless()
.maxAttempts(3)
.backOffOptions(1000, 2, 10000)
.build()
);
return containerFactory;
}
// ========== 队列配置 ==========
@Bean
public Queue productionQueue() {
return QueueBuilder
.durable("production.queue")
// 死信队列
.withArgument("x-dead-letter-exchange", "production.dlx")
.withArgument("x-dead-letter-routing-key", "production.dlq")
// 队列限制(防止内存溢出)
.withArgument("x-max-length", 100000)
.withArgument("x-max-length-bytes", 10737418240) // 10GB
// 惰性分发
.lazy()
// 主节点定位
.withArgument("x-queue-master-locator", "client-local")
.build();
}
} // 启用返回确认(消息无法路由时)`
`#/**
* 生产环境推荐配置
*
* 适用于:金融、电商等核心业务场景
*/
@Configuration
public class ProductionRabbitMQConfig {
// ========== 生产者配置 ==========
@Bean
public RabbitTemplate productionRabbitTemplate(ConnectionFactory factory) {
RabbitTemplate template = new RabbitTemplate(factory);
// 启用发布确认
template.setConfirmCallback((correlationData, ack, cause) -> {
if (!ack) {
log.error("消息发送失败: {}", cause);
// 触发告警和重试
}
});
// 启用返回确认(消息无法路由时)
template.setReturnsCallback(returned -> {
log.error("消息无法路由: {}", returned.getMessage());
// 记录到死信队列或告警
});
// 启用消息强制回调
template.setMandatory(true);
return template;
}
// ========== 消费者配置 ==========
@Bean
public SimpleRabbitListenerContainerFactory productionContainerFactory(
ConnectionFactory factory) {
SimpleRabbitListenerContainerFactory containerFactory =
new SimpleRabbitListenerContainerFactory();
containerFactory.setConnectionFactory(factory);
// 手动确认
containerFactory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 公平分发
containerFactory.setPrefetch(1);
// 并发消费者数量
containerFactory.setConcurrentConsumers(5);
containerFactory.setMaxConcurrentConsumers(20);
// 重试配置
containerFactory.setAdviceChain(
RetryInterceptorBuilder
.stateless()
.maxAttempts(3)
.backOffOptions(1000, 2, 10000)
.build()
);
return containerFactory;
}
// ========== 队列配置 ==========
@Bean
public Queue productionQueue() {
return QueueBuilder
.durable("production.queue")
// 死信队列
.withArgument("x-dead-letter-exchange", "production.dlx")
.withArgument("x-dead-letter-routing-key", "production.dlq")
// 队列限制(防止内存溢出)
.withArgument("x-max-length", 100000)
.withArgument("x-max-length-bytes", 10737418240) // 10GB
// 惰性分发
.lazy()
// 主节点定位
.withArgument("x-queue-master-locator", "client-local")
.build();
}
} template.setReturnsCallback(returned -> {`
`#/**
* 生产环境推荐配置
*
* 适用于:金融、电商等核心业务场景
*/
@Configuration
public class ProductionRabbitMQConfig {
// ========== 生产者配置 ==========
@Bean
public RabbitTemplate productionRabbitTemplate(ConnectionFactory factory) {
RabbitTemplate template = new RabbitTemplate(factory);
// 启用发布确认
template.setConfirmCallback((correlationData, ack, cause) -> {
if (!ack) {
log.error("消息发送失败: {}", cause);
// 触发告警和重试
}
});
// 启用返回确认(消息无法路由时)
template.setReturnsCallback(returned -> {
log.error("消息无法路由: {}", returned.getMessage());
// 记录到死信队列或告警
});
// 启用消息强制回调
template.setMandatory(true);
return template;
}
// ========== 消费者配置 ==========
@Bean
public SimpleRabbitListenerContainerFactory productionContainerFactory(
ConnectionFactory factory) {
SimpleRabbitListenerContainerFactory containerFactory =
new SimpleRabbitListenerContainerFactory();
containerFactory.setConnectionFactory(factory);
// 手动确认
containerFactory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 公平分发
containerFactory.setPrefetch(1);
// 并发消费者数量
containerFactory.setConcurrentConsumers(5);
containerFactory.setMaxConcurrentConsumers(20);
// 重试配置
containerFactory.setAdviceChain(
RetryInterceptorBuilder
.stateless()
.maxAttempts(3)
.backOffOptions(1000, 2, 10000)
.build()
);
return containerFactory;
}
// ========== 队列配置 ==========
@Bean
public Queue productionQueue() {
return QueueBuilder
.durable("production.queue")
// 死信队列
.withArgument("x-dead-letter-exchange", "production.dlx")
.withArgument("x-dead-letter-routing-key", "production.dlq")
// 队列限制(防止内存溢出)
.withArgument("x-max-length", 100000)
.withArgument("x-max-length-bytes", 10737418240) // 10GB
// 惰性分发
.lazy()
// 主节点定位
.withArgument("x-queue-master-locator", "client-local")
.build();
}
} log.error("消息无法路由: {}", returned.getMessage());`
`#/**
* 生产环境推荐配置
*
* 适用于:金融、电商等核心业务场景
*/
@Configuration
public class ProductionRabbitMQConfig {
// ========== 生产者配置 ==========
@Bean
public RabbitTemplate productionRabbitTemplate(ConnectionFactory factory) {
RabbitTemplate template = new RabbitTemplate(factory);
// 启用发布确认
template.setConfirmCallback((correlationData, ack, cause) -> {
if (!ack) {
log.error("消息发送失败: {}", cause);
// 触发告警和重试
}
});
// 启用返回确认(消息无法路由时)
template.setReturnsCallback(returned -> {
log.error("消息无法路由: {}", returned.getMessage());
// 记录到死信队列或告警
});
// 启用消息强制回调
template.setMandatory(true);
return template;
}
// ========== 消费者配置 ==========
@Bean
public SimpleRabbitListenerContainerFactory productionContainerFactory(
ConnectionFactory factory) {
SimpleRabbitListenerContainerFactory containerFactory =
new SimpleRabbitListenerContainerFactory();
containerFactory.setConnectionFactory(factory);
// 手动确认
containerFactory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 公平分发
containerFactory.setPrefetch(1);
// 并发消费者数量
containerFactory.setConcurrentConsumers(5);
containerFactory.setMaxConcurrentConsumers(20);
// 重试配置
containerFactory.setAdviceChain(
RetryInterceptorBuilder
.stateless()
.maxAttempts(3)
.backOffOptions(1000, 2, 10000)
.build()
);
return containerFactory;
}
// ========== 队列配置 ==========
@Bean
public Queue productionQueue() {
return QueueBuilder
.durable("production.queue")
// 死信队列
.withArgument("x-dead-letter-exchange", "production.dlx")
.withArgument("x-dead-letter-routing-key", "production.dlq")
// 队列限制(防止内存溢出)
.withArgument("x-max-length", 100000)
.withArgument("x-max-length-bytes", 10737418240) // 10GB
// 惰性分发
.lazy()
// 主节点定位
.withArgument("x-queue-master-locator", "client-local")
.build();
}
} // 记录到死信队列或告警`
`#/**
* 生产环境推荐配置
*
* 适用于:金融、电商等核心业务场景
*/
@Configuration
public class ProductionRabbitMQConfig {
// ========== 生产者配置 ==========
@Bean
public RabbitTemplate productionRabbitTemplate(ConnectionFactory factory) {
RabbitTemplate template = new RabbitTemplate(factory);
// 启用发布确认
template.setConfirmCallback((correlationData, ack, cause) -> {
if (!ack) {
log.error("消息发送失败: {}", cause);
// 触发告警和重试
}
});
// 启用返回确认(消息无法路由时)
template.setReturnsCallback(returned -> {
log.error("消息无法路由: {}", returned.getMessage());
// 记录到死信队列或告警
});
// 启用消息强制回调
template.setMandatory(true);
return template;
}
// ========== 消费者配置 ==========
@Bean
public SimpleRabbitListenerContainerFactory productionContainerFactory(
ConnectionFactory factory) {
SimpleRabbitListenerContainerFactory containerFactory =
new SimpleRabbitListenerContainerFactory();
containerFactory.setConnectionFactory(factory);
// 手动确认
containerFactory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 公平分发
containerFactory.setPrefetch(1);
// 并发消费者数量
containerFactory.setConcurrentConsumers(5);
containerFactory.setMaxConcurrentConsumers(20);
// 重试配置
containerFactory.setAdviceChain(
RetryInterceptorBuilder
.stateless()
.maxAttempts(3)
.backOffOptions(1000, 2, 10000)
.build()
);
return containerFactory;
}
// ========== 队列配置 ==========
@Bean
public Queue productionQueue() {
return QueueBuilder
.durable("production.queue")
// 死信队列
.withArgument("x-dead-letter-exchange", "production.dlx")
.withArgument("x-dead-letter-routing-key", "production.dlq")
// 队列限制(防止内存溢出)
.withArgument("x-max-length", 100000)
.withArgument("x-max-length-bytes", 10737418240) // 10GB
// 惰性分发
.lazy()
// 主节点定位
.withArgument("x-queue-master-locator", "client-local")
.build();
}
} });`
`#/**
* 生产环境推荐配置
*
* 适用于:金融、电商等核心业务场景
*/
@Configuration
public class ProductionRabbitMQConfig {
// ========== 生产者配置 ==========
@Bean
public RabbitTemplate productionRabbitTemplate(ConnectionFactory factory) {
RabbitTemplate template = new RabbitTemplate(factory);
// 启用发布确认
template.setConfirmCallback((correlationData, ack, cause) -> {
if (!ack) {
log.error("消息发送失败: {}", cause);
// 触发告警和重试
}
});
// 启用返回确认(消息无法路由时)
template.setReturnsCallback(returned -> {
log.error("消息无法路由: {}", returned.getMessage());
// 记录到死信队列或告警
});
// 启用消息强制回调
template.setMandatory(true);
return template;
}
// ========== 消费者配置 ==========
@Bean
public SimpleRabbitListenerContainerFactory productionContainerFactory(
ConnectionFactory factory) {
SimpleRabbitListenerContainerFactory containerFactory =
new SimpleRabbitListenerContainerFactory();
containerFactory.setConnectionFactory(factory);
// 手动确认
containerFactory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 公平分发
containerFactory.setPrefetch(1);
// 并发消费者数量
containerFactory.setConcurrentConsumers(5);
containerFactory.setMaxConcurrentConsumers(20);
// 重试配置
containerFactory.setAdviceChain(
RetryInterceptorBuilder
.stateless()
.maxAttempts(3)
.backOffOptions(1000, 2, 10000)
.build()
);
return containerFactory;
}
// ========== 队列配置 ==========
@Bean
public Queue productionQueue() {
return QueueBuilder
.durable("production.queue")
// 死信队列
.withArgument("x-dead-letter-exchange", "production.dlx")
.withArgument("x-dead-letter-routing-key", "production.dlq")
// 队列限制(防止内存溢出)
.withArgument("x-max-length", 100000)
.withArgument("x-max-length-bytes", 10737418240) // 10GB
// 惰性分发
.lazy()
// 主节点定位
.withArgument("x-queue-master-locator", "client-local")
.build();
}
} `
`#/**
* 生产环境推荐配置
*
* 适用于:金融、电商等核心业务场景
*/
@Configuration
public class ProductionRabbitMQConfig {
// ========== 生产者配置 ==========
@Bean
public RabbitTemplate productionRabbitTemplate(ConnectionFactory factory) {
RabbitTemplate template = new RabbitTemplate(factory);
// 启用发布确认
template.setConfirmCallback((correlationData, ack, cause) -> {
if (!ack) {
log.error("消息发送失败: {}", cause);
// 触发告警和重试
}
});
// 启用返回确认(消息无法路由时)
template.setReturnsCallback(returned -> {
log.error("消息无法路由: {}", returned.getMessage());
// 记录到死信队列或告警
});
// 启用消息强制回调
template.setMandatory(true);
return template;
}
// ========== 消费者配置 ==========
@Bean
public SimpleRabbitListenerContainerFactory productionContainerFactory(
ConnectionFactory factory) {
SimpleRabbitListenerContainerFactory containerFactory =
new SimpleRabbitListenerContainerFactory();
containerFactory.setConnectionFactory(factory);
// 手动确认
containerFactory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 公平分发
containerFactory.setPrefetch(1);
// 并发消费者数量
containerFactory.setConcurrentConsumers(5);
containerFactory.setMaxConcurrentConsumers(20);
// 重试配置
containerFactory.setAdviceChain(
RetryInterceptorBuilder
.stateless()
.maxAttempts(3)
.backOffOptions(1000, 2, 10000)
.build()
);
return containerFactory;
}
// ========== 队列配置 ==========
@Bean
public Queue productionQueue() {
return QueueBuilder
.durable("production.queue")
// 死信队列
.withArgument("x-dead-letter-exchange", "production.dlx")
.withArgument("x-dead-letter-routing-key", "production.dlq")
// 队列限制(防止内存溢出)
.withArgument("x-max-length", 100000)
.withArgument("x-max-length-bytes", 10737418240) // 10GB
// 惰性分发
.lazy()
// 主节点定位
.withArgument("x-queue-master-locator", "client-local")
.build();
}
} // 启用消息强制回调`
`#/**
* 生产环境推荐配置
*
* 适用于:金融、电商等核心业务场景
*/
@Configuration
public class ProductionRabbitMQConfig {
// ========== 生产者配置 ==========
@Bean
public RabbitTemplate productionRabbitTemplate(ConnectionFactory factory) {
RabbitTemplate template = new RabbitTemplate(factory);
// 启用发布确认
template.setConfirmCallback((correlationData, ack, cause) -> {
if (!ack) {
log.error("消息发送失败: {}", cause);
// 触发告警和重试
}
});
// 启用返回确认(消息无法路由时)
template.setReturnsCallback(returned -> {
log.error("消息无法路由: {}", returned.getMessage());
// 记录到死信队列或告警
});
// 启用消息强制回调
template.setMandatory(true);
return template;
}
// ========== 消费者配置 ==========
@Bean
public SimpleRabbitListenerContainerFactory productionContainerFactory(
ConnectionFactory factory) {
SimpleRabbitListenerContainerFactory containerFactory =
new SimpleRabbitListenerContainerFactory();
containerFactory.setConnectionFactory(factory);
// 手动确认
containerFactory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 公平分发
containerFactory.setPrefetch(1);
// 并发消费者数量
containerFactory.setConcurrentConsumers(5);
containerFactory.setMaxConcurrentConsumers(20);
// 重试配置
containerFactory.setAdviceChain(
RetryInterceptorBuilder
.stateless()
.maxAttempts(3)
.backOffOptions(1000, 2, 10000)
.build()
);
return containerFactory;
}
// ========== 队列配置 ==========
@Bean
public Queue productionQueue() {
return QueueBuilder
.durable("production.queue")
// 死信队列
.withArgument("x-dead-letter-exchange", "production.dlx")
.withArgument("x-dead-letter-routing-key", "production.dlq")
// 队列限制(防止内存溢出)
.withArgument("x-max-length", 100000)
.withArgument("x-max-length-bytes", 10737418240) // 10GB
// 惰性分发
.lazy()
// 主节点定位
.withArgument("x-queue-master-locator", "client-local")
.build();
}
} template.setMandatory(true);`
`#/**
* 生产环境推荐配置
*
* 适用于:金融、电商等核心业务场景
*/
@Configuration
public class ProductionRabbitMQConfig {
// ========== 生产者配置 ==========
@Bean
public RabbitTemplate productionRabbitTemplate(ConnectionFactory factory) {
RabbitTemplate template = new RabbitTemplate(factory);
// 启用发布确认
template.setConfirmCallback((correlationData, ack, cause) -> {
if (!ack) {
log.error("消息发送失败: {}", cause);
// 触发告警和重试
}
});
// 启用返回确认(消息无法路由时)
template.setReturnsCallback(returned -> {
log.error("消息无法路由: {}", returned.getMessage());
// 记录到死信队列或告警
});
// 启用消息强制回调
template.setMandatory(true);
return template;
}
// ========== 消费者配置 ==========
@Bean
public SimpleRabbitListenerContainerFactory productionContainerFactory(
ConnectionFactory factory) {
SimpleRabbitListenerContainerFactory containerFactory =
new SimpleRabbitListenerContainerFactory();
containerFactory.setConnectionFactory(factory);
// 手动确认
containerFactory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 公平分发
containerFactory.setPrefetch(1);
// 并发消费者数量
containerFactory.setConcurrentConsumers(5);
containerFactory.setMaxConcurrentConsumers(20);
// 重试配置
containerFactory.setAdviceChain(
RetryInterceptorBuilder
.stateless()
.maxAttempts(3)
.backOffOptions(1000, 2, 10000)
.build()
);
return containerFactory;
}
// ========== 队列配置 ==========
@Bean
public Queue productionQueue() {
return QueueBuilder
.durable("production.queue")
// 死信队列
.withArgument("x-dead-letter-exchange", "production.dlx")
.withArgument("x-dead-letter-routing-key", "production.dlq")
// 队列限制(防止内存溢出)
.withArgument("x-max-length", 100000)
.withArgument("x-max-length-bytes", 10737418240) // 10GB
// 惰性分发
.lazy()
// 主节点定位
.withArgument("x-queue-master-locator", "client-local")
.build();
}
} `
`#/**
* 生产环境推荐配置
*
* 适用于:金融、电商等核心业务场景
*/
@Configuration
public class ProductionRabbitMQConfig {
// ========== 生产者配置 ==========
@Bean
public RabbitTemplate productionRabbitTemplate(ConnectionFactory factory) {
RabbitTemplate template = new RabbitTemplate(factory);
// 启用发布确认
template.setConfirmCallback((correlationData, ack, cause) -> {
if (!ack) {
log.error("消息发送失败: {}", cause);
// 触发告警和重试
}
});
// 启用返回确认(消息无法路由时)
template.setReturnsCallback(returned -> {
log.error("消息无法路由: {}", returned.getMessage());
// 记录到死信队列或告警
});
// 启用消息强制回调
template.setMandatory(true);
return template;
}
// ========== 消费者配置 ==========
@Bean
public SimpleRabbitListenerContainerFactory productionContainerFactory(
ConnectionFactory factory) {
SimpleRabbitListenerContainerFactory containerFactory =
new SimpleRabbitListenerContainerFactory();
containerFactory.setConnectionFactory(factory);
// 手动确认
containerFactory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 公平分发
containerFactory.setPrefetch(1);
// 并发消费者数量
containerFactory.setConcurrentConsumers(5);
containerFactory.setMaxConcurrentConsumers(20);
// 重试配置
containerFactory.setAdviceChain(
RetryInterceptorBuilder
.stateless()
.maxAttempts(3)
.backOffOptions(1000, 2, 10000)
.build()
);
return containerFactory;
}
// ========== 队列配置 ==========
@Bean
public Queue productionQueue() {
return QueueBuilder
.durable("production.queue")
// 死信队列
.withArgument("x-dead-letter-exchange", "production.dlx")
.withArgument("x-dead-letter-routing-key", "production.dlq")
// 队列限制(防止内存溢出)
.withArgument("x-max-length", 100000)
.withArgument("x-max-length-bytes", 10737418240) // 10GB
// 惰性分发
.lazy()
// 主节点定位
.withArgument("x-queue-master-locator", "client-local")
.build();
}
} return template;`
`#/**
* 生产环境推荐配置
*
* 适用于:金融、电商等核心业务场景
*/
@Configuration
public class ProductionRabbitMQConfig {
// ========== 生产者配置 ==========
@Bean
public RabbitTemplate productionRabbitTemplate(ConnectionFactory factory) {
RabbitTemplate template = new RabbitTemplate(factory);
// 启用发布确认
template.setConfirmCallback((correlationData, ack, cause) -> {
if (!ack) {
log.error("消息发送失败: {}", cause);
// 触发告警和重试
}
});
// 启用返回确认(消息无法路由时)
template.setReturnsCallback(returned -> {
log.error("消息无法路由: {}", returned.getMessage());
// 记录到死信队列或告警
});
// 启用消息强制回调
template.setMandatory(true);
return template;
}
// ========== 消费者配置 ==========
@Bean
public SimpleRabbitListenerContainerFactory productionContainerFactory(
ConnectionFactory factory) {
SimpleRabbitListenerContainerFactory containerFactory =
new SimpleRabbitListenerContainerFactory();
containerFactory.setConnectionFactory(factory);
// 手动确认
containerFactory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 公平分发
containerFactory.setPrefetch(1);
// 并发消费者数量
containerFactory.setConcurrentConsumers(5);
containerFactory.setMaxConcurrentConsumers(20);
// 重试配置
containerFactory.setAdviceChain(
RetryInterceptorBuilder
.stateless()
.maxAttempts(3)
.backOffOptions(1000, 2, 10000)
.build()
);
return containerFactory;
}
// ========== 队列配置 ==========
@Bean
public Queue productionQueue() {
return QueueBuilder
.durable("production.queue")
// 死信队列
.withArgument("x-dead-letter-exchange", "production.dlx")
.withArgument("x-dead-letter-routing-key", "production.dlq")
// 队列限制(防止内存溢出)
.withArgument("x-max-length", 100000)
.withArgument("x-max-length-bytes", 10737418240) // 10GB
// 惰性分发
.lazy()
// 主节点定位
.withArgument("x-queue-master-locator", "client-local")
.build();
}
} }`
`#/**
* 生产环境推荐配置
*
* 适用于:金融、电商等核心业务场景
*/
@Configuration
public class ProductionRabbitMQConfig {
// ========== 生产者配置 ==========
@Bean
public RabbitTemplate productionRabbitTemplate(ConnectionFactory factory) {
RabbitTemplate template = new RabbitTemplate(factory);
// 启用发布确认
template.setConfirmCallback((correlationData, ack, cause) -> {
if (!ack) {
log.error("消息发送失败: {}", cause);
// 触发告警和重试
}
});
// 启用返回确认(消息无法路由时)
template.setReturnsCallback(returned -> {
log.error("消息无法路由: {}", returned.getMessage());
// 记录到死信队列或告警
});
// 启用消息强制回调
template.setMandatory(true);
return template;
}
// ========== 消费者配置 ==========
@Bean
public SimpleRabbitListenerContainerFactory productionContainerFactory(
ConnectionFactory factory) {
SimpleRabbitListenerContainerFactory containerFactory =
new SimpleRabbitListenerContainerFactory();
containerFactory.setConnectionFactory(factory);
// 手动确认
containerFactory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 公平分发
containerFactory.setPrefetch(1);
// 并发消费者数量
containerFactory.setConcurrentConsumers(5);
containerFactory.setMaxConcurrentConsumers(20);
// 重试配置
containerFactory.setAdviceChain(
RetryInterceptorBuilder
.stateless()
.maxAttempts(3)
.backOffOptions(1000, 2, 10000)
.build()
);
return containerFactory;
}
// ========== 队列配置 ==========
@Bean
public Queue productionQueue() {
return QueueBuilder
.durable("production.queue")
// 死信队列
.withArgument("x-dead-letter-exchange", "production.dlx")
.withArgument("x-dead-letter-routing-key", "production.dlq")
// 队列限制(防止内存溢出)
.withArgument("x-max-length", 100000)
.withArgument("x-max-length-bytes", 10737418240) // 10GB
// 惰性分发
.lazy()
// 主节点定位
.withArgument("x-queue-master-locator", "client-local")
.build();
}
}`
`#/**
* 生产环境推荐配置
*
* 适用于:金融、电商等核心业务场景
*/
@Configuration
public class ProductionRabbitMQConfig {
// ========== 生产者配置 ==========
@Bean
public RabbitTemplate productionRabbitTemplate(ConnectionFactory factory) {
RabbitTemplate template = new RabbitTemplate(factory);
// 启用发布确认
template.setConfirmCallback((correlationData, ack, cause) -> {
if (!ack) {
log.error("消息发送失败: {}", cause);
// 触发告警和重试
}
});
// 启用返回确认(消息无法路由时)
template.setReturnsCallback(returned -> {
log.error("消息无法路由: {}", returned.getMessage());
// 记录到死信队列或告警
});
// 启用消息强制回调
template.setMandatory(true);
return template;
}
// ========== 消费者配置 ==========
@Bean
public SimpleRabbitListenerContainerFactory productionContainerFactory(
ConnectionFactory factory) {
SimpleRabbitListenerContainerFactory containerFactory =
new SimpleRabbitListenerContainerFactory();
containerFactory.setConnectionFactory(factory);
// 手动确认
containerFactory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 公平分发
containerFactory.setPrefetch(1);
// 并发消费者数量
containerFactory.setConcurrentConsumers(5);
containerFactory.setMaxConcurrentConsumers(20);
// 重试配置
containerFactory.setAdviceChain(
RetryInterceptorBuilder
.stateless()
.maxAttempts(3)
.backOffOptions(1000, 2, 10000)
.build()
);
return containerFactory;
}
// ========== 队列配置 ==========
@Bean
public Queue productionQueue() {
return QueueBuilder
.durable("production.queue")
// 死信队列
.withArgument("x-dead-letter-exchange", "production.dlx")
.withArgument("x-dead-letter-routing-key", "production.dlq")
// 队列限制(防止内存溢出)
.withArgument("x-max-length", 100000)
.withArgument("x-max-length-bytes", 10737418240) // 10GB
// 惰性分发
.lazy()
// 主节点定位
.withArgument("x-queue-master-locator", "client-local")
.build();
}
} // ========== 消费者配置 ==========`
`#/**
* 生产环境推荐配置
*
* 适用于:金融、电商等核心业务场景
*/
@Configuration
public class ProductionRabbitMQConfig {
// ========== 生产者配置 ==========
@Bean
public RabbitTemplate productionRabbitTemplate(ConnectionFactory factory) {
RabbitTemplate template = new RabbitTemplate(factory);
// 启用发布确认
template.setConfirmCallback((correlationData, ack, cause) -> {
if (!ack) {
log.error("消息发送失败: {}", cause);
// 触发告警和重试
}
});
// 启用返回确认(消息无法路由时)
template.setReturnsCallback(returned -> {
log.error("消息无法路由: {}", returned.getMessage());
// 记录到死信队列或告警
});
// 启用消息强制回调
template.setMandatory(true);
return template;
}
// ========== 消费者配置 ==========
@Bean
public SimpleRabbitListenerContainerFactory productionContainerFactory(
ConnectionFactory factory) {
SimpleRabbitListenerContainerFactory containerFactory =
new SimpleRabbitListenerContainerFactory();
containerFactory.setConnectionFactory(factory);
// 手动确认
containerFactory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 公平分发
containerFactory.setPrefetch(1);
// 并发消费者数量
containerFactory.setConcurrentConsumers(5);
containerFactory.setMaxConcurrentConsumers(20);
// 重试配置
containerFactory.setAdviceChain(
RetryInterceptorBuilder
.stateless()
.maxAttempts(3)
.backOffOptions(1000, 2, 10000)
.build()
);
return containerFactory;
}
// ========== 队列配置 ==========
@Bean
public Queue productionQueue() {
return QueueBuilder
.durable("production.queue")
// 死信队列
.withArgument("x-dead-letter-exchange", "production.dlx")
.withArgument("x-dead-letter-routing-key", "production.dlq")
// 队列限制(防止内存溢出)
.withArgument("x-max-length", 100000)
.withArgument("x-max-length-bytes", 10737418240) // 10GB
// 惰性分发
.lazy()
// 主节点定位
.withArgument("x-queue-master-locator", "client-local")
.build();
}
} `
`#/**
* 生产环境推荐配置
*
* 适用于:金融、电商等核心业务场景
*/
@Configuration
public class ProductionRabbitMQConfig {
// ========== 生产者配置 ==========
@Bean
public RabbitTemplate productionRabbitTemplate(ConnectionFactory factory) {
RabbitTemplate template = new RabbitTemplate(factory);
// 启用发布确认
template.setConfirmCallback((correlationData, ack, cause) -> {
if (!ack) {
log.error("消息发送失败: {}", cause);
// 触发告警和重试
}
});
// 启用返回确认(消息无法路由时)
template.setReturnsCallback(returned -> {
log.error("消息无法路由: {}", returned.getMessage());
// 记录到死信队列或告警
});
// 启用消息强制回调
template.setMandatory(true);
return template;
}
// ========== 消费者配置 ==========
@Bean
public SimpleRabbitListenerContainerFactory productionContainerFactory(
ConnectionFactory factory) {
SimpleRabbitListenerContainerFactory containerFactory =
new SimpleRabbitListenerContainerFactory();
containerFactory.setConnectionFactory(factory);
// 手动确认
containerFactory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 公平分发
containerFactory.setPrefetch(1);
// 并发消费者数量
containerFactory.setConcurrentConsumers(5);
containerFactory.setMaxConcurrentConsumers(20);
// 重试配置
containerFactory.setAdviceChain(
RetryInterceptorBuilder
.stateless()
.maxAttempts(3)
.backOffOptions(1000, 2, 10000)
.build()
);
return containerFactory;
}
// ========== 队列配置 ==========
@Bean
public Queue productionQueue() {
return QueueBuilder
.durable("production.queue")
// 死信队列
.withArgument("x-dead-letter-exchange", "production.dlx")
.withArgument("x-dead-letter-routing-key", "production.dlq")
// 队列限制(防止内存溢出)
.withArgument("x-max-length", 100000)
.withArgument("x-max-length-bytes", 10737418240) // 10GB
// 惰性分发
.lazy()
// 主节点定位
.withArgument("x-queue-master-locator", "client-local")
.build();
}
} @Bean`
`#/**
* 生产环境推荐配置
*
* 适用于:金融、电商等核心业务场景
*/
@Configuration
public class ProductionRabbitMQConfig {
// ========== 生产者配置 ==========
@Bean
public RabbitTemplate productionRabbitTemplate(ConnectionFactory factory) {
RabbitTemplate template = new RabbitTemplate(factory);
// 启用发布确认
template.setConfirmCallback((correlationData, ack, cause) -> {
if (!ack) {
log.error("消息发送失败: {}", cause);
// 触发告警和重试
}
});
// 启用返回确认(消息无法路由时)
template.setReturnsCallback(returned -> {
log.error("消息无法路由: {}", returned.getMessage());
// 记录到死信队列或告警
});
// 启用消息强制回调
template.setMandatory(true);
return template;
}
// ========== 消费者配置 ==========
@Bean
public SimpleRabbitListenerContainerFactory productionContainerFactory(
ConnectionFactory factory) {
SimpleRabbitListenerContainerFactory containerFactory =
new SimpleRabbitListenerContainerFactory();
containerFactory.setConnectionFactory(factory);
// 手动确认
containerFactory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 公平分发
containerFactory.setPrefetch(1);
// 并发消费者数量
containerFactory.setConcurrentConsumers(5);
containerFactory.setMaxConcurrentConsumers(20);
// 重试配置
containerFactory.setAdviceChain(
RetryInterceptorBuilder
.stateless()
.maxAttempts(3)
.backOffOptions(1000, 2, 10000)
.build()
);
return containerFactory;
}
// ========== 队列配置 ==========
@Bean
public Queue productionQueue() {
return QueueBuilder
.durable("production.queue")
// 死信队列
.withArgument("x-dead-letter-exchange", "production.dlx")
.withArgument("x-dead-letter-routing-key", "production.dlq")
// 队列限制(防止内存溢出)
.withArgument("x-max-length", 100000)
.withArgument("x-max-length-bytes", 10737418240) // 10GB
// 惰性分发
.lazy()
// 主节点定位
.withArgument("x-queue-master-locator", "client-local")
.build();
}
} public SimpleRabbitListenerContainerFactory productionContainerFactory(`
`#/**
* 生产环境推荐配置
*
* 适用于:金融、电商等核心业务场景
*/
@Configuration
public class ProductionRabbitMQConfig {
// ========== 生产者配置 ==========
@Bean
public RabbitTemplate productionRabbitTemplate(ConnectionFactory factory) {
RabbitTemplate template = new RabbitTemplate(factory);
// 启用发布确认
template.setConfirmCallback((correlationData, ack, cause) -> {
if (!ack) {
log.error("消息发送失败: {}", cause);
// 触发告警和重试
}
});
// 启用返回确认(消息无法路由时)
template.setReturnsCallback(returned -> {
log.error("消息无法路由: {}", returned.getMessage());
// 记录到死信队列或告警
});
// 启用消息强制回调
template.setMandatory(true);
return template;
}
// ========== 消费者配置 ==========
@Bean
public SimpleRabbitListenerContainerFactory productionContainerFactory(
ConnectionFactory factory) {
SimpleRabbitListenerContainerFactory containerFactory =
new SimpleRabbitListenerContainerFactory();
containerFactory.setConnectionFactory(factory);
// 手动确认
containerFactory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 公平分发
containerFactory.setPrefetch(1);
// 并发消费者数量
containerFactory.setConcurrentConsumers(5);
containerFactory.setMaxConcurrentConsumers(20);
// 重试配置
containerFactory.setAdviceChain(
RetryInterceptorBuilder
.stateless()
.maxAttempts(3)
.backOffOptions(1000, 2, 10000)
.build()
);
return containerFactory;
}
// ========== 队列配置 ==========
@Bean
public Queue productionQueue() {
return QueueBuilder
.durable("production.queue")
// 死信队列
.withArgument("x-dead-letter-exchange", "production.dlx")
.withArgument("x-dead-letter-routing-key", "production.dlq")
// 队列限制(防止内存溢出)
.withArgument("x-max-length", 100000)
.withArgument("x-max-length-bytes", 10737418240) // 10GB
// 惰性分发
.lazy()
// 主节点定位
.withArgument("x-queue-master-locator", "client-local")
.build();
}
} ConnectionFactory factory) {`
`#/**
* 生产环境推荐配置
*
* 适用于:金融、电商等核心业务场景
*/
@Configuration
public class ProductionRabbitMQConfig {
// ========== 生产者配置 ==========
@Bean
public RabbitTemplate productionRabbitTemplate(ConnectionFactory factory) {
RabbitTemplate template = new RabbitTemplate(factory);
// 启用发布确认
template.setConfirmCallback((correlationData, ack, cause) -> {
if (!ack) {
log.error("消息发送失败: {}", cause);
// 触发告警和重试
}
});
// 启用返回确认(消息无法路由时)
template.setReturnsCallback(returned -> {
log.error("消息无法路由: {}", returned.getMessage());
// 记录到死信队列或告警
});
// 启用消息强制回调
template.setMandatory(true);
return template;
}
// ========== 消费者配置 ==========
@Bean
public SimpleRabbitListenerContainerFactory productionContainerFactory(
ConnectionFactory factory) {
SimpleRabbitListenerContainerFactory containerFactory =
new SimpleRabbitListenerContainerFactory();
containerFactory.setConnectionFactory(factory);
// 手动确认
containerFactory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 公平分发
containerFactory.setPrefetch(1);
// 并发消费者数量
containerFactory.setConcurrentConsumers(5);
containerFactory.setMaxConcurrentConsumers(20);
// 重试配置
containerFactory.setAdviceChain(
RetryInterceptorBuilder
.stateless()
.maxAttempts(3)
.backOffOptions(1000, 2, 10000)
.build()
);
return containerFactory;
}
// ========== 队列配置 ==========
@Bean
public Queue productionQueue() {
return QueueBuilder
.durable("production.queue")
// 死信队列
.withArgument("x-dead-letter-exchange", "production.dlx")
.withArgument("x-dead-letter-routing-key", "production.dlq")
// 队列限制(防止内存溢出)
.withArgument("x-max-length", 100000)
.withArgument("x-max-length-bytes", 10737418240) // 10GB
// 惰性分发
.lazy()
// 主节点定位
.withArgument("x-queue-master-locator", "client-local")
.build();
}
} SimpleRabbitListenerContainerFactory containerFactory = `
`#/**
* 生产环境推荐配置
*
* 适用于:金融、电商等核心业务场景
*/
@Configuration
public class ProductionRabbitMQConfig {
// ========== 生产者配置 ==========
@Bean
public RabbitTemplate productionRabbitTemplate(ConnectionFactory factory) {
RabbitTemplate template = new RabbitTemplate(factory);
// 启用发布确认
template.setConfirmCallback((correlationData, ack, cause) -> {
if (!ack) {
log.error("消息发送失败: {}", cause);
// 触发告警和重试
}
});
// 启用返回确认(消息无法路由时)
template.setReturnsCallback(returned -> {
log.error("消息无法路由: {}", returned.getMessage());
// 记录到死信队列或告警
});
// 启用消息强制回调
template.setMandatory(true);
return template;
}
// ========== 消费者配置 ==========
@Bean
public SimpleRabbitListenerContainerFactory productionContainerFactory(
ConnectionFactory factory) {
SimpleRabbitListenerContainerFactory containerFactory =
new SimpleRabbitListenerContainerFactory();
containerFactory.setConnectionFactory(factory);
// 手动确认
containerFactory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 公平分发
containerFactory.setPrefetch(1);
// 并发消费者数量
containerFactory.setConcurrentConsumers(5);
containerFactory.setMaxConcurrentConsumers(20);
// 重试配置
containerFactory.setAdviceChain(
RetryInterceptorBuilder
.stateless()
.maxAttempts(3)
.backOffOptions(1000, 2, 10000)
.build()
);
return containerFactory;
}
// ========== 队列配置 ==========
@Bean
public Queue productionQueue() {
return QueueBuilder
.durable("production.queue")
// 死信队列
.withArgument("x-dead-letter-exchange", "production.dlx")
.withArgument("x-dead-letter-routing-key", "production.dlq")
// 队列限制(防止内存溢出)
.withArgument("x-max-length", 100000)
.withArgument("x-max-length-bytes", 10737418240) // 10GB
// 惰性分发
.lazy()
// 主节点定位
.withArgument("x-queue-master-locator", "client-local")
.build();
}
} new SimpleRabbitListenerContainerFactory();`
`#/**
* 生产环境推荐配置
*
* 适用于:金融、电商等核心业务场景
*/
@Configuration
public class ProductionRabbitMQConfig {
// ========== 生产者配置 ==========
@Bean
public RabbitTemplate productionRabbitTemplate(ConnectionFactory factory) {
RabbitTemplate template = new RabbitTemplate(factory);
// 启用发布确认
template.setConfirmCallback((correlationData, ack, cause) -> {
if (!ack) {
log.error("消息发送失败: {}", cause);
// 触发告警和重试
}
});
// 启用返回确认(消息无法路由时)
template.setReturnsCallback(returned -> {
log.error("消息无法路由: {}", returned.getMessage());
// 记录到死信队列或告警
});
// 启用消息强制回调
template.setMandatory(true);
return template;
}
// ========== 消费者配置 ==========
@Bean
public SimpleRabbitListenerContainerFactory productionContainerFactory(
ConnectionFactory factory) {
SimpleRabbitListenerContainerFactory containerFactory =
new SimpleRabbitListenerContainerFactory();
containerFactory.setConnectionFactory(factory);
// 手动确认
containerFactory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 公平分发
containerFactory.setPrefetch(1);
// 并发消费者数量
containerFactory.setConcurrentConsumers(5);
containerFactory.setMaxConcurrentConsumers(20);
// 重试配置
containerFactory.setAdviceChain(
RetryInterceptorBuilder
.stateless()
.maxAttempts(3)
.backOffOptions(1000, 2, 10000)
.build()
);
return containerFactory;
}
// ========== 队列配置 ==========
@Bean
public Queue productionQueue() {
return QueueBuilder
.durable("production.queue")
// 死信队列
.withArgument("x-dead-letter-exchange", "production.dlx")
.withArgument("x-dead-letter-routing-key", "production.dlq")
// 队列限制(防止内存溢出)
.withArgument("x-max-length", 100000)
.withArgument("x-max-length-bytes", 10737418240) // 10GB
// 惰性分发
.lazy()
// 主节点定位
.withArgument("x-queue-master-locator", "client-local")
.build();
}
} containerFactory.setConnectionFactory(factory);`
`#/**
* 生产环境推荐配置
*
* 适用于:金融、电商等核心业务场景
*/
@Configuration
public class ProductionRabbitMQConfig {
// ========== 生产者配置 ==========
@Bean
public RabbitTemplate productionRabbitTemplate(ConnectionFactory factory) {
RabbitTemplate template = new RabbitTemplate(factory);
// 启用发布确认
template.setConfirmCallback((correlationData, ack, cause) -> {
if (!ack) {
log.error("消息发送失败: {}", cause);
// 触发告警和重试
}
});
// 启用返回确认(消息无法路由时)
template.setReturnsCallback(returned -> {
log.error("消息无法路由: {}", returned.getMessage());
// 记录到死信队列或告警
});
// 启用消息强制回调
template.setMandatory(true);
return template;
}
// ========== 消费者配置 ==========
@Bean
public SimpleRabbitListenerContainerFactory productionContainerFactory(
ConnectionFactory factory) {
SimpleRabbitListenerContainerFactory containerFactory =
new SimpleRabbitListenerContainerFactory();
containerFactory.setConnectionFactory(factory);
// 手动确认
containerFactory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 公平分发
containerFactory.setPrefetch(1);
// 并发消费者数量
containerFactory.setConcurrentConsumers(5);
containerFactory.setMaxConcurrentConsumers(20);
// 重试配置
containerFactory.setAdviceChain(
RetryInterceptorBuilder
.stateless()
.maxAttempts(3)
.backOffOptions(1000, 2, 10000)
.build()
);
return containerFactory;
}
// ========== 队列配置 ==========
@Bean
public Queue productionQueue() {
return QueueBuilder
.durable("production.queue")
// 死信队列
.withArgument("x-dead-letter-exchange", "production.dlx")
.withArgument("x-dead-letter-routing-key", "production.dlq")
// 队列限制(防止内存溢出)
.withArgument("x-max-length", 100000)
.withArgument("x-max-length-bytes", 10737418240) // 10GB
// 惰性分发
.lazy()
// 主节点定位
.withArgument("x-queue-master-locator", "client-local")
.build();
}
} `
`#/**
* 生产环境推荐配置
*
* 适用于:金融、电商等核心业务场景
*/
@Configuration
public class ProductionRabbitMQConfig {
// ========== 生产者配置 ==========
@Bean
public RabbitTemplate productionRabbitTemplate(ConnectionFactory factory) {
RabbitTemplate template = new RabbitTemplate(factory);
// 启用发布确认
template.setConfirmCallback((correlationData, ack, cause) -> {
if (!ack) {
log.error("消息发送失败: {}", cause);
// 触发告警和重试
}
});
// 启用返回确认(消息无法路由时)
template.setReturnsCallback(returned -> {
log.error("消息无法路由: {}", returned.getMessage());
// 记录到死信队列或告警
});
// 启用消息强制回调
template.setMandatory(true);
return template;
}
// ========== 消费者配置 ==========
@Bean
public SimpleRabbitListenerContainerFactory productionContainerFactory(
ConnectionFactory factory) {
SimpleRabbitListenerContainerFactory containerFactory =
new SimpleRabbitListenerContainerFactory();
containerFactory.setConnectionFactory(factory);
// 手动确认
containerFactory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 公平分发
containerFactory.setPrefetch(1);
// 并发消费者数量
containerFactory.setConcurrentConsumers(5);
containerFactory.setMaxConcurrentConsumers(20);
// 重试配置
containerFactory.setAdviceChain(
RetryInterceptorBuilder
.stateless()
.maxAttempts(3)
.backOffOptions(1000, 2, 10000)
.build()
);
return containerFactory;
}
// ========== 队列配置 ==========
@Bean
public Queue productionQueue() {
return QueueBuilder
.durable("production.queue")
// 死信队列
.withArgument("x-dead-letter-exchange", "production.dlx")
.withArgument("x-dead-letter-routing-key", "production.dlq")
// 队列限制(防止内存溢出)
.withArgument("x-max-length", 100000)
.withArgument("x-max-length-bytes", 10737418240) // 10GB
// 惰性分发
.lazy()
// 主节点定位
.withArgument("x-queue-master-locator", "client-local")
.build();
}
} // 手动确认`
`#/**
* 生产环境推荐配置
*
* 适用于:金融、电商等核心业务场景
*/
@Configuration
public class ProductionRabbitMQConfig {
// ========== 生产者配置 ==========
@Bean
public RabbitTemplate productionRabbitTemplate(ConnectionFactory factory) {
RabbitTemplate template = new RabbitTemplate(factory);
// 启用发布确认
template.setConfirmCallback((correlationData, ack, cause) -> {
if (!ack) {
log.error("消息发送失败: {}", cause);
// 触发告警和重试
}
});
// 启用返回确认(消息无法路由时)
template.setReturnsCallback(returned -> {
log.error("消息无法路由: {}", returned.getMessage());
// 记录到死信队列或告警
});
// 启用消息强制回调
template.setMandatory(true);
return template;
}
// ========== 消费者配置 ==========
@Bean
public SimpleRabbitListenerContainerFactory productionContainerFactory(
ConnectionFactory factory) {
SimpleRabbitListenerContainerFactory containerFactory =
new SimpleRabbitListenerContainerFactory();
containerFactory.setConnectionFactory(factory);
// 手动确认
containerFactory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 公平分发
containerFactory.setPrefetch(1);
// 并发消费者数量
containerFactory.setConcurrentConsumers(5);
containerFactory.setMaxConcurrentConsumers(20);
// 重试配置
containerFactory.setAdviceChain(
RetryInterceptorBuilder
.stateless()
.maxAttempts(3)
.backOffOptions(1000, 2, 10000)
.build()
);
return containerFactory;
}
// ========== 队列配置 ==========
@Bean
public Queue productionQueue() {
return QueueBuilder
.durable("production.queue")
// 死信队列
.withArgument("x-dead-letter-exchange", "production.dlx")
.withArgument("x-dead-letter-routing-key", "production.dlq")
// 队列限制(防止内存溢出)
.withArgument("x-max-length", 100000)
.withArgument("x-max-length-bytes", 10737418240) // 10GB
// 惰性分发
.lazy()
// 主节点定位
.withArgument("x-queue-master-locator", "client-local")
.build();
}
} containerFactory.setAcknowledgeMode(AcknowledgeMode.MANUAL);`
`#/**
* 生产环境推荐配置
*
* 适用于:金融、电商等核心业务场景
*/
@Configuration
public class ProductionRabbitMQConfig {
// ========== 生产者配置 ==========
@Bean
public RabbitTemplate productionRabbitTemplate(ConnectionFactory factory) {
RabbitTemplate template = new RabbitTemplate(factory);
// 启用发布确认
template.setConfirmCallback((correlationData, ack, cause) -> {
if (!ack) {
log.error("消息发送失败: {}", cause);
// 触发告警和重试
}
});
// 启用返回确认(消息无法路由时)
template.setReturnsCallback(returned -> {
log.error("消息无法路由: {}", returned.getMessage());
// 记录到死信队列或告警
});
// 启用消息强制回调
template.setMandatory(true);
return template;
}
// ========== 消费者配置 ==========
@Bean
public SimpleRabbitListenerContainerFactory productionContainerFactory(
ConnectionFactory factory) {
SimpleRabbitListenerContainerFactory containerFactory =
new SimpleRabbitListenerContainerFactory();
containerFactory.setConnectionFactory(factory);
// 手动确认
containerFactory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 公平分发
containerFactory.setPrefetch(1);
// 并发消费者数量
containerFactory.setConcurrentConsumers(5);
containerFactory.setMaxConcurrentConsumers(20);
// 重试配置
containerFactory.setAdviceChain(
RetryInterceptorBuilder
.stateless()
.maxAttempts(3)
.backOffOptions(1000, 2, 10000)
.build()
);
return containerFactory;
}
// ========== 队列配置 ==========
@Bean
public Queue productionQueue() {
return QueueBuilder
.durable("production.queue")
// 死信队列
.withArgument("x-dead-letter-exchange", "production.dlx")
.withArgument("x-dead-letter-routing-key", "production.dlq")
// 队列限制(防止内存溢出)
.withArgument("x-max-length", 100000)
.withArgument("x-max-length-bytes", 10737418240) // 10GB
// 惰性分发
.lazy()
// 主节点定位
.withArgument("x-queue-master-locator", "client-local")
.build();
}
} `
`#/**
* 生产环境推荐配置
*
* 适用于:金融、电商等核心业务场景
*/
@Configuration
public class ProductionRabbitMQConfig {
// ========== 生产者配置 ==========
@Bean
public RabbitTemplate productionRabbitTemplate(ConnectionFactory factory) {
RabbitTemplate template = new RabbitTemplate(factory);
// 启用发布确认
template.setConfirmCallback((correlationData, ack, cause) -> {
if (!ack) {
log.error("消息发送失败: {}", cause);
// 触发告警和重试
}
});
// 启用返回确认(消息无法路由时)
template.setReturnsCallback(returned -> {
log.error("消息无法路由: {}", returned.getMessage());
// 记录到死信队列或告警
});
// 启用消息强制回调
template.setMandatory(true);
return template;
}
// ========== 消费者配置 ==========
@Bean
public SimpleRabbitListenerContainerFactory productionContainerFactory(
ConnectionFactory factory) {
SimpleRabbitListenerContainerFactory containerFactory =
new SimpleRabbitListenerContainerFactory();
containerFactory.setConnectionFactory(factory);
// 手动确认
containerFactory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 公平分发
containerFactory.setPrefetch(1);
// 并发消费者数量
containerFactory.setConcurrentConsumers(5);
containerFactory.setMaxConcurrentConsumers(20);
// 重试配置
containerFactory.setAdviceChain(
RetryInterceptorBuilder
.stateless()
.maxAttempts(3)
.backOffOptions(1000, 2, 10000)
.build()
);
return containerFactory;
}
// ========== 队列配置 ==========
@Bean
public Queue productionQueue() {
return QueueBuilder
.durable("production.queue")
// 死信队列
.withArgument("x-dead-letter-exchange", "production.dlx")
.withArgument("x-dead-letter-routing-key", "production.dlq")
// 队列限制(防止内存溢出)
.withArgument("x-max-length", 100000)
.withArgument("x-max-length-bytes", 10737418240) // 10GB
// 惰性分发
.lazy()
// 主节点定位
.withArgument("x-queue-master-locator", "client-local")
.build();
}
} // 公平分发`
`#/**
* 生产环境推荐配置
*
* 适用于:金融、电商等核心业务场景
*/
@Configuration
public class ProductionRabbitMQConfig {
// ========== 生产者配置 ==========
@Bean
public RabbitTemplate productionRabbitTemplate(ConnectionFactory factory) {
RabbitTemplate template = new RabbitTemplate(factory);
// 启用发布确认
template.setConfirmCallback((correlationData, ack, cause) -> {
if (!ack) {
log.error("消息发送失败: {}", cause);
// 触发告警和重试
}
});
// 启用返回确认(消息无法路由时)
template.setReturnsCallback(returned -> {
log.error("消息无法路由: {}", returned.getMessage());
// 记录到死信队列或告警
});
// 启用消息强制回调
template.setMandatory(true);
return template;
}
// ========== 消费者配置 ==========
@Bean
public SimpleRabbitListenerContainerFactory productionContainerFactory(
ConnectionFactory factory) {
SimpleRabbitListenerContainerFactory containerFactory =
new SimpleRabbitListenerContainerFactory();
containerFactory.setConnectionFactory(factory);
// 手动确认
containerFactory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 公平分发
containerFactory.setPrefetch(1);
// 并发消费者数量
containerFactory.setConcurrentConsumers(5);
containerFactory.setMaxConcurrentConsumers(20);
// 重试配置
containerFactory.setAdviceChain(
RetryInterceptorBuilder
.stateless()
.maxAttempts(3)
.backOffOptions(1000, 2, 10000)
.build()
);
return containerFactory;
}
// ========== 队列配置 ==========
@Bean
public Queue productionQueue() {
return QueueBuilder
.durable("production.queue")
// 死信队列
.withArgument("x-dead-letter-exchange", "production.dlx")
.withArgument("x-dead-letter-routing-key", "production.dlq")
// 队列限制(防止内存溢出)
.withArgument("x-max-length", 100000)
.withArgument("x-max-length-bytes", 10737418240) // 10GB
// 惰性分发
.lazy()
// 主节点定位
.withArgument("x-queue-master-locator", "client-local")
.build();
}
} containerFactory.setPrefetch(1);`
`#/**
* 生产环境推荐配置
*
* 适用于:金融、电商等核心业务场景
*/
@Configuration
public class ProductionRabbitMQConfig {
// ========== 生产者配置 ==========
@Bean
public RabbitTemplate productionRabbitTemplate(ConnectionFactory factory) {
RabbitTemplate template = new RabbitTemplate(factory);
// 启用发布确认
template.setConfirmCallback((correlationData, ack, cause) -> {
if (!ack) {
log.error("消息发送失败: {}", cause);
// 触发告警和重试
}
});
// 启用返回确认(消息无法路由时)
template.setReturnsCallback(returned -> {
log.error("消息无法路由: {}", returned.getMessage());
// 记录到死信队列或告警
});
// 启用消息强制回调
template.setMandatory(true);
return template;
}
// ========== 消费者配置 ==========
@Bean
public SimpleRabbitListenerContainerFactory productionContainerFactory(
ConnectionFactory factory) {
SimpleRabbitListenerContainerFactory containerFactory =
new SimpleRabbitListenerContainerFactory();
containerFactory.setConnectionFactory(factory);
// 手动确认
containerFactory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 公平分发
containerFactory.setPrefetch(1);
// 并发消费者数量
containerFactory.setConcurrentConsumers(5);
containerFactory.setMaxConcurrentConsumers(20);
// 重试配置
containerFactory.setAdviceChain(
RetryInterceptorBuilder
.stateless()
.maxAttempts(3)
.backOffOptions(1000, 2, 10000)
.build()
);
return containerFactory;
}
// ========== 队列配置 ==========
@Bean
public Queue productionQueue() {
return QueueBuilder
.durable("production.queue")
// 死信队列
.withArgument("x-dead-letter-exchange", "production.dlx")
.withArgument("x-dead-letter-routing-key", "production.dlq")
// 队列限制(防止内存溢出)
.withArgument("x-max-length", 100000)
.withArgument("x-max-length-bytes", 10737418240) // 10GB
// 惰性分发
.lazy()
// 主节点定位
.withArgument("x-queue-master-locator", "client-local")
.build();
}
} `
`#/**
* 生产环境推荐配置
*
* 适用于:金融、电商等核心业务场景
*/
@Configuration
public class ProductionRabbitMQConfig {
// ========== 生产者配置 ==========
@Bean
public RabbitTemplate productionRabbitTemplate(ConnectionFactory factory) {
RabbitTemplate template = new RabbitTemplate(factory);
// 启用发布确认
template.setConfirmCallback((correlationData, ack, cause) -> {
if (!ack) {
log.error("消息发送失败: {}", cause);
// 触发告警和重试
}
});
// 启用返回确认(消息无法路由时)
template.setReturnsCallback(returned -> {
log.error("消息无法路由: {}", returned.getMessage());
// 记录到死信队列或告警
});
// 启用消息强制回调
template.setMandatory(true);
return template;
}
// ========== 消费者配置 ==========
@Bean
public SimpleRabbitListenerContainerFactory productionContainerFactory(
ConnectionFactory factory) {
SimpleRabbitListenerContainerFactory containerFactory =
new SimpleRabbitListenerContainerFactory();
containerFactory.setConnectionFactory(factory);
// 手动确认
containerFactory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 公平分发
containerFactory.setPrefetch(1);
// 并发消费者数量
containerFactory.setConcurrentConsumers(5);
containerFactory.setMaxConcurrentConsumers(20);
// 重试配置
containerFactory.setAdviceChain(
RetryInterceptorBuilder
.stateless()
.maxAttempts(3)
.backOffOptions(1000, 2, 10000)
.build()
);
return containerFactory;
}
// ========== 队列配置 ==========
@Bean
public Queue productionQueue() {
return QueueBuilder
.durable("production.queue")
// 死信队列
.withArgument("x-dead-letter-exchange", "production.dlx")
.withArgument("x-dead-letter-routing-key", "production.dlq")
// 队列限制(防止内存溢出)
.withArgument("x-max-length", 100000)
.withArgument("x-max-length-bytes", 10737418240) // 10GB
// 惰性分发
.lazy()
// 主节点定位
.withArgument("x-queue-master-locator", "client-local")
.build();
}
} // 并发消费者数量`
`#/**
* 生产环境推荐配置
*
* 适用于:金融、电商等核心业务场景
*/
@Configuration
public class ProductionRabbitMQConfig {
// ========== 生产者配置 ==========
@Bean
public RabbitTemplate productionRabbitTemplate(ConnectionFactory factory) {
RabbitTemplate template = new RabbitTemplate(factory);
// 启用发布确认
template.setConfirmCallback((correlationData, ack, cause) -> {
if (!ack) {
log.error("消息发送失败: {}", cause);
// 触发告警和重试
}
});
// 启用返回确认(消息无法路由时)
template.setReturnsCallback(returned -> {
log.error("消息无法路由: {}", returned.getMessage());
// 记录到死信队列或告警
});
// 启用消息强制回调
template.setMandatory(true);
return template;
}
// ========== 消费者配置 ==========
@Bean
public SimpleRabbitListenerContainerFactory productionContainerFactory(
ConnectionFactory factory) {
SimpleRabbitListenerContainerFactory containerFactory =
new SimpleRabbitListenerContainerFactory();
containerFactory.setConnectionFactory(factory);
// 手动确认
containerFactory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 公平分发
containerFactory.setPrefetch(1);
// 并发消费者数量
containerFactory.setConcurrentConsumers(5);
containerFactory.setMaxConcurrentConsumers(20);
// 重试配置
containerFactory.setAdviceChain(
RetryInterceptorBuilder
.stateless()
.maxAttempts(3)
.backOffOptions(1000, 2, 10000)
.build()
);
return containerFactory;
}
// ========== 队列配置 ==========
@Bean
public Queue productionQueue() {
return QueueBuilder
.durable("production.queue")
// 死信队列
.withArgument("x-dead-letter-exchange", "production.dlx")
.withArgument("x-dead-letter-routing-key", "production.dlq")
// 队列限制(防止内存溢出)
.withArgument("x-max-length", 100000)
.withArgument("x-max-length-bytes", 10737418240) // 10GB
// 惰性分发
.lazy()
// 主节点定位
.withArgument("x-queue-master-locator", "client-local")
.build();
}
} containerFactory.setConcurrentConsumers(5);`
`#/**
* 生产环境推荐配置
*
* 适用于:金融、电商等核心业务场景
*/
@Configuration
public class ProductionRabbitMQConfig {
// ========== 生产者配置 ==========
@Bean
public RabbitTemplate productionRabbitTemplate(ConnectionFactory factory) {
RabbitTemplate template = new RabbitTemplate(factory);
// 启用发布确认
template.setConfirmCallback((correlationData, ack, cause) -> {
if (!ack) {
log.error("消息发送失败: {}", cause);
// 触发告警和重试
}
});
// 启用返回确认(消息无法路由时)
template.setReturnsCallback(returned -> {
log.error("消息无法路由: {}", returned.getMessage());
// 记录到死信队列或告警
});
// 启用消息强制回调
template.setMandatory(true);
return template;
}
// ========== 消费者配置 ==========
@Bean
public SimpleRabbitListenerContainerFactory productionContainerFactory(
ConnectionFactory factory) {
SimpleRabbitListenerContainerFactory containerFactory =
new SimpleRabbitListenerContainerFactory();
containerFactory.setConnectionFactory(factory);
// 手动确认
containerFactory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 公平分发
containerFactory.setPrefetch(1);
// 并发消费者数量
containerFactory.setConcurrentConsumers(5);
containerFactory.setMaxConcurrentConsumers(20);
// 重试配置
containerFactory.setAdviceChain(
RetryInterceptorBuilder
.stateless()
.maxAttempts(3)
.backOffOptions(1000, 2, 10000)
.build()
);
return containerFactory;
}
// ========== 队列配置 ==========
@Bean
public Queue productionQueue() {
return QueueBuilder
.durable("production.queue")
// 死信队列
.withArgument("x-dead-letter-exchange", "production.dlx")
.withArgument("x-dead-letter-routing-key", "production.dlq")
// 队列限制(防止内存溢出)
.withArgument("x-max-length", 100000)
.withArgument("x-max-length-bytes", 10737418240) // 10GB
// 惰性分发
.lazy()
// 主节点定位
.withArgument("x-queue-master-locator", "client-local")
.build();
}
} containerFactory.setMaxConcurrentConsumers(20);`
`#/**
* 生产环境推荐配置
*
* 适用于:金融、电商等核心业务场景
*/
@Configuration
public class ProductionRabbitMQConfig {
// ========== 生产者配置 ==========
@Bean
public RabbitTemplate productionRabbitTemplate(ConnectionFactory factory) {
RabbitTemplate template = new RabbitTemplate(factory);
// 启用发布确认
template.setConfirmCallback((correlationData, ack, cause) -> {
if (!ack) {
log.error("消息发送失败: {}", cause);
// 触发告警和重试
}
});
// 启用返回确认(消息无法路由时)
template.setReturnsCallback(returned -> {
log.error("消息无法路由: {}", returned.getMessage());
// 记录到死信队列或告警
});
// 启用消息强制回调
template.setMandatory(true);
return template;
}
// ========== 消费者配置 ==========
@Bean
public SimpleRabbitListenerContainerFactory productionContainerFactory(
ConnectionFactory factory) {
SimpleRabbitListenerContainerFactory containerFactory =
new SimpleRabbitListenerContainerFactory();
containerFactory.setConnectionFactory(factory);
// 手动确认
containerFactory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 公平分发
containerFactory.setPrefetch(1);
// 并发消费者数量
containerFactory.setConcurrentConsumers(5);
containerFactory.setMaxConcurrentConsumers(20);
// 重试配置
containerFactory.setAdviceChain(
RetryInterceptorBuilder
.stateless()
.maxAttempts(3)
.backOffOptions(1000, 2, 10000)
.build()
);
return containerFactory;
}
// ========== 队列配置 ==========
@Bean
public Queue productionQueue() {
return QueueBuilder
.durable("production.queue")
// 死信队列
.withArgument("x-dead-letter-exchange", "production.dlx")
.withArgument("x-dead-letter-routing-key", "production.dlq")
// 队列限制(防止内存溢出)
.withArgument("x-max-length", 100000)
.withArgument("x-max-length-bytes", 10737418240) // 10GB
// 惰性分发
.lazy()
// 主节点定位
.withArgument("x-queue-master-locator", "client-local")
.build();
}
} `
`#/**
* 生产环境推荐配置
*
* 适用于:金融、电商等核心业务场景
*/
@Configuration
public class ProductionRabbitMQConfig {
// ========== 生产者配置 ==========
@Bean
public RabbitTemplate productionRabbitTemplate(ConnectionFactory factory) {
RabbitTemplate template = new RabbitTemplate(factory);
// 启用发布确认
template.setConfirmCallback((correlationData, ack, cause) -> {
if (!ack) {
log.error("消息发送失败: {}", cause);
// 触发告警和重试
}
});
// 启用返回确认(消息无法路由时)
template.setReturnsCallback(returned -> {
log.error("消息无法路由: {}", returned.getMessage());
// 记录到死信队列或告警
});
// 启用消息强制回调
template.setMandatory(true);
return template;
}
// ========== 消费者配置 ==========
@Bean
public SimpleRabbitListenerContainerFactory productionContainerFactory(
ConnectionFactory factory) {
SimpleRabbitListenerContainerFactory containerFactory =
new SimpleRabbitListenerContainerFactory();
containerFactory.setConnectionFactory(factory);
// 手动确认
containerFactory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 公平分发
containerFactory.setPrefetch(1);
// 并发消费者数量
containerFactory.setConcurrentConsumers(5);
containerFactory.setMaxConcurrentConsumers(20);
// 重试配置
containerFactory.setAdviceChain(
RetryInterceptorBuilder
.stateless()
.maxAttempts(3)
.backOffOptions(1000, 2, 10000)
.build()
);
return containerFactory;
}
// ========== 队列配置 ==========
@Bean
public Queue productionQueue() {
return QueueBuilder
.durable("production.queue")
// 死信队列
.withArgument("x-dead-letter-exchange", "production.dlx")
.withArgument("x-dead-letter-routing-key", "production.dlq")
// 队列限制(防止内存溢出)
.withArgument("x-max-length", 100000)
.withArgument("x-max-length-bytes", 10737418240) // 10GB
// 惰性分发
.lazy()
// 主节点定位
.withArgument("x-queue-master-locator", "client-local")
.build();
}
} // 重试配置`
`#/**
* 生产环境推荐配置
*
* 适用于:金融、电商等核心业务场景
*/
@Configuration
public class ProductionRabbitMQConfig {
// ========== 生产者配置 ==========
@Bean
public RabbitTemplate productionRabbitTemplate(ConnectionFactory factory) {
RabbitTemplate template = new RabbitTemplate(factory);
// 启用发布确认
template.setConfirmCallback((correlationData, ack, cause) -> {
if (!ack) {
log.error("消息发送失败: {}", cause);
// 触发告警和重试
}
});
// 启用返回确认(消息无法路由时)
template.setReturnsCallback(returned -> {
log.error("消息无法路由: {}", returned.getMessage());
// 记录到死信队列或告警
});
// 启用消息强制回调
template.setMandatory(true);
return template;
}
// ========== 消费者配置 ==========
@Bean
public SimpleRabbitListenerContainerFactory productionContainerFactory(
ConnectionFactory factory) {
SimpleRabbitListenerContainerFactory containerFactory =
new SimpleRabbitListenerContainerFactory();
containerFactory.setConnectionFactory(factory);
// 手动确认
containerFactory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 公平分发
containerFactory.setPrefetch(1);
// 并发消费者数量
containerFactory.setConcurrentConsumers(5);
containerFactory.setMaxConcurrentConsumers(20);
// 重试配置
containerFactory.setAdviceChain(
RetryInterceptorBuilder
.stateless()
.maxAttempts(3)
.backOffOptions(1000, 2, 10000)
.build()
);
return containerFactory;
}
// ========== 队列配置 ==========
@Bean
public Queue productionQueue() {
return QueueBuilder
.durable("production.queue")
// 死信队列
.withArgument("x-dead-letter-exchange", "production.dlx")
.withArgument("x-dead-letter-routing-key", "production.dlq")
// 队列限制(防止内存溢出)
.withArgument("x-max-length", 100000)
.withArgument("x-max-length-bytes", 10737418240) // 10GB
// 惰性分发
.lazy()
// 主节点定位
.withArgument("x-queue-master-locator", "client-local")
.build();
}
} containerFactory.setAdviceChain(`
`#/**
* 生产环境推荐配置
*
* 适用于:金融、电商等核心业务场景
*/
@Configuration
public class ProductionRabbitMQConfig {
// ========== 生产者配置 ==========
@Bean
public RabbitTemplate productionRabbitTemplate(ConnectionFactory factory) {
RabbitTemplate template = new RabbitTemplate(factory);
// 启用发布确认
template.setConfirmCallback((correlationData, ack, cause) -> {
if (!ack) {
log.error("消息发送失败: {}", cause);
// 触发告警和重试
}
});
// 启用返回确认(消息无法路由时)
template.setReturnsCallback(returned -> {
log.error("消息无法路由: {}", returned.getMessage());
// 记录到死信队列或告警
});
// 启用消息强制回调
template.setMandatory(true);
return template;
}
// ========== 消费者配置 ==========
@Bean
public SimpleRabbitListenerContainerFactory productionContainerFactory(
ConnectionFactory factory) {
SimpleRabbitListenerContainerFactory containerFactory =
new SimpleRabbitListenerContainerFactory();
containerFactory.setConnectionFactory(factory);
// 手动确认
containerFactory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 公平分发
containerFactory.setPrefetch(1);
// 并发消费者数量
containerFactory.setConcurrentConsumers(5);
containerFactory.setMaxConcurrentConsumers(20);
// 重试配置
containerFactory.setAdviceChain(
RetryInterceptorBuilder
.stateless()
.maxAttempts(3)
.backOffOptions(1000, 2, 10000)
.build()
);
return containerFactory;
}
// ========== 队列配置 ==========
@Bean
public Queue productionQueue() {
return QueueBuilder
.durable("production.queue")
// 死信队列
.withArgument("x-dead-letter-exchange", "production.dlx")
.withArgument("x-dead-letter-routing-key", "production.dlq")
// 队列限制(防止内存溢出)
.withArgument("x-max-length", 100000)
.withArgument("x-max-length-bytes", 10737418240) // 10GB
// 惰性分发
.lazy()
// 主节点定位
.withArgument("x-queue-master-locator", "client-local")
.build();
}
} RetryInterceptorBuilder`
`#/**
* 生产环境推荐配置
*
* 适用于:金融、电商等核心业务场景
*/
@Configuration
public class ProductionRabbitMQConfig {
// ========== 生产者配置 ==========
@Bean
public RabbitTemplate productionRabbitTemplate(ConnectionFactory factory) {
RabbitTemplate template = new RabbitTemplate(factory);
// 启用发布确认
template.setConfirmCallback((correlationData, ack, cause) -> {
if (!ack) {
log.error("消息发送失败: {}", cause);
// 触发告警和重试
}
});
// 启用返回确认(消息无法路由时)
template.setReturnsCallback(returned -> {
log.error("消息无法路由: {}", returned.getMessage());
// 记录到死信队列或告警
});
// 启用消息强制回调
template.setMandatory(true);
return template;
}
// ========== 消费者配置 ==========
@Bean
public SimpleRabbitListenerContainerFactory productionContainerFactory(
ConnectionFactory factory) {
SimpleRabbitListenerContainerFactory containerFactory =
new SimpleRabbitListenerContainerFactory();
containerFactory.setConnectionFactory(factory);
// 手动确认
containerFactory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 公平分发
containerFactory.setPrefetch(1);
// 并发消费者数量
containerFactory.setConcurrentConsumers(5);
containerFactory.setMaxConcurrentConsumers(20);
// 重试配置
containerFactory.setAdviceChain(
RetryInterceptorBuilder
.stateless()
.maxAttempts(3)
.backOffOptions(1000, 2, 10000)
.build()
);
return containerFactory;
}
// ========== 队列配置 ==========
@Bean
public Queue productionQueue() {
return QueueBuilder
.durable("production.queue")
// 死信队列
.withArgument("x-dead-letter-exchange", "production.dlx")
.withArgument("x-dead-letter-routing-key", "production.dlq")
// 队列限制(防止内存溢出)
.withArgument("x-max-length", 100000)
.withArgument("x-max-length-bytes", 10737418240) // 10GB
// 惰性分发
.lazy()
// 主节点定位
.withArgument("x-queue-master-locator", "client-local")
.build();
}
} .stateless()`
`#/**
* 生产环境推荐配置
*
* 适用于:金融、电商等核心业务场景
*/
@Configuration
public class ProductionRabbitMQConfig {
// ========== 生产者配置 ==========
@Bean
public RabbitTemplate productionRabbitTemplate(ConnectionFactory factory) {
RabbitTemplate template = new RabbitTemplate(factory);
// 启用发布确认
template.setConfirmCallback((correlationData, ack, cause) -> {
if (!ack) {
log.error("消息发送失败: {}", cause);
// 触发告警和重试
}
});
// 启用返回确认(消息无法路由时)
template.setReturnsCallback(returned -> {
log.error("消息无法路由: {}", returned.getMessage());
// 记录到死信队列或告警
});
// 启用消息强制回调
template.setMandatory(true);
return template;
}
// ========== 消费者配置 ==========
@Bean
public SimpleRabbitListenerContainerFactory productionContainerFactory(
ConnectionFactory factory) {
SimpleRabbitListenerContainerFactory containerFactory =
new SimpleRabbitListenerContainerFactory();
containerFactory.setConnectionFactory(factory);
// 手动确认
containerFactory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 公平分发
containerFactory.setPrefetch(1);
// 并发消费者数量
containerFactory.setConcurrentConsumers(5);
containerFactory.setMaxConcurrentConsumers(20);
// 重试配置
containerFactory.setAdviceChain(
RetryInterceptorBuilder
.stateless()
.maxAttempts(3)
.backOffOptions(1000, 2, 10000)
.build()
);
return containerFactory;
}
// ========== 队列配置 ==========
@Bean
public Queue productionQueue() {
return QueueBuilder
.durable("production.queue")
// 死信队列
.withArgument("x-dead-letter-exchange", "production.dlx")
.withArgument("x-dead-letter-routing-key", "production.dlq")
// 队列限制(防止内存溢出)
.withArgument("x-max-length", 100000)
.withArgument("x-max-length-bytes", 10737418240) // 10GB
// 惰性分发
.lazy()
// 主节点定位
.withArgument("x-queue-master-locator", "client-local")
.build();
}
} .maxAttempts(3)`
`#/**
* 生产环境推荐配置
*
* 适用于:金融、电商等核心业务场景
*/
@Configuration
public class ProductionRabbitMQConfig {
// ========== 生产者配置 ==========
@Bean
public RabbitTemplate productionRabbitTemplate(ConnectionFactory factory) {
RabbitTemplate template = new RabbitTemplate(factory);
// 启用发布确认
template.setConfirmCallback((correlationData, ack, cause) -> {
if (!ack) {
log.error("消息发送失败: {}", cause);
// 触发告警和重试
}
});
// 启用返回确认(消息无法路由时)
template.setReturnsCallback(returned -> {
log.error("消息无法路由: {}", returned.getMessage());
// 记录到死信队列或告警
});
// 启用消息强制回调
template.setMandatory(true);
return template;
}
// ========== 消费者配置 ==========
@Bean
public SimpleRabbitListenerContainerFactory productionContainerFactory(
ConnectionFactory factory) {
SimpleRabbitListenerContainerFactory containerFactory =
new SimpleRabbitListenerContainerFactory();
containerFactory.setConnectionFactory(factory);
// 手动确认
containerFactory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 公平分发
containerFactory.setPrefetch(1);
// 并发消费者数量
containerFactory.setConcurrentConsumers(5);
containerFactory.setMaxConcurrentConsumers(20);
// 重试配置
containerFactory.setAdviceChain(
RetryInterceptorBuilder
.stateless()
.maxAttempts(3)
.backOffOptions(1000, 2, 10000)
.build()
);
return containerFactory;
}
// ========== 队列配置 ==========
@Bean
public Queue productionQueue() {
return QueueBuilder
.durable("production.queue")
// 死信队列
.withArgument("x-dead-letter-exchange", "production.dlx")
.withArgument("x-dead-letter-routing-key", "production.dlq")
// 队列限制(防止内存溢出)
.withArgument("x-max-length", 100000)
.withArgument("x-max-length-bytes", 10737418240) // 10GB
// 惰性分发
.lazy()
// 主节点定位
.withArgument("x-queue-master-locator", "client-local")
.build();
}
} .backOffOptions(1000, 2, 10000)`
`#/**
* 生产环境推荐配置
*
* 适用于:金融、电商等核心业务场景
*/
@Configuration
public class ProductionRabbitMQConfig {
// ========== 生产者配置 ==========
@Bean
public RabbitTemplate productionRabbitTemplate(ConnectionFactory factory) {
RabbitTemplate template = new RabbitTemplate(factory);
// 启用发布确认
template.setConfirmCallback((correlationData, ack, cause) -> {
if (!ack) {
log.error("消息发送失败: {}", cause);
// 触发告警和重试
}
});
// 启用返回确认(消息无法路由时)
template.setReturnsCallback(returned -> {
log.error("消息无法路由: {}", returned.getMessage());
// 记录到死信队列或告警
});
// 启用消息强制回调
template.setMandatory(true);
return template;
}
// ========== 消费者配置 ==========
@Bean
public SimpleRabbitListenerContainerFactory productionContainerFactory(
ConnectionFactory factory) {
SimpleRabbitListenerContainerFactory containerFactory =
new SimpleRabbitListenerContainerFactory();
containerFactory.setConnectionFactory(factory);
// 手动确认
containerFactory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 公平分发
containerFactory.setPrefetch(1);
// 并发消费者数量
containerFactory.setConcurrentConsumers(5);
containerFactory.setMaxConcurrentConsumers(20);
// 重试配置
containerFactory.setAdviceChain(
RetryInterceptorBuilder
.stateless()
.maxAttempts(3)
.backOffOptions(1000, 2, 10000)
.build()
);
return containerFactory;
}
// ========== 队列配置 ==========
@Bean
public Queue productionQueue() {
return QueueBuilder
.durable("production.queue")
// 死信队列
.withArgument("x-dead-letter-exchange", "production.dlx")
.withArgument("x-dead-letter-routing-key", "production.dlq")
// 队列限制(防止内存溢出)
.withArgument("x-max-length", 100000)
.withArgument("x-max-length-bytes", 10737418240) // 10GB
// 惰性分发
.lazy()
// 主节点定位
.withArgument("x-queue-master-locator", "client-local")
.build();
}
} .build()`
`#/**
* 生产环境推荐配置
*
* 适用于:金融、电商等核心业务场景
*/
@Configuration
public class ProductionRabbitMQConfig {
// ========== 生产者配置 ==========
@Bean
public RabbitTemplate productionRabbitTemplate(ConnectionFactory factory) {
RabbitTemplate template = new RabbitTemplate(factory);
// 启用发布确认
template.setConfirmCallback((correlationData, ack, cause) -> {
if (!ack) {
log.error("消息发送失败: {}", cause);
// 触发告警和重试
}
});
// 启用返回确认(消息无法路由时)
template.setReturnsCallback(returned -> {
log.error("消息无法路由: {}", returned.getMessage());
// 记录到死信队列或告警
});
// 启用消息强制回调
template.setMandatory(true);
return template;
}
// ========== 消费者配置 ==========
@Bean
public SimpleRabbitListenerContainerFactory productionContainerFactory(
ConnectionFactory factory) {
SimpleRabbitListenerContainerFactory containerFactory =
new SimpleRabbitListenerContainerFactory();
containerFactory.setConnectionFactory(factory);
// 手动确认
containerFactory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 公平分发
containerFactory.setPrefetch(1);
// 并发消费者数量
containerFactory.setConcurrentConsumers(5);
containerFactory.setMaxConcurrentConsumers(20);
// 重试配置
containerFactory.setAdviceChain(
RetryInterceptorBuilder
.stateless()
.maxAttempts(3)
.backOffOptions(1000, 2, 10000)
.build()
);
return containerFactory;
}
// ========== 队列配置 ==========
@Bean
public Queue productionQueue() {
return QueueBuilder
.durable("production.queue")
// 死信队列
.withArgument("x-dead-letter-exchange", "production.dlx")
.withArgument("x-dead-letter-routing-key", "production.dlq")
// 队列限制(防止内存溢出)
.withArgument("x-max-length", 100000)
.withArgument("x-max-length-bytes", 10737418240) // 10GB
// 惰性分发
.lazy()
// 主节点定位
.withArgument("x-queue-master-locator", "client-local")
.build();
}
} );`
`#/**
* 生产环境推荐配置
*
* 适用于:金融、电商等核心业务场景
*/
@Configuration
public class ProductionRabbitMQConfig {
// ========== 生产者配置 ==========
@Bean
public RabbitTemplate productionRabbitTemplate(ConnectionFactory factory) {
RabbitTemplate template = new RabbitTemplate(factory);
// 启用发布确认
template.setConfirmCallback((correlationData, ack, cause) -> {
if (!ack) {
log.error("消息发送失败: {}", cause);
// 触发告警和重试
}
});
// 启用返回确认(消息无法路由时)
template.setReturnsCallback(returned -> {
log.error("消息无法路由: {}", returned.getMessage());
// 记录到死信队列或告警
});
// 启用消息强制回调
template.setMandatory(true);
return template;
}
// ========== 消费者配置 ==========
@Bean
public SimpleRabbitListenerContainerFactory productionContainerFactory(
ConnectionFactory factory) {
SimpleRabbitListenerContainerFactory containerFactory =
new SimpleRabbitListenerContainerFactory();
containerFactory.setConnectionFactory(factory);
// 手动确认
containerFactory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 公平分发
containerFactory.setPrefetch(1);
// 并发消费者数量
containerFactory.setConcurrentConsumers(5);
containerFactory.setMaxConcurrentConsumers(20);
// 重试配置
containerFactory.setAdviceChain(
RetryInterceptorBuilder
.stateless()
.maxAttempts(3)
.backOffOptions(1000, 2, 10000)
.build()
);
return containerFactory;
}
// ========== 队列配置 ==========
@Bean
public Queue productionQueue() {
return QueueBuilder
.durable("production.queue")
// 死信队列
.withArgument("x-dead-letter-exchange", "production.dlx")
.withArgument("x-dead-letter-routing-key", "production.dlq")
// 队列限制(防止内存溢出)
.withArgument("x-max-length", 100000)
.withArgument("x-max-length-bytes", 10737418240) // 10GB
// 惰性分发
.lazy()
// 主节点定位
.withArgument("x-queue-master-locator", "client-local")
.build();
}
} `
`#/**
* 生产环境推荐配置
*
* 适用于:金融、电商等核心业务场景
*/
@Configuration
public class ProductionRabbitMQConfig {
// ========== 生产者配置 ==========
@Bean
public RabbitTemplate productionRabbitTemplate(ConnectionFactory factory) {
RabbitTemplate template = new RabbitTemplate(factory);
// 启用发布确认
template.setConfirmCallback((correlationData, ack, cause) -> {
if (!ack) {
log.error("消息发送失败: {}", cause);
// 触发告警和重试
}
});
// 启用返回确认(消息无法路由时)
template.setReturnsCallback(returned -> {
log.error("消息无法路由: {}", returned.getMessage());
// 记录到死信队列或告警
});
// 启用消息强制回调
template.setMandatory(true);
return template;
}
// ========== 消费者配置 ==========
@Bean
public SimpleRabbitListenerContainerFactory productionContainerFactory(
ConnectionFactory factory) {
SimpleRabbitListenerContainerFactory containerFactory =
new SimpleRabbitListenerContainerFactory();
containerFactory.setConnectionFactory(factory);
// 手动确认
containerFactory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 公平分发
containerFactory.setPrefetch(1);
// 并发消费者数量
containerFactory.setConcurrentConsumers(5);
containerFactory.setMaxConcurrentConsumers(20);
// 重试配置
containerFactory.setAdviceChain(
RetryInterceptorBuilder
.stateless()
.maxAttempts(3)
.backOffOptions(1000, 2, 10000)
.build()
);
return containerFactory;
}
// ========== 队列配置 ==========
@Bean
public Queue productionQueue() {
return QueueBuilder
.durable("production.queue")
// 死信队列
.withArgument("x-dead-letter-exchange", "production.dlx")
.withArgument("x-dead-letter-routing-key", "production.dlq")
// 队列限制(防止内存溢出)
.withArgument("x-max-length", 100000)
.withArgument("x-max-length-bytes", 10737418240) // 10GB
// 惰性分发
.lazy()
// 主节点定位
.withArgument("x-queue-master-locator", "client-local")
.build();
}
} return containerFactory;`
`#/**
* 生产环境推荐配置
*
* 适用于:金融、电商等核心业务场景
*/
@Configuration
public class ProductionRabbitMQConfig {
// ========== 生产者配置 ==========
@Bean
public RabbitTemplate productionRabbitTemplate(ConnectionFactory factory) {
RabbitTemplate template = new RabbitTemplate(factory);
// 启用发布确认
template.setConfirmCallback((correlationData, ack, cause) -> {
if (!ack) {
log.error("消息发送失败: {}", cause);
// 触发告警和重试
}
});
// 启用返回确认(消息无法路由时)
template.setReturnsCallback(returned -> {
log.error("消息无法路由: {}", returned.getMessage());
// 记录到死信队列或告警
});
// 启用消息强制回调
template.setMandatory(true);
return template;
}
// ========== 消费者配置 ==========
@Bean
public SimpleRabbitListenerContainerFactory productionContainerFactory(
ConnectionFactory factory) {
SimpleRabbitListenerContainerFactory containerFactory =
new SimpleRabbitListenerContainerFactory();
containerFactory.setConnectionFactory(factory);
// 手动确认
containerFactory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 公平分发
containerFactory.setPrefetch(1);
// 并发消费者数量
containerFactory.setConcurrentConsumers(5);
containerFactory.setMaxConcurrentConsumers(20);
// 重试配置
containerFactory.setAdviceChain(
RetryInterceptorBuilder
.stateless()
.maxAttempts(3)
.backOffOptions(1000, 2, 10000)
.build()
);
return containerFactory;
}
// ========== 队列配置 ==========
@Bean
public Queue productionQueue() {
return QueueBuilder
.durable("production.queue")
// 死信队列
.withArgument("x-dead-letter-exchange", "production.dlx")
.withArgument("x-dead-letter-routing-key", "production.dlq")
// 队列限制(防止内存溢出)
.withArgument("x-max-length", 100000)
.withArgument("x-max-length-bytes", 10737418240) // 10GB
// 惰性分发
.lazy()
// 主节点定位
.withArgument("x-queue-master-locator", "client-local")
.build();
}
} }`
`#/**
* 生产环境推荐配置
*
* 适用于:金融、电商等核心业务场景
*/
@Configuration
public class ProductionRabbitMQConfig {
// ========== 生产者配置 ==========
@Bean
public RabbitTemplate productionRabbitTemplate(ConnectionFactory factory) {
RabbitTemplate template = new RabbitTemplate(factory);
// 启用发布确认
template.setConfirmCallback((correlationData, ack, cause) -> {
if (!ack) {
log.error("消息发送失败: {}", cause);
// 触发告警和重试
}
});
// 启用返回确认(消息无法路由时)
template.setReturnsCallback(returned -> {
log.error("消息无法路由: {}", returned.getMessage());
// 记录到死信队列或告警
});
// 启用消息强制回调
template.setMandatory(true);
return template;
}
// ========== 消费者配置 ==========
@Bean
public SimpleRabbitListenerContainerFactory productionContainerFactory(
ConnectionFactory factory) {
SimpleRabbitListenerContainerFactory containerFactory =
new SimpleRabbitListenerContainerFactory();
containerFactory.setConnectionFactory(factory);
// 手动确认
containerFactory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 公平分发
containerFactory.setPrefetch(1);
// 并发消费者数量
containerFactory.setConcurrentConsumers(5);
containerFactory.setMaxConcurrentConsumers(20);
// 重试配置
containerFactory.setAdviceChain(
RetryInterceptorBuilder
.stateless()
.maxAttempts(3)
.backOffOptions(1000, 2, 10000)
.build()
);
return containerFactory;
}
// ========== 队列配置 ==========
@Bean
public Queue productionQueue() {
return QueueBuilder
.durable("production.queue")
// 死信队列
.withArgument("x-dead-letter-exchange", "production.dlx")
.withArgument("x-dead-letter-routing-key", "production.dlq")
// 队列限制(防止内存溢出)
.withArgument("x-max-length", 100000)
.withArgument("x-max-length-bytes", 10737418240) // 10GB
// 惰性分发
.lazy()
// 主节点定位
.withArgument("x-queue-master-locator", "client-local")
.build();
}
}`
`#/**
* 生产环境推荐配置
*
* 适用于:金融、电商等核心业务场景
*/
@Configuration
public class ProductionRabbitMQConfig {
// ========== 生产者配置 ==========
@Bean
public RabbitTemplate productionRabbitTemplate(ConnectionFactory factory) {
RabbitTemplate template = new RabbitTemplate(factory);
// 启用发布确认
template.setConfirmCallback((correlationData, ack, cause) -> {
if (!ack) {
log.error("消息发送失败: {}", cause);
// 触发告警和重试
}
});
// 启用返回确认(消息无法路由时)
template.setReturnsCallback(returned -> {
log.error("消息无法路由: {}", returned.getMessage());
// 记录到死信队列或告警
});
// 启用消息强制回调
template.setMandatory(true);
return template;
}
// ========== 消费者配置 ==========
@Bean
public SimpleRabbitListenerContainerFactory productionContainerFactory(
ConnectionFactory factory) {
SimpleRabbitListenerContainerFactory containerFactory =
new SimpleRabbitListenerContainerFactory();
containerFactory.setConnectionFactory(factory);
// 手动确认
containerFactory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 公平分发
containerFactory.setPrefetch(1);
// 并发消费者数量
containerFactory.setConcurrentConsumers(5);
containerFactory.setMaxConcurrentConsumers(20);
// 重试配置
containerFactory.setAdviceChain(
RetryInterceptorBuilder
.stateless()
.maxAttempts(3)
.backOffOptions(1000, 2, 10000)
.build()
);
return containerFactory;
}
// ========== 队列配置 ==========
@Bean
public Queue productionQueue() {
return QueueBuilder
.durable("production.queue")
// 死信队列
.withArgument("x-dead-letter-exchange", "production.dlx")
.withArgument("x-dead-letter-routing-key", "production.dlq")
// 队列限制(防止内存溢出)
.withArgument("x-max-length", 100000)
.withArgument("x-max-length-bytes", 10737418240) // 10GB
// 惰性分发
.lazy()
// 主节点定位
.withArgument("x-queue-master-locator", "client-local")
.build();
}
} // ========== 队列配置 ==========`
`#/**
* 生产环境推荐配置
*
* 适用于:金融、电商等核心业务场景
*/
@Configuration
public class ProductionRabbitMQConfig {
// ========== 生产者配置 ==========
@Bean
public RabbitTemplate productionRabbitTemplate(ConnectionFactory factory) {
RabbitTemplate template = new RabbitTemplate(factory);
// 启用发布确认
template.setConfirmCallback((correlationData, ack, cause) -> {
if (!ack) {
log.error("消息发送失败: {}", cause);
// 触发告警和重试
}
});
// 启用返回确认(消息无法路由时)
template.setReturnsCallback(returned -> {
log.error("消息无法路由: {}", returned.getMessage());
// 记录到死信队列或告警
});
// 启用消息强制回调
template.setMandatory(true);
return template;
}
// ========== 消费者配置 ==========
@Bean
public SimpleRabbitListenerContainerFactory productionContainerFactory(
ConnectionFactory factory) {
SimpleRabbitListenerContainerFactory containerFactory =
new SimpleRabbitListenerContainerFactory();
containerFactory.setConnectionFactory(factory);
// 手动确认
containerFactory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 公平分发
containerFactory.setPrefetch(1);
// 并发消费者数量
containerFactory.setConcurrentConsumers(5);
containerFactory.setMaxConcurrentConsumers(20);
// 重试配置
containerFactory.setAdviceChain(
RetryInterceptorBuilder
.stateless()
.maxAttempts(3)
.backOffOptions(1000, 2, 10000)
.build()
);
return containerFactory;
}
// ========== 队列配置 ==========
@Bean
public Queue productionQueue() {
return QueueBuilder
.durable("production.queue")
// 死信队列
.withArgument("x-dead-letter-exchange", "production.dlx")
.withArgument("x-dead-letter-routing-key", "production.dlq")
// 队列限制(防止内存溢出)
.withArgument("x-max-length", 100000)
.withArgument("x-max-length-bytes", 10737418240) // 10GB
// 惰性分发
.lazy()
// 主节点定位
.withArgument("x-queue-master-locator", "client-local")
.build();
}
} `
`#/**
* 生产环境推荐配置
*
* 适用于:金融、电商等核心业务场景
*/
@Configuration
public class ProductionRabbitMQConfig {
// ========== 生产者配置 ==========
@Bean
public RabbitTemplate productionRabbitTemplate(ConnectionFactory factory) {
RabbitTemplate template = new RabbitTemplate(factory);
// 启用发布确认
template.setConfirmCallback((correlationData, ack, cause) -> {
if (!ack) {
log.error("消息发送失败: {}", cause);
// 触发告警和重试
}
});
// 启用返回确认(消息无法路由时)
template.setReturnsCallback(returned -> {
log.error("消息无法路由: {}", returned.getMessage());
// 记录到死信队列或告警
});
// 启用消息强制回调
template.setMandatory(true);
return template;
}
// ========== 消费者配置 ==========
@Bean
public SimpleRabbitListenerContainerFactory productionContainerFactory(
ConnectionFactory factory) {
SimpleRabbitListenerContainerFactory containerFactory =
new SimpleRabbitListenerContainerFactory();
containerFactory.setConnectionFactory(factory);
// 手动确认
containerFactory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 公平分发
containerFactory.setPrefetch(1);
// 并发消费者数量
containerFactory.setConcurrentConsumers(5);
containerFactory.setMaxConcurrentConsumers(20);
// 重试配置
containerFactory.setAdviceChain(
RetryInterceptorBuilder
.stateless()
.maxAttempts(3)
.backOffOptions(1000, 2, 10000)
.build()
);
return containerFactory;
}
// ========== 队列配置 ==========
@Bean
public Queue productionQueue() {
return QueueBuilder
.durable("production.queue")
// 死信队列
.withArgument("x-dead-letter-exchange", "production.dlx")
.withArgument("x-dead-letter-routing-key", "production.dlq")
// 队列限制(防止内存溢出)
.withArgument("x-max-length", 100000)
.withArgument("x-max-length-bytes", 10737418240) // 10GB
// 惰性分发
.lazy()
// 主节点定位
.withArgument("x-queue-master-locator", "client-local")
.build();
}
} @Bean`
`#/**
* 生产环境推荐配置
*
* 适用于:金融、电商等核心业务场景
*/
@Configuration
public class ProductionRabbitMQConfig {
// ========== 生产者配置 ==========
@Bean
public RabbitTemplate productionRabbitTemplate(ConnectionFactory factory) {
RabbitTemplate template = new RabbitTemplate(factory);
// 启用发布确认
template.setConfirmCallback((correlationData, ack, cause) -> {
if (!ack) {
log.error("消息发送失败: {}", cause);
// 触发告警和重试
}
});
// 启用返回确认(消息无法路由时)
template.setReturnsCallback(returned -> {
log.error("消息无法路由: {}", returned.getMessage());
// 记录到死信队列或告警
});
// 启用消息强制回调
template.setMandatory(true);
return template;
}
// ========== 消费者配置 ==========
@Bean
public SimpleRabbitListenerContainerFactory productionContainerFactory(
ConnectionFactory factory) {
SimpleRabbitListenerContainerFactory containerFactory =
new SimpleRabbitListenerContainerFactory();
containerFactory.setConnectionFactory(factory);
// 手动确认
containerFactory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 公平分发
containerFactory.setPrefetch(1);
// 并发消费者数量
containerFactory.setConcurrentConsumers(5);
containerFactory.setMaxConcurrentConsumers(20);
// 重试配置
containerFactory.setAdviceChain(
RetryInterceptorBuilder
.stateless()
.maxAttempts(3)
.backOffOptions(1000, 2, 10000)
.build()
);
return containerFactory;
}
// ========== 队列配置 ==========
@Bean
public Queue productionQueue() {
return QueueBuilder
.durable("production.queue")
// 死信队列
.withArgument("x-dead-letter-exchange", "production.dlx")
.withArgument("x-dead-letter-routing-key", "production.dlq")
// 队列限制(防止内存溢出)
.withArgument("x-max-length", 100000)
.withArgument("x-max-length-bytes", 10737418240) // 10GB
// 惰性分发
.lazy()
// 主节点定位
.withArgument("x-queue-master-locator", "client-local")
.build();
}
} public Queue productionQueue() {`
`#/**
* 生产环境推荐配置
*
* 适用于:金融、电商等核心业务场景
*/
@Configuration
public class ProductionRabbitMQConfig {
// ========== 生产者配置 ==========
@Bean
public RabbitTemplate productionRabbitTemplate(ConnectionFactory factory) {
RabbitTemplate template = new RabbitTemplate(factory);
// 启用发布确认
template.setConfirmCallback((correlationData, ack, cause) -> {
if (!ack) {
log.error("消息发送失败: {}", cause);
// 触发告警和重试
}
});
// 启用返回确认(消息无法路由时)
template.setReturnsCallback(returned -> {
log.error("消息无法路由: {}", returned.getMessage());
// 记录到死信队列或告警
});
// 启用消息强制回调
template.setMandatory(true);
return template;
}
// ========== 消费者配置 ==========
@Bean
public SimpleRabbitListenerContainerFactory productionContainerFactory(
ConnectionFactory factory) {
SimpleRabbitListenerContainerFactory containerFactory =
new SimpleRabbitListenerContainerFactory();
containerFactory.setConnectionFactory(factory);
// 手动确认
containerFactory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 公平分发
containerFactory.setPrefetch(1);
// 并发消费者数量
containerFactory.setConcurrentConsumers(5);
containerFactory.setMaxConcurrentConsumers(20);
// 重试配置
containerFactory.setAdviceChain(
RetryInterceptorBuilder
.stateless()
.maxAttempts(3)
.backOffOptions(1000, 2, 10000)
.build()
);
return containerFactory;
}
// ========== 队列配置 ==========
@Bean
public Queue productionQueue() {
return QueueBuilder
.durable("production.queue")
// 死信队列
.withArgument("x-dead-letter-exchange", "production.dlx")
.withArgument("x-dead-letter-routing-key", "production.dlq")
// 队列限制(防止内存溢出)
.withArgument("x-max-length", 100000)
.withArgument("x-max-length-bytes", 10737418240) // 10GB
// 惰性分发
.lazy()
// 主节点定位
.withArgument("x-queue-master-locator", "client-local")
.build();
}
} return QueueBuilder`
`#/**
* 生产环境推荐配置
*
* 适用于:金融、电商等核心业务场景
*/
@Configuration
public class ProductionRabbitMQConfig {
// ========== 生产者配置 ==========
@Bean
public RabbitTemplate productionRabbitTemplate(ConnectionFactory factory) {
RabbitTemplate template = new RabbitTemplate(factory);
// 启用发布确认
template.setConfirmCallback((correlationData, ack, cause) -> {
if (!ack) {
log.error("消息发送失败: {}", cause);
// 触发告警和重试
}
});
// 启用返回确认(消息无法路由时)
template.setReturnsCallback(returned -> {
log.error("消息无法路由: {}", returned.getMessage());
// 记录到死信队列或告警
});
// 启用消息强制回调
template.setMandatory(true);
return template;
}
// ========== 消费者配置 ==========
@Bean
public SimpleRabbitListenerContainerFactory productionContainerFactory(
ConnectionFactory factory) {
SimpleRabbitListenerContainerFactory containerFactory =
new SimpleRabbitListenerContainerFactory();
containerFactory.setConnectionFactory(factory);
// 手动确认
containerFactory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 公平分发
containerFactory.setPrefetch(1);
// 并发消费者数量
containerFactory.setConcurrentConsumers(5);
containerFactory.setMaxConcurrentConsumers(20);
// 重试配置
containerFactory.setAdviceChain(
RetryInterceptorBuilder
.stateless()
.maxAttempts(3)
.backOffOptions(1000, 2, 10000)
.build()
);
return containerFactory;
}
// ========== 队列配置 ==========
@Bean
public Queue productionQueue() {
return QueueBuilder
.durable("production.queue")
// 死信队列
.withArgument("x-dead-letter-exchange", "production.dlx")
.withArgument("x-dead-letter-routing-key", "production.dlq")
// 队列限制(防止内存溢出)
.withArgument("x-max-length", 100000)
.withArgument("x-max-length-bytes", 10737418240) // 10GB
// 惰性分发
.lazy()
// 主节点定位
.withArgument("x-queue-master-locator", "client-local")
.build();
}
} .durable("production.queue")`
`#/**
* 生产环境推荐配置
*
* 适用于:金融、电商等核心业务场景
*/
@Configuration
public class ProductionRabbitMQConfig {
// ========== 生产者配置 ==========
@Bean
public RabbitTemplate productionRabbitTemplate(ConnectionFactory factory) {
RabbitTemplate template = new RabbitTemplate(factory);
// 启用发布确认
template.setConfirmCallback((correlationData, ack, cause) -> {
if (!ack) {
log.error("消息发送失败: {}", cause);
// 触发告警和重试
}
});
// 启用返回确认(消息无法路由时)
template.setReturnsCallback(returned -> {
log.error("消息无法路由: {}", returned.getMessage());
// 记录到死信队列或告警
});
// 启用消息强制回调
template.setMandatory(true);
return template;
}
// ========== 消费者配置 ==========
@Bean
public SimpleRabbitListenerContainerFactory productionContainerFactory(
ConnectionFactory factory) {
SimpleRabbitListenerContainerFactory containerFactory =
new SimpleRabbitListenerContainerFactory();
containerFactory.setConnectionFactory(factory);
// 手动确认
containerFactory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 公平分发
containerFactory.setPrefetch(1);
// 并发消费者数量
containerFactory.setConcurrentConsumers(5);
containerFactory.setMaxConcurrentConsumers(20);
// 重试配置
containerFactory.setAdviceChain(
RetryInterceptorBuilder
.stateless()
.maxAttempts(3)
.backOffOptions(1000, 2, 10000)
.build()
);
return containerFactory;
}
// ========== 队列配置 ==========
@Bean
public Queue productionQueue() {
return QueueBuilder
.durable("production.queue")
// 死信队列
.withArgument("x-dead-letter-exchange", "production.dlx")
.withArgument("x-dead-letter-routing-key", "production.dlq")
// 队列限制(防止内存溢出)
.withArgument("x-max-length", 100000)
.withArgument("x-max-length-bytes", 10737418240) // 10GB
// 惰性分发
.lazy()
// 主节点定位
.withArgument("x-queue-master-locator", "client-local")
.build();
}
} // 死信队列`
`#/**
* 生产环境推荐配置
*
* 适用于:金融、电商等核心业务场景
*/
@Configuration
public class ProductionRabbitMQConfig {
// ========== 生产者配置 ==========
@Bean
public RabbitTemplate productionRabbitTemplate(ConnectionFactory factory) {
RabbitTemplate template = new RabbitTemplate(factory);
// 启用发布确认
template.setConfirmCallback((correlationData, ack, cause) -> {
if (!ack) {
log.error("消息发送失败: {}", cause);
// 触发告警和重试
}
});
// 启用返回确认(消息无法路由时)
template.setReturnsCallback(returned -> {
log.error("消息无法路由: {}", returned.getMessage());
// 记录到死信队列或告警
});
// 启用消息强制回调
template.setMandatory(true);
return template;
}
// ========== 消费者配置 ==========
@Bean
public SimpleRabbitListenerContainerFactory productionContainerFactory(
ConnectionFactory factory) {
SimpleRabbitListenerContainerFactory containerFactory =
new SimpleRabbitListenerContainerFactory();
containerFactory.setConnectionFactory(factory);
// 手动确认
containerFactory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 公平分发
containerFactory.setPrefetch(1);
// 并发消费者数量
containerFactory.setConcurrentConsumers(5);
containerFactory.setMaxConcurrentConsumers(20);
// 重试配置
containerFactory.setAdviceChain(
RetryInterceptorBuilder
.stateless()
.maxAttempts(3)
.backOffOptions(1000, 2, 10000)
.build()
);
return containerFactory;
}
// ========== 队列配置 ==========
@Bean
public Queue productionQueue() {
return QueueBuilder
.durable("production.queue")
// 死信队列
.withArgument("x-dead-letter-exchange", "production.dlx")
.withArgument("x-dead-letter-routing-key", "production.dlq")
// 队列限制(防止内存溢出)
.withArgument("x-max-length", 100000)
.withArgument("x-max-length-bytes", 10737418240) // 10GB
// 惰性分发
.lazy()
// 主节点定位
.withArgument("x-queue-master-locator", "client-local")
.build();
}
} .withArgument("x-dead-letter-exchange", "production.dlx")`
`#/**
* 生产环境推荐配置
*
* 适用于:金融、电商等核心业务场景
*/
@Configuration
public class ProductionRabbitMQConfig {
// ========== 生产者配置 ==========
@Bean
public RabbitTemplate productionRabbitTemplate(ConnectionFactory factory) {
RabbitTemplate template = new RabbitTemplate(factory);
// 启用发布确认
template.setConfirmCallback((correlationData, ack, cause) -> {
if (!ack) {
log.error("消息发送失败: {}", cause);
// 触发告警和重试
}
});
// 启用返回确认(消息无法路由时)
template.setReturnsCallback(returned -> {
log.error("消息无法路由: {}", returned.getMessage());
// 记录到死信队列或告警
});
// 启用消息强制回调
template.setMandatory(true);
return template;
}
// ========== 消费者配置 ==========
@Bean
public SimpleRabbitListenerContainerFactory productionContainerFactory(
ConnectionFactory factory) {
SimpleRabbitListenerContainerFactory containerFactory =
new SimpleRabbitListenerContainerFactory();
containerFactory.setConnectionFactory(factory);
// 手动确认
containerFactory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 公平分发
containerFactory.setPrefetch(1);
// 并发消费者数量
containerFactory.setConcurrentConsumers(5);
containerFactory.setMaxConcurrentConsumers(20);
// 重试配置
containerFactory.setAdviceChain(
RetryInterceptorBuilder
.stateless()
.maxAttempts(3)
.backOffOptions(1000, 2, 10000)
.build()
);
return containerFactory;
}
// ========== 队列配置 ==========
@Bean
public Queue productionQueue() {
return QueueBuilder
.durable("production.queue")
// 死信队列
.withArgument("x-dead-letter-exchange", "production.dlx")
.withArgument("x-dead-letter-routing-key", "production.dlq")
// 队列限制(防止内存溢出)
.withArgument("x-max-length", 100000)
.withArgument("x-max-length-bytes", 10737418240) // 10GB
// 惰性分发
.lazy()
// 主节点定位
.withArgument("x-queue-master-locator", "client-local")
.build();
}
} .withArgument("x-dead-letter-routing-key", "production.dlq")`
`#/**
* 生产环境推荐配置
*
* 适用于:金融、电商等核心业务场景
*/
@Configuration
public class ProductionRabbitMQConfig {
// ========== 生产者配置 ==========
@Bean
public RabbitTemplate productionRabbitTemplate(ConnectionFactory factory) {
RabbitTemplate template = new RabbitTemplate(factory);
// 启用发布确认
template.setConfirmCallback((correlationData, ack, cause) -> {
if (!ack) {
log.error("消息发送失败: {}", cause);
// 触发告警和重试
}
});
// 启用返回确认(消息无法路由时)
template.setReturnsCallback(returned -> {
log.error("消息无法路由: {}", returned.getMessage());
// 记录到死信队列或告警
});
// 启用消息强制回调
template.setMandatory(true);
return template;
}
// ========== 消费者配置 ==========
@Bean
public SimpleRabbitListenerContainerFactory productionContainerFactory(
ConnectionFactory factory) {
SimpleRabbitListenerContainerFactory containerFactory =
new SimpleRabbitListenerContainerFactory();
containerFactory.setConnectionFactory(factory);
// 手动确认
containerFactory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 公平分发
containerFactory.setPrefetch(1);
// 并发消费者数量
containerFactory.setConcurrentConsumers(5);
containerFactory.setMaxConcurrentConsumers(20);
// 重试配置
containerFactory.setAdviceChain(
RetryInterceptorBuilder
.stateless()
.maxAttempts(3)
.backOffOptions(1000, 2, 10000)
.build()
);
return containerFactory;
}
// ========== 队列配置 ==========
@Bean
public Queue productionQueue() {
return QueueBuilder
.durable("production.queue")
// 死信队列
.withArgument("x-dead-letter-exchange", "production.dlx")
.withArgument("x-dead-letter-routing-key", "production.dlq")
// 队列限制(防止内存溢出)
.withArgument("x-max-length", 100000)
.withArgument("x-max-length-bytes", 10737418240) // 10GB
// 惰性分发
.lazy()
// 主节点定位
.withArgument("x-queue-master-locator", "client-local")
.build();
}
} // 队列限制(防止内存溢出)`
`#/**
* 生产环境推荐配置
*
* 适用于:金融、电商等核心业务场景
*/
@Configuration
public class ProductionRabbitMQConfig {
// ========== 生产者配置 ==========
@Bean
public RabbitTemplate productionRabbitTemplate(ConnectionFactory factory) {
RabbitTemplate template = new RabbitTemplate(factory);
// 启用发布确认
template.setConfirmCallback((correlationData, ack, cause) -> {
if (!ack) {
log.error("消息发送失败: {}", cause);
// 触发告警和重试
}
});
// 启用返回确认(消息无法路由时)
template.setReturnsCallback(returned -> {
log.error("消息无法路由: {}", returned.getMessage());
// 记录到死信队列或告警
});
// 启用消息强制回调
template.setMandatory(true);
return template;
}
// ========== 消费者配置 ==========
@Bean
public SimpleRabbitListenerContainerFactory productionContainerFactory(
ConnectionFactory factory) {
SimpleRabbitListenerContainerFactory containerFactory =
new SimpleRabbitListenerContainerFactory();
containerFactory.setConnectionFactory(factory);
// 手动确认
containerFactory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 公平分发
containerFactory.setPrefetch(1);
// 并发消费者数量
containerFactory.setConcurrentConsumers(5);
containerFactory.setMaxConcurrentConsumers(20);
// 重试配置
containerFactory.setAdviceChain(
RetryInterceptorBuilder
.stateless()
.maxAttempts(3)
.backOffOptions(1000, 2, 10000)
.build()
);
return containerFactory;
}
// ========== 队列配置 ==========
@Bean
public Queue productionQueue() {
return QueueBuilder
.durable("production.queue")
// 死信队列
.withArgument("x-dead-letter-exchange", "production.dlx")
.withArgument("x-dead-letter-routing-key", "production.dlq")
// 队列限制(防止内存溢出)
.withArgument("x-max-length", 100000)
.withArgument("x-max-length-bytes", 10737418240) // 10GB
// 惰性分发
.lazy()
// 主节点定位
.withArgument("x-queue-master-locator", "client-local")
.build();
}
} .withArgument("x-max-length", 100000)`
`#/**
* 生产环境推荐配置
*
* 适用于:金融、电商等核心业务场景
*/
@Configuration
public class ProductionRabbitMQConfig {
// ========== 生产者配置 ==========
@Bean
public RabbitTemplate productionRabbitTemplate(ConnectionFactory factory) {
RabbitTemplate template = new RabbitTemplate(factory);
// 启用发布确认
template.setConfirmCallback((correlationData, ack, cause) -> {
if (!ack) {
log.error("消息发送失败: {}", cause);
// 触发告警和重试
}
});
// 启用返回确认(消息无法路由时)
template.setReturnsCallback(returned -> {
log.error("消息无法路由: {}", returned.getMessage());
// 记录到死信队列或告警
});
// 启用消息强制回调
template.setMandatory(true);
return template;
}
// ========== 消费者配置 ==========
@Bean
public SimpleRabbitListenerContainerFactory productionContainerFactory(
ConnectionFactory factory) {
SimpleRabbitListenerContainerFactory containerFactory =
new SimpleRabbitListenerContainerFactory();
containerFactory.setConnectionFactory(factory);
// 手动确认
containerFactory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 公平分发
containerFactory.setPrefetch(1);
// 并发消费者数量
containerFactory.setConcurrentConsumers(5);
containerFactory.setMaxConcurrentConsumers(20);
// 重试配置
containerFactory.setAdviceChain(
RetryInterceptorBuilder
.stateless()
.maxAttempts(3)
.backOffOptions(1000, 2, 10000)
.build()
);
return containerFactory;
}
// ========== 队列配置 ==========
@Bean
public Queue productionQueue() {
return QueueBuilder
.durable("production.queue")
// 死信队列
.withArgument("x-dead-letter-exchange", "production.dlx")
.withArgument("x-dead-letter-routing-key", "production.dlq")
// 队列限制(防止内存溢出)
.withArgument("x-max-length", 100000)
.withArgument("x-max-length-bytes", 10737418240) // 10GB
// 惰性分发
.lazy()
// 主节点定位
.withArgument("x-queue-master-locator", "client-local")
.build();
}
} .withArgument("x-max-length-bytes", 10737418240) // 10GB`
`#/**
* 生产环境推荐配置
*
* 适用于:金融、电商等核心业务场景
*/
@Configuration
public class ProductionRabbitMQConfig {
// ========== 生产者配置 ==========
@Bean
public RabbitTemplate productionRabbitTemplate(ConnectionFactory factory) {
RabbitTemplate template = new RabbitTemplate(factory);
// 启用发布确认
template.setConfirmCallback((correlationData, ack, cause) -> {
if (!ack) {
log.error("消息发送失败: {}", cause);
// 触发告警和重试
}
});
// 启用返回确认(消息无法路由时)
template.setReturnsCallback(returned -> {
log.error("消息无法路由: {}", returned.getMessage());
// 记录到死信队列或告警
});
// 启用消息强制回调
template.setMandatory(true);
return template;
}
// ========== 消费者配置 ==========
@Bean
public SimpleRabbitListenerContainerFactory productionContainerFactory(
ConnectionFactory factory) {
SimpleRabbitListenerContainerFactory containerFactory =
new SimpleRabbitListenerContainerFactory();
containerFactory.setConnectionFactory(factory);
// 手动确认
containerFactory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 公平分发
containerFactory.setPrefetch(1);
// 并发消费者数量
containerFactory.setConcurrentConsumers(5);
containerFactory.setMaxConcurrentConsumers(20);
// 重试配置
containerFactory.setAdviceChain(
RetryInterceptorBuilder
.stateless()
.maxAttempts(3)
.backOffOptions(1000, 2, 10000)
.build()
);
return containerFactory;
}
// ========== 队列配置 ==========
@Bean
public Queue productionQueue() {
return QueueBuilder
.durable("production.queue")
// 死信队列
.withArgument("x-dead-letter-exchange", "production.dlx")
.withArgument("x-dead-letter-routing-key", "production.dlq")
// 队列限制(防止内存溢出)
.withArgument("x-max-length", 100000)
.withArgument("x-max-length-bytes", 10737418240) // 10GB
// 惰性分发
.lazy()
// 主节点定位
.withArgument("x-queue-master-locator", "client-local")
.build();
}
} // 惰性分发`
`#/**
* 生产环境推荐配置
*
* 适用于:金融、电商等核心业务场景
*/
@Configuration
public class ProductionRabbitMQConfig {
// ========== 生产者配置 ==========
@Bean
public RabbitTemplate productionRabbitTemplate(ConnectionFactory factory) {
RabbitTemplate template = new RabbitTemplate(factory);
// 启用发布确认
template.setConfirmCallback((correlationData, ack, cause) -> {
if (!ack) {
log.error("消息发送失败: {}", cause);
// 触发告警和重试
}
});
// 启用返回确认(消息无法路由时)
template.setReturnsCallback(returned -> {
log.error("消息无法路由: {}", returned.getMessage());
// 记录到死信队列或告警
});
// 启用消息强制回调
template.setMandatory(true);
return template;
}
// ========== 消费者配置 ==========
@Bean
public SimpleRabbitListenerContainerFactory productionContainerFactory(
ConnectionFactory factory) {
SimpleRabbitListenerContainerFactory containerFactory =
new SimpleRabbitListenerContainerFactory();
containerFactory.setConnectionFactory(factory);
// 手动确认
containerFactory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 公平分发
containerFactory.setPrefetch(1);
// 并发消费者数量
containerFactory.setConcurrentConsumers(5);
containerFactory.setMaxConcurrentConsumers(20);
// 重试配置
containerFactory.setAdviceChain(
RetryInterceptorBuilder
.stateless()
.maxAttempts(3)
.backOffOptions(1000, 2, 10000)
.build()
);
return containerFactory;
}
// ========== 队列配置 ==========
@Bean
public Queue productionQueue() {
return QueueBuilder
.durable("production.queue")
// 死信队列
.withArgument("x-dead-letter-exchange", "production.dlx")
.withArgument("x-dead-letter-routing-key", "production.dlq")
// 队列限制(防止内存溢出)
.withArgument("x-max-length", 100000)
.withArgument("x-max-length-bytes", 10737418240) // 10GB
// 惰性分发
.lazy()
// 主节点定位
.withArgument("x-queue-master-locator", "client-local")
.build();
}
} .lazy()`
`#/**
* 生产环境推荐配置
*
* 适用于:金融、电商等核心业务场景
*/
@Configuration
public class ProductionRabbitMQConfig {
// ========== 生产者配置 ==========
@Bean
public RabbitTemplate productionRabbitTemplate(ConnectionFactory factory) {
RabbitTemplate template = new RabbitTemplate(factory);
// 启用发布确认
template.setConfirmCallback((correlationData, ack, cause) -> {
if (!ack) {
log.error("消息发送失败: {}", cause);
// 触发告警和重试
}
});
// 启用返回确认(消息无法路由时)
template.setReturnsCallback(returned -> {
log.error("消息无法路由: {}", returned.getMessage());
// 记录到死信队列或告警
});
// 启用消息强制回调
template.setMandatory(true);
return template;
}
// ========== 消费者配置 ==========
@Bean
public SimpleRabbitListenerContainerFactory productionContainerFactory(
ConnectionFactory factory) {
SimpleRabbitListenerContainerFactory containerFactory =
new SimpleRabbitListenerContainerFactory();
containerFactory.setConnectionFactory(factory);
// 手动确认
containerFactory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 公平分发
containerFactory.setPrefetch(1);
// 并发消费者数量
containerFactory.setConcurrentConsumers(5);
containerFactory.setMaxConcurrentConsumers(20);
// 重试配置
containerFactory.setAdviceChain(
RetryInterceptorBuilder
.stateless()
.maxAttempts(3)
.backOffOptions(1000, 2, 10000)
.build()
);
return containerFactory;
}
// ========== 队列配置 ==========
@Bean
public Queue productionQueue() {
return QueueBuilder
.durable("production.queue")
// 死信队列
.withArgument("x-dead-letter-exchange", "production.dlx")
.withArgument("x-dead-letter-routing-key", "production.dlq")
// 队列限制(防止内存溢出)
.withArgument("x-max-length", 100000)
.withArgument("x-max-length-bytes", 10737418240) // 10GB
// 惰性分发
.lazy()
// 主节点定位
.withArgument("x-queue-master-locator", "client-local")
.build();
}
} // 主节点定位`
`#/**
* 生产环境推荐配置
*
* 适用于:金融、电商等核心业务场景
*/
@Configuration
public class ProductionRabbitMQConfig {
// ========== 生产者配置 ==========
@Bean
public RabbitTemplate productionRabbitTemplate(ConnectionFactory factory) {
RabbitTemplate template = new RabbitTemplate(factory);
// 启用发布确认
template.setConfirmCallback((correlationData, ack, cause) -> {
if (!ack) {
log.error("消息发送失败: {}", cause);
// 触发告警和重试
}
});
// 启用返回确认(消息无法路由时)
template.setReturnsCallback(returned -> {
log.error("消息无法路由: {}", returned.getMessage());
// 记录到死信队列或告警
});
// 启用消息强制回调
template.setMandatory(true);
return template;
}
// ========== 消费者配置 ==========
@Bean
public SimpleRabbitListenerContainerFactory productionContainerFactory(
ConnectionFactory factory) {
SimpleRabbitListenerContainerFactory containerFactory =
new SimpleRabbitListenerContainerFactory();
containerFactory.setConnectionFactory(factory);
// 手动确认
containerFactory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 公平分发
containerFactory.setPrefetch(1);
// 并发消费者数量
containerFactory.setConcurrentConsumers(5);
containerFactory.setMaxConcurrentConsumers(20);
// 重试配置
containerFactory.setAdviceChain(
RetryInterceptorBuilder
.stateless()
.maxAttempts(3)
.backOffOptions(1000, 2, 10000)
.build()
);
return containerFactory;
}
// ========== 队列配置 ==========
@Bean
public Queue productionQueue() {
return QueueBuilder
.durable("production.queue")
// 死信队列
.withArgument("x-dead-letter-exchange", "production.dlx")
.withArgument("x-dead-letter-routing-key", "production.dlq")
// 队列限制(防止内存溢出)
.withArgument("x-max-length", 100000)
.withArgument("x-max-length-bytes", 10737418240) // 10GB
// 惰性分发
.lazy()
// 主节点定位
.withArgument("x-queue-master-locator", "client-local")
.build();
}
} .withArgument("x-queue-master-locator", "client-local")`
`#/**
* 生产环境推荐配置
*
* 适用于:金融、电商等核心业务场景
*/
@Configuration
public class ProductionRabbitMQConfig {
// ========== 生产者配置 ==========
@Bean
public RabbitTemplate productionRabbitTemplate(ConnectionFactory factory) {
RabbitTemplate template = new RabbitTemplate(factory);
// 启用发布确认
template.setConfirmCallback((correlationData, ack, cause) -> {
if (!ack) {
log.error("消息发送失败: {}", cause);
// 触发告警和重试
}
});
// 启用返回确认(消息无法路由时)
template.setReturnsCallback(returned -> {
log.error("消息无法路由: {}", returned.getMessage());
// 记录到死信队列或告警
});
// 启用消息强制回调
template.setMandatory(true);
return template;
}
// ========== 消费者配置 ==========
@Bean
public SimpleRabbitListenerContainerFactory productionContainerFactory(
ConnectionFactory factory) {
SimpleRabbitListenerContainerFactory containerFactory =
new SimpleRabbitListenerContainerFactory();
containerFactory.setConnectionFactory(factory);
// 手动确认
containerFactory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 公平分发
containerFactory.setPrefetch(1);
// 并发消费者数量
containerFactory.setConcurrentConsumers(5);
containerFactory.setMaxConcurrentConsumers(20);
// 重试配置
containerFactory.setAdviceChain(
RetryInterceptorBuilder
.stateless()
.maxAttempts(3)
.backOffOptions(1000, 2, 10000)
.build()
);
return containerFactory;
}
// ========== 队列配置 ==========
@Bean
public Queue productionQueue() {
return QueueBuilder
.durable("production.queue")
// 死信队列
.withArgument("x-dead-letter-exchange", "production.dlx")
.withArgument("x-dead-letter-routing-key", "production.dlq")
// 队列限制(防止内存溢出)
.withArgument("x-max-length", 100000)
.withArgument("x-max-length-bytes", 10737418240) // 10GB
// 惰性分发
.lazy()
// 主节点定位
.withArgument("x-queue-master-locator", "client-local")
.build();
}
} .build();`
`#/**
* 生产环境推荐配置
*
* 适用于:金融、电商等核心业务场景
*/
@Configuration
public class ProductionRabbitMQConfig {
// ========== 生产者配置 ==========
@Bean
public RabbitTemplate productionRabbitTemplate(ConnectionFactory factory) {
RabbitTemplate template = new RabbitTemplate(factory);
// 启用发布确认
template.setConfirmCallback((correlationData, ack, cause) -> {
if (!ack) {
log.error("消息发送失败: {}", cause);
// 触发告警和重试
}
});
// 启用返回确认(消息无法路由时)
template.setReturnsCallback(returned -> {
log.error("消息无法路由: {}", returned.getMessage());
// 记录到死信队列或告警
});
// 启用消息强制回调
template.setMandatory(true);
return template;
}
// ========== 消费者配置 ==========
@Bean
public SimpleRabbitListenerContainerFactory productionContainerFactory(
ConnectionFactory factory) {
SimpleRabbitListenerContainerFactory containerFactory =
new SimpleRabbitListenerContainerFactory();
containerFactory.setConnectionFactory(factory);
// 手动确认
containerFactory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 公平分发
containerFactory.setPrefetch(1);
// 并发消费者数量
containerFactory.setConcurrentConsumers(5);
containerFactory.setMaxConcurrentConsumers(20);
// 重试配置
containerFactory.setAdviceChain(
RetryInterceptorBuilder
.stateless()
.maxAttempts(3)
.backOffOptions(1000, 2, 10000)
.build()
);
return containerFactory;
}
// ========== 队列配置 ==========
@Bean
public Queue productionQueue() {
return QueueBuilder
.durable("production.queue")
// 死信队列
.withArgument("x-dead-letter-exchange", "production.dlx")
.withArgument("x-dead-letter-routing-key", "production.dlq")
// 队列限制(防止内存溢出)
.withArgument("x-max-length", 100000)
.withArgument("x-max-length-bytes", 10737418240) // 10GB
// 惰性分发
.lazy()
// 主节点定位
.withArgument("x-queue-master-locator", "client-local")
.build();
}
} }`
`#/**
* 生产环境推荐配置
*
* 适用于:金融、电商等核心业务场景
*/
@Configuration
public class ProductionRabbitMQConfig {
// ========== 生产者配置 ==========
@Bean
public RabbitTemplate productionRabbitTemplate(ConnectionFactory factory) {
RabbitTemplate template = new RabbitTemplate(factory);
// 启用发布确认
template.setConfirmCallback((correlationData, ack, cause) -> {
if (!ack) {
log.error("消息发送失败: {}", cause);
// 触发告警和重试
}
});
// 启用返回确认(消息无法路由时)
template.setReturnsCallback(returned -> {
log.error("消息无法路由: {}", returned.getMessage());
// 记录到死信队列或告警
});
// 启用消息强制回调
template.setMandatory(true);
return template;
}
// ========== 消费者配置 ==========
@Bean
public SimpleRabbitListenerContainerFactory productionContainerFactory(
ConnectionFactory factory) {
SimpleRabbitListenerContainerFactory containerFactory =
new SimpleRabbitListenerContainerFactory();
containerFactory.setConnectionFactory(factory);
// 手动确认
containerFactory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 公平分发
containerFactory.setPrefetch(1);
// 并发消费者数量
containerFactory.setConcurrentConsumers(5);
containerFactory.setMaxConcurrentConsumers(20);
// 重试配置
containerFactory.setAdviceChain(
RetryInterceptorBuilder
.stateless()
.maxAttempts(3)
.backOffOptions(1000, 2, 10000)
.build()
);
return containerFactory;
}
// ========== 队列配置 ==========
@Bean
public Queue productionQueue() {
return QueueBuilder
.durable("production.queue")
// 死信队列
.withArgument("x-dead-letter-exchange", "production.dlx")
.withArgument("x-dead-letter-routing-key", "production.dlq")
// 队列限制(防止内存溢出)
.withArgument("x-max-length", 100000)
.withArgument("x-max-length-bytes", 10737418240) // 10GB
// 惰性分发
.lazy()
// 主节点定位
.withArgument("x-queue-master-locator", "client-local")
.build();
}
}}
7.4 监控指标
关键监控指标:
java
#/**
* RabbitMQ 监控指标
*/
public class RabbitMQMetrics {
// 1. 队列维度
private long queueDepth; // 队列深度(消息数)
private long queueBytes; // 队列大小(字节)
private int consumerCount; // 消费者数量
private double ackRate; // 确认速率
private double publishRate; // 发布速率
// 2. 消费者维度
private double consumeRate; // 消费速率
private double avgProcessTime; // 平均处理时间
private int retryCount; // 重试次数
// 3. 死信维度
private long deadLetterCount; // 死信队列消息数
private double deadLetterRate; // 死信速率
// 4. 告警阈值
private static final long QUEUE_DEPTH_ALERT = 10000;
private static final double PROCESS_TIME_ALERT = 5000; // 5秒
private static final int RETRY_COUNT_ALERT = 10;
}
/**
* 监控实现
*/
@Component
public class RabbitMQMonitor {
@Autowired
private RabbitAdmin rabbitAdmin;
@Scheduled(fixedRate = 60000) // 每分钟检查
public void monitor() {
QueueInfo info = rabbitAdmin.getQueueInfo("production.queue");
// 检查队列深度
if (info.getMessageCount() > QUEUE_DEPTH_ALERT) {
sendAlert("队列积压告警: " + info.getMessageCount());
}
// 检查消费者状态
if (info.getConsumerCount() == 0) {
sendAlert("无消费者运行");
}
}
private void sendAlert(String message) {
// 实现告警逻辑:钉钉、企业微信、邮件等
}
}/**`
`#/**
* RabbitMQ 监控指标
*/
public class RabbitMQMetrics {
// 1. 队列维度
private long queueDepth; // 队列深度(消息数)
private long queueBytes; // 队列大小(字节)
private int consumerCount; // 消费者数量
private double ackRate; // 确认速率
private double publishRate; // 发布速率
// 2. 消费者维度
private double consumeRate; // 消费速率
private double avgProcessTime; // 平均处理时间
private int retryCount; // 重试次数
// 3. 死信维度
private long deadLetterCount; // 死信队列消息数
private double deadLetterRate; // 死信速率
// 4. 告警阈值
private static final long QUEUE_DEPTH_ALERT = 10000;
private static final double PROCESS_TIME_ALERT = 5000; // 5秒
private static final int RETRY_COUNT_ALERT = 10;
}
/**
* 监控实现
*/
@Component
public class RabbitMQMonitor {
@Autowired
private RabbitAdmin rabbitAdmin;
@Scheduled(fixedRate = 60000) // 每分钟检查
public void monitor() {
QueueInfo info = rabbitAdmin.getQueueInfo("production.queue");
// 检查队列深度
if (info.getMessageCount() > QUEUE_DEPTH_ALERT) {
sendAlert("队列积压告警: " + info.getMessageCount());
}
// 检查消费者状态
if (info.getConsumerCount() == 0) {
sendAlert("无消费者运行");
}
}
private void sendAlert(String message) {
// 实现告警逻辑:钉钉、企业微信、邮件等
}
} * RabbitMQ 监控指标`
`#/**
* RabbitMQ 监控指标
*/
public class RabbitMQMetrics {
// 1. 队列维度
private long queueDepth; // 队列深度(消息数)
private long queueBytes; // 队列大小(字节)
private int consumerCount; // 消费者数量
private double ackRate; // 确认速率
private double publishRate; // 发布速率
// 2. 消费者维度
private double consumeRate; // 消费速率
private double avgProcessTime; // 平均处理时间
private int retryCount; // 重试次数
// 3. 死信维度
private long deadLetterCount; // 死信队列消息数
private double deadLetterRate; // 死信速率
// 4. 告警阈值
private static final long QUEUE_DEPTH_ALERT = 10000;
private static final double PROCESS_TIME_ALERT = 5000; // 5秒
private static final int RETRY_COUNT_ALERT = 10;
}
/**
* 监控实现
*/
@Component
public class RabbitMQMonitor {
@Autowired
private RabbitAdmin rabbitAdmin;
@Scheduled(fixedRate = 60000) // 每分钟检查
public void monitor() {
QueueInfo info = rabbitAdmin.getQueueInfo("production.queue");
// 检查队列深度
if (info.getMessageCount() > QUEUE_DEPTH_ALERT) {
sendAlert("队列积压告警: " + info.getMessageCount());
}
// 检查消费者状态
if (info.getConsumerCount() == 0) {
sendAlert("无消费者运行");
}
}
private void sendAlert(String message) {
// 实现告警逻辑:钉钉、企业微信、邮件等
}
} */`
`#/**
* RabbitMQ 监控指标
*/
public class RabbitMQMetrics {
// 1. 队列维度
private long queueDepth; // 队列深度(消息数)
private long queueBytes; // 队列大小(字节)
private int consumerCount; // 消费者数量
private double ackRate; // 确认速率
private double publishRate; // 发布速率
// 2. 消费者维度
private double consumeRate; // 消费速率
private double avgProcessTime; // 平均处理时间
private int retryCount; // 重试次数
// 3. 死信维度
private long deadLetterCount; // 死信队列消息数
private double deadLetterRate; // 死信速率
// 4. 告警阈值
private static final long QUEUE_DEPTH_ALERT = 10000;
private static final double PROCESS_TIME_ALERT = 5000; // 5秒
private static final int RETRY_COUNT_ALERT = 10;
}
/**
* 监控实现
*/
@Component
public class RabbitMQMonitor {
@Autowired
private RabbitAdmin rabbitAdmin;
@Scheduled(fixedRate = 60000) // 每分钟检查
public void monitor() {
QueueInfo info = rabbitAdmin.getQueueInfo("production.queue");
// 检查队列深度
if (info.getMessageCount() > QUEUE_DEPTH_ALERT) {
sendAlert("队列积压告警: " + info.getMessageCount());
}
// 检查消费者状态
if (info.getConsumerCount() == 0) {
sendAlert("无消费者运行");
}
}
private void sendAlert(String message) {
// 实现告警逻辑:钉钉、企业微信、邮件等
}
}public class RabbitMQMetrics {`
`#/**
* RabbitMQ 监控指标
*/
public class RabbitMQMetrics {
// 1. 队列维度
private long queueDepth; // 队列深度(消息数)
private long queueBytes; // 队列大小(字节)
private int consumerCount; // 消费者数量
private double ackRate; // 确认速率
private double publishRate; // 发布速率
// 2. 消费者维度
private double consumeRate; // 消费速率
private double avgProcessTime; // 平均处理时间
private int retryCount; // 重试次数
// 3. 死信维度
private long deadLetterCount; // 死信队列消息数
private double deadLetterRate; // 死信速率
// 4. 告警阈值
private static final long QUEUE_DEPTH_ALERT = 10000;
private static final double PROCESS_TIME_ALERT = 5000; // 5秒
private static final int RETRY_COUNT_ALERT = 10;
}
/**
* 监控实现
*/
@Component
public class RabbitMQMonitor {
@Autowired
private RabbitAdmin rabbitAdmin;
@Scheduled(fixedRate = 60000) // 每分钟检查
public void monitor() {
QueueInfo info = rabbitAdmin.getQueueInfo("production.queue");
// 检查队列深度
if (info.getMessageCount() > QUEUE_DEPTH_ALERT) {
sendAlert("队列积压告警: " + info.getMessageCount());
}
// 检查消费者状态
if (info.getConsumerCount() == 0) {
sendAlert("无消费者运行");
}
}
private void sendAlert(String message) {
// 实现告警逻辑:钉钉、企业微信、邮件等
}
}`
`#/**
* RabbitMQ 监控指标
*/
public class RabbitMQMetrics {
// 1. 队列维度
private long queueDepth; // 队列深度(消息数)
private long queueBytes; // 队列大小(字节)
private int consumerCount; // 消费者数量
private double ackRate; // 确认速率
private double publishRate; // 发布速率
// 2. 消费者维度
private double consumeRate; // 消费速率
private double avgProcessTime; // 平均处理时间
private int retryCount; // 重试次数
// 3. 死信维度
private long deadLetterCount; // 死信队列消息数
private double deadLetterRate; // 死信速率
// 4. 告警阈值
private static final long QUEUE_DEPTH_ALERT = 10000;
private static final double PROCESS_TIME_ALERT = 5000; // 5秒
private static final int RETRY_COUNT_ALERT = 10;
}
/**
* 监控实现
*/
@Component
public class RabbitMQMonitor {
@Autowired
private RabbitAdmin rabbitAdmin;
@Scheduled(fixedRate = 60000) // 每分钟检查
public void monitor() {
QueueInfo info = rabbitAdmin.getQueueInfo("production.queue");
// 检查队列深度
if (info.getMessageCount() > QUEUE_DEPTH_ALERT) {
sendAlert("队列积压告警: " + info.getMessageCount());
}
// 检查消费者状态
if (info.getConsumerCount() == 0) {
sendAlert("无消费者运行");
}
}
private void sendAlert(String message) {
// 实现告警逻辑:钉钉、企业微信、邮件等
}
} // 1. 队列维度`
`#/**
* RabbitMQ 监控指标
*/
public class RabbitMQMetrics {
// 1. 队列维度
private long queueDepth; // 队列深度(消息数)
private long queueBytes; // 队列大小(字节)
private int consumerCount; // 消费者数量
private double ackRate; // 确认速率
private double publishRate; // 发布速率
// 2. 消费者维度
private double consumeRate; // 消费速率
private double avgProcessTime; // 平均处理时间
private int retryCount; // 重试次数
// 3. 死信维度
private long deadLetterCount; // 死信队列消息数
private double deadLetterRate; // 死信速率
// 4. 告警阈值
private static final long QUEUE_DEPTH_ALERT = 10000;
private static final double PROCESS_TIME_ALERT = 5000; // 5秒
private static final int RETRY_COUNT_ALERT = 10;
}
/**
* 监控实现
*/
@Component
public class RabbitMQMonitor {
@Autowired
private RabbitAdmin rabbitAdmin;
@Scheduled(fixedRate = 60000) // 每分钟检查
public void monitor() {
QueueInfo info = rabbitAdmin.getQueueInfo("production.queue");
// 检查队列深度
if (info.getMessageCount() > QUEUE_DEPTH_ALERT) {
sendAlert("队列积压告警: " + info.getMessageCount());
}
// 检查消费者状态
if (info.getConsumerCount() == 0) {
sendAlert("无消费者运行");
}
}
private void sendAlert(String message) {
// 实现告警逻辑:钉钉、企业微信、邮件等
}
} private long queueDepth; // 队列深度(消息数)`
`#/**
* RabbitMQ 监控指标
*/
public class RabbitMQMetrics {
// 1. 队列维度
private long queueDepth; // 队列深度(消息数)
private long queueBytes; // 队列大小(字节)
private int consumerCount; // 消费者数量
private double ackRate; // 确认速率
private double publishRate; // 发布速率
// 2. 消费者维度
private double consumeRate; // 消费速率
private double avgProcessTime; // 平均处理时间
private int retryCount; // 重试次数
// 3. 死信维度
private long deadLetterCount; // 死信队列消息数
private double deadLetterRate; // 死信速率
// 4. 告警阈值
private static final long QUEUE_DEPTH_ALERT = 10000;
private static final double PROCESS_TIME_ALERT = 5000; // 5秒
private static final int RETRY_COUNT_ALERT = 10;
}
/**
* 监控实现
*/
@Component
public class RabbitMQMonitor {
@Autowired
private RabbitAdmin rabbitAdmin;
@Scheduled(fixedRate = 60000) // 每分钟检查
public void monitor() {
QueueInfo info = rabbitAdmin.getQueueInfo("production.queue");
// 检查队列深度
if (info.getMessageCount() > QUEUE_DEPTH_ALERT) {
sendAlert("队列积压告警: " + info.getMessageCount());
}
// 检查消费者状态
if (info.getConsumerCount() == 0) {
sendAlert("无消费者运行");
}
}
private void sendAlert(String message) {
// 实现告警逻辑:钉钉、企业微信、邮件等
}
} private long queueBytes; // 队列大小(字节)`
`#/**
* RabbitMQ 监控指标
*/
public class RabbitMQMetrics {
// 1. 队列维度
private long queueDepth; // 队列深度(消息数)
private long queueBytes; // 队列大小(字节)
private int consumerCount; // 消费者数量
private double ackRate; // 确认速率
private double publishRate; // 发布速率
// 2. 消费者维度
private double consumeRate; // 消费速率
private double avgProcessTime; // 平均处理时间
private int retryCount; // 重试次数
// 3. 死信维度
private long deadLetterCount; // 死信队列消息数
private double deadLetterRate; // 死信速率
// 4. 告警阈值
private static final long QUEUE_DEPTH_ALERT = 10000;
private static final double PROCESS_TIME_ALERT = 5000; // 5秒
private static final int RETRY_COUNT_ALERT = 10;
}
/**
* 监控实现
*/
@Component
public class RabbitMQMonitor {
@Autowired
private RabbitAdmin rabbitAdmin;
@Scheduled(fixedRate = 60000) // 每分钟检查
public void monitor() {
QueueInfo info = rabbitAdmin.getQueueInfo("production.queue");
// 检查队列深度
if (info.getMessageCount() > QUEUE_DEPTH_ALERT) {
sendAlert("队列积压告警: " + info.getMessageCount());
}
// 检查消费者状态
if (info.getConsumerCount() == 0) {
sendAlert("无消费者运行");
}
}
private void sendAlert(String message) {
// 实现告警逻辑:钉钉、企业微信、邮件等
}
} private int consumerCount; // 消费者数量`
`#/**
* RabbitMQ 监控指标
*/
public class RabbitMQMetrics {
// 1. 队列维度
private long queueDepth; // 队列深度(消息数)
private long queueBytes; // 队列大小(字节)
private int consumerCount; // 消费者数量
private double ackRate; // 确认速率
private double publishRate; // 发布速率
// 2. 消费者维度
private double consumeRate; // 消费速率
private double avgProcessTime; // 平均处理时间
private int retryCount; // 重试次数
// 3. 死信维度
private long deadLetterCount; // 死信队列消息数
private double deadLetterRate; // 死信速率
// 4. 告警阈值
private static final long QUEUE_DEPTH_ALERT = 10000;
private static final double PROCESS_TIME_ALERT = 5000; // 5秒
private static final int RETRY_COUNT_ALERT = 10;
}
/**
* 监控实现
*/
@Component
public class RabbitMQMonitor {
@Autowired
private RabbitAdmin rabbitAdmin;
@Scheduled(fixedRate = 60000) // 每分钟检查
public void monitor() {
QueueInfo info = rabbitAdmin.getQueueInfo("production.queue");
// 检查队列深度
if (info.getMessageCount() > QUEUE_DEPTH_ALERT) {
sendAlert("队列积压告警: " + info.getMessageCount());
}
// 检查消费者状态
if (info.getConsumerCount() == 0) {
sendAlert("无消费者运行");
}
}
private void sendAlert(String message) {
// 实现告警逻辑:钉钉、企业微信、邮件等
}
} private double ackRate; // 确认速率`
`#/**
* RabbitMQ 监控指标
*/
public class RabbitMQMetrics {
// 1. 队列维度
private long queueDepth; // 队列深度(消息数)
private long queueBytes; // 队列大小(字节)
private int consumerCount; // 消费者数量
private double ackRate; // 确认速率
private double publishRate; // 发布速率
// 2. 消费者维度
private double consumeRate; // 消费速率
private double avgProcessTime; // 平均处理时间
private int retryCount; // 重试次数
// 3. 死信维度
private long deadLetterCount; // 死信队列消息数
private double deadLetterRate; // 死信速率
// 4. 告警阈值
private static final long QUEUE_DEPTH_ALERT = 10000;
private static final double PROCESS_TIME_ALERT = 5000; // 5秒
private static final int RETRY_COUNT_ALERT = 10;
}
/**
* 监控实现
*/
@Component
public class RabbitMQMonitor {
@Autowired
private RabbitAdmin rabbitAdmin;
@Scheduled(fixedRate = 60000) // 每分钟检查
public void monitor() {
QueueInfo info = rabbitAdmin.getQueueInfo("production.queue");
// 检查队列深度
if (info.getMessageCount() > QUEUE_DEPTH_ALERT) {
sendAlert("队列积压告警: " + info.getMessageCount());
}
// 检查消费者状态
if (info.getConsumerCount() == 0) {
sendAlert("无消费者运行");
}
}
private void sendAlert(String message) {
// 实现告警逻辑:钉钉、企业微信、邮件等
}
} private double publishRate; // 发布速率`
`#/**
* RabbitMQ 监控指标
*/
public class RabbitMQMetrics {
// 1. 队列维度
private long queueDepth; // 队列深度(消息数)
private long queueBytes; // 队列大小(字节)
private int consumerCount; // 消费者数量
private double ackRate; // 确认速率
private double publishRate; // 发布速率
// 2. 消费者维度
private double consumeRate; // 消费速率
private double avgProcessTime; // 平均处理时间
private int retryCount; // 重试次数
// 3. 死信维度
private long deadLetterCount; // 死信队列消息数
private double deadLetterRate; // 死信速率
// 4. 告警阈值
private static final long QUEUE_DEPTH_ALERT = 10000;
private static final double PROCESS_TIME_ALERT = 5000; // 5秒
private static final int RETRY_COUNT_ALERT = 10;
}
/**
* 监控实现
*/
@Component
public class RabbitMQMonitor {
@Autowired
private RabbitAdmin rabbitAdmin;
@Scheduled(fixedRate = 60000) // 每分钟检查
public void monitor() {
QueueInfo info = rabbitAdmin.getQueueInfo("production.queue");
// 检查队列深度
if (info.getMessageCount() > QUEUE_DEPTH_ALERT) {
sendAlert("队列积压告警: " + info.getMessageCount());
}
// 检查消费者状态
if (info.getConsumerCount() == 0) {
sendAlert("无消费者运行");
}
}
private void sendAlert(String message) {
// 实现告警逻辑:钉钉、企业微信、邮件等
}
} `
`#/**
* RabbitMQ 监控指标
*/
public class RabbitMQMetrics {
// 1. 队列维度
private long queueDepth; // 队列深度(消息数)
private long queueBytes; // 队列大小(字节)
private int consumerCount; // 消费者数量
private double ackRate; // 确认速率
private double publishRate; // 发布速率
// 2. 消费者维度
private double consumeRate; // 消费速率
private double avgProcessTime; // 平均处理时间
private int retryCount; // 重试次数
// 3. 死信维度
private long deadLetterCount; // 死信队列消息数
private double deadLetterRate; // 死信速率
// 4. 告警阈值
private static final long QUEUE_DEPTH_ALERT = 10000;
private static final double PROCESS_TIME_ALERT = 5000; // 5秒
private static final int RETRY_COUNT_ALERT = 10;
}
/**
* 监控实现
*/
@Component
public class RabbitMQMonitor {
@Autowired
private RabbitAdmin rabbitAdmin;
@Scheduled(fixedRate = 60000) // 每分钟检查
public void monitor() {
QueueInfo info = rabbitAdmin.getQueueInfo("production.queue");
// 检查队列深度
if (info.getMessageCount() > QUEUE_DEPTH_ALERT) {
sendAlert("队列积压告警: " + info.getMessageCount());
}
// 检查消费者状态
if (info.getConsumerCount() == 0) {
sendAlert("无消费者运行");
}
}
private void sendAlert(String message) {
// 实现告警逻辑:钉钉、企业微信、邮件等
}
} // 2. 消费者维度`
`#/**
* RabbitMQ 监控指标
*/
public class RabbitMQMetrics {
// 1. 队列维度
private long queueDepth; // 队列深度(消息数)
private long queueBytes; // 队列大小(字节)
private int consumerCount; // 消费者数量
private double ackRate; // 确认速率
private double publishRate; // 发布速率
// 2. 消费者维度
private double consumeRate; // 消费速率
private double avgProcessTime; // 平均处理时间
private int retryCount; // 重试次数
// 3. 死信维度
private long deadLetterCount; // 死信队列消息数
private double deadLetterRate; // 死信速率
// 4. 告警阈值
private static final long QUEUE_DEPTH_ALERT = 10000;
private static final double PROCESS_TIME_ALERT = 5000; // 5秒
private static final int RETRY_COUNT_ALERT = 10;
}
/**
* 监控实现
*/
@Component
public class RabbitMQMonitor {
@Autowired
private RabbitAdmin rabbitAdmin;
@Scheduled(fixedRate = 60000) // 每分钟检查
public void monitor() {
QueueInfo info = rabbitAdmin.getQueueInfo("production.queue");
// 检查队列深度
if (info.getMessageCount() > QUEUE_DEPTH_ALERT) {
sendAlert("队列积压告警: " + info.getMessageCount());
}
// 检查消费者状态
if (info.getConsumerCount() == 0) {
sendAlert("无消费者运行");
}
}
private void sendAlert(String message) {
// 实现告警逻辑:钉钉、企业微信、邮件等
}
} private double consumeRate; // 消费速率`
`#/**
* RabbitMQ 监控指标
*/
public class RabbitMQMetrics {
// 1. 队列维度
private long queueDepth; // 队列深度(消息数)
private long queueBytes; // 队列大小(字节)
private int consumerCount; // 消费者数量
private double ackRate; // 确认速率
private double publishRate; // 发布速率
// 2. 消费者维度
private double consumeRate; // 消费速率
private double avgProcessTime; // 平均处理时间
private int retryCount; // 重试次数
// 3. 死信维度
private long deadLetterCount; // 死信队列消息数
private double deadLetterRate; // 死信速率
// 4. 告警阈值
private static final long QUEUE_DEPTH_ALERT = 10000;
private static final double PROCESS_TIME_ALERT = 5000; // 5秒
private static final int RETRY_COUNT_ALERT = 10;
}
/**
* 监控实现
*/
@Component
public class RabbitMQMonitor {
@Autowired
private RabbitAdmin rabbitAdmin;
@Scheduled(fixedRate = 60000) // 每分钟检查
public void monitor() {
QueueInfo info = rabbitAdmin.getQueueInfo("production.queue");
// 检查队列深度
if (info.getMessageCount() > QUEUE_DEPTH_ALERT) {
sendAlert("队列积压告警: " + info.getMessageCount());
}
// 检查消费者状态
if (info.getConsumerCount() == 0) {
sendAlert("无消费者运行");
}
}
private void sendAlert(String message) {
// 实现告警逻辑:钉钉、企业微信、邮件等
}
} private double avgProcessTime; // 平均处理时间`
`#/**
* RabbitMQ 监控指标
*/
public class RabbitMQMetrics {
// 1. 队列维度
private long queueDepth; // 队列深度(消息数)
private long queueBytes; // 队列大小(字节)
private int consumerCount; // 消费者数量
private double ackRate; // 确认速率
private double publishRate; // 发布速率
// 2. 消费者维度
private double consumeRate; // 消费速率
private double avgProcessTime; // 平均处理时间
private int retryCount; // 重试次数
// 3. 死信维度
private long deadLetterCount; // 死信队列消息数
private double deadLetterRate; // 死信速率
// 4. 告警阈值
private static final long QUEUE_DEPTH_ALERT = 10000;
private static final double PROCESS_TIME_ALERT = 5000; // 5秒
private static final int RETRY_COUNT_ALERT = 10;
}
/**
* 监控实现
*/
@Component
public class RabbitMQMonitor {
@Autowired
private RabbitAdmin rabbitAdmin;
@Scheduled(fixedRate = 60000) // 每分钟检查
public void monitor() {
QueueInfo info = rabbitAdmin.getQueueInfo("production.queue");
// 检查队列深度
if (info.getMessageCount() > QUEUE_DEPTH_ALERT) {
sendAlert("队列积压告警: " + info.getMessageCount());
}
// 检查消费者状态
if (info.getConsumerCount() == 0) {
sendAlert("无消费者运行");
}
}
private void sendAlert(String message) {
// 实现告警逻辑:钉钉、企业微信、邮件等
}
} private int retryCount; // 重试次数`
`#/**
* RabbitMQ 监控指标
*/
public class RabbitMQMetrics {
// 1. 队列维度
private long queueDepth; // 队列深度(消息数)
private long queueBytes; // 队列大小(字节)
private int consumerCount; // 消费者数量
private double ackRate; // 确认速率
private double publishRate; // 发布速率
// 2. 消费者维度
private double consumeRate; // 消费速率
private double avgProcessTime; // 平均处理时间
private int retryCount; // 重试次数
// 3. 死信维度
private long deadLetterCount; // 死信队列消息数
private double deadLetterRate; // 死信速率
// 4. 告警阈值
private static final long QUEUE_DEPTH_ALERT = 10000;
private static final double PROCESS_TIME_ALERT = 5000; // 5秒
private static final int RETRY_COUNT_ALERT = 10;
}
/**
* 监控实现
*/
@Component
public class RabbitMQMonitor {
@Autowired
private RabbitAdmin rabbitAdmin;
@Scheduled(fixedRate = 60000) // 每分钟检查
public void monitor() {
QueueInfo info = rabbitAdmin.getQueueInfo("production.queue");
// 检查队列深度
if (info.getMessageCount() > QUEUE_DEPTH_ALERT) {
sendAlert("队列积压告警: " + info.getMessageCount());
}
// 检查消费者状态
if (info.getConsumerCount() == 0) {
sendAlert("无消费者运行");
}
}
private void sendAlert(String message) {
// 实现告警逻辑:钉钉、企业微信、邮件等
}
} `
`#/**
* RabbitMQ 监控指标
*/
public class RabbitMQMetrics {
// 1. 队列维度
private long queueDepth; // 队列深度(消息数)
private long queueBytes; // 队列大小(字节)
private int consumerCount; // 消费者数量
private double ackRate; // 确认速率
private double publishRate; // 发布速率
// 2. 消费者维度
private double consumeRate; // 消费速率
private double avgProcessTime; // 平均处理时间
private int retryCount; // 重试次数
// 3. 死信维度
private long deadLetterCount; // 死信队列消息数
private double deadLetterRate; // 死信速率
// 4. 告警阈值
private static final long QUEUE_DEPTH_ALERT = 10000;
private static final double PROCESS_TIME_ALERT = 5000; // 5秒
private static final int RETRY_COUNT_ALERT = 10;
}
/**
* 监控实现
*/
@Component
public class RabbitMQMonitor {
@Autowired
private RabbitAdmin rabbitAdmin;
@Scheduled(fixedRate = 60000) // 每分钟检查
public void monitor() {
QueueInfo info = rabbitAdmin.getQueueInfo("production.queue");
// 检查队列深度
if (info.getMessageCount() > QUEUE_DEPTH_ALERT) {
sendAlert("队列积压告警: " + info.getMessageCount());
}
// 检查消费者状态
if (info.getConsumerCount() == 0) {
sendAlert("无消费者运行");
}
}
private void sendAlert(String message) {
// 实现告警逻辑:钉钉、企业微信、邮件等
}
} // 3. 死信维度`
`#/**
* RabbitMQ 监控指标
*/
public class RabbitMQMetrics {
// 1. 队列维度
private long queueDepth; // 队列深度(消息数)
private long queueBytes; // 队列大小(字节)
private int consumerCount; // 消费者数量
private double ackRate; // 确认速率
private double publishRate; // 发布速率
// 2. 消费者维度
private double consumeRate; // 消费速率
private double avgProcessTime; // 平均处理时间
private int retryCount; // 重试次数
// 3. 死信维度
private long deadLetterCount; // 死信队列消息数
private double deadLetterRate; // 死信速率
// 4. 告警阈值
private static final long QUEUE_DEPTH_ALERT = 10000;
private static final double PROCESS_TIME_ALERT = 5000; // 5秒
private static final int RETRY_COUNT_ALERT = 10;
}
/**
* 监控实现
*/
@Component
public class RabbitMQMonitor {
@Autowired
private RabbitAdmin rabbitAdmin;
@Scheduled(fixedRate = 60000) // 每分钟检查
public void monitor() {
QueueInfo info = rabbitAdmin.getQueueInfo("production.queue");
// 检查队列深度
if (info.getMessageCount() > QUEUE_DEPTH_ALERT) {
sendAlert("队列积压告警: " + info.getMessageCount());
}
// 检查消费者状态
if (info.getConsumerCount() == 0) {
sendAlert("无消费者运行");
}
}
private void sendAlert(String message) {
// 实现告警逻辑:钉钉、企业微信、邮件等
}
} private long deadLetterCount; // 死信队列消息数`
`#/**
* RabbitMQ 监控指标
*/
public class RabbitMQMetrics {
// 1. 队列维度
private long queueDepth; // 队列深度(消息数)
private long queueBytes; // 队列大小(字节)
private int consumerCount; // 消费者数量
private double ackRate; // 确认速率
private double publishRate; // 发布速率
// 2. 消费者维度
private double consumeRate; // 消费速率
private double avgProcessTime; // 平均处理时间
private int retryCount; // 重试次数
// 3. 死信维度
private long deadLetterCount; // 死信队列消息数
private double deadLetterRate; // 死信速率
// 4. 告警阈值
private static final long QUEUE_DEPTH_ALERT = 10000;
private static final double PROCESS_TIME_ALERT = 5000; // 5秒
private static final int RETRY_COUNT_ALERT = 10;
}
/**
* 监控实现
*/
@Component
public class RabbitMQMonitor {
@Autowired
private RabbitAdmin rabbitAdmin;
@Scheduled(fixedRate = 60000) // 每分钟检查
public void monitor() {
QueueInfo info = rabbitAdmin.getQueueInfo("production.queue");
// 检查队列深度
if (info.getMessageCount() > QUEUE_DEPTH_ALERT) {
sendAlert("队列积压告警: " + info.getMessageCount());
}
// 检查消费者状态
if (info.getConsumerCount() == 0) {
sendAlert("无消费者运行");
}
}
private void sendAlert(String message) {
// 实现告警逻辑:钉钉、企业微信、邮件等
}
} private double deadLetterRate; // 死信速率`
`#/**
* RabbitMQ 监控指标
*/
public class RabbitMQMetrics {
// 1. 队列维度
private long queueDepth; // 队列深度(消息数)
private long queueBytes; // 队列大小(字节)
private int consumerCount; // 消费者数量
private double ackRate; // 确认速率
private double publishRate; // 发布速率
// 2. 消费者维度
private double consumeRate; // 消费速率
private double avgProcessTime; // 平均处理时间
private int retryCount; // 重试次数
// 3. 死信维度
private long deadLetterCount; // 死信队列消息数
private double deadLetterRate; // 死信速率
// 4. 告警阈值
private static final long QUEUE_DEPTH_ALERT = 10000;
private static final double PROCESS_TIME_ALERT = 5000; // 5秒
private static final int RETRY_COUNT_ALERT = 10;
}
/**
* 监控实现
*/
@Component
public class RabbitMQMonitor {
@Autowired
private RabbitAdmin rabbitAdmin;
@Scheduled(fixedRate = 60000) // 每分钟检查
public void monitor() {
QueueInfo info = rabbitAdmin.getQueueInfo("production.queue");
// 检查队列深度
if (info.getMessageCount() > QUEUE_DEPTH_ALERT) {
sendAlert("队列积压告警: " + info.getMessageCount());
}
// 检查消费者状态
if (info.getConsumerCount() == 0) {
sendAlert("无消费者运行");
}
}
private void sendAlert(String message) {
// 实现告警逻辑:钉钉、企业微信、邮件等
}
} `
`#/**
* RabbitMQ 监控指标
*/
public class RabbitMQMetrics {
// 1. 队列维度
private long queueDepth; // 队列深度(消息数)
private long queueBytes; // 队列大小(字节)
private int consumerCount; // 消费者数量
private double ackRate; // 确认速率
private double publishRate; // 发布速率
// 2. 消费者维度
private double consumeRate; // 消费速率
private double avgProcessTime; // 平均处理时间
private int retryCount; // 重试次数
// 3. 死信维度
private long deadLetterCount; // 死信队列消息数
private double deadLetterRate; // 死信速率
// 4. 告警阈值
private static final long QUEUE_DEPTH_ALERT = 10000;
private static final double PROCESS_TIME_ALERT = 5000; // 5秒
private static final int RETRY_COUNT_ALERT = 10;
}
/**
* 监控实现
*/
@Component
public class RabbitMQMonitor {
@Autowired
private RabbitAdmin rabbitAdmin;
@Scheduled(fixedRate = 60000) // 每分钟检查
public void monitor() {
QueueInfo info = rabbitAdmin.getQueueInfo("production.queue");
// 检查队列深度
if (info.getMessageCount() > QUEUE_DEPTH_ALERT) {
sendAlert("队列积压告警: " + info.getMessageCount());
}
// 检查消费者状态
if (info.getConsumerCount() == 0) {
sendAlert("无消费者运行");
}
}
private void sendAlert(String message) {
// 实现告警逻辑:钉钉、企业微信、邮件等
}
} // 4. 告警阈值`
`#/**
* RabbitMQ 监控指标
*/
public class RabbitMQMetrics {
// 1. 队列维度
private long queueDepth; // 队列深度(消息数)
private long queueBytes; // 队列大小(字节)
private int consumerCount; // 消费者数量
private double ackRate; // 确认速率
private double publishRate; // 发布速率
// 2. 消费者维度
private double consumeRate; // 消费速率
private double avgProcessTime; // 平均处理时间
private int retryCount; // 重试次数
// 3. 死信维度
private long deadLetterCount; // 死信队列消息数
private double deadLetterRate; // 死信速率
// 4. 告警阈值
private static final long QUEUE_DEPTH_ALERT = 10000;
private static final double PROCESS_TIME_ALERT = 5000; // 5秒
private static final int RETRY_COUNT_ALERT = 10;
}
/**
* 监控实现
*/
@Component
public class RabbitMQMonitor {
@Autowired
private RabbitAdmin rabbitAdmin;
@Scheduled(fixedRate = 60000) // 每分钟检查
public void monitor() {
QueueInfo info = rabbitAdmin.getQueueInfo("production.queue");
// 检查队列深度
if (info.getMessageCount() > QUEUE_DEPTH_ALERT) {
sendAlert("队列积压告警: " + info.getMessageCount());
}
// 检查消费者状态
if (info.getConsumerCount() == 0) {
sendAlert("无消费者运行");
}
}
private void sendAlert(String message) {
// 实现告警逻辑:钉钉、企业微信、邮件等
}
} private static final long QUEUE_DEPTH_ALERT = 10000;`
`#/**
* RabbitMQ 监控指标
*/
public class RabbitMQMetrics {
// 1. 队列维度
private long queueDepth; // 队列深度(消息数)
private long queueBytes; // 队列大小(字节)
private int consumerCount; // 消费者数量
private double ackRate; // 确认速率
private double publishRate; // 发布速率
// 2. 消费者维度
private double consumeRate; // 消费速率
private double avgProcessTime; // 平均处理时间
private int retryCount; // 重试次数
// 3. 死信维度
private long deadLetterCount; // 死信队列消息数
private double deadLetterRate; // 死信速率
// 4. 告警阈值
private static final long QUEUE_DEPTH_ALERT = 10000;
private static final double PROCESS_TIME_ALERT = 5000; // 5秒
private static final int RETRY_COUNT_ALERT = 10;
}
/**
* 监控实现
*/
@Component
public class RabbitMQMonitor {
@Autowired
private RabbitAdmin rabbitAdmin;
@Scheduled(fixedRate = 60000) // 每分钟检查
public void monitor() {
QueueInfo info = rabbitAdmin.getQueueInfo("production.queue");
// 检查队列深度
if (info.getMessageCount() > QUEUE_DEPTH_ALERT) {
sendAlert("队列积压告警: " + info.getMessageCount());
}
// 检查消费者状态
if (info.getConsumerCount() == 0) {
sendAlert("无消费者运行");
}
}
private void sendAlert(String message) {
// 实现告警逻辑:钉钉、企业微信、邮件等
}
} private static final double PROCESS_TIME_ALERT = 5000; // 5秒`
`#/**
* RabbitMQ 监控指标
*/
public class RabbitMQMetrics {
// 1. 队列维度
private long queueDepth; // 队列深度(消息数)
private long queueBytes; // 队列大小(字节)
private int consumerCount; // 消费者数量
private double ackRate; // 确认速率
private double publishRate; // 发布速率
// 2. 消费者维度
private double consumeRate; // 消费速率
private double avgProcessTime; // 平均处理时间
private int retryCount; // 重试次数
// 3. 死信维度
private long deadLetterCount; // 死信队列消息数
private double deadLetterRate; // 死信速率
// 4. 告警阈值
private static final long QUEUE_DEPTH_ALERT = 10000;
private static final double PROCESS_TIME_ALERT = 5000; // 5秒
private static final int RETRY_COUNT_ALERT = 10;
}
/**
* 监控实现
*/
@Component
public class RabbitMQMonitor {
@Autowired
private RabbitAdmin rabbitAdmin;
@Scheduled(fixedRate = 60000) // 每分钟检查
public void monitor() {
QueueInfo info = rabbitAdmin.getQueueInfo("production.queue");
// 检查队列深度
if (info.getMessageCount() > QUEUE_DEPTH_ALERT) {
sendAlert("队列积压告警: " + info.getMessageCount());
}
// 检查消费者状态
if (info.getConsumerCount() == 0) {
sendAlert("无消费者运行");
}
}
private void sendAlert(String message) {
// 实现告警逻辑:钉钉、企业微信、邮件等
}
} private static final int RETRY_COUNT_ALERT = 10;`
`#/**
* RabbitMQ 监控指标
*/
public class RabbitMQMetrics {
// 1. 队列维度
private long queueDepth; // 队列深度(消息数)
private long queueBytes; // 队列大小(字节)
private int consumerCount; // 消费者数量
private double ackRate; // 确认速率
private double publishRate; // 发布速率
// 2. 消费者维度
private double consumeRate; // 消费速率
private double avgProcessTime; // 平均处理时间
private int retryCount; // 重试次数
// 3. 死信维度
private long deadLetterCount; // 死信队列消息数
private double deadLetterRate; // 死信速率
// 4. 告警阈值
private static final long QUEUE_DEPTH_ALERT = 10000;
private static final double PROCESS_TIME_ALERT = 5000; // 5秒
private static final int RETRY_COUNT_ALERT = 10;
}
/**
* 监控实现
*/
@Component
public class RabbitMQMonitor {
@Autowired
private RabbitAdmin rabbitAdmin;
@Scheduled(fixedRate = 60000) // 每分钟检查
public void monitor() {
QueueInfo info = rabbitAdmin.getQueueInfo("production.queue");
// 检查队列深度
if (info.getMessageCount() > QUEUE_DEPTH_ALERT) {
sendAlert("队列积压告警: " + info.getMessageCount());
}
// 检查消费者状态
if (info.getConsumerCount() == 0) {
sendAlert("无消费者运行");
}
}
private void sendAlert(String message) {
// 实现告警逻辑:钉钉、企业微信、邮件等
}
}}`
`#/**
* RabbitMQ 监控指标
*/
public class RabbitMQMetrics {
// 1. 队列维度
private long queueDepth; // 队列深度(消息数)
private long queueBytes; // 队列大小(字节)
private int consumerCount; // 消费者数量
private double ackRate; // 确认速率
private double publishRate; // 发布速率
// 2. 消费者维度
private double consumeRate; // 消费速率
private double avgProcessTime; // 平均处理时间
private int retryCount; // 重试次数
// 3. 死信维度
private long deadLetterCount; // 死信队列消息数
private double deadLetterRate; // 死信速率
// 4. 告警阈值
private static final long QUEUE_DEPTH_ALERT = 10000;
private static final double PROCESS_TIME_ALERT = 5000; // 5秒
private static final int RETRY_COUNT_ALERT = 10;
}
/**
* 监控实现
*/
@Component
public class RabbitMQMonitor {
@Autowired
private RabbitAdmin rabbitAdmin;
@Scheduled(fixedRate = 60000) // 每分钟检查
public void monitor() {
QueueInfo info = rabbitAdmin.getQueueInfo("production.queue");
// 检查队列深度
if (info.getMessageCount() > QUEUE_DEPTH_ALERT) {
sendAlert("队列积压告警: " + info.getMessageCount());
}
// 检查消费者状态
if (info.getConsumerCount() == 0) {
sendAlert("无消费者运行");
}
}
private void sendAlert(String message) {
// 实现告警逻辑:钉钉、企业微信、邮件等
}
}`
`#/**
* RabbitMQ 监控指标
*/
public class RabbitMQMetrics {
// 1. 队列维度
private long queueDepth; // 队列深度(消息数)
private long queueBytes; // 队列大小(字节)
private int consumerCount; // 消费者数量
private double ackRate; // 确认速率
private double publishRate; // 发布速率
// 2. 消费者维度
private double consumeRate; // 消费速率
private double avgProcessTime; // 平均处理时间
private int retryCount; // 重试次数
// 3. 死信维度
private long deadLetterCount; // 死信队列消息数
private double deadLetterRate; // 死信速率
// 4. 告警阈值
private static final long QUEUE_DEPTH_ALERT = 10000;
private static final double PROCESS_TIME_ALERT = 5000; // 5秒
private static final int RETRY_COUNT_ALERT = 10;
}
/**
* 监控实现
*/
@Component
public class RabbitMQMonitor {
@Autowired
private RabbitAdmin rabbitAdmin;
@Scheduled(fixedRate = 60000) // 每分钟检查
public void monitor() {
QueueInfo info = rabbitAdmin.getQueueInfo("production.queue");
// 检查队列深度
if (info.getMessageCount() > QUEUE_DEPTH_ALERT) {
sendAlert("队列积压告警: " + info.getMessageCount());
}
// 检查消费者状态
if (info.getConsumerCount() == 0) {
sendAlert("无消费者运行");
}
}
private void sendAlert(String message) {
// 实现告警逻辑:钉钉、企业微信、邮件等
}
}/**`
`#/**
* RabbitMQ 监控指标
*/
public class RabbitMQMetrics {
// 1. 队列维度
private long queueDepth; // 队列深度(消息数)
private long queueBytes; // 队列大小(字节)
private int consumerCount; // 消费者数量
private double ackRate; // 确认速率
private double publishRate; // 发布速率
// 2. 消费者维度
private double consumeRate; // 消费速率
private double avgProcessTime; // 平均处理时间
private int retryCount; // 重试次数
// 3. 死信维度
private long deadLetterCount; // 死信队列消息数
private double deadLetterRate; // 死信速率
// 4. 告警阈值
private static final long QUEUE_DEPTH_ALERT = 10000;
private static final double PROCESS_TIME_ALERT = 5000; // 5秒
private static final int RETRY_COUNT_ALERT = 10;
}
/**
* 监控实现
*/
@Component
public class RabbitMQMonitor {
@Autowired
private RabbitAdmin rabbitAdmin;
@Scheduled(fixedRate = 60000) // 每分钟检查
public void monitor() {
QueueInfo info = rabbitAdmin.getQueueInfo("production.queue");
// 检查队列深度
if (info.getMessageCount() > QUEUE_DEPTH_ALERT) {
sendAlert("队列积压告警: " + info.getMessageCount());
}
// 检查消费者状态
if (info.getConsumerCount() == 0) {
sendAlert("无消费者运行");
}
}
private void sendAlert(String message) {
// 实现告警逻辑:钉钉、企业微信、邮件等
}
} * 监控实现`
`#/**
* RabbitMQ 监控指标
*/
public class RabbitMQMetrics {
// 1. 队列维度
private long queueDepth; // 队列深度(消息数)
private long queueBytes; // 队列大小(字节)
private int consumerCount; // 消费者数量
private double ackRate; // 确认速率
private double publishRate; // 发布速率
// 2. 消费者维度
private double consumeRate; // 消费速率
private double avgProcessTime; // 平均处理时间
private int retryCount; // 重试次数
// 3. 死信维度
private long deadLetterCount; // 死信队列消息数
private double deadLetterRate; // 死信速率
// 4. 告警阈值
private static final long QUEUE_DEPTH_ALERT = 10000;
private static final double PROCESS_TIME_ALERT = 5000; // 5秒
private static final int RETRY_COUNT_ALERT = 10;
}
/**
* 监控实现
*/
@Component
public class RabbitMQMonitor {
@Autowired
private RabbitAdmin rabbitAdmin;
@Scheduled(fixedRate = 60000) // 每分钟检查
public void monitor() {
QueueInfo info = rabbitAdmin.getQueueInfo("production.queue");
// 检查队列深度
if (info.getMessageCount() > QUEUE_DEPTH_ALERT) {
sendAlert("队列积压告警: " + info.getMessageCount());
}
// 检查消费者状态
if (info.getConsumerCount() == 0) {
sendAlert("无消费者运行");
}
}
private void sendAlert(String message) {
// 实现告警逻辑:钉钉、企业微信、邮件等
}
} */`
`#/**
* RabbitMQ 监控指标
*/
public class RabbitMQMetrics {
// 1. 队列维度
private long queueDepth; // 队列深度(消息数)
private long queueBytes; // 队列大小(字节)
private int consumerCount; // 消费者数量
private double ackRate; // 确认速率
private double publishRate; // 发布速率
// 2. 消费者维度
private double consumeRate; // 消费速率
private double avgProcessTime; // 平均处理时间
private int retryCount; // 重试次数
// 3. 死信维度
private long deadLetterCount; // 死信队列消息数
private double deadLetterRate; // 死信速率
// 4. 告警阈值
private static final long QUEUE_DEPTH_ALERT = 10000;
private static final double PROCESS_TIME_ALERT = 5000; // 5秒
private static final int RETRY_COUNT_ALERT = 10;
}
/**
* 监控实现
*/
@Component
public class RabbitMQMonitor {
@Autowired
private RabbitAdmin rabbitAdmin;
@Scheduled(fixedRate = 60000) // 每分钟检查
public void monitor() {
QueueInfo info = rabbitAdmin.getQueueInfo("production.queue");
// 检查队列深度
if (info.getMessageCount() > QUEUE_DEPTH_ALERT) {
sendAlert("队列积压告警: " + info.getMessageCount());
}
// 检查消费者状态
if (info.getConsumerCount() == 0) {
sendAlert("无消费者运行");
}
}
private void sendAlert(String message) {
// 实现告警逻辑:钉钉、企业微信、邮件等
}
}@Component`
`#/**
* RabbitMQ 监控指标
*/
public class RabbitMQMetrics {
// 1. 队列维度
private long queueDepth; // 队列深度(消息数)
private long queueBytes; // 队列大小(字节)
private int consumerCount; // 消费者数量
private double ackRate; // 确认速率
private double publishRate; // 发布速率
// 2. 消费者维度
private double consumeRate; // 消费速率
private double avgProcessTime; // 平均处理时间
private int retryCount; // 重试次数
// 3. 死信维度
private long deadLetterCount; // 死信队列消息数
private double deadLetterRate; // 死信速率
// 4. 告警阈值
private static final long QUEUE_DEPTH_ALERT = 10000;
private static final double PROCESS_TIME_ALERT = 5000; // 5秒
private static final int RETRY_COUNT_ALERT = 10;
}
/**
* 监控实现
*/
@Component
public class RabbitMQMonitor {
@Autowired
private RabbitAdmin rabbitAdmin;
@Scheduled(fixedRate = 60000) // 每分钟检查
public void monitor() {
QueueInfo info = rabbitAdmin.getQueueInfo("production.queue");
// 检查队列深度
if (info.getMessageCount() > QUEUE_DEPTH_ALERT) {
sendAlert("队列积压告警: " + info.getMessageCount());
}
// 检查消费者状态
if (info.getConsumerCount() == 0) {
sendAlert("无消费者运行");
}
}
private void sendAlert(String message) {
// 实现告警逻辑:钉钉、企业微信、邮件等
}
}public class RabbitMQMonitor {`
`#/**
* RabbitMQ 监控指标
*/
public class RabbitMQMetrics {
// 1. 队列维度
private long queueDepth; // 队列深度(消息数)
private long queueBytes; // 队列大小(字节)
private int consumerCount; // 消费者数量
private double ackRate; // 确认速率
private double publishRate; // 发布速率
// 2. 消费者维度
private double consumeRate; // 消费速率
private double avgProcessTime; // 平均处理时间
private int retryCount; // 重试次数
// 3. 死信维度
private long deadLetterCount; // 死信队列消息数
private double deadLetterRate; // 死信速率
// 4. 告警阈值
private static final long QUEUE_DEPTH_ALERT = 10000;
private static final double PROCESS_TIME_ALERT = 5000; // 5秒
private static final int RETRY_COUNT_ALERT = 10;
}
/**
* 监控实现
*/
@Component
public class RabbitMQMonitor {
@Autowired
private RabbitAdmin rabbitAdmin;
@Scheduled(fixedRate = 60000) // 每分钟检查
public void monitor() {
QueueInfo info = rabbitAdmin.getQueueInfo("production.queue");
// 检查队列深度
if (info.getMessageCount() > QUEUE_DEPTH_ALERT) {
sendAlert("队列积压告警: " + info.getMessageCount());
}
// 检查消费者状态
if (info.getConsumerCount() == 0) {
sendAlert("无消费者运行");
}
}
private void sendAlert(String message) {
// 实现告警逻辑:钉钉、企业微信、邮件等
}
}`
`#/**
* RabbitMQ 监控指标
*/
public class RabbitMQMetrics {
// 1. 队列维度
private long queueDepth; // 队列深度(消息数)
private long queueBytes; // 队列大小(字节)
private int consumerCount; // 消费者数量
private double ackRate; // 确认速率
private double publishRate; // 发布速率
// 2. 消费者维度
private double consumeRate; // 消费速率
private double avgProcessTime; // 平均处理时间
private int retryCount; // 重试次数
// 3. 死信维度
private long deadLetterCount; // 死信队列消息数
private double deadLetterRate; // 死信速率
// 4. 告警阈值
private static final long QUEUE_DEPTH_ALERT = 10000;
private static final double PROCESS_TIME_ALERT = 5000; // 5秒
private static final int RETRY_COUNT_ALERT = 10;
}
/**
* 监控实现
*/
@Component
public class RabbitMQMonitor {
@Autowired
private RabbitAdmin rabbitAdmin;
@Scheduled(fixedRate = 60000) // 每分钟检查
public void monitor() {
QueueInfo info = rabbitAdmin.getQueueInfo("production.queue");
// 检查队列深度
if (info.getMessageCount() > QUEUE_DEPTH_ALERT) {
sendAlert("队列积压告警: " + info.getMessageCount());
}
// 检查消费者状态
if (info.getConsumerCount() == 0) {
sendAlert("无消费者运行");
}
}
private void sendAlert(String message) {
// 实现告警逻辑:钉钉、企业微信、邮件等
}
} @Autowired`
`#/**
* RabbitMQ 监控指标
*/
public class RabbitMQMetrics {
// 1. 队列维度
private long queueDepth; // 队列深度(消息数)
private long queueBytes; // 队列大小(字节)
private int consumerCount; // 消费者数量
private double ackRate; // 确认速率
private double publishRate; // 发布速率
// 2. 消费者维度
private double consumeRate; // 消费速率
private double avgProcessTime; // 平均处理时间
private int retryCount; // 重试次数
// 3. 死信维度
private long deadLetterCount; // 死信队列消息数
private double deadLetterRate; // 死信速率
// 4. 告警阈值
private static final long QUEUE_DEPTH_ALERT = 10000;
private static final double PROCESS_TIME_ALERT = 5000; // 5秒
private static final int RETRY_COUNT_ALERT = 10;
}
/**
* 监控实现
*/
@Component
public class RabbitMQMonitor {
@Autowired
private RabbitAdmin rabbitAdmin;
@Scheduled(fixedRate = 60000) // 每分钟检查
public void monitor() {
QueueInfo info = rabbitAdmin.getQueueInfo("production.queue");
// 检查队列深度
if (info.getMessageCount() > QUEUE_DEPTH_ALERT) {
sendAlert("队列积压告警: " + info.getMessageCount());
}
// 检查消费者状态
if (info.getConsumerCount() == 0) {
sendAlert("无消费者运行");
}
}
private void sendAlert(String message) {
// 实现告警逻辑:钉钉、企业微信、邮件等
}
} private RabbitAdmin rabbitAdmin;`
`#/**
* RabbitMQ 监控指标
*/
public class RabbitMQMetrics {
// 1. 队列维度
private long queueDepth; // 队列深度(消息数)
private long queueBytes; // 队列大小(字节)
private int consumerCount; // 消费者数量
private double ackRate; // 确认速率
private double publishRate; // 发布速率
// 2. 消费者维度
private double consumeRate; // 消费速率
private double avgProcessTime; // 平均处理时间
private int retryCount; // 重试次数
// 3. 死信维度
private long deadLetterCount; // 死信队列消息数
private double deadLetterRate; // 死信速率
// 4. 告警阈值
private static final long QUEUE_DEPTH_ALERT = 10000;
private static final double PROCESS_TIME_ALERT = 5000; // 5秒
private static final int RETRY_COUNT_ALERT = 10;
}
/**
* 监控实现
*/
@Component
public class RabbitMQMonitor {
@Autowired
private RabbitAdmin rabbitAdmin;
@Scheduled(fixedRate = 60000) // 每分钟检查
public void monitor() {
QueueInfo info = rabbitAdmin.getQueueInfo("production.queue");
// 检查队列深度
if (info.getMessageCount() > QUEUE_DEPTH_ALERT) {
sendAlert("队列积压告警: " + info.getMessageCount());
}
// 检查消费者状态
if (info.getConsumerCount() == 0) {
sendAlert("无消费者运行");
}
}
private void sendAlert(String message) {
// 实现告警逻辑:钉钉、企业微信、邮件等
}
}`
`#/**
* RabbitMQ 监控指标
*/
public class RabbitMQMetrics {
// 1. 队列维度
private long queueDepth; // 队列深度(消息数)
private long queueBytes; // 队列大小(字节)
private int consumerCount; // 消费者数量
private double ackRate; // 确认速率
private double publishRate; // 发布速率
// 2. 消费者维度
private double consumeRate; // 消费速率
private double avgProcessTime; // 平均处理时间
private int retryCount; // 重试次数
// 3. 死信维度
private long deadLetterCount; // 死信队列消息数
private double deadLetterRate; // 死信速率
// 4. 告警阈值
private static final long QUEUE_DEPTH_ALERT = 10000;
private static final double PROCESS_TIME_ALERT = 5000; // 5秒
private static final int RETRY_COUNT_ALERT = 10;
}
/**
* 监控实现
*/
@Component
public class RabbitMQMonitor {
@Autowired
private RabbitAdmin rabbitAdmin;
@Scheduled(fixedRate = 60000) // 每分钟检查
public void monitor() {
QueueInfo info = rabbitAdmin.getQueueInfo("production.queue");
// 检查队列深度
if (info.getMessageCount() > QUEUE_DEPTH_ALERT) {
sendAlert("队列积压告警: " + info.getMessageCount());
}
// 检查消费者状态
if (info.getConsumerCount() == 0) {
sendAlert("无消费者运行");
}
}
private void sendAlert(String message) {
// 实现告警逻辑:钉钉、企业微信、邮件等
}
} @Scheduled(fixedRate = 60000) // 每分钟检查`
`#/**
* RabbitMQ 监控指标
*/
public class RabbitMQMetrics {
// 1. 队列维度
private long queueDepth; // 队列深度(消息数)
private long queueBytes; // 队列大小(字节)
private int consumerCount; // 消费者数量
private double ackRate; // 确认速率
private double publishRate; // 发布速率
// 2. 消费者维度
private double consumeRate; // 消费速率
private double avgProcessTime; // 平均处理时间
private int retryCount; // 重试次数
// 3. 死信维度
private long deadLetterCount; // 死信队列消息数
private double deadLetterRate; // 死信速率
// 4. 告警阈值
private static final long QUEUE_DEPTH_ALERT = 10000;
private static final double PROCESS_TIME_ALERT = 5000; // 5秒
private static final int RETRY_COUNT_ALERT = 10;
}
/**
* 监控实现
*/
@Component
public class RabbitMQMonitor {
@Autowired
private RabbitAdmin rabbitAdmin;
@Scheduled(fixedRate = 60000) // 每分钟检查
public void monitor() {
QueueInfo info = rabbitAdmin.getQueueInfo("production.queue");
// 检查队列深度
if (info.getMessageCount() > QUEUE_DEPTH_ALERT) {
sendAlert("队列积压告警: " + info.getMessageCount());
}
// 检查消费者状态
if (info.getConsumerCount() == 0) {
sendAlert("无消费者运行");
}
}
private void sendAlert(String message) {
// 实现告警逻辑:钉钉、企业微信、邮件等
}
} public void monitor() {`
`#/**
* RabbitMQ 监控指标
*/
public class RabbitMQMetrics {
// 1. 队列维度
private long queueDepth; // 队列深度(消息数)
private long queueBytes; // 队列大小(字节)
private int consumerCount; // 消费者数量
private double ackRate; // 确认速率
private double publishRate; // 发布速率
// 2. 消费者维度
private double consumeRate; // 消费速率
private double avgProcessTime; // 平均处理时间
private int retryCount; // 重试次数
// 3. 死信维度
private long deadLetterCount; // 死信队列消息数
private double deadLetterRate; // 死信速率
// 4. 告警阈值
private static final long QUEUE_DEPTH_ALERT = 10000;
private static final double PROCESS_TIME_ALERT = 5000; // 5秒
private static final int RETRY_COUNT_ALERT = 10;
}
/**
* 监控实现
*/
@Component
public class RabbitMQMonitor {
@Autowired
private RabbitAdmin rabbitAdmin;
@Scheduled(fixedRate = 60000) // 每分钟检查
public void monitor() {
QueueInfo info = rabbitAdmin.getQueueInfo("production.queue");
// 检查队列深度
if (info.getMessageCount() > QUEUE_DEPTH_ALERT) {
sendAlert("队列积压告警: " + info.getMessageCount());
}
// 检查消费者状态
if (info.getConsumerCount() == 0) {
sendAlert("无消费者运行");
}
}
private void sendAlert(String message) {
// 实现告警逻辑:钉钉、企业微信、邮件等
}
} QueueInfo info = rabbitAdmin.getQueueInfo("production.queue");`
`#/**
* RabbitMQ 监控指标
*/
public class RabbitMQMetrics {
// 1. 队列维度
private long queueDepth; // 队列深度(消息数)
private long queueBytes; // 队列大小(字节)
private int consumerCount; // 消费者数量
private double ackRate; // 确认速率
private double publishRate; // 发布速率
// 2. 消费者维度
private double consumeRate; // 消费速率
private double avgProcessTime; // 平均处理时间
private int retryCount; // 重试次数
// 3. 死信维度
private long deadLetterCount; // 死信队列消息数
private double deadLetterRate; // 死信速率
// 4. 告警阈值
private static final long QUEUE_DEPTH_ALERT = 10000;
private static final double PROCESS_TIME_ALERT = 5000; // 5秒
private static final int RETRY_COUNT_ALERT = 10;
}
/**
* 监控实现
*/
@Component
public class RabbitMQMonitor {
@Autowired
private RabbitAdmin rabbitAdmin;
@Scheduled(fixedRate = 60000) // 每分钟检查
public void monitor() {
QueueInfo info = rabbitAdmin.getQueueInfo("production.queue");
// 检查队列深度
if (info.getMessageCount() > QUEUE_DEPTH_ALERT) {
sendAlert("队列积压告警: " + info.getMessageCount());
}
// 检查消费者状态
if (info.getConsumerCount() == 0) {
sendAlert("无消费者运行");
}
}
private void sendAlert(String message) {
// 实现告警逻辑:钉钉、企业微信、邮件等
}
} `
`#/**
* RabbitMQ 监控指标
*/
public class RabbitMQMetrics {
// 1. 队列维度
private long queueDepth; // 队列深度(消息数)
private long queueBytes; // 队列大小(字节)
private int consumerCount; // 消费者数量
private double ackRate; // 确认速率
private double publishRate; // 发布速率
// 2. 消费者维度
private double consumeRate; // 消费速率
private double avgProcessTime; // 平均处理时间
private int retryCount; // 重试次数
// 3. 死信维度
private long deadLetterCount; // 死信队列消息数
private double deadLetterRate; // 死信速率
// 4. 告警阈值
private static final long QUEUE_DEPTH_ALERT = 10000;
private static final double PROCESS_TIME_ALERT = 5000; // 5秒
private static final int RETRY_COUNT_ALERT = 10;
}
/**
* 监控实现
*/
@Component
public class RabbitMQMonitor {
@Autowired
private RabbitAdmin rabbitAdmin;
@Scheduled(fixedRate = 60000) // 每分钟检查
public void monitor() {
QueueInfo info = rabbitAdmin.getQueueInfo("production.queue");
// 检查队列深度
if (info.getMessageCount() > QUEUE_DEPTH_ALERT) {
sendAlert("队列积压告警: " + info.getMessageCount());
}
// 检查消费者状态
if (info.getConsumerCount() == 0) {
sendAlert("无消费者运行");
}
}
private void sendAlert(String message) {
// 实现告警逻辑:钉钉、企业微信、邮件等
}
} // 检查队列深度`
`#/**
* RabbitMQ 监控指标
*/
public class RabbitMQMetrics {
// 1. 队列维度
private long queueDepth; // 队列深度(消息数)
private long queueBytes; // 队列大小(字节)
private int consumerCount; // 消费者数量
private double ackRate; // 确认速率
private double publishRate; // 发布速率
// 2. 消费者维度
private double consumeRate; // 消费速率
private double avgProcessTime; // 平均处理时间
private int retryCount; // 重试次数
// 3. 死信维度
private long deadLetterCount; // 死信队列消息数
private double deadLetterRate; // 死信速率
// 4. 告警阈值
private static final long QUEUE_DEPTH_ALERT = 10000;
private static final double PROCESS_TIME_ALERT = 5000; // 5秒
private static final int RETRY_COUNT_ALERT = 10;
}
/**
* 监控实现
*/
@Component
public class RabbitMQMonitor {
@Autowired
private RabbitAdmin rabbitAdmin;
@Scheduled(fixedRate = 60000) // 每分钟检查
public void monitor() {
QueueInfo info = rabbitAdmin.getQueueInfo("production.queue");
// 检查队列深度
if (info.getMessageCount() > QUEUE_DEPTH_ALERT) {
sendAlert("队列积压告警: " + info.getMessageCount());
}
// 检查消费者状态
if (info.getConsumerCount() == 0) {
sendAlert("无消费者运行");
}
}
private void sendAlert(String message) {
// 实现告警逻辑:钉钉、企业微信、邮件等
}
} if (info.getMessageCount() > QUEUE_DEPTH_ALERT) {`
`#/**
* RabbitMQ 监控指标
*/
public class RabbitMQMetrics {
// 1. 队列维度
private long queueDepth; // 队列深度(消息数)
private long queueBytes; // 队列大小(字节)
private int consumerCount; // 消费者数量
private double ackRate; // 确认速率
private double publishRate; // 发布速率
// 2. 消费者维度
private double consumeRate; // 消费速率
private double avgProcessTime; // 平均处理时间
private int retryCount; // 重试次数
// 3. 死信维度
private long deadLetterCount; // 死信队列消息数
private double deadLetterRate; // 死信速率
// 4. 告警阈值
private static final long QUEUE_DEPTH_ALERT = 10000;
private static final double PROCESS_TIME_ALERT = 5000; // 5秒
private static final int RETRY_COUNT_ALERT = 10;
}
/**
* 监控实现
*/
@Component
public class RabbitMQMonitor {
@Autowired
private RabbitAdmin rabbitAdmin;
@Scheduled(fixedRate = 60000) // 每分钟检查
public void monitor() {
QueueInfo info = rabbitAdmin.getQueueInfo("production.queue");
// 检查队列深度
if (info.getMessageCount() > QUEUE_DEPTH_ALERT) {
sendAlert("队列积压告警: " + info.getMessageCount());
}
// 检查消费者状态
if (info.getConsumerCount() == 0) {
sendAlert("无消费者运行");
}
}
private void sendAlert(String message) {
// 实现告警逻辑:钉钉、企业微信、邮件等
}
} sendAlert("队列积压告警: " + info.getMessageCount());`
`#/**
* RabbitMQ 监控指标
*/
public class RabbitMQMetrics {
// 1. 队列维度
private long queueDepth; // 队列深度(消息数)
private long queueBytes; // 队列大小(字节)
private int consumerCount; // 消费者数量
private double ackRate; // 确认速率
private double publishRate; // 发布速率
// 2. 消费者维度
private double consumeRate; // 消费速率
private double avgProcessTime; // 平均处理时间
private int retryCount; // 重试次数
// 3. 死信维度
private long deadLetterCount; // 死信队列消息数
private double deadLetterRate; // 死信速率
// 4. 告警阈值
private static final long QUEUE_DEPTH_ALERT = 10000;
private static final double PROCESS_TIME_ALERT = 5000; // 5秒
private static final int RETRY_COUNT_ALERT = 10;
}
/**
* 监控实现
*/
@Component
public class RabbitMQMonitor {
@Autowired
private RabbitAdmin rabbitAdmin;
@Scheduled(fixedRate = 60000) // 每分钟检查
public void monitor() {
QueueInfo info = rabbitAdmin.getQueueInfo("production.queue");
// 检查队列深度
if (info.getMessageCount() > QUEUE_DEPTH_ALERT) {
sendAlert("队列积压告警: " + info.getMessageCount());
}
// 检查消费者状态
if (info.getConsumerCount() == 0) {
sendAlert("无消费者运行");
}
}
private void sendAlert(String message) {
// 实现告警逻辑:钉钉、企业微信、邮件等
}
} }`
`#/**
* RabbitMQ 监控指标
*/
public class RabbitMQMetrics {
// 1. 队列维度
private long queueDepth; // 队列深度(消息数)
private long queueBytes; // 队列大小(字节)
private int consumerCount; // 消费者数量
private double ackRate; // 确认速率
private double publishRate; // 发布速率
// 2. 消费者维度
private double consumeRate; // 消费速率
private double avgProcessTime; // 平均处理时间
private int retryCount; // 重试次数
// 3. 死信维度
private long deadLetterCount; // 死信队列消息数
private double deadLetterRate; // 死信速率
// 4. 告警阈值
private static final long QUEUE_DEPTH_ALERT = 10000;
private static final double PROCESS_TIME_ALERT = 5000; // 5秒
private static final int RETRY_COUNT_ALERT = 10;
}
/**
* 监控实现
*/
@Component
public class RabbitMQMonitor {
@Autowired
private RabbitAdmin rabbitAdmin;
@Scheduled(fixedRate = 60000) // 每分钟检查
public void monitor() {
QueueInfo info = rabbitAdmin.getQueueInfo("production.queue");
// 检查队列深度
if (info.getMessageCount() > QUEUE_DEPTH_ALERT) {
sendAlert("队列积压告警: " + info.getMessageCount());
}
// 检查消费者状态
if (info.getConsumerCount() == 0) {
sendAlert("无消费者运行");
}
}
private void sendAlert(String message) {
// 实现告警逻辑:钉钉、企业微信、邮件等
}
} `
`#/**
* RabbitMQ 监控指标
*/
public class RabbitMQMetrics {
// 1. 队列维度
private long queueDepth; // 队列深度(消息数)
private long queueBytes; // 队列大小(字节)
private int consumerCount; // 消费者数量
private double ackRate; // 确认速率
private double publishRate; // 发布速率
// 2. 消费者维度
private double consumeRate; // 消费速率
private double avgProcessTime; // 平均处理时间
private int retryCount; // 重试次数
// 3. 死信维度
private long deadLetterCount; // 死信队列消息数
private double deadLetterRate; // 死信速率
// 4. 告警阈值
private static final long QUEUE_DEPTH_ALERT = 10000;
private static final double PROCESS_TIME_ALERT = 5000; // 5秒
private static final int RETRY_COUNT_ALERT = 10;
}
/**
* 监控实现
*/
@Component
public class RabbitMQMonitor {
@Autowired
private RabbitAdmin rabbitAdmin;
@Scheduled(fixedRate = 60000) // 每分钟检查
public void monitor() {
QueueInfo info = rabbitAdmin.getQueueInfo("production.queue");
// 检查队列深度
if (info.getMessageCount() > QUEUE_DEPTH_ALERT) {
sendAlert("队列积压告警: " + info.getMessageCount());
}
// 检查消费者状态
if (info.getConsumerCount() == 0) {
sendAlert("无消费者运行");
}
}
private void sendAlert(String message) {
// 实现告警逻辑:钉钉、企业微信、邮件等
}
} // 检查消费者状态`
`#/**
* RabbitMQ 监控指标
*/
public class RabbitMQMetrics {
// 1. 队列维度
private long queueDepth; // 队列深度(消息数)
private long queueBytes; // 队列大小(字节)
private int consumerCount; // 消费者数量
private double ackRate; // 确认速率
private double publishRate; // 发布速率
// 2. 消费者维度
private double consumeRate; // 消费速率
private double avgProcessTime; // 平均处理时间
private int retryCount; // 重试次数
// 3. 死信维度
private long deadLetterCount; // 死信队列消息数
private double deadLetterRate; // 死信速率
// 4. 告警阈值
private static final long QUEUE_DEPTH_ALERT = 10000;
private static final double PROCESS_TIME_ALERT = 5000; // 5秒
private static final int RETRY_COUNT_ALERT = 10;
}
/**
* 监控实现
*/
@Component
public class RabbitMQMonitor {
@Autowired
private RabbitAdmin rabbitAdmin;
@Scheduled(fixedRate = 60000) // 每分钟检查
public void monitor() {
QueueInfo info = rabbitAdmin.getQueueInfo("production.queue");
// 检查队列深度
if (info.getMessageCount() > QUEUE_DEPTH_ALERT) {
sendAlert("队列积压告警: " + info.getMessageCount());
}
// 检查消费者状态
if (info.getConsumerCount() == 0) {
sendAlert("无消费者运行");
}
}
private void sendAlert(String message) {
// 实现告警逻辑:钉钉、企业微信、邮件等
}
} if (info.getConsumerCount() == 0) {`
`#/**
* RabbitMQ 监控指标
*/
public class RabbitMQMetrics {
// 1. 队列维度
private long queueDepth; // 队列深度(消息数)
private long queueBytes; // 队列大小(字节)
private int consumerCount; // 消费者数量
private double ackRate; // 确认速率
private double publishRate; // 发布速率
// 2. 消费者维度
private double consumeRate; // 消费速率
private double avgProcessTime; // 平均处理时间
private int retryCount; // 重试次数
// 3. 死信维度
private long deadLetterCount; // 死信队列消息数
private double deadLetterRate; // 死信速率
// 4. 告警阈值
private static final long QUEUE_DEPTH_ALERT = 10000;
private static final double PROCESS_TIME_ALERT = 5000; // 5秒
private static final int RETRY_COUNT_ALERT = 10;
}
/**
* 监控实现
*/
@Component
public class RabbitMQMonitor {
@Autowired
private RabbitAdmin rabbitAdmin;
@Scheduled(fixedRate = 60000) // 每分钟检查
public void monitor() {
QueueInfo info = rabbitAdmin.getQueueInfo("production.queue");
// 检查队列深度
if (info.getMessageCount() > QUEUE_DEPTH_ALERT) {
sendAlert("队列积压告警: " + info.getMessageCount());
}
// 检查消费者状态
if (info.getConsumerCount() == 0) {
sendAlert("无消费者运行");
}
}
private void sendAlert(String message) {
// 实现告警逻辑:钉钉、企业微信、邮件等
}
} sendAlert("无消费者运行");`
`#/**
* RabbitMQ 监控指标
*/
public class RabbitMQMetrics {
// 1. 队列维度
private long queueDepth; // 队列深度(消息数)
private long queueBytes; // 队列大小(字节)
private int consumerCount; // 消费者数量
private double ackRate; // 确认速率
private double publishRate; // 发布速率
// 2. 消费者维度
private double consumeRate; // 消费速率
private double avgProcessTime; // 平均处理时间
private int retryCount; // 重试次数
// 3. 死信维度
private long deadLetterCount; // 死信队列消息数
private double deadLetterRate; // 死信速率
// 4. 告警阈值
private static final long QUEUE_DEPTH_ALERT = 10000;
private static final double PROCESS_TIME_ALERT = 5000; // 5秒
private static final int RETRY_COUNT_ALERT = 10;
}
/**
* 监控实现
*/
@Component
public class RabbitMQMonitor {
@Autowired
private RabbitAdmin rabbitAdmin;
@Scheduled(fixedRate = 60000) // 每分钟检查
public void monitor() {
QueueInfo info = rabbitAdmin.getQueueInfo("production.queue");
// 检查队列深度
if (info.getMessageCount() > QUEUE_DEPTH_ALERT) {
sendAlert("队列积压告警: " + info.getMessageCount());
}
// 检查消费者状态
if (info.getConsumerCount() == 0) {
sendAlert("无消费者运行");
}
}
private void sendAlert(String message) {
// 实现告警逻辑:钉钉、企业微信、邮件等
}
} }`
`#/**
* RabbitMQ 监控指标
*/
public class RabbitMQMetrics {
// 1. 队列维度
private long queueDepth; // 队列深度(消息数)
private long queueBytes; // 队列大小(字节)
private int consumerCount; // 消费者数量
private double ackRate; // 确认速率
private double publishRate; // 发布速率
// 2. 消费者维度
private double consumeRate; // 消费速率
private double avgProcessTime; // 平均处理时间
private int retryCount; // 重试次数
// 3. 死信维度
private long deadLetterCount; // 死信队列消息数
private double deadLetterRate; // 死信速率
// 4. 告警阈值
private static final long QUEUE_DEPTH_ALERT = 10000;
private static final double PROCESS_TIME_ALERT = 5000; // 5秒
private static final int RETRY_COUNT_ALERT = 10;
}
/**
* 监控实现
*/
@Component
public class RabbitMQMonitor {
@Autowired
private RabbitAdmin rabbitAdmin;
@Scheduled(fixedRate = 60000) // 每分钟检查
public void monitor() {
QueueInfo info = rabbitAdmin.getQueueInfo("production.queue");
// 检查队列深度
if (info.getMessageCount() > QUEUE_DEPTH_ALERT) {
sendAlert("队列积压告警: " + info.getMessageCount());
}
// 检查消费者状态
if (info.getConsumerCount() == 0) {
sendAlert("无消费者运行");
}
}
private void sendAlert(String message) {
// 实现告警逻辑:钉钉、企业微信、邮件等
}
} }`
`#/**
* RabbitMQ 监控指标
*/
public class RabbitMQMetrics {
// 1. 队列维度
private long queueDepth; // 队列深度(消息数)
private long queueBytes; // 队列大小(字节)
private int consumerCount; // 消费者数量
private double ackRate; // 确认速率
private double publishRate; // 发布速率
// 2. 消费者维度
private double consumeRate; // 消费速率
private double avgProcessTime; // 平均处理时间
private int retryCount; // 重试次数
// 3. 死信维度
private long deadLetterCount; // 死信队列消息数
private double deadLetterRate; // 死信速率
// 4. 告警阈值
private static final long QUEUE_DEPTH_ALERT = 10000;
private static final double PROCESS_TIME_ALERT = 5000; // 5秒
private static final int RETRY_COUNT_ALERT = 10;
}
/**
* 监控实现
*/
@Component
public class RabbitMQMonitor {
@Autowired
private RabbitAdmin rabbitAdmin;
@Scheduled(fixedRate = 60000) // 每分钟检查
public void monitor() {
QueueInfo info = rabbitAdmin.getQueueInfo("production.queue");
// 检查队列深度
if (info.getMessageCount() > QUEUE_DEPTH_ALERT) {
sendAlert("队列积压告警: " + info.getMessageCount());
}
// 检查消费者状态
if (info.getConsumerCount() == 0) {
sendAlert("无消费者运行");
}
}
private void sendAlert(String message) {
// 实现告警逻辑:钉钉、企业微信、邮件等
}
}`
`#/**
* RabbitMQ 监控指标
*/
public class RabbitMQMetrics {
// 1. 队列维度
private long queueDepth; // 队列深度(消息数)
private long queueBytes; // 队列大小(字节)
private int consumerCount; // 消费者数量
private double ackRate; // 确认速率
private double publishRate; // 发布速率
// 2. 消费者维度
private double consumeRate; // 消费速率
private double avgProcessTime; // 平均处理时间
private int retryCount; // 重试次数
// 3. 死信维度
private long deadLetterCount; // 死信队列消息数
private double deadLetterRate; // 死信速率
// 4. 告警阈值
private static final long QUEUE_DEPTH_ALERT = 10000;
private static final double PROCESS_TIME_ALERT = 5000; // 5秒
private static final int RETRY_COUNT_ALERT = 10;
}
/**
* 监控实现
*/
@Component
public class RabbitMQMonitor {
@Autowired
private RabbitAdmin rabbitAdmin;
@Scheduled(fixedRate = 60000) // 每分钟检查
public void monitor() {
QueueInfo info = rabbitAdmin.getQueueInfo("production.queue");
// 检查队列深度
if (info.getMessageCount() > QUEUE_DEPTH_ALERT) {
sendAlert("队列积压告警: " + info.getMessageCount());
}
// 检查消费者状态
if (info.getConsumerCount() == 0) {
sendAlert("无消费者运行");
}
}
private void sendAlert(String message) {
// 实现告警逻辑:钉钉、企业微信、邮件等
}
} private void sendAlert(String message) {`
`#/**
* RabbitMQ 监控指标
*/
public class RabbitMQMetrics {
// 1. 队列维度
private long queueDepth; // 队列深度(消息数)
private long queueBytes; // 队列大小(字节)
private int consumerCount; // 消费者数量
private double ackRate; // 确认速率
private double publishRate; // 发布速率
// 2. 消费者维度
private double consumeRate; // 消费速率
private double avgProcessTime; // 平均处理时间
private int retryCount; // 重试次数
// 3. 死信维度
private long deadLetterCount; // 死信队列消息数
private double deadLetterRate; // 死信速率
// 4. 告警阈值
private static final long QUEUE_DEPTH_ALERT = 10000;
private static final double PROCESS_TIME_ALERT = 5000; // 5秒
private static final int RETRY_COUNT_ALERT = 10;
}
/**
* 监控实现
*/
@Component
public class RabbitMQMonitor {
@Autowired
private RabbitAdmin rabbitAdmin;
@Scheduled(fixedRate = 60000) // 每分钟检查
public void monitor() {
QueueInfo info = rabbitAdmin.getQueueInfo("production.queue");
// 检查队列深度
if (info.getMessageCount() > QUEUE_DEPTH_ALERT) {
sendAlert("队列积压告警: " + info.getMessageCount());
}
// 检查消费者状态
if (info.getConsumerCount() == 0) {
sendAlert("无消费者运行");
}
}
private void sendAlert(String message) {
// 实现告警逻辑:钉钉、企业微信、邮件等
}
} // 实现告警逻辑:钉钉、企业微信、邮件等`
`#/**
* RabbitMQ 监控指标
*/
public class RabbitMQMetrics {
// 1. 队列维度
private long queueDepth; // 队列深度(消息数)
private long queueBytes; // 队列大小(字节)
private int consumerCount; // 消费者数量
private double ackRate; // 确认速率
private double publishRate; // 发布速率
// 2. 消费者维度
private double consumeRate; // 消费速率
private double avgProcessTime; // 平均处理时间
private int retryCount; // 重试次数
// 3. 死信维度
private long deadLetterCount; // 死信队列消息数
private double deadLetterRate; // 死信速率
// 4. 告警阈值
private static final long QUEUE_DEPTH_ALERT = 10000;
private static final double PROCESS_TIME_ALERT = 5000; // 5秒
private static final int RETRY_COUNT_ALERT = 10;
}
/**
* 监控实现
*/
@Component
public class RabbitMQMonitor {
@Autowired
private RabbitAdmin rabbitAdmin;
@Scheduled(fixedRate = 60000) // 每分钟检查
public void monitor() {
QueueInfo info = rabbitAdmin.getQueueInfo("production.queue");
// 检查队列深度
if (info.getMessageCount() > QUEUE_DEPTH_ALERT) {
sendAlert("队列积压告警: " + info.getMessageCount());
}
// 检查消费者状态
if (info.getConsumerCount() == 0) {
sendAlert("无消费者运行");
}
}
private void sendAlert(String message) {
// 实现告警逻辑:钉钉、企业微信、邮件等
}
} }`
`#/**
* RabbitMQ 监控指标
*/
public class RabbitMQMetrics {
// 1. 队列维度
private long queueDepth; // 队列深度(消息数)
private long queueBytes; // 队列大小(字节)
private int consumerCount; // 消费者数量
private double ackRate; // 确认速率
private double publishRate; // 发布速率
// 2. 消费者维度
private double consumeRate; // 消费速率
private double avgProcessTime; // 平均处理时间
private int retryCount; // 重试次数
// 3. 死信维度
private long deadLetterCount; // 死信队列消息数
private double deadLetterRate; // 死信速率
// 4. 告警阈值
private static final long QUEUE_DEPTH_ALERT = 10000;
private static final double PROCESS_TIME_ALERT = 5000; // 5秒
private static final int RETRY_COUNT_ALERT = 10;
}
/**
* 监控实现
*/
@Component
public class RabbitMQMonitor {
@Autowired
private RabbitAdmin rabbitAdmin;
@Scheduled(fixedRate = 60000) // 每分钟检查
public void monitor() {
QueueInfo info = rabbitAdmin.getQueueInfo("production.queue");
// 检查队列深度
if (info.getMessageCount() > QUEUE_DEPTH_ALERT) {
sendAlert("队列积压告警: " + info.getMessageCount());
}
// 检查消费者状态
if (info.getConsumerCount() == 0) {
sendAlert("无消费者运行");
}
}
private void sendAlert(String message) {
// 实现告警逻辑:钉钉、企业微信、邮件等
}
}}
总结
本文深入剖析了 RabbitMQ 可靠性投递的三大核心机制:
- 持久化:通过交换机、队列、消息的三层持久化,确保数据在 Broker 宕机时不丢失
- 确认机制:生产者 Confirm 和消费者 ACK 组成的双向确认,保障消息可靠传输
- 死信队列:异常消息的最终处理机制,防止消息无限重试导致的资源耗尽
关键要点:
- ✅ 可靠性需要全链路保障:生产者→Broker→消费者,任一环节出问题都可能导致消息丢失
- ✅ 权衡是必要的:最高可靠性方案会带来性能损耗,需根据业务场景选择
- ✅ 幂等性设计不可少:即使有确认机制,仍需防止消息重复消费
- ✅ 监控告警要跟上:死信队列、消息堆积等异常需要及时发现和处理
技术选型建议:
| 场景 | 推荐方案 |
|---|---|
| 金融交易、支付 | 完整可靠性方案(持久化+ACK+DLQ+幂等) |
| 订单处理、库存扣减 | 持久化+ACK+DLQ |
| 日志收集、监控数据 | 持久化+自动ACK |
| 实时通信、即时消息 | 内存模式+自动ACK(追求性能) |
希望本文能帮助你构建高可用的 RabbitMQ 消息系统!
参考资源:
- RabbitMQ 官方文档 - Reliability Guide
- RabbitMQ 官方文档 - Confirms
- RabbitMQ 官方文档 - Dead Letter Exchange
- Spring AMQP 参考文档
- RabbitMQ 源码:https://github.com/rabbitmq/rabbitmq-server (版本 3.12.x)
标签: RabbitMQ 可靠性 持久化 确认机制 死信队列 消息队列 分布式系统 Java Spring Boot