Мне бы чуточку асинхронности
Мне бы чуточку асинхронности
Добрый день.
Для проекта в одном месте требуется быстрая отработка. Необходимо отправить по API запрос к 10-20 внешним серверам, принять ответ и вывести его пользователю. Сервера отвечают всегда с разной скоростью, поэтому пользователю нужно показывать ответы серверов по мере собственно получения ответов. Что-то вроде поиска билетов у Aviasales и подобных сервисах.
Знаю, PHP и Yii2 не для того созданы, но тем не менее есть такая потребность, всё остальное в проекте работает хорошо.
придумал 3 варианта, первый:
1) для каждого API создать свой контроллер
2) при необходимости пользователь делает запрос, на этой же странице с помощью AJAX идут запросы к каждому контроллеру
3) по мере получения ответов (все серверы отвечают с разной скоростью) с помощью JS заполняется табличка с ответами
Но в таком случае 10-20 раз запустится весь yii и даст ненужную нагрузку
другой вариант - создать REST API и делать всё примерно так же, но с использованием API - тогда, насколько я понимаю, будет использоваться меньше ресурсов (или нет?)
ну и третий вариант - вообще колхозный: вынести всю логику работы с этими внешними серверами в отдельное место, которое не будет связано с yii, которые будут только отвечать на запросы всё того же ajax.
Что можете посоветовать?
Для проекта в одном месте требуется быстрая отработка. Необходимо отправить по API запрос к 10-20 внешним серверам, принять ответ и вывести его пользователю. Сервера отвечают всегда с разной скоростью, поэтому пользователю нужно показывать ответы серверов по мере собственно получения ответов. Что-то вроде поиска билетов у Aviasales и подобных сервисах.
Знаю, PHP и Yii2 не для того созданы, но тем не менее есть такая потребность, всё остальное в проекте работает хорошо.
придумал 3 варианта, первый:
1) для каждого API создать свой контроллер
2) при необходимости пользователь делает запрос, на этой же странице с помощью AJAX идут запросы к каждому контроллеру
3) по мере получения ответов (все серверы отвечают с разной скоростью) с помощью JS заполняется табличка с ответами
Но в таком случае 10-20 раз запустится весь yii и даст ненужную нагрузку
другой вариант - создать REST API и делать всё примерно так же, но с использованием API - тогда, насколько я понимаю, будет использоваться меньше ресурсов (или нет?)
ну и третий вариант - вообще колхозный: вынести всю логику работы с этими внешними серверами в отдельное место, которое не будет связано с yii, которые будут только отвечать на запросы всё того же ajax.
Что можете посоветовать?
- proctoleha
- Сообщения: 298
- Зарегистрирован: 2016.07.10, 19:00
Re: Мне бы чуточку асинхронности
Как вариант - использовать web socket. Не ajax
Вот за что я не люблю линукс, так это за свои кривые, временами, руки
Re: Мне бы чуточку асинхронности
с веб сокетами я знаком, но не понимаю, как их в данном случае применить.
для начала нужно принять данные от пользователя, и потом их отправить запрос внешним серверам. я понимаю, что можно на стороне клиента "слушать" эти веб-сокеты, но важно максимально быстро отослать все запросы на внешние сервера. как помогут веб сокеты?
для начала нужно принять данные от пользователя, и потом их отправить запрос внешним серверам. я понимаю, что можно на стороне клиента "слушать" эти веб-сокеты, но важно максимально быстро отослать все запросы на внешние сервера. как помогут веб сокеты?
- proctoleha
- Сообщения: 298
- Зарегистрирован: 2016.07.10, 19:00
Re: Мне бы чуточку асинхронности
При нажатии на кнопу принять данные, у вас отрабатывает js, который за этой кнопкой следит. И используете стандартный метод socket.send для отправки данных.
https://learn.javascript.ru/websockets
Например, вы передали socket.send("MyKey");
Сервер, который слушает нужный сокет, получает ключ, запускает стописят http клиентов, по завершении соединения каждый из них, также через сокет отсылает ответ.
Не?
https://learn.javascript.ru/websockets
Например, вы передали socket.send("MyKey");
Сервер, который слушает нужный сокет, получает ключ, запускает стописят http клиентов, по завершении соединения каждый из них, также через сокет отсылает ответ.
Не?
Вот за что я не люблю линукс, так это за свои кривые, временами, руки
Re: Мне бы чуточку асинхронности
понял, а в чем преимущество такого метода перед AJAX? использование веб-сокетов всё-таки усложнит разработку, а основное его преимущество, насколько я знаю - это то, что клиент может постоянно слушать сообщения от сервера. в моём случае в этом нет необходимости, нужен один запрос и один ответ.
но даже если и использовать сокеты, начальный вопрос всё же остаётся - как всё организовать?
но даже если и использовать сокеты, начальный вопрос всё же остаётся - как всё организовать?
Re: Мне бы чуточку асинхронности
Как раз и прилетят постепенно по одному сокетному соединению двадцать ответов вашему JS скрипту на странице.
А для Ajax, как вы и сказали, нужно двадцать запросов отправить и все с учётом тайм-аутов дождаться.
Re: Мне бы чуточку асинхронности
Попробуйте Swoole, Redis pub/sub, WebSocket.
Вот: https://github.com/immusen/yii2-swoole-websocket.
Вообще в PHP как-то не очень много альтернатив для WebSocket. Ratchet и Swoole, кажись.
Я для этого использую Mojolicious.
Вот: https://github.com/immusen/yii2-swoole-websocket.
Вообще в PHP как-то не очень много альтернатив для WebSocket. Ratchet и Swoole, кажись.
Я для этого использую Mojolicious.
Re: Мне бы чуточку асинхронности
но мне не нужно постепенно, мне нужно чтобы запросы отправлялись асинхронно.
в вашем же варианте, насколько я понял, будет так: пользователь "даёт отмашку", и включается скрипт, который будет постепенно отправлять запросы на 20 серверов.каждый сервер отвечает примерно 1-2 секунды, постепенный опрос 20 серверов это минимум 20 секунд. да, первые результаты прилетят на страницу уже через 1-2 секунды, но ведь всё равно нужно ждать 20 секунд пока дойдёт очередь до последнего запроса на последний сервер.
и в то же время ajax может отправить 20 запросов одновременно, а не постепенно. да и принять он может 20 запросов. и теоретически через 1-2 секунды в ajax уже начнут поступать ответы на эти 20 запросов
разве я не прав?
- proctoleha
- Сообщения: 298
- Зарегистрирован: 2016.07.10, 19:00
Re: Мне бы чуточку асинхронности
Вот пришла команда скрипту отправь 20 запросов.
Скрипт, например, из массива (или др. логика), берет адреса, команды, в цикле запускает 20 http клиентов, меньше чем за одну миллисекунду, после завершения запроса, каждый из http клиентов проталкивает через сокет ответ. На странице клиента js слушатель сокета их разруливает.
В случае с ajax читайте пост Дм. Елисеева
Разработка, конечно, усложнится, но цель, поставленная в первом посте, будет достигнута.
Скрипт, например, из массива (или др. логика), берет адреса, команды, в цикле запускает 20 http клиентов, меньше чем за одну миллисекунду, после завершения запроса, каждый из http клиентов проталкивает через сокет ответ. На странице клиента js слушатель сокета их разруливает.
В случае с ajax читайте пост Дм. Елисеева
Разработка, конечно, усложнится, но цель, поставленная в первом посте, будет достигнута.
Вот за что я не люблю линукс, так это за свои кривые, временами, руки
Re: Мне бы чуточку асинхронности
Я как раз и рассказал про общение с асинхронным сервером по одному вебсокету вместо двадцати Ajax-подключений к синхронному серверу.TopClans писал(а): ↑2019.07.03, 11:36 но мне не нужно постепенно, мне нужно чтобы запросы отправлялись асинхронно.
в вашем же варианте, насколько я понял, будет так: пользователь "даёт отмашку", и включается скрипт, который будет постепенно отправлять запросы на 20 серверов.каждый сервер отвечает примерно 1-2 секунды, постепенный опрос 20 серверов это минимум 20 секунд. да, первые результаты прилетят на страницу уже через 1-2 секунды, но ведь всё равно нужно ждать 20 секунд пока дойдёт очередь до последнего запроса на последний сервер.
и в то же время ajax может отправить 20 запросов одновременно, а не постепенно. да и принять он может 20 запросов. и теоретически через 1-2 секунды в ajax уже начнут поступать ответы на эти 20 запросов
разве я не прав?
Страница из JS отправляет один Ajax-запрос и висит на одном сокете. Сервер асинхронно/многопоточно/многопроцессно/как угодно одновременно отправляет свои 20 запросов и каждый этот процесс отправляет свой ответ в один и тот же канал вебсокета.
Отправляете отмашку по одному Ajax и получаете все результаты по одному вебсокету, не упираясь в ограничения браузера и сервера на число одновременных Ajax-подключений.
Re: Мне бы чуточку асинхронности
ну хоть убейте, не понимаю: в yii приходит один ajax-запрос, как его заставить выполнить 20 запросов одновременно?Сервер асинхронно/многопоточно/многопроцессно/как угодно одновременно отправляет свои 20 запросов и каждый этот процесс отправляет свой ответ в один и тот же канал вебсокета.
или вы имеете в виду ситуацию, когда в качестве сервера выступает не yii, а что-то поддерживающее многопоточность, типа nodejs?
Re: Мне бы чуточку асинхронности
Код: Выделить всё
foreach ($urls as $url) {
exec("php yii parser/parse $url $userId > /dev/null &");
}
Re: Мне бы чуточку асинхронности
вот это мне и было нужно.ElisDN писал(а): ↑2019.07.05, 00:02Код: Выделить всё
foreach ($urls as $url) { exec("php yii parser/parse $url $userId > /dev/null &"); }
в результате использовал не совсем сокеты, а комет-сервер (получилось менее трудозатратно, а комет как раз идеально под мою задачу подошёл), и код выглядит так:
Код: Выделить всё
$out = Yii::getAlias('@app');
$ex = exec('php '.$out.'/yii controller > /dev/null &');
Re: Мне бы чуточку асинхронности
а где тут комет?TopClans писал(а): ↑2019.08.02, 18:08 вот это мне и было нужно.
в результате использовал не совсем сокеты, а комет-сервер (получилось менее трудозатратно, а комет как раз идеально под мою задачу подошёл), и код выглядит так:работает именно так, как и хотел. спасибо за помощь!Код: Выделить всё
$out = Yii::getAlias('@app'); $ex = exec('php '.$out.'/yii controller > /dev/null &');
Re: Мне бы чуточку асинхронности
комет - в конце каждого из скриптов, которые запускаются в консоли. он отправляет сообщение на внешний comet сервер, а оттуда приходит сообщение в JS на сайте.
в контексте темы - мне нужна было просто возможность запустить несколько PHP скриптов одновременно, и о запуске через консоль я не задумывался, пока мне не подсказали.