`

RabbitMQ与PHP(一)—— RabbitMQ的原理与操作示例

 
阅读更多

RabbitMQ是流行的开源消息队列系统,用erlang语言开发,完整的实现了AMQP(高级消息队列协议)。网站在: http://www.rabbitmq.com/  上面有教程和实例代码(Python和Java的)。

7af40ad162d9f2d36b6bf89fa8ec8a136327cc4c

AMPQ协议为了能够满足各种消息队列需求,在概念上比较复杂。首先,rabbitMQ启动默认是没有任何配置的,需要客户端连接上去,设置交换机等才能工作。不把这些基础概念弄清楚,后面程序设计就容易产生问题。

1.vhosts : 虚拟主机。

一个RabbitMQ的实体上可以有多个vhosts,用户与权限设置就是依附于vhosts。对一般PHP应用,不需要用户权限设定,直接使用默认就存在的"/"就可以了,用户可以使用默认就存在的"guest"。一个简单的配置示例:

$conn_args = array(
    'host' => '127.0.0.1',
    'port' => '5672',
    'login' => 'guest',
    'password' => 'guest',
    'vhost'=>'/'
);

2.connection 与 channel :  连接与信道

connection是指物理的连接,一个client与一个server之间有一个连接;一个连接上可以建立多个channel,可以理解为逻辑上的连接。一般应用的情况下,有一个channel就够用了,不需要创建更多的channel。示例代码:

//创建连接和channel
$conn = new AMQPConnection($conn_args);
if (!$conn->connect()) {
    die("Cannot connect to the broker!\n");
}
$channel = new AMQPChannel($conn);

3.exchange 与  routingkey : 交换机与路由键

为了将不同类型的消息进行区分,设置了交换机与路由两个概念。比如,将A类型的消息发送到名为‘C1’的交换机,将类型为B的发送到'C2'的交换机。当客户端连接C1处理队列消息时,取到的就只是A类型消息。进一步的,如果A类型消息也非常多,需要进一步细化区分,比如某个客户端只处理A类型消息中针对K用户的消息,routingkey就是来做这个用途的。

$e_name = 'e_linvo'; //交换机名
$k_route = array(0=> 'key_1', 1=> 'key_2'); //路由key
//创建交换机
$ex = new AMQPExchange($channel);
$ex->setName($e_name);
$ex->setType(AMQP_EX_TYPE_DIRECT); //direct类型
$ex->setFlags(AMQP_DURABLE); //持久化
echo "Exchange Status:".$ex->declare()."\n";
for($i=0; $i<5; ++$i){
    echo "Send Message:".$ex->publish($message . date('H:i:s'), $k_route[i%2])."\n";
}

由以上代码可以看到,发送消息时,只要有“交换机”就够了。至于交换机后面有没有对应的处理队列,发送方是不用管的。routingkey可以是空的字符串。在示例中,我使用了两个key交替发送消息,是为了下面更便于理解routingkey的作用。

对于交换机,有两个重要的概念:

A,类型。有三种类型: Fanout类型最简单,这种模型忽略routingkey;Direct类型是使用最多的,使用确定的routingkey。这种模型下,接收消息时绑定'key_1'则只接收key_1的消息;最后一种是Topic,这种模式与Direct类似,但是支持通配符进行匹配,比如: 'key_*',就会接受key_1和key_2。Topic貌似美好,但是有可能导致不严谨,所以还是推荐使用Direct。

B,持久化。指定了持久化的交换机,在重新启动时才能重建,否则需要客户端重新声明生成才行。

需要特别明确的概念:交换机的持久化,并不等于消息的持久化。只有在持久化队列中的消息,才能持久化;如果没有队列,消息是没有地方存储的;消息本身在投递时也有一个持久化标志的,PHP中默认投递到持久化交换机就是持久的消息,不用特别指定。

4.queue: 队列

讲了这么多,才讲到队列呀。事实上,队列仅是针对接收方(consumer)的,由接收方根据需求创建的。只有队列创建了,交换机才会将新接受到的消息送到队列中,交换机是不会在队列创建之前的消息放进来的。换句话说,在建立队列之前,发出的所有消息都被丢弃了。下面这个图比RabbitMQ官方的图更清楚——Queue是属于ReceiveMessage的一部分。

024f78f0f736afc37053e415b219ebc4b7451266

接下来看一下创建队列及接收消息的示例:

$e_name = 'e_linvo'; //交换机名
$q_name = 'q_linvo'; //队列名
$k_route = ''; //路由key

//创建连接和channel
$conn = new AMQPConnection($conn_args);
if (!$conn->connect()) {
    die("Cannot connect to the broker!\n");
}
$channel = new AMQPChannel($conn);

//创建交换机
$ex = new AMQPExchange($channel);
$ex->setName($e_name);
$ex->setType(AMQP_EX_TYPE_DIRECT); //direct类型
$ex->setFlags(AMQP_DURABLE); //持久化
echo "Exchange Status:".$ex->declare()."\n";

//创建队列
$q = new AMQPQueue($channel);
$q->setName($q_name);
$q->setFlags(AMQP_DURABLE); //持久化

//绑定交换机与队列,并指定路由键
echo 'Queue Bind: '.$q->bind($e_name, $k_route)."\n";

//阻塞模式接收消息
echo "Message:\n";
$q->consume('processMessage', AMQP_AUTOACK); //自动ACK应答

$conn->disconnect();

/**
* 消费回调函数
* 处理消息
*/
function processMessage($envelope, $queue) {
    var_dump($envelope->getRoutingKey);
    $msg = $envelope->getBody();
    echo $msg."\n"; //处理消息
}

从上述示例中可以看到,交换机既可以由消息发送端创建,也可以由消息消费者创建。

创建一个队列(line:20)后,需要将队列绑定到交换机上(line:25)队列才能工作,routingkey也是在这里指定的。有的资料上写成bindingkey,其实一回事儿,弄两个名词反倒容易混淆。

消息的处理,是有两种方式:

A,一次性。用 $q->get([...]),不管取到取不到消息都会立即返回,一般情况下使用轮询处理消息队列就要用这种方式;

B,阻塞。用 $q->consum( callback, [...] ) 程序会进入持续侦听状态,每收到一个消息就会调用callback指定的函数一次,直到某个callback函数返回FALSE才结束。

关于callback,这里多说几句: PHP的call_back是支持使用数组的,比如: $c = new MyClass(); $c->counter = 100; $q->consume( array($c,'myfunc') ) 这样就可以调用自己写的处理类。MyClass中myfunc的参数定义,与上例中processMessage一样就行。

在上述示例中,使用的$routingkey = '', 意味着接收全部的消息。我们可以将其改为 $routingkey = 'key_1',可以看到结果中仅有设置routingkey为key_1的内容了。

注意: routingkey = 'key_1'  与 routingkey = 'key_2' 是两个不同的队列。假设: client1 与 client2 都连接到 key_1 的队列上,一个消息被client1处理之后,就不会被client2处理。而 routingkey = '' 是另类,client_all绑定到 '' 上,将消息全都处理后,client1和client2上也就没有消息了。

在程序设计上,需要规划好exchange的名称,以及如何使用key区分开不同类型的标记,在消息产生的地方插入发送消息代码。后端处理,可以针对每一个key启动一个或多个client,以提高消息处理的实时性。如何使用PHP进行多线程的消息处理,将在下一节中讲述。

更多消息模型,可以参考: http://www.rabbitmq.com/tutorials/tutorial-two-python.html

 

http://nonfu.me/p/8833.html

b03533fa828ba61e15fc0e5f4034970a304e59b4

分享到:
评论

相关推荐

    php 连接rabbitmq例子含PhpAmqpLib库

    在PHP中,与RabbitMQ进行交互通常会用到第三方库,其中最流行的一个就是`PhpAmqpLib`。这个库允许PHP开发者方便地连接到RabbitMQ服务器,发布和消费消息,从而实现异步任务处理和消息队列的功能。在你提供的资料中,...

    rabbitmq教程

    整理的rabbitmq教程,里面包含四个文档: RabbitMQ 三种Exchange.wps————————三种exchange解释及代码 rabbitmq结构.wps————————rabbitmq架构简介 ...RabbitMQ研究与应用.pdf——————简单的研究

    rabbitmq与spring集成示例demo

    2. **Spring AMQP**:Spring框架提供了一个名为Spring AMQP的模块,它为RabbitMQ提供了一种简单的方式来配置和操作AMQP代理。通过Spring AMQP,我们可以声明Exchange(交换机)、Queue(队列)和Binding(绑定),并...

    RabbitMQ整合spring示例代码(java maven)

    这个示例代码将帮助开发者理解如何在实际项目中利用RabbitMQ进行消息通信,同时利用Spring简化相关配置和操作。对于大型分布式系统而言,这样的集成是至关重要的,它能提高系统的稳定性和可维护性。

    RabbitMQ示例代码

    RabbitMQ是一个开源的消息代理和队列服务器,它在分布式系统中广泛用于处理异步任务、消息传递和解耦组件。在这个"RabbitMQ示例代码"中,我们可以期待找到如何在SpringBoot应用中集成和使用RabbitMQ的实例。 首先,...

    RabbitMQ与SpringMVC集成

    在提供的`spring.amqp.stocks.rar`文件中,可能包含了一个示例应用,展示了如何在SpringMVC项目中配置和使用RabbitMQ进行股票数据的发布和订阅。用户可以通过解压文件,查看源代码和文档(如`安装说明.docx`),了解...

    rabbitmq代码示例

    在这个“rabbitmq代码示例”中,我们将深入探讨如何使用C语言和Python(对应压缩包中的`RabbitMQDemo-C`和`RabbitMQDemo-P`)来与RabbitMQ进行交互。 首先,让我们了解RabbitMQ的基本概念: 1. **生产者(Producer...

    C#操作RabbitMQ的完整实例

    一、下载RabbitMQ http://www.rabbitmq.com/install-windows.html 二、下载OTP http://www.erlang.org/downloads 三、安装OTP、RabbitMQ 四、配置RabbitMQ 找到bat的目录 执行相关命令 1.添加用户密码 ...

    RabbitMQ操作demo

    本教程将通过一个PHP操作RabbitMQ的实例——"RabbitMQ操作demo",来讲解如何在PHP环境中使用RabbitMQ。 首先,安装RabbitMQ是基础步骤。你需要在服务器上下载并安装RabbitMQ,这通常涉及访问其官方网站下载适合你...

    rabbitMQ实战java版-rabbitMQ-demo.zip

    《RabbitMQ实战Java版——基于rabbitMQ-demo.zip的详解》 在当今的分布式系统中,消息队列作为异步处理、解耦组件的关键技术,得到了广泛应用。RabbitMQ作为一款开源的消息代理和队列服务器,以其稳定性和易用性...

    ActiveMQ / RabbitMQ 示例

    总之,这个示例程序将帮助你理解如何在不同的消息队列系统中使用JMS API进行消息通信,包括设置服务器配置、创建和管理连接、发送和接收消息等核心操作。这对于构建可扩展的、健壮的分布式系统至关重要。

    rabbitMQ 示例代码

    ”这表明提供的代码是基于先前发布的文档编写的,目的是帮助读者通过实际操作理解RabbitMQ的工作原理。示例代码通常包括生产者(发布消息)和消费者(接收消息)的实现,以及可能的队列、交换机和绑定等概念的展示。...

    Windows c++中RabbitMQ-c特殊消息队列的保姆教程(csdn)————程序.pdf

    在Windows环境下,使用C++与RabbitMQ进行通信,我们需要首先了解RabbitMQ的基本概念,它是一个开源的消息代理和队列服务器,常用于处理异步任务和分布式系统中的消息传递。RabbitMQ-c是一个C语言编写的轻量级...

    rabbitmqdemo

    Spring 框架提供了与 RabbitMQ 集成的模块——Spring AMQP,它简化了 RabbitMQ 的使用,提供了一套更高级的抽象。在 Spring 中,你可以使用 `RabbitTemplate` 进行消息发送,通过配置 `@RabbitListener` 注解来创建...

    C#RabbitMQ示例

    以上就是一个简单的C#与RabbitMQ交互的示例。在实际应用中,可能会涉及到更复杂的消息处理,如工作队列、发布/订阅模式、延迟消息等。通过RabbitMQ,你可以构建出健壮、高并发的后台处理系统,有效地解耦各个服务,...

    php7可用 rabbitmq-c 插件

    在PHP7环境中,与RabbitMQ进行交互通常需要一个PHP扩展。`rabbitmq-c`就是这样一个扩展,它允许PHP代码直接调用C语言实现的RabbitMQ客户端库。然而,需要注意的是,`rabbitmq-c`本身并不能直接在PHP中使用,还需要...

    RabbitMq与Spring整合实例

    RabbitMQ是一个开源的消息代理和队列服务器,广泛应用于各种业务场景,而Spring框架则是一个企业级应用开发的Java平台,提供了丰富的功能和良好的社区支持。将RabbitMQ与Spring整合,可以方便地在Spring应用中使用...

    最新最全rabbitmq与erlang版本匹配-2020-04-23.docx

    综上所述,RabbitMQ与Erlang的版本匹配是一项关键任务,关系到系统的稳定性和安全性。正确匹配和升级版本可以提升性能,增强安全性,并确保服务的连续性。因此,了解和遵循这个匹配指南是非常重要的。

    rabbitmq+PHP教程代码.rar

    《RabbitMQ与PHP结合应用实战教程》 在IT领域,消息队列作为一种重要的中间件技术,被广泛应用于异步处理、系统解耦等场景。RabbitMQ作为最流行的开源消息队列系统,以其稳定性和易用性备受青睐。本教程以"rabbitmq...

    tp6使用rabbitmq

    2. **安装PHP RabbitMQ客户端**:TP6需要一个PHP的RabbitMQ客户端库来与RabbitMQ服务器交互。可以使用Composer来安装`php-amqplib/php-amqplib`这个库,执行命令:`composer require php-amqplib/php-amqplib`。 3....

Global site tag (gtag.js) - Google Analytics