这正是你在事件循环中做任何事情时必须避免的问题:它不能阻塞,因为其他任何人都试图订阅,或者调用消息,或者其他任何事件驱动的事情都不会发生,直到这完成了.
这更像是一个架构问题,一旦你找到了最好的方法,它就是简化它并确保它适用于你需要的所有任务.
Ratchet提供了一个ZMQ绑定 – 这很棒,因为一旦你设置它,你在端口5555上收到的任何东西都会在onYourMethodName()或你想要的任何东西上点击你的事件循环!
考虑到这一点,你需要将需要完成的工作发送到一个作业队列,另一个进程(反应有它的child-process扩展,我不是特别喜欢,因为它在用户区域进行轮询而不是中断驱动的I / O像PHP的PCNTL extension)或类似的.
如果你想“让它正常工作”,可以启动需要完成的工作,以及连接ID或其他id,这样你就可以知道响应需要回到谁,在子进程中以及何时发送出来.这不会阻止!
如果你想以更好的方式做到这一点,我强烈建议你研究一下这个和它的架构,这样你就可以在你的职业生涯中随时掌握这些知识,当你再次遇到这样的异步问题时,采用“火 – 和 – 忘记’方法.在事件循环中消除需要对作业队列执行的操作,然后忘记它.
你的工作队列可以执行它的工作,当它完成后,通过ZMQ(正在侦听的端口5555,请记住)发回该结果,然后可以将数据发送回客户端.
对于关于工作队列的精彩演讲,我强烈推荐来自PHPNW的this one.
最后一点,因为你打开这个东西并在端口5555上监听数据,你可以从任何地方发送这些数据.它可以是进程间通信,就像你有一个将数据发送到端口5555的java应用程序,或者几乎任何东西.它将事物绑定在一起,但不能将它们耦合在一起,这在您的架构中很重要.
有关实际使用ZMQ的示例,他们在this page here(如上所述)提供了所有内容,但我会尝试解释一下发生了什么.
$pull->bind('tcp://127.0.0.1:5555');
$pull->on('message', array($pusher, 'onYourMethodName'));
这部分意味着当任何东西向端口5555发送数据时,它是一个“消息”(你可以谷歌其他选项而不是消息),它将在你的$pusher对象中调用onYourMethodName.它真的很简单.超过5555,点击$pusher :: onYourMethodName.
因此,您只需要在事件处理程序中创建您的方法(在onMessage(),onSubscribe()等旁边)…再次在页面上提到这一点.
public function onYourMethodName($data)
{
/** You'll probably want to send the data in JSON format **/
/** Imagine you get through a 'topic' in here... **/
$data = json_decode($data, true);
/** You should already have stored the people who are connected, topics etc - see the tutorial **/
$topic = $this->subscribedTopics[$data['topic']];
/** Send the data out to everyone subscribed to this topic **/
$topic->broadcast($data);
}
如果您希望能够将数据发送给特定用户而不是每个人,那么有很多方法可以实现.看看this question我是怎么做到的,但现在已经有一段时间了.
你现在唯一需要做的就是,在你的处理程序中(在onMessage或其他任何东西),实际上把需要在队列中完成的东西连同它应该被发回的人(主题)放在一起.
在你的工作人员完成它并获取数据的最后,它需要调用它来命中我上面显示的代码:
$context = new ZMQContext();
$socket = $context->getSocket(ZMQ::SOCKET_PUSH, 'my pusher');
$socket->connect("tcp://localhost:5555");
$socket->send(json_encode($data));
所以这就是你需要做的:
>让第一位听到端口5555>在事件处理程序等中创建方法>不要担心队列或任何事情>创建一个非常简单的PHP脚本来完成上述4行代码,并证明当你单独运行该脚本时,它确实将数据发送到你的事件循环中>然后担心如何将它添加到您的队列并让您的工作人员处理它