(使用php-amqplib)前提条件本教程假设RabbitMQ已安装并运行在标准端口(5672)。如果您使用不同的主机、端口或凭据,则需要调整您的连接设置。从哪里获得帮助如果您在学习本教程时遇到困难,可以通过邮件列表与我们联系。在之前的教程中,我们改进了日志系统。我们使用直接广播的方式,而不是只使用直接(direct)广播方式的fanoutswitch,从而获得了选择性接收日志的可能。虽然使用直接交换机改进了我们的系统,但它仍然有局限性——它不能根据多个标准进行路由。在我们的日志系统中,我们可能希望根据严重性以及发出日志的源来订阅日志。您可能从syslogUNIX工具知道这个概念,它根据严重性(信息/警告/暴击...)和设备(auth/cron/kern...)路由日志。这会给我们带来很大的灵活性,我们可能想监听来自kern的严重错误,以及来自kern的所有日志。要在日志系统中实现这一点,我们需要了解更复杂的主题交换。主题交换发送to主题交换消息,不能是任何routing_key-它必须是单词列表,用逗号分隔。单词可以是任何东西,但通常它们指定与消息相关的某些特征。一些有效的路由键示例:stock.usd.nyse,nyse.vmw,"quick.orange.rabbit"。你最喜欢的路由键中最多可以有255个字节的字。绑定键也必须是相同的形式。主题交换背后的逻辑类似于直接message,使用特定routingkey发送的消息将被发送到所有绑定到bindingkey的队列。但是bindingkey有两个重要的特例:*(starnumber)可以替换一个词。#(hash)可以替换零个或多个单词。在exa中最容易解释这一点mple:在这个例子中,我们将发送所有描述动物的消息。消息将使用包含三个词(两个点)的路由键发送。路由键中的第一个词将描述速度,第二个词是颜色,第三个词是:..。我们创建了三个绑定:使用绑定键*.orange.*的Q1绑定和使用*.*.rabbit和lazy.#的Q2。这些绑定可以概括如下:Q1对所有橙色动物感兴趣。Q2想听听关于兔子的一切,关于懒惰动物的一切。具有quick.orange.rabbit路由键的消息将被传递到两个队列。信息lazy.orange.elephant也会发送给他们两个。另一方面,quick.orange.fox只会到第一行,而lazy.brown.fox只会到第二行。lazy.pink.rabbit只会被发送到第二个队列一次,即使它同时匹配两个绑定。quick.brown.fox不匹配任何绑定,因此将被丢弃。如果我们违约,用一四个词,比如orange或者quick.orange.male.rabbit?那么这些消息将不会匹配任何绑定并且会丢失。另一方面,lazy.orange.male.rabbit,即使它有四个词,也会匹配最后一个绑定并被传递到第二个队列。话题交流话题交流(Topicexchange)功能强大,可以像其他交流一样。当队列绑定到#(hash)绑定键时——它将接收所有消息,而不管路由键与扇出开关相同。当绑定中未使用特殊字符*(星号)和#(散列)时,主题交换的行为类似于直接交换。综上所述,我们将在我们的日志系统中使用主题交换。我们将从一个工作假设开始,即日志的路由键有两个词:.。代码与上一个教程几乎相同。emit_log_topic.php代码:channel();$channel->exchange_declare('topic_logs','topic',false,false,false);$routing_key=isset($argv[1])&&!empty($argv[1])?$argv[1]:'anonymous.info';$data=implode('',array_slice($argv,2));if(empty($data))$data="HelloWorld!";$msg=newAMQPMessage($data);$channel->basic_publish($msg,'topic_logs',$routing_key);echo"[x]Sent",$routing_key,':',$data,"\n";$channel->close();$connection->close();?>receive_logs_topic.php代码:channel();$channel->exchange_declare('topic_logs','topic',false,false,false);列表($queue_name,,)=$channel->queue_declare("",false,false,true,false);$binding_keys=array_slice($argv,1);if(empty($binding_keys)){file_put_contents('php://stderr',"Usage:$argv[0][binding_key]\n");exit(1);}foreach($binding_keysas$binding_key){$channel->queue_bind($queue_name,'topic_logs',$binding_key);}echo'[*]等待日志。要退出,请按CTRL+C',"\n";$callback=function($msg){echo'[x]',$msg->delivery_info['routing_key'],':',$msg->body,"\n";};$channel->basic_consume($queue_name,'',false,true,false,false,$callback);while(count($channel->callbacks)){$channel->wait();}$channel->close();$connection->close();?>接收所有日志:phpreceive_logs_topic.php"#"从kern接收所有日志:phpreceive_logs_topic.php"kern.*"或者,如果你只想听关于关键的日志:phpreceive_logs_topic.php"*.critical"你可以创建多个绑定:phpreceive_logs_topic.php"kern.*""*.critical"从路由键kern.critical类型phpemit_log_topic.php"kern.critical""Acriticalkernelerror"中触发日志希望使用两个以上的路由关键参数。(完整源码:emit_log_topic.php和receive_logs_topic)接下来,要了解如何通过远程过程调用进行消息往返,可以阅读下一章:RabbitMQ+PHP教程六(RPC).RabbitMQ翻译-RabbitMQtutorial-Topics