내 프로젝트에 Server Side Events 역학을 사용하려고했습니다. (이것은 스테로이드에 대한 긴 폴링과 같습니다)RabbitMQ와의 연결 해제 후 Apache 프로세스가 종료되지 않습니다.
"Sending events from the server"의 예제는 아름답게 작동합니다. 몇 초 후에 연결 해제에서 아파치 프로세스가 종료됩니다. 이 방법은 잘 작동합니다.
BUT! RabbitMQ을 사용하려고하면 서버가 브라우저와 연결을 끊은 후에 프로세스가 종료되지 않습니다 (es.close()
). 그리고 프로세스는 그대로두고 도커 컨테이너가 다시 시작된 후에 만 죽습니다.
connection_aborted 및 connection_status이 전혀 작동하지 않습니다. connection_aborted
은 연결이 끊긴 후에도 0
만 반환하고 connection_status는 CONNECTION_NORMAL
을 반환합니다. RabbitMQ를 사용할 때만 발생합니다. RMQ가 없으면이 기능이 잘 작동합니다.
ignore_user_abort(false)
도 작동하지 않습니다.
코드 예제 :
- 브라우저가 서버에 SSE 연결을 설정합니다 : 어떻게됩니까
<?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);
- Apache2는이 요청을 처리하기위한 새로운 프로세스를 생성합니다.
- PHP는 새로운 대기열을 생성하고 그것에 연결합니다.
- 브라우저가 닫히는 연결
es.close()
- 아파치 2는 프로세스를 죽이지 않으며 그대로 유지됩니다. RabbitMQ의 대기열은 삭제되지 않습니다. 몇 가지 재 연결을하면 여러 개의 프로세스와 여러 개의 대기열이 생성됩니다 (1 재 연결 = 1 프로세스 = 1 대기열).
- 나는 모든 탭을 닫습니다 - 프로세스가 살아 있습니다. 나는 브라우저를 닫는다 - 같은 상황.
일종의 PHP 버그가 있습니다. 아니면 Apach2?
내가 사용하는 :
- 마지막 도커 및
일부 스크린 샷 (이 두가지 버전의 PHP에서 발생)
제발, 무슨 일이 일어나는지 알아 내도록 도와주세요.
P. 미안해, 내 영어로. 실수 나 오타를 찾을 수 있다면 주석에서 가리 키십시오. 나는 매우 감사 할 것입니다.
아니요. 프로세스는 apache2에 의해 종료되지 않습니다. 이것은 2004 년 이래 가장 오래된 버그입니다 - https://bugs.php.net/bug.php?id=30301. 'connection_aborted'와'connection_status' 함수가 작동하지 않습니다. 그리고 이것들을 고칠 방법이 없습니다. Websocketd (끝 부분에 D가 있음)를 사용하는 것이 좋습니다 –