我试图在我的项目中使用Server Side Events机制。 (这就像对类固醇的长轮询)
“Sending events from the server”字幕的示例效果很好。几秒钟后,断开连接,apache进程被终止。这种方法很好。
BUT!如果我尝试使用RabbitMQ,则在浏览器与服务器(es.close()
)断开连接后,Apache不会终止该进程。并且进程按原样离开,并且仅在docker容器重新启动后才被杀死。
connection_aborted和connection_status根本不起作用。 connection_aborted
仅返回0
,即使断开连接,connection_status也会返回CONNECTION_NORMAL
。它只在我使用RabbitMQ时才会发生。没有RMQ,这个功能运作良好。
ignore_user_abort(false)
也不起作用。
代码示例:
<?php
use PhpAmqpLib\Channel\AMQPChannel;
use PhpAmqpLib\Connection\AbstractConnection;
use PhpAmqpLib\Exception\AMQPTimeoutException;
use PhpAmqpLib\Message\AMQPMessage;
class RequestsRabbit
{
protected $rabbit;
/** @var AMQPChannel */
protected $channel;
public $exchange = 'requests.events';
public function __construct(AbstractConnection $rabbit)
{
$this->rabbit = $rabbit;
}
public function getChannel()
{
if ($this->channel === null) {
$channel = $this->rabbit->channel();
$channel->exchange_declare($this->exchange, 'fanout', false, false, false);
$this->channel = $channel;
}
return $this->channel;
}
public function send($message)
{
$channel = $this->getChannel();
$message = json_encode($message);
$channel->basic_publish(new AMQPMessage($message), $this->exchange);
}
public function subscribe(callable $callable)
{
$channel = $this->getChannel();
list($queue_name) = $channel->queue_declare('', false, false, true, false);
$channel->queue_bind($queue_name, $this->exchange);
$callback = function (AMQPMessage $msg) use ($callable) {
call_user_func($callable, json_decode($msg->body));
};
$channel->basic_consume($queue_name, '', false, true, false, false, $callback);
while (count($channel->callbacks)) {
if (connection_aborted()) {
break;
}
try {
$channel->wait(null, true, 5);
} catch (AMQPTimeoutException $exception) {
}
}
$channel->close();
$this->rabbit->close();
}
}
会发生什么:
var es = new EventSource(url);
es.close()
看起来某种PHP错误。还是Apach2?
我用的是什么:
一些截图:
请帮我弄清楚发生了什么......
P.S。对不起我的英语不好。如果您可以找到错误或拼写错误,请在评论中指出。我将非常感激:)
答案 0 :(得分:0)
您没有说在服务器端事件期间是否使用send()
或subscribe()
(或两者)。假设您正在使用subscribe()
,则没有错误。这个循环:
while (count($channel->callbacks)) {
if (connection_aborted()) {
break;
}
try {
$channel->wait(null, true, 5);
} catch (AMQPTimeoutException $exception) {
}
}
将一直运行,直到进程被终止或从RabbitMQ远程关闭连接。这在侦听排队的消息时是正常的。如果你需要在某个时刻停止循环,你可以设置一个变量来检查循环,或者在SSE结束时抛出一个异常(虽然我觉得这很尴尬)。