Я давно использую простой шаблон запрос/ответ (клиент/сервер), и он очень стабилен. Однако я попытался улучшить это, чтобы ни клиент, ни сервер не могли зависнуть, если что-то пойдет не так с другим.
Исходный (блокирующий) шаблон выглядит следующим образом:
< Сильный > server.php
$zmq = new ZMQContext;
$sock = new ZMQSocket( $zmq, ZMQ::SOCKET_REP );
$sock->bind('tcp://*:5555');
while( true ){
echo "Server waiting..\n";
$ping = $sock->recv();
echo "Acknowledging ",$ping,"..\n";
$sock->send('Pong');
}
< Сильный > client.php
$zmq = new ZMQContext;
$sock = new ZMQSocket( $zmq, ZMQ::SOCKET_REQ );
$sock->connect('tcp://localhost:5555');
echo "Pinging..\n";
$sock->send('Ping');
echo "Client waiting..\n";
$pong = $sock->recv();
echo $pong," in reply. exiting.\n";
Это работает отлично, за исключением того, что если сервер умирает между получением запроса и отправкой ответа, клиент будет зависать навсегда.
Что я хочу сделать, так это выполнить вызовы $sock->recv
без блокировки и разрешить тайм-аут, если нет ответа. Я пытался добиться этого с помощью опроса. например Замена блокирующего вызова recv сверху на что-то вроде этого на стороне клиента:
client.php (опрос)
$zmq = new ZMQContext;
$sock = new ZMQSocket( $zmq, ZMQ::SOCKET_REQ );
$sock->connect('tcp://localhost:5555');
echo "Pinging..\n";
$sock->send('Ping');
echo "Client polling..\n";
$poller = new ZMQPoll;
$poller->add( $sock, ZMQ::POLL_IN );
$readable = [];
$writeable = [];
$poller->poll( $readable, $writeable, 1000 );
foreach( $readable as $sock ){
$pong = $sock->recv();
echo $pong," in reply. exiting.\n";
exit(0);
}
echo "No reply after 1s\n";
Однако я думаю, что этот подход создает риск того, что полученный ответ может быть предназначен для другого клиента, если два или более клиентов отправили запрос примерно в одно и то же время. Я предполагаю, что синхронный метод гарантирует, что этого не произойдет, но нарушает ли это метод опроса?
Итак, мой вопрос вкратце. Как запрашивающий сокет должен получить ответ без блокировки, при этом гарантируя, что сообщение не предназначено для другого клиента?
1 ответ
Вопрос : Как запрашивающий сокет должен получить ответ без блокировки, гарантируя, что сообщение не предназначено для другого клиента?
Добро пожаловать в Zen-of-Zero (включая нулевую гарантию)
Помимо стратегий, как обойти взаимный тупик (ы), REQ/REP
dFSA обязательно попадет (просто неизвестно, как скоро это произойдет, но это произойдет), где я всегда предпочитайте двустороннее неблокирующее циклическое сканирование .poll()
-before-.recv()
, гарантированная-"доставка"-и-"маршрутизация" — это вопрос другого уровня.
REQ/REP
(задокументированный в ZMTP/RFC(28)) работает сам по себе следующим образом:
Каждый отправленный запрос проходит циклическую проверку среди всех сервисов, и каждый полученный ответ сопоставляется с последним отправленным запросом.
Если сервисы недоступны, любая операция отправки на сокете блокируется до тех пор, пока по крайней мере одна услуга становится доступной. Сокет REQ не должен отбрасывать сообщения.
Наблюдается на REQ.send()
-стороне, и
Каждый полученный запрос ставится в очередь среди всех клиентов, и каждый отправленный ответ направляется клиенту, отправившему последний запрос. Если первоначальный запросчик больше не существует, ответ автоматически отбрасывается.
Наблюдается на REP.recv()
-стороне.
Последнее предложение решило неправомерную доставку для случаев, когда REQ
-сторона перестала существовать прямо перед вызовом REP.send()
.
Сообщения, с другой стороны,
может содержать самопроверку надлежащей доставки (может проверить их перед принятием {процесса|забыть}-решения),
может содержать криптографически гарантированную форму «спасения вашей шеи» для случаев, когда полезная нагрузка попадает в чужие руки (имея нулевое значение, если не имеет также «правильного» ключа) — поэтому может отправлять всем всем без греха Нарушение любой политики защиты контента (но все же довольно жестокая и ресурсоемкая «дорогая» стратегия, не так ли?)
все,
на самом деле все,
зависит от ваших предпочтений
и уровней надежности, приемлемых с учетом уровня паранойи, связанной с безопасностью (и, в основном, должного уровня разумного) паранойи, которая была установлена и взаимно признана как правдоподобная среди всех соответствующих участников проблемы предметной области и владельцы рисков.
Лучший следующий шаг:
Просмотрите все свои требования и риски в проблемной области, оцените разумные затраты на устранение проблем и примите решение о разумной, но экономически эффективной конструкции специализированного многоагентного распределенного протокола уровня приложения, который добавит все требования, которые ZeroMQ сознательно пропустил. для включения в интеллектуальные, масштабируемые, тривиальные архетипы с почти нулевой задержкой (которые могут не подходить для варианта использования «как есть», поскольку любое из ваших требований к надстройкам высокого уровня требует дополнительной работы, которую необходимо выполнить до/во время/после сообщение должно было быть доставлено )
Похожие вопросы
Новые вопросы
php
PHP — это широко используемый язык сценариев общего назначения с открытым исходным кодом, мультипарадигмальный, динамически типизированный и интерпретируемый, изначально разработанный для веб-разработки на стороне сервера. Используйте этот тег для вопросов о программировании на языке PHP.