私のプロジェクトでメカニックServer Side Eventsを使用しようとしていました。 (これはステロイドのロングポーリングのようなものです)RabbitMQとの接続解除後にApacheプロセスが終了しない
「Sending events from the server」の例題は、美しく動作します。数秒後に切断されると、Apacheプロセスが強制終了されます。このメソッドは正常に動作します。
BUT! RabbitMQを使用しようとすると、ブラウザからサーバーとの接続が切断された後にプロセスが終了しない(es.close()
)。処理はそのままで、ドッカーコンテナが再起動した後でのみ終了します。
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バグのようなものがあります。またはApach2の?
私は何を使用します。
- 最終ドッカーと
- php:7.1.12-apache or php:5.6-apache画像(これはPHPの両方のバージョンで発生)
いくつかのスクリーンショットをドッキングウィンドウ-構成:
してください、私は何が起こっているかを把握するのに役立つ...
P.S.私の英語には申し訳ありません。間違いやタイプミスが見つかった場合は、そのコメントをポイントしてください。私は非常に感謝します:)
いいえ。プロセスはapache2によって強制終了されません。これは2004年以来の最も古いバグです - https://bugs.php.net/bug.php?id=30301。 'connection_aborted'と' connection_status'関数は動作しません。そして、これを修正する方法はありません。私のためにWebsocketd(最後にDが付いている)を使う方が良いです –