都有什么公司需要网站建设,wordpress能批量上传图片么,合肥住房和建设厅网站首页,网站制作与设计(using php-amqplib) 前提必读 本教程假设RabbitMQ是安装在标准端口上运行#xff08;5672#xff09;。如果您使用不同的主机、端口或凭据#xff0c;则连接设置需要调整。 如果您在本教程中遇到困难#xff0c;可以通过邮件列表与我们联系。 开始 在第二个教程中#xf… (using php-amqplib) 前提必读 本教程假设RabbitMQ是安装在标准端口上运行5672。如果您使用不同的主机、端口或凭据则连接设置需要调整。 如果您在本教程中遇到困难可以通过邮件列表与我们联系。 开始 在第二个教程中我们学习了如何使用工作队列在多个工人之间分配耗时的任务。 但是如果我们需要在远程计算机上运行一个函数并等待结果呢嗯那是另一回事了。这种模式通常称为远程过程调用或RPC。 在本教程中我们将使用RabbitMQ搭建一个RPC系统一个客户端和一个可扩展的RPC服务器。由于我们没有任何值得分配的耗时的任务所以我们将创建一个返回Fibonacci数的模拟一个RPC服务。 Client interface 为了说明如何使用RPC服务我们将创建一个简单的客户类。它将公开一个名为调用的方法该方法发送一个RPC请求并阻塞直到接收到结果为止 $fibonacci_rpc new FibonacciRpcClient();
$response $fibonacci_rpc-call(30);
echo [.] Got , $response, \n; 关于RPC的一些建议 虽然RPC是计算中非常常见的模式但它经常遭到批评。当程序员不知道函数调用是本地的或者它是一个缓慢的RPC时问题就出现了。这样的混乱导致了不可预知的系统并给调试增加了不必要的复杂性。而简化软件滥用会导致难以维护的RPC代码。 考虑到这一点请考虑以下建议 确保很明显哪个函数调用是本地调用并且它是远程的。记录系统。使组件之间的依赖关系清晰。处理错误案例。RPC服务器长时间处于下行状态时客户端应如何响应有疑问时避免RPC。如果可以则应该使用异步管道而不是像阻塞这样的RPC结果被异步推送到下一个计算阶段。 回调队列(Callback queue) 一般在RabbitMQ做RPC是容易的。客户端发送一条请求消息和一个响应消息的服务器回复。为了接收响应我们需要向请求发送一个“回调”队列地址。我们可以使用默认队列。让我们试试看 list($queue_name, ,) $channel-queue_declare(, false, false, true, false);$msg new AMQPMessage($payload,array(reply_to $queue_name));$channel-basic_publish($msg, , rpc_queue);
# ... then code to read a response message from the callback_queue ... 消息属性AMQP协议(0-9-1 protocol)预定义了一套14个属性去一个消息。大多数属性很少使用除了以下内容delivery_mode: 将消息标记为持久性。 (with a value of 2) or transient (1). 您可能会从第二个教程中记住这个属性。content_type用来描述编码的MIME类型。例如对于常用的JSON编码将此属性设置为应用程序/ JSON是一个很好的做法。reply_to常用的名字一个回调队列。correlation_id有助于将RPC响应与请求关联起来。 Correlation Id 在上面介绍的方法中我们建议为每个RPC请求创建一个回调队列。这是非常低效的但幸运的是有一个更好的方法——让我们为每个客户机创建一个回调队列。 这引发了一个新问题在队列中收到了响应不清楚响应的请求属于哪个。那时候correlation_id属性用于。我们将把它设置为每个请求的唯一值。稍后当我们在回调队列中接收消息时我们将查看这个属性并在此基础上我们将能够将响应与请求匹配。如果我们看到一个未知的correlation_id值我们可以安全地忽略信息-它不属于我们的请求。 您可能会问为什么我们应该忽略回调队列中的未知消息而不是失败出错呢这是由于服务器端可能出现竞争情况。虽然不太可能RPC服务器可能在发送完答案后死亡但在发出请求的确认消息之前。如果发生这种情况重新启动的RPC服务器将再次处理请求。这就是为什么在客户机上我们必须优雅地处理重复响应而RPC应该理想地是幂等的。 总结 我们的RPC会像这样工作 当客户端启动时它创建一个匿名的独占回调队列。 一个RPC请求客户端发送消息两个属性reply_to设置回调队列和correlation_id它被设置为每个请求的唯一值。 请求被发送到一个rpc_queue队列。 RPC worker又名服务器正在等待该队列上的请求。当一个请求时它的工作和发送消息的结果返回给客户端使用从reply_to队列。 客户机等待回调队列上的数据。当消息出现时它检查correlation_id属性。如果它与请求的值匹配则返回对应用程序的响应。 汇总 Fibonacci 递归源码: function fib($n) {if ($n 0)return 0;if ($n 1)return 1;return fib($n-1) fib($n-2);
}我们声明fibonacci(斐波那契)函数。它只假设有效的正整数输入。不要指望这一个能为大数字工作而且这可能是最慢的递归实现。我们的RPC服务器rpc_server.php代码看起来像这样 ?php require_once DIR . /vendor/autoload.php;use PhpAmqpLibConnectionAMQPStreamConnection;use PhpAmqpLibMessageAMQPMessage; $connection new AMQPStreamConnection(localhost, 5672, guest, guest);$channel $connection-channel(); $channel-queue_declare(rpc_queue, false, false, false, false); function fib($n) { if ($n 0)return 0;
if ($n 1)return 1;
return fib($n-1) fib($n-2); } echo [x] Awaiting RPC requestsn;$callback function($req) { $n intval($req-body);
echo [.] fib(, $n, )\n;$msg new AMQPMessage((string) fib($n),array(correlation_id $req-get(correlation_id)));$req-delivery_info[channel]-basic_publish($msg, , $req-get(reply_to));
$req-delivery_info[channel]-basic_ack($req-delivery_info[delivery_tag]); }; $channel-basic_qos(null, 1, null);$channel-basic_consume(rpc_queue, , false, false, false, false, $callback); while(count($channel-callbacks)) { $channel-wait(); } $channel-close();$connection-close(); ?
服务器代码相当简单像往常一样我们从建立连接、通道和声明队列开始。我们可能需要运行多个服务器进程。为了分散负载同样多的服务器需要设置prefetch_count, 设置$channel.basic_qos美元。我们用basic_consume访问队列。然后我们进入while循环在其中等待请求消息完成工作并发送响应。我们rpc_client.php RPC客户端代码 ?php require_once DIR . /vendor/autoload.php;use PhpAmqpLibConnectionAMQPStreamConnection;use PhpAmqpLibMessageAMQPMessage; class FibonacciRpcClient { private $connection;
private $channel;
private $callback_queue;
private $response;
private $corr_id;public function __construct() {$this-connection new AMQPStreamConnection(localhost, 5672, guest, guest);$this-channel $this-connection-channel();list($this-callback_queue, ,) $this-channel-queue_declare(, false, false, true, false);$this-channel-basic_consume($this-callback_queue, , false, false, false, false,array($this, on_response));
}
public function on_response($rep) {if($rep-get(correlation_id) $this-corr_id) {$this-response $rep-body;}
}public function call($n) {$this-response null;$this-corr_id uniqid();$msg new AMQPMessage((string) $n,array(correlation_id $this-corr_id,reply_to $this-callback_queue));$this-channel-basic_publish($msg, , rpc_queue);while(!$this-response) {$this-channel-wait();}return intval($this-response);
} }; $fibonacci_rpc new FibonacciRpcClient();$response $fibonacci_rpc-call(30);echo [.] Got , $response, n; ? 现在是一个很好的时间来让我们完整的示例源代码rpc_client.php和rpc_server.php。我们的RPC服务现在准备好了。我们可以启动服务器php rpc_server.php# [x] Awaiting RPC requests 请求斐波那契数运行客户机 php rpc_client.php# [x] Requesting fib(30)这里介绍的设计并不是RPC服务的唯一实现但它有一些重要的要点 如果RPC服务器太慢您可以通过运行另一个服务器来扩展。试着在一个新的控制台再运行第一个rpc_server.php。 在客户端RPC只需要发送和接收一条消息。不喜欢queue_declare需要同步调用。因此RPC客户机只需要一次RPC请求的一次网络往返。 我们的代码仍然非常简单并没有试图解决更复杂但重要的问题例如 如果没有服务器运行客户端应该如何反应 客户端应该对RPC有某种超时吗 如果服务器发生故障并引发异常是否应该转发给客户端 在处理前防止无效传入消息如检查边界、类型。 如果您想进行实验您可能会发现management UI对于查看队列非常有用。