Мне бы чуточку асинхронности

Общие вопросы по использованию второй версии фреймворка. Если не знаете как что-то сделать и это про Yii 2, вам сюда.
Ответить
TopClans
Сообщения: 11
Зарегистрирован: 2019.04.27, 10:44

Мне бы чуточку асинхронности

Сообщение TopClans » 2019.07.01, 14:33

Добрый день.
Для проекта в одном месте требуется быстрая отработка. Необходимо отправить по API запрос к 10-20 внешним серверам, принять ответ и вывести его пользователю. Сервера отвечают всегда с разной скоростью, поэтому пользователю нужно показывать ответы серверов по мере собственно получения ответов. Что-то вроде поиска билетов у Aviasales и подобных сервисах.

Знаю, PHP и Yii2 не для того созданы, но тем не менее есть такая потребность, всё остальное в проекте работает хорошо.

придумал 3 варианта, первый:
1) для каждого API создать свой контроллер
2) при необходимости пользователь делает запрос, на этой же странице с помощью AJAX идут запросы к каждому контроллеру
3) по мере получения ответов (все серверы отвечают с разной скоростью) с помощью JS заполняется табличка с ответами
Но в таком случае 10-20 раз запустится весь yii и даст ненужную нагрузку

другой вариант - создать REST API и делать всё примерно так же, но с использованием API - тогда, насколько я понимаю, будет использоваться меньше ресурсов (или нет?)

ну и третий вариант - вообще колхозный: вынести всю логику работы с этими внешними серверами в отдельное место, которое не будет связано с yii, которые будут только отвечать на запросы всё того же ajax.

Что можете посоветовать?

Аватара пользователя
proctoleha
Сообщения: 259
Зарегистрирован: 2016.07.10, 19:00

Re: Мне бы чуточку асинхронности

Сообщение proctoleha » 2019.07.01, 15:33

Как вариант - использовать web socket. Не ajax
Вот за что я не люблю линукс, так это за свои кривые, временами, руки

TopClans
Сообщения: 11
Зарегистрирован: 2019.04.27, 10:44

Re: Мне бы чуточку асинхронности

Сообщение TopClans » 2019.07.01, 16:08

с веб сокетами я знаком, но не понимаю, как их в данном случае применить.
для начала нужно принять данные от пользователя, и потом их отправить запрос внешним серверам. я понимаю, что можно на стороне клиента "слушать" эти веб-сокеты, но важно максимально быстро отослать все запросы на внешние сервера. как помогут веб сокеты?

Аватара пользователя
proctoleha
Сообщения: 259
Зарегистрирован: 2016.07.10, 19:00

Re: Мне бы чуточку асинхронности

Сообщение proctoleha » 2019.07.01, 17:12

При нажатии на кнопу принять данные, у вас отрабатывает js, который за этой кнопкой следит. И используете стандартный метод socket.send для отправки данных.
https://learn.javascript.ru/websockets

Например, вы передали socket.send("MyKey");

Сервер, который слушает нужный сокет, получает ключ, запускает стописят http клиентов, по завершении соединения каждый из них, также через сокет отсылает ответ.

Не?
Вот за что я не люблю линукс, так это за свои кривые, временами, руки

TopClans
Сообщения: 11
Зарегистрирован: 2019.04.27, 10:44

Re: Мне бы чуточку асинхронности

Сообщение TopClans » 2019.07.01, 17:24

понял, а в чем преимущество такого метода перед AJAX? использование веб-сокетов всё-таки усложнит разработку, а основное его преимущество, насколько я знаю - это то, что клиент может постоянно слушать сообщения от сервера. в моём случае в этом нет необходимости, нужен один запрос и один ответ.

но даже если и использовать сокеты, начальный вопрос всё же остаётся - как всё организовать?

Аватара пользователя
ElisDN
Сообщения: 5315
Зарегистрирован: 2012.10.07, 10:24
Контактная информация:

Re: Мне бы чуточку асинхронности

Сообщение ElisDN » 2019.07.01, 21:10

TopClans писал(а):
2019.07.01, 17:24
это то, что клиент может постоянно слушать сообщения от сервера. в моём случае в этом нет необходимости, нужен один запрос и один ответ.
Как раз и прилетят постепенно по одному сокетному соединению двадцать ответов вашему JS скрипту на странице.

А для Ajax, как вы и сказали, нужно двадцать запросов отправить и все с учётом тайм-аутов дождаться.

Аватара пользователя
ivanbcdef
Сообщения: 14
Зарегистрирован: 2017.08.19, 13:50
Откуда: Бровары
Контактная информация:

Re: Мне бы чуточку асинхронности

Сообщение ivanbcdef » 2019.07.02, 06:45

Попробуйте Swoole, Redis pub/sub, WebSocket.

Вот: https://github.com/immusen/yii2-swoole-websocket.

Вообще в PHP как-то не очень много альтернатив для WebSocket. Ratchet и Swoole, кажись.

Я для этого использую Mojolicious.

TopClans
Сообщения: 11
Зарегистрирован: 2019.04.27, 10:44

Re: Мне бы чуточку асинхронности

Сообщение TopClans » 2019.07.03, 11:36

ElisDN писал(а):
2019.07.01, 21:10
TopClans писал(а):
2019.07.01, 17:24
это то, что клиент может постоянно слушать сообщения от сервера. в моём случае в этом нет необходимости, нужен один запрос и один ответ.
Как раз и прилетят постепенно по одному сокетному соединению двадцать ответов вашему JS скрипту на странице.

А для Ajax, как вы и сказали, нужно двадцать запросов отправить и все с учётом тайм-аутов дождаться.
но мне не нужно постепенно, мне нужно чтобы запросы отправлялись асинхронно.
в вашем же варианте, насколько я понял, будет так: пользователь "даёт отмашку", и включается скрипт, который будет постепенно отправлять запросы на 20 серверов.каждый сервер отвечает примерно 1-2 секунды, постепенный опрос 20 серверов это минимум 20 секунд. да, первые результаты прилетят на страницу уже через 1-2 секунды, но ведь всё равно нужно ждать 20 секунд пока дойдёт очередь до последнего запроса на последний сервер.
и в то же время ajax может отправить 20 запросов одновременно, а не постепенно. да и принять он может 20 запросов. и теоретически через 1-2 секунды в ajax уже начнут поступать ответы на эти 20 запросов
разве я не прав?

Аватара пользователя
proctoleha
Сообщения: 259
Зарегистрирован: 2016.07.10, 19:00

Re: Мне бы чуточку асинхронности

Сообщение proctoleha » 2019.07.03, 14:26

Вот пришла команда скрипту отправь 20 запросов.

Скрипт, например, из массива (или др. логика), берет адреса, команды, в цикле запускает 20 http клиентов, меньше чем за одну миллисекунду, после завершения запроса, каждый из http клиентов проталкивает через сокет ответ. На странице клиента js слушатель сокета их разруливает.

В случае с ajax читайте пост Дм. Елисеева

Разработка, конечно, усложнится, но цель, поставленная в первом посте, будет достигнута.
Вот за что я не люблю линукс, так это за свои кривые, временами, руки

Аватара пользователя
ElisDN
Сообщения: 5315
Зарегистрирован: 2012.10.07, 10:24
Контактная информация:

Re: Мне бы чуточку асинхронности

Сообщение ElisDN » 2019.07.03, 16:29

TopClans писал(а):
2019.07.03, 11:36
но мне не нужно постепенно, мне нужно чтобы запросы отправлялись асинхронно.
в вашем же варианте, насколько я понял, будет так: пользователь "даёт отмашку", и включается скрипт, который будет постепенно отправлять запросы на 20 серверов.каждый сервер отвечает примерно 1-2 секунды, постепенный опрос 20 серверов это минимум 20 секунд. да, первые результаты прилетят на страницу уже через 1-2 секунды, но ведь всё равно нужно ждать 20 секунд пока дойдёт очередь до последнего запроса на последний сервер.
и в то же время ajax может отправить 20 запросов одновременно, а не постепенно. да и принять он может 20 запросов. и теоретически через 1-2 секунды в ajax уже начнут поступать ответы на эти 20 запросов
разве я не прав?
Я как раз и рассказал про общение с асинхронным сервером по одному вебсокету вместо двадцати Ajax-подключений к синхронному серверу.

Страница из JS отправляет один Ajax-запрос и висит на одном сокете. Сервер асинхронно/многопоточно/многопроцессно/как угодно одновременно отправляет свои 20 запросов и каждый этот процесс отправляет свой ответ в один и тот же канал вебсокета.

Отправляете отмашку по одному Ajax и получаете все результаты по одному вебсокету, не упираясь в ограничения браузера и сервера на число одновременных Ajax-подключений.

TopClans
Сообщения: 11
Зарегистрирован: 2019.04.27, 10:44

Re: Мне бы чуточку асинхронности

Сообщение TopClans » 2019.07.04, 23:26

Сервер асинхронно/многопоточно/многопроцессно/как угодно одновременно отправляет свои 20 запросов и каждый этот процесс отправляет свой ответ в один и тот же канал вебсокета.
ну хоть убейте, не понимаю: в yii приходит один ajax-запрос, как его заставить выполнить 20 запросов одновременно?
или вы имеете в виду ситуацию, когда в качестве сервера выступает не yii, а что-то поддерживающее многопоточность, типа nodejs?

Аватара пользователя
ElisDN
Сообщения: 5315
Зарегистрирован: 2012.10.07, 10:24
Контактная информация:

Re: Мне бы чуточку асинхронности

Сообщение ElisDN » 2019.07.05, 00:02

Код: Выделить всё

foreach ($urls as $url) {
    exec("php yii parser/parse $url $userId > /dev/null &");
}

TopClans
Сообщения: 11
Зарегистрирован: 2019.04.27, 10:44

Re: Мне бы чуточку асинхронности

Сообщение TopClans » 2019.08.02, 18:08

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 &');
работает именно так, как и хотел. спасибо за помощь!

kukuruku
Сообщения: 1262
Зарегистрирован: 2011.02.14, 11:36

Re: Мне бы чуточку асинхронности

Сообщение kukuruku » 2019.08.03, 14:20

TopClans писал(а):
2019.08.02, 18:08
вот это мне и было нужно.
в результате использовал не совсем сокеты, а комет-сервер (получилось менее трудозатратно, а комет как раз идеально под мою задачу подошёл), и код выглядит так:

Код: Выделить всё

$out = Yii::getAlias('@app');
$ex = exec('php '.$out.'/yii controller > /dev/null &');
работает именно так, как и хотел. спасибо за помощь!
а где тут комет?

Ответить