Intereting Posts
Автоматическое добавление пробелов после периодов и запятых, избегая номеров Почему мы должны включать кавычку при вставке строковой переменной в базу данных mysql php Как вызвать фильтр «time_diff» в Twig назначить клиента нескольким группам клиентов на пурпурный Шрифт Bangla (Unicode) не корректно отображается в tcpdf Каковы плюсы и минусы различных типов полей даты и времени в MySQL? Представление массива array_merge_recursive PHP для целых ключей Как я взорву эту строку в PHP? Передача по ссылке третьего параметра в PHP array_walk без предупреждения Тернарные операторы. Возможно одностороннее действие? Как вы настраиваете / стилируете ошибки codeigniter? Laravel: Общая ошибка: 1615 Подготовленное заявление нужно переплатить Извлечение автоматических заголовков из видео YouTube Как я вставляю только определенные части PHP-страницы, используя PHP Справка с PHP Pagination Script для базы данных с плоским файлом

Как реализовать прослушивание событий в PHP

вот моя проблема: у меня есть сценарий (назовем его comet.php), который подкрепляется клиентским скриптом AJAX и ждет, когда произойдут изменения:

while(no_changes){ usleep(100000); //check for changes } 

Мне не нравится это слишком много, это не очень масштабируемо, и это («imho») «плохая практика». Я хотел бы улучшить это поведение с помощью семафора (?) Или в любом случае при параллельном программировании. Не могли бы вы дать мне несколько советов о том, как справиться с этим? (Я знаю, это не короткий ответ, но отправной точки было бы достаточно.)

Изменить : как насчет LibEvent ?

Вы можете решить эту проблему с помощью ZeroMQ .

ZeroMQ – это библиотека, которая обеспечивает наддувные сокеты для соединения вещей (потоки, процессы и даже отдельные машины) вместе.

Я предполагаю, что вы пытаетесь передать данные с сервера клиенту. Ну, хороший способ сделать это – использовать API EventSource ( доступные полисы ).

client.js

Подключается к stream.php через EventSource.

 var stream = new EventSource('stream.php'); stream.addEventListener('debug', function (event) { var data = JSON.parse(event.data); console.log([event.type, data]); }); stream.addEventListener('message', function (event) { var data = JSON.parse(event.data); console.log([event.type, data]); }); 

router.php

Это длительный процесс, который прослушивает входящие сообщения и отправляет их любому слушающему.

 <?php $context = new ZMQContext(); $pull = $context->getSocket(ZMQ::SOCKET_PULL); $pull->bind("tcp://*:5555"); $pub = $context->getSocket(ZMQ::SOCKET_PUB); $pub->bind("tcp://*:5556"); while (true) { $msg = $pull->recv(); echo "publishing received message $msg\n"; $pub->send($msg); } - <?php $context = new ZMQContext(); $pull = $context->getSocket(ZMQ::SOCKET_PULL); $pull->bind("tcp://*:5555"); $pub = $context->getSocket(ZMQ::SOCKET_PUB); $pub->bind("tcp://*:5556"); while (true) { $msg = $pull->recv(); echo "publishing received message $msg\n"; $pub->send($msg); } 

stream.php

Каждый пользователь, подключающийся к сайту, получает свой собственный stream.php. Этот сценарий длительный и ждет сообщений от маршрутизатора. После получения нового сообщения оно выведет это сообщение в формате EventSource.

 <?php $context = new ZMQContext(); $sock = $context->getSocket(ZMQ::SOCKET_SUB); $sock->setSockOpt(ZMQ::SOCKOPT_SUBSCRIBE, ""); $sock->connect("tcp://127.0.0.1:5556"); set_time_limit(0); ini_set('memory_limit', '512M'); header("Content-Type: text/event-stream"); header("Cache-Control: no-cache"); while (true) { $msg = $sock->recv(); $event = json_decode($msg, true); if (isset($event['type'])) { echo "event: {$event['type']}\n"; } $data = json_encode($event['data']); echo "data: $data\n\n"; ob_flush(); flush(); } 

Чтобы отправлять сообщения всем пользователям, просто отправьте их на маршрутизатор. Затем маршрутизатор распространит это сообщение на все прослушивающие потоки. Вот пример:

 <?php $context = new ZMQContext(); $sock = $context->getSocket(ZMQ::SOCKET_PUSH); $sock->connect("tcp://127.0.0.1:5555"); $msg = json_encode(array('type' => 'debug', 'data' => array('foo', 'bar', 'baz'))); $sock->send($msg); $msg = json_encode(array('data' => array('foo', 'bar', 'baz'))); $sock->send($msg); 

Это должно доказать, что вам не нужно, чтобы node.js выполнял программирование в реальном времени. PHP может справиться с этим просто отлично.

Кроме того, socket.io – действительно хороший способ сделать это. И вы можете легко подключиться к socket.io к вашему PHP-коду через ZeroMQ.

Смотрите также

  • ZeroMQ
  • ZeroMQ PHP Bindings
  • ZeroMQ – это ответ – Ian Barber (видео)
  • socket.io

Это действительно зависит от того, что вы делаете в своем скрипте на стороне сервера. Есть ситуации, когда у вас нет выбора, кроме как делать то, что вы делаете выше.

Однако, если вы делаете что-то, что связано с вызовом функции, которая будет блокироваться до тех пор, пока что-то не произойдет, вы можете использовать это, чтобы избежать гонок вместо вызова usleep() (что является ИМХО частью, которая будет считаться «плохой практикой») ,

Предположим, что вы ожидали данных из файла или какого-либо другого потока, который блокирует. Вы можете сделать это:

 while (($str = fgets($fp)) === FALSE) continue; // Handle the event here 

Действительно, PHP – это неправильный язык для подобных действий. Но есть ситуации (я знаю, потому что я сам их рассматривал), где PHP – единственный вариант.

Насколько мне нравится PHP, я должен сказать, что PHP не лучший выбор для этой задачи. Node.js намного лучше подходит для такого рода вещей, и он очень хорош. Это также довольно просто реализовать, если у вас есть знание JS.

Теперь, если вы не хотите тратить процессорные циклы, вам нужно создать скрипт PHP, который будет подключаться к определенному серверу на определенном порту. Указанный сервер должен прослушивать соединения на выбранном порту и каждый X-период проверки времени для того, что вы хотите проверить (например, записи db для новых сообщений), а затем отправляет сообщение каждому подключенному клиенту, что новая запись готова.

Теперь не так сложно реализовать эту архитектуру очереди событий в PHP, но вам потребуется буквально 5 минут, чтобы сделать это с помощью Node.js и Socket.IO, не беспокоясь, будет ли это работать в большинстве браузеров.

Я согласен с консенсусом здесь в том, что PHP не лучшее решение здесь. Вам действительно нужно искать специализированные технологии реального времени для решения этой асинхронной проблемы доставки данных с вашего сервера вашим клиентам. Похоже, вы пытаетесь внедрить HTTP-Long Polling, что нелегко решить кросс-браузер. Это много раз решалось разработчиками продуктов Comet, поэтому я предлагаю вам взглянуть на решение Comet или даже на лучшее решение для WebSocket с резервной поддержкой старых браузеров.

Я бы предположил, что вы позволили PHP выполнять функциональность веб-приложения, в которой он подходит, и выбрать выделенное решение для вашей азартной функциональности в реальном времени, событий, асинхронных.

Вам нужна библиотека в реальном времени.

Одним из примеров является Ratchet http://socketo.me/

Часть, которая заботится о пабе, обсуждается на http://socketo.me/docs/wamp

Ограничение здесь заключается в том, что PHP также должен быть инициатором изменяемых данных.

Другими словами, это не волшебство позволяет вам подписаться на обновление MySQL. Но если вы можете отредактировать код настройки MySQL, вы можете добавить туда часть публикации.