Здравствуйте. Пытаюсь реализовать long polling для crm системы. Имеем <100 пользователей и хостинг (если это имеет значение). На тестовом все четко выходило (1 пользователь) при переносе на публичную часть начинало все висеть дико висеть.
Мое предположение такое: при загрузки страницы идет запрос на сервер который там крутится какое-то время при обновлении страницы идет второй запрос и третий и тд и все это от одного пользователя, от одной вкладки, так же и вкладок может быть несколько. И поэтому один пользователь может создавать кучу запросов одновременно.
Есть конечно и другие методы реализации этой задачи, но хотелось бы эту довести до ума.
Как можно обрубать неактуальные запросы которые крутятся в цикле на сервере?
Появилась идея. На стороне клиента генерировать номер для каждой вкладки (только еще не знаю как сохранять номер при обновлении страницы). и с запросом отправлять этот номер. К клинскому номеру генерировать серверный номер и все другие циклы с другими серверными номерами но одинаковыми клинскими номерами обрубать. Вопрос: как реализовать передачу кода в обновленную вкладку?
Если честно, еще не разобрался. Я не считаю что текущий метод меня завел в тупик, вот и пытаюсь его доработать. Если не получится то буду искать другие пути решения
Ну в данном случае видно минусы, что один пользователь создает вам кучу висящих в памяти процессов, что есть очень плохо, если не ограничивать их в этом. Мне кажется, что сокеты решат вашу проблему проще и лаконичней.
Вячеслав Беляев: неактуальные процессы long polling отключаются по условию, т.е. после каждой итерации сна делайте проверку, которая точно когда-нибудь вернет false и long polling закроется. Ситуацию с несколькими вкладками можно решить записью сессий в быстрые бд вроде redis.
Суть long polling - вы посылаете запрос на сервер и этот запрос там висит без ответа, пока не появится условие , чтобы отдать ответ и закрыть его. Т.е. мы посылаем запрос, а на сервере проверяем (в цикле) есть ли, допустим, новые сообщения для пользователя (в базе), если их нет, то мы делаем sleep() , после выхода из sleep() мы опять проверяем есть ли новые сообщения для пользователя , и если есть, то отдаем, а если нет, то опять засыпаем и проверяем в следующей итерации. Это та реализация лонгполлинга, к которой привык я, возможно вы ее неправильно реализовываете. Т.е. на сервере должна быть итеративная проверка данных для отдачи запросу, сон и условие, которое когда-нибудь выполнится, чтобы запрос закрылся, отдались данные и заново послался запрос на сервер. Если условие проверяется нечасто(допустим раз в 30-60 секунд), то смысл в лонгполлинге остается. Если данные от сервера пользователю должны доставляться чаще или сервер должен сам инициировать отправку данных пользователям - тут больше подходят вебсокеты.
Вячеслав Беляев: просто недообъяснено.
на каждый запрос лонг-поллинга возникает зацикленный процесс, который мог бы завершиться при наличии данных на отправку или при повторном запросе. С данными понятно, а повторный запрос (другая вкладка, обновление страницы) можно отследить уникальным именем процесса.
Например, при первом запросе в каком-то внешнем хранилище запоминается какой-то случайный код, в цикле процесса этот код является условием повторения, если код сменится, цикл завершится. Второй запрос, созданный преждевременно, перепишет случайный код на новый, и новый процесс будет смотреть за ним, а старый закроется.
Вячеслав Беляев: тогда невозможно отследить закрытие вкладок или усиленное ф5. Лучше ограничить клиента одним легальным лонг-запросом, а обмен между вкладками через localStorage делать как-нибудь (даже библиотека есть такая).
Вячеслав Беляев: тогда как поступать в случае появления четвертой вкладки? или обновления первой? лонг-полл не установится, пока не закончится таймаут первого соединения. Или первое соединение будет отваливаться сразу? тогда обновив три раза четвертую вкладку отвалятся первые три вкладки.
Вячеслав Беляев: вы делаете велосипед, попробуйте вебсокеты, на nodejs или python + tornado. Они разворачиваются за полчаса-час. Если не знаете, то потратите 3-4 часа и получите хорошее решение.
Обычно такие запросы обрубаются таймаутом.
Т.е. нужно просто сделать лимит для запроса примерно 60 сек. и отдавать какую-то ошибку на клиент, а там биндите ее и делаете реконект.
К сожалению Вы не правильно поняли суть моей проблемы, сам процесс long polling реализован, и работает как описано в основных документациях на эту тему. Но в течении 60сек клиент может отправить 30 запросов на сервер путем обновления страницы именно это создает нагрузку
А почему каждые 10 сек. это маловато?
Ну и сами понимаете если у вас на хостинге 150 воркеров то 150 пользователей забьют их (это не учитывая остальных запросов и статику)
Вячеслав Беляев: да, перед запросом полинга сделать задержку, максимально возможную в Вашем случае. Просто с ограниченными ресурсами (хостингом) ничего толкового не получится, разве что делать запросы каждые n сек.