【发布时间】:2017-12-27 17:28:46
【问题描述】:
我试图在我的项目中使用Server Side Events 机制。 (这就像类固醇上的长轮询)
来自“Sending events from the server”的示例字幕效果很好。几秒钟后,从断开连接,apache 进程被杀死。这个方法很好用。
但是!如果我尝试使用RabbitMQ,Apache 不会在浏览器与服务器断开连接后终止进程 (es.close())。并且进程保持原样,只有在 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();
}
}
会发生什么:
- 浏览器与服务器建立 SSE 连接。
var es = new EventSource(url); - Apache2 生成新进程来处理此请求。
- PHP 生成一个新队列并连接到它。
- 浏览器关闭连接
es.close() - Apache2 不会终止进程并保持原样。 RabbitMQ 的队列不会被删除。如果我进行一些重新连接,它会产生一堆进程和一堆队列(1 个重新连接 = 1 个进程 = 1 个队列)。
- 我关闭了所有选项卡 -- 进程处于活动状态。我关闭了浏览器——同样的情况。
看起来有点 PHP 错误。还是 Apache2 的?
我用什么:
- 最后一个 Docker 和 docker-compose
- php:7.1.12-apache or php:5.6-apache 图像(这发生在两个版本的 PHP 上)
一些截图:
请帮我弄清楚发生了什么...
附:对不起我的英语不好。如果您能找到错误或拼写错误,请在 cmets 中指出。我将不胜感激:)
【问题讨论】:
标签: php apache docker rabbitmq amqp