Всем привет. Очень нужно объяснение одной проблемы, попробую коротко.
Начну с задачи: нужно сделать поисковую выдачу на вебсокетах. То есть пользователь ввел запрос, браузер соединился по вебсокету с сервером, при нахождении очередного результата сервер отправляет его браузеру и браузер отображает. Вебсокет нужен потому, что поиск может длиться хоть полчаса (очень большое количество разных источников), и использовать тут ajax я не хочу (чтобы не опрашивать сервер постоянно и не нагружать его), а просто загрузка страницы и вовсе исключена в силу постановки самой задачи (долгое время выполнения). Очень привлекательной выглядит событийная модель вебсокета, в общем.
Теперь о проблеме. Я прочитал и просмотрел много материалов про связку, которая, видимо, самая популярная. Ставится node.js, в браузер грузится socket.io. Браузер общается с node.js. Сам node.js общается с laravel через redis. Laravel броадкастом рассылает ивент с именем канала, он (видимо), пишется в redis, а node.js слушает redis, подхватывает новый ивент и рассылает его всем браузерам, слушающим этот канал.
Но мне нужно:
а) Передать параметры поиска в Laravel из браузера
б) Вернуть результат обработки от Laravel конкретному браузеру, а не всем подряд вообще
Пункт "б" вообще нигде не раскрывается. Если пользователь не авторизован, то совершенно (мне) не понятно как laravel будет передавать что-то ему, ведь о том, кто именно запрашивает результат laravel не знает.
Я нигде не могу найти ответы на эти вопросы и даже не понимаю, туда ли я двигаюсь. Кто-нибудь сталкивался, может подсказать?
Дополню, что и выкидывать отсюда Laravel не хочется. Там уже есть сам функционал поиска. Писать демон на PHP и как-то засовывать туда этот функционал - дело сомнительное...
Дополню, что вызывать как-то Laravel из node.js тоже не подходит - тогда придется ждать, когда ларавел полностью отработает. По идее надо как-то сделать так, чтобы при пользовательском запросе лара начал искать, и в процессе поиска, прямо в огромном цикле кидал события наружу о найденных новых данных.
Не исключено, что я вообще не понимаю как это работает и может ли так работать, т.к. сталкиваюсь первый раз.
поиск может длиться хоть полчаса (очень большое количество разных источников)
Может тогда стоит отправлять запрос на поиск, ставить его в очередь, а результат записывать в БД, тогда пользователю не нужно будет ждать.
Сюда же можно и общение с сервером через сокеты прикрутить, чтобы сразу отобразить результат поиска, если пользователь ещё никуда не ушёл, но в базу всё равно лучше записывать результаты такой длительной операции.
а) Передать параметры поиска в Laravel из браузера
Как я и сказал, отправляем обычный запрос на сервер, но сам поиск делаем в очереди. По завершению поиска пишем результат в БД и выполняем broadcast нужного события.
б) Вернуть результат обработки от Laravel конкретному браузеру, а не всем подряд вообще
Собственно, результаты поиска и так уже пишутся в БД и подчас из нее и берутся, но не всегда.
Я не смог только найти информацию о том, как конкретно (какой код?) мне через связку node+redis+lara+socket.io кинуть броадкаст так, чтобы его получил конкретный мне пользователь.
Мне кажется, что я что-то концептуально не понимаю. Например: ведь в момент посылки из браузера сообщение в node.js никакой экземпляр laravel вообще не существует, не запущен. Кто будет обрабатывать этот запрос, как инициализировать php-процесс?..
Туплю. Я, кажется, понял вашу идею. То есть браузер отправляет прямой GET-запрос (например) в ларавел. Ларавел инициализирует поиск и шлет броадкасты обратно, но уже через node.js+socket.io.
Звучит здраво. А не подскажете, как тогда понять - кому именно отсылать запросы обратно? На момент GET-запроса сокет еще не инициализирован же.
aanon: клиент подключается к сокет-серверу в момент, когда заходит на сайт, вместе с этим отправляет через сокеты на Node.js данные для авторизации, тот в свою очередь отправляет запрос к laravel (происходит авторизация) и добавляет нужный сокет в приватный канал (комнату). Так работают приватные каналы в Laravel Echo.
Сергей Семенко: Прошу прощения, если я откровенно туплю. Буду благодарен, если вы не махнете рукой, а объясните. Первый раз столкнулся сегодня днем, не прошло 10 часов. Поэтому вопросы могут быть самыми дебильными.
Сергей Семенко: Понял. Спасибо большое за ответы. Во всяком случае инициализация обычным GET-запросом и постановка в очередь мне в голову не пришла. Поковыряю в этом направлении. Пожалуйста, не умирайте там, думаю, через неделю у меня могу возникнуть вопросы :) Еще раз спасибо.
Сергей Семенко: Всё сделал. Но проблема все же возникла. И какая! Оказалось, что Laravel не может распараллелить выполнение очередей. То есть каждый artisan queue:work выполняет очередь и переходит к следующей. Получается, что если у меня 100 пользователей одновременно что-то запросили, то 100ый должен ждать, пока выполнятся все очереди до 99ого. При этом большое количество воркеров не поможет: если я даже запущу 100 воркеров, а запросов будет 10.000, возникнет картина только хуже.
Можно ли как-то распараллелить выполнение очередей, вы не в курсе?