PHP操作rabbitmq实战

PHP操作rabbitmq实战

    随着近几年来消息队列越来越多的被各大企业应用到业务场景中,rabbitmq也成为了一款被广大码农所喜爱的消息中间件产品。rabbitmq是基于amqp协议实现的,且与redis内置的队列相比在消费的可靠性保障、高可用、队列监控、流量控制等方面都有明显的优势,下面是php操作rabbitmq的实战演习(个人亲测可用)。

    rabbitmq的安装和php amqp扩展的安装大家可以参考:rabbitmq安装
  
  在操作之前还需要理解以下几个rabbit概念:
  broker:rabbitmq中的broker个人理解是server的意思,相对于客户端,是服务端rabbitmq-server的一个实例;
  vhost:虚拟主机,一个rabbitmq服务可以建立多个虚拟主机,默认所有队列在“/”虚拟主机目录下;
  connection:即对应一个客户端的连接;
  channel:通道,通道建立在connection之上,一个connection可以建立多个channel,一个channel内可以可进行多次数据的交互,channel的使用多次connect的开销;
  exchange:交换机,类似于网络交换机的原理,rabbitmq的队列生产者先将信息发送到交换机上,再按一定的规则发送给队列;
  queue:队列,需要绑定到交换机上才能接收到数据;

    php安装amqp扩展之后,可以采用以下方式实现队列数据的发布和消费:
consumer.php:

<?php
$config = [
    'host'      => 'localhost',
    'vhost'     => '/',
    'port'      => 5672,
    'login'     => 'admin',
    'password'  => 'admin'
];

//链接broker
$conn = new AMQPConnection($config);
if(!$conn->connect()) {
    echo "cannot connect to broker.";
    exit();
}

//创建一个通道
$ch = new AMQPChannel($conn);
//创建一个交换机
$ex = new AMQPExchange($ch);
//路由键
$routeKey = "key_1";
//交换机名称
$exchangeName = "exchange_1";
//设置交换机名称
$ex->setName($exchangeName);
//设置交换机类型
$ex->setType(AMQP_EX_TYPE_DIRECT);
//设置持久化
$ex->setFlags(AMQP_DURABLE);
//声明交换机
$ex->declareExchange();

//创建一个消息队列
$q = new AMQPQueue($ch);
//设置队列名称
$q->setName('queue_1');
//设置队列持久
$q->setFlags(AMQP_DURABLE);
//声明消息队列
$q->declareQueue();

//交换机和队列通过routeKey进行绑定
$q->bind($ex->getName(), $routeKey);

//接收消息并进行处理的回调方法
function receive($envelope, $queue) {
    echo $envelope->getBody()."\n";
    $queue->ack($envelope->getDeliveryTag());
}

//设置队列消费者回调方法,并阻塞
$q->consume('receive');

执行php consumer.php后,将会初始化交换机、队列的信息,可以在rabbitmq web管理界面看到相应的信息,需要注意的是执行consume方法后进程会阻塞,队列里有数据就会处理,没数据就会一直阻塞,可以使用php consumer.php &放后台执行。

publisher.php:

<?php
$config = [
    'host'      => 'localhost',
    'vhost'     => '/',
    'port'      => 5672,
    'login'     => 'admin',
    'password'  => 'admin'
];

//链接broker
$conn = new AMQPConnection($config);
if(!$conn->connect()) {
    echo "cannot connect to broker.";
    exit();
}

//创建一个通道
$ch = new AMQPChannel($conn);
//创建一个交换机
$ex = new AMQPExchange($ch);
//路由键
$routeKey = "key_1";
//交换机名称
$exchangeName = "exchange_1";
//设置交换机名称
$ex->setName($exchangeName);
//设置交换机类型
$ex->setType(AMQP_EX_TYPE_DIRECT);
//设置持久化
$ex->setFlags(AMQP_DURABLE);
//声明交换机
$ex->declareExchange();

//创建10个消息
for($i=0;$i<1000;$i++) {
    $msg = [
        'data' => 'message_'.$i,
        'hello' => 'world',
    ];

    echo "Send message:".$ex->publish(json_encode($msg), $routeKey, AMQP_NOPARAM, array('delivery_mode' => 2))."\n";
}

这里需要注意的是,由于在之前的consumer脚本中创建队列并绑定交换机时,通过“key_1”进行绑定,这里在发布信息的时候也需要绑定相同的routeKey,要不然不同的话交换机就会把消息丢弃,相应的队列也接收不到消息。

$ex->publish(json_encode($msg), $routeKey, AMQP_NOPARAM, array('delivery_mode' => 2))

这里的delivery_mode为2意味着我们发送到队列里的信息需要持久化存储,即使rabbitmq服务器故障,下次重启的时候消息依然会在队列中存在。

    在实际的项目开发中,其实用到更多的是基于php-amqplib库对rabbitmq进行操作,php-amqplib库也是开源的,github项目地址:https://github.com/php-amqplib/php-amqplib,需要的大家可以自己去下载安装,github项目也都有介绍,下面是基于php-amqplib库实现队列的发布和消费:
consumer.php

// 设置交换机名、路由键、队列名
$_conf = [
    'exchange_name' => 'exchange_test',
    'route_key'     => 'hello',
    'queue_name'    => 'test',
];

// 连接 rabbitmq 服务
$connection = new AMQPStreamConnection('locahost', 5672, 'admin', 'admin');

// 获取信道
$channel = $connection->channel();

// 声明队列
$channel->queue_declare($_conf['queue_name']);

// 绑定队列
$channel->queue_bind($_conf['queue_name'], $_conf['exchange_name'], $_conf['route_key']);

// 定义回调函数
$callback = function ($msg) {
// 消息确认
$msg->delivery_info['channel']->basic_ack($msg->delivery_info['delivery_tag']);

if ($msg->body == 'quit') {
	// 停止消费并退出
	$msg->delivery_info['channel']->basic_cancel($msg->delivery_info['consumer_tag']);
	} else {
	echo 'Hello ', $msg->body, PHP_EOL;
	}
};

//没收到上一条消息的ack前,暂时不接收下一条消息
$channel->basic_qos(null, 1, null);

//消费者订阅队列
$channel->basic_consume($_conf['queue_name'],
'',
false,
false,
false,
false,
$callback);

//开始消费
while (count($channel->callbacks)) {
$channel->wait();
}

注意,需要先在管理界面建立好相应交换机和队列。callback回调函数里执行相应的消费端业务逻辑,之后再ack掉。

publisher.php

// 设置交换机名、路由键、队列名
$_conf = [
	'exchange_name' => 'exchange_test',
	'route_key'     => 'hello',
	'queue_name'    => 'test',
];

// 连接 rabbitmq 服务
$connection = new AMQPStreamConnection('localhost', 5672, 'admin', 'admin');
// 获取信道
$channel = $connection->channel();

// 创建消息
$data = "{$_conf['exchange_name']}#{$_conf['route_key']}#{$_conf['queue_name']} " . date('H:i:s');
$msg = new AMQPMessage($data);

// 发送消息
$channel->basic_publish($msg, $_conf['exchange_name'], $_conf['route_key']);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值