以 Direct 类型的 交换机和 Queue 的 get 方法为例.

producer.php

// 连接设置
$conConfig = [
'host' => '127.0.0.1',
'port' => 5672,
'login' => 'root',
'password' => 'root',
'vhost' => '/'
];
try
{
// RabbitMQ 连接实例
$con = new AMQPConnection($conConfig);
// 发起连接
$con->connect();
// 新建通道
$channel = new AMQPChannel($con);
// 在指定通道上新建交换机
$exchange = new AMQPExchange($channel);
// 交换机名称
$exchange->setName('test.exchange.ack');
// 交换机类型
$exchange->setType('direct');
// 声明交换机
$exchange->declareExchange(); for($i = 1; $i <= 3; $i++)
{
$msg = '消息' . $i;
// 发送消息,同时为消息指定routing key,成功返回true,失败false
$state = $exchange->publish($msg, 'test.rt.ack');
if($state)
{
echo 'Success' . PHP_EOL;
}else
{
echo 'Fail' . PHP_EOL;
}
} // 关闭连接
//$con->disconnect();
}catch(\Exception $e)
{
echo $e->getMessage();
}

自动 ACK

consumer.php

$conConfig = [
'host' => '127.0.0.1',
'port' => 5672,
'login' => 'root',
'password' => 'root',
'vhost' => '/'
]; try
{
$con = new AMQPConnection($conConfig);
$con->connect(); $channel = new AMQPChannel($con);
$exchange =new AMQPExchange($channel);
$exchange->setName('test.exchange.ack');
$exchange->setType('direct');
$exchange->declareExchange(); $queue = new AMQPQueue($channel);
$queue->setName('test.ack.queue');
// 声明队列同时返回队列中的消息数量
$messageCount = $queue->declareQueue();
echo '消息数量: ' . $messageCount . PHP_EOL;
$queue->bind('test.exchange.ack', 'test.rt.ack'); // 获取消息后进行自动应答时, get方法的参数设置为AMQP_AUTOACK即可
while($msgEnvelope = $queue->get(AMQP_AUTOACK))
{
$msg = $msgEnvelope->getBody();
echo $msg . PHP_EOL;
}
$con->disconnect();
}catch(Exception $e)
{
echo $e->getMessage();
}

将 Queue 的 get 方法参数设置为 AMQP_AUTOACK 即可在获取到消息后自动发送消息已收到响应.

手动 ack

如果不需要自动 ack, 而是根据实际的业务处理结果进行处理. Queue 的 get 方法参数修改为 AMQP_NOPARM 即可.

修改后推送三条消息:

连续两次从队列中获取消息:

如果不进行 ack, 队列中的消息将一直存在, 可以反复获取.

继续修改 while 循环为:

while($msgEnvelope = $queue->get(AMQP_NOPARAM))
{
$msg = $msgEnvelope->getBody();
if(preg_match("/.*?消息2.*?/", $msg))
{
// 对消息2执行确定响应
$queue->ack($msgEnvelope->getDeliveryTag());
}
echo date('Y-m-d H:i:s') . ' ' . $msg . PHP_EOL;
}

连续执行两次 comsumer.php:

第一次获取到 3 条消息, 但第一次执行中对消息 2 执行了确认响应, 剩余消息不进行确认响应. 第二次执行中只获取到剩余消息.

NACK (否定响应)

如果既不想对消息执行确定响应, 也不需要消息继续出现在队列中, 可以使用 Queue 的 nack 方法. 继续修改 while 循环:

while($msgEnvelope = $queue->get(AMQP_NOPARAM))
{
$msg = $msgEnvelope->getBody();
if(preg_match("/.*?消息2.*?/", $msg))
{
// 对消息2执行确定响应
$queue->ack($msgEnvelope->getDeliveryTag());
}else
{
$queue->nack($msgEnvelope->getDeliveryTag());
}
echo date('Y-m-d H:i:s') . ' ' . $msg . PHP_EOL;
}

推送 3 条消息后, 连续执行两次 consumper.php:

第一次执行, 获取到 3 条数据; 第二次执行未获取到任何数据. nack 方法除了可以从队列中过滤掉不需要的方法, 也可以将暂时不需要的方法重新放回队列, 将该方法的调用修改为:

$queue->nack($msgEnvelope->getDeliveryTag(), AMQP_REQUEUE);

注意: nack 方法将消息放回队列后, 队列会将消息再次推送给消费者. 如果此时队列只有一个消费者, 将会造成死循环.

PHP 下基于 php-amqp 扩展的 RabbitMQ 简单用例 (五) -- 自动 ACK、手动 ACK、NACK的更多相关文章

  1. PHP 下基于 php-amqp 扩展的 RabbitMQ 简单用例 (一) -- 安装 AMQP 扩展和 Direct Exchange 模式

    Windows 安装 amqp 扩展 RabbitMQ 是基于 amqp(高级消息队列协议) 协议的.使用 RabbitMQ 前必须为 PHP 安装相应的 amqp 扩展. 下载相应版本的 amqp ...

  2. PHP 下基于 php-amqp 扩展的 RabbitMQ 简单用例 (三) -- Header Exchange

    此模式下,消息的routing key 和队列的 routing key 会被完全忽略,而是在交换机推送消息和队列绑定交换机时, 分别为消息和队列设置 headers 属性, 通过匹配消息和队列的 h ...

  3. PHP 下基于 php-amqp 扩展的 RabbitMQ 简单用例 (二) -- Topic Exchange 和 Fanout Exchange

    Topic Exchange 此模式下交换机,在推送消息时, 会根据消息的主题词和队列的主题词决定将消息推送到哪个队列. 交换机只会为 Queue 分发符合其指定的主题的消息. 向交换机发送消息时,消 ...

  4. PHP 下基于 php-amqp 扩展的 RabbitMQ 简单用例 (四) -- Push API 和 Pull API

    RabbitMQ 中针对消息的分发提供了 Push API (订阅模式) 和 Pull API (主动获取) 两种模式. 在 PHP 中, 这两种模式分别通过 AMQPQueue 类中的 consum ...

  5. flask框架----基于flask的扩展实现的简单的页面登录

    废话不多说,直接上代码 from flask import Flask,render_template,request,redirect,session app = Flask(__name__,te ...

  6. gtk+3.0的环境配置及基于gtk+3.0的python简单样例

    /*********************************************************************  * Author  : Samson  * Date   ...

  7. RabbitMQ除开RPC的五种消模型----原生API

    2.五种消息模型 RabbitMQ提供了6种消息模型,但是第6种其实是RPC,并不是MQ,因此不予学习.那么也就剩下5种. 但是其实3.4.5这三种都属于订阅模型,只不过进行路由的方式不同. 通过一个 ...

  8. php的amqp扩展 安装(windows) rabbitmq学习篇

    因为RabbitMQ是由erlang语言实现的,所以先要安装erlang环境erlang 下载安装 http://www.erlang.org/download.htmlrabbitmq 下载安装 h ...

  9. centos7 安装rabbitmq rabbitmq-c以及amqp扩展 详细篇

    自己鼓捣了一晚上总算整明白了,有几个坑分享给小伙伴,希望能帮到你 前期准备 安装erlang 下载rpm包地址:https://github.com/rabbitmq/erlang-rpm (注意er ...

随机推荐

  1. 小程序-demo:知乎日报

    ylbtech-小程序-demo:知乎日报 1.返回顶部 0.         1.app.js //app.js App({ onLaunch: function () { //调用API从本地缓存 ...

  2. 视图表单访问控制器操作方法的POST、GET方式对应关系

    在视图中,表单默认访问方式是FormMethod.Post(不会将请求显示在地址栏中).在控制器中,操作方法不标注属性,默认为HttpGet属性.会有以下情况出现. 1.表单不指定访问方式(默认形式为 ...

  3. linux简单技巧和怎么样进入root用户

    1.使用shell的Tab键自动补全 Tab在linux命令行输入中可以自动完成.在linux 命令行中使用Tab键会极大提高输入效率2.使用shell的历史记录 shell会记录用户执行命令的历史记 ...

  4. Codeforces785D - Anton and School - 2

    传送门 题意 给出一个只包含'(',')'的字符序列,询问有多少个\(RSBS\) 分析 首先需要知道一个公式 \[\sum_{i=0}^{min(x,y)}C_x^i*C_y^i=C_{x+y}^x ...

  5. bzoj 1912: [Apio2010]patrol 巡逻【不是dp是枚举+堆】

    我是智障系列.用了及其麻烦的方法= =其实树形sp就能解决 设直径长度+1为len(环长) 首先k=1,直接连直径两端就好,答案是2*n-len 然后对于k=2,正常人的做法是树形dp:先求直径,然后 ...

  6. spoj 371 Boxes【最小费用最大流】

    对于ai==0连接(i,t,1,0),对于ai>1(s,i,ai-1,0),然后对以相邻的两个点(i,j)连接(i,j,inf,1),注意这里是一个环的形式,所以1和n+1相连 #include ...

  7. spoj 962 IM - Intergalactic Map【最大流】

    因为是无向图,所以从1到2再到3等于从2到1和3.用拆点来限制流量(i,i+n,1),然后连接(s,2+n,1),(1,t,1),(3,t,1),对于原图中的边连接(x+n,y,1)(y+n,x,1) ...

  8. 【插件开发】—— 8 IPreferenceStore,插件的键/值存储!

    前文回顾: 1 插件学习篇 2 简单的建立插件工程以及模型文件分析 3 利用扩展点,开发透视图 4 SWT编程须知 5 SWT简单控件的使用与布局搭配 6 SWT复杂空间与布局搭配 7 SWT布局详解 ...

  9. 如何快捷安装并配置MySQL 下载破解Navicat for mysql

    首先,要先下载MySQL,进官网下载相应的mysql版本,这个不收费,实在不知道的可以参考一下这篇:https://blog.csdn.net/qq_37172528/article/details/ ...

  10. python数据库连接例子

    import sqlite3 conn = sqlite3.connect('food.db') curs = conn.cursor() curs.execute(''' CREATE TABLE ...