Hyperf 3.0 默认不启用 RabbitMQ 的 Publisher Confirm 机制,需在 amqp.php 的 connection params 中手动添加 'publisher-confirms' => true 和 'mandatory' => true,并重启服务;confirm 回调须在 Producer 中通过 $channel->confirmSelect() 和 addConfirmHandler() 动态绑定。

Hyperf 3.0 默认不启用 RabbitMQ 的 Publisher Confirm 机制,必须手动配置 RabbitTemplate 并开启 publisher-confirms 和 mandatory 才能生效。
确认机制在 Hyperf 中是否默认开启
Hyperf 的 hyperf/amqp 组件基于 AMQP 协议封装,但其默认连接配置中 publisher-confirms 是关闭的。即使 RabbitMQ Broker 端支持 confirm,Hyperf 不显式启用就收不到回调。这和 Spring Boot 的 publisher-confirm-type: correlated 完全不同——Hyperf 没有自动绑定 CorrelationData 或全局回调注册机制。
常见错误现象:confirmCallback 从不触发、日志里看不到“消息已到达 Exchange”、网络中断后消息静默丢失。
- Hyperf 的 AMQP 连接配置(
config/autoload/amqp.php)里没有publisher-confirms字段,需手动加到params中 - 必须配合
mandatory: true才能联动returnCallback,否则路由失败时连退回都不会发生 - Hyperf 不提供类似 Spring 的
RabbitTemplate.setConfirmCallback()链式调用,回调需在消费者/生产者类中自行注入并绑定
如何在 amqp.php 中启用 confirm 和 mandatory
Hyperf 的 AMQP 配置是连接级的,不是模板级。要在连接建立时就启用 confirm,必须在 params 中声明,且该参数会被底层 php-amqplib 直接识别。
修改 config/autoload/amqp.php,在对应 connection 的 params 数组中添加:
'params' => [
'insist' => false,
'login_method' => 'AMQPLAIN',
'publisher-confirms' => true, // ← 关键:启用 confirm
'mandatory' => true, // ← 关键:启用 return 回退
],
注意:publisher-confirms 是小写短横线写法(AMQP 协议原生参数),不是 camelCase;写成 publisherConfirms 或 publisher_confirms 都无效。
- 该配置仅影响当前 connection,多个 connection 需分别设置
- 修改后必须重启 Hyperf worker(
php bin/hyperf.php start),热重载不生效 - 若使用 Docker 部署,确保容器内
amqp.php已挂载并更新,而非只改了宿主机文件
如何监听 confirm 和 return 回调
Hyperf 没有全局 setConfirmCallback 入口,回调必须在具体发送消息时通过 Producer 实例动态绑定。本质是利用 php-amqplib 的 Channel::confirmSelect() + 事件监听模式。
典型做法是在自定义 Producer 类中封装:
use Hyperf\Amqp\Producer;
use PhpAmqpLib\Channel\AMQPChannel;
<p>class OrderProducer extends Producer
{
public function produce($data)
{
$channel = $this->getChannel();
// 启用 confirm 模式(必须在每次 channel 复用前调用)
$channel->confirmSelect();</p><pre class="brush:php;toolbar:false;"> // 绑定 confirm 回调(注意:是 PHP 原生 callback,非 Hyperf 注解)
$channel->addConfirmHandler(new class implements \PhpAmqpLib\Wire\IO\ConfirmHandlerInterface {
public function handleConfirm($deliveryTag, $multiple) { /* ... */ }
public function handleNack($deliveryTag, $multiple) { /* ... */ }
});
// 发送消息(带 correlation_id 用于追踪)
$message = new \PhpAmqpLib\Message\AMQPMessage(json_encode($data), [
'correlation_id' => uniqid('ord_'),
'delivery_mode' => 2, // 持久化
]);
$channel->basic_publish($message, 'order.exchange', 'order.create');
}}
- 不能依赖
$this->rabbitTemplate—— Hyperf 的Amqp组件没有RabbitTemplate概念 -
confirmSelect()必须在每次basic_publish前调用,否则 confirm 不生效 -
correlation_id需手动设在 message 属性中,Hyperf 不自动注入或关联回调上下文 - return 回调需额外调用
$channel->addReturnListener(),且仅当mandatory: true且路由失败时触发
为什么 confirm 失败却没报错
最常被忽略的一点:Hyperf 的 Producer::produce() 方法默认不等待 confirm 结果,它只是发出去就返回。即使网络断开、Broker 不可用,只要 AMQP channel 没抛异常,produce() 就算“成功”。
这意味着:
- 你看到
produce()返回了,不代表消息到了 Exchange - confirm 回调里的
handleNack是唯一可靠失败信号,必须在这里做重试或落库 - 不要在
produce()后直接echo "sent"就认为 OK —— 那只是 TCP 层发出了数据包 - 高并发下大量未确认消息堆积在 channel 缓冲区,可能触发内存溢出或超时,需控制
confirmSelect()后的批量大小
真正可靠的发送逻辑,必须把业务主键 + correlation_id 写入本地 DB,并在 handleNack 中查库重发,而不是依赖“发完即忘”。


















