Pull to refresh

Comments 27

Проблема с SSE, в том что если соединение разорвалось со стороны сервера и бекенд перестал отвечать (например временная проблема или тормоза сервера), то браузер продолжает долбить с попытками подключения к SSE бекенду с невероятной скоростью без каких-либо задержек (до сотен запросов в секунду). Т.е. получаем такой маленький ддос если клиентов подключено много одновременно. Но обычно это не проблема, т.к. объем трафика не сильно большой по современным меркам, за исключением случаев когда включена какая либо анти ддос зашита (cloudflare/ovh/incapsula и т.д.). Т.е. клиент блокируется полностью на какой-то период времени только из-за временной недоступности SSE бекенда

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

Так надо было об этом в статье написать. Просто это не совсем явное поведение SSE, которое нигде не описывается (никому заренее в голову не придет что браузер будет генерить столько запросов на ровном месте).

Бекенд не Ванга и не знает когда он упадет. Т.е. как сервер заранее может выставить большую задержку прямо перед падением?
Т.е. или сразу или всегда выставлять какую-то задержку, например в 1 сек при любых ответах сервера, что иногда не вариант (если вдруг нужно моментальное переподключение) или вот это:


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

да, это оба решения проблемы, но это очень неявные и в доках насчет этого ничего нет. Вот как раз о таких неявных моментах хорошо бы было написать в статье.

В качестве транспорта мы используем локальное хранилище браузера (LocalStorage).

Тиньки это запилили через сервис-воркер - 471718

Вы не пробовали такую схему?

Нет, у нас не возникло таких проблем как у Тинькофф, поэтому мы дальше localStorage не изучали вопрос

А вместо всего этого взяли бы Centrifugo - и все бы работало, тем более, коллеги по рынку делали )

первый коммит - 2020 год. мы сделали нашу реализацию немного раньше.

при этом клиент для Node.js в npm лежит как альфа версия и скачиваний не больше 20 в сутки. вряд ли такое стоит в продакшне использовать

А зачем ему клиент для ноды? Учитывая что клиентская либа универсальная а сервер имеет несколько транспортов. Ну и почитайте блог, они здесь, включая автора, есть на хабре. В суровом продакшине многие годы.

И да, первый коммит - 5 марта 2015-го года. Пруф: https://github.com/centrifugal/centrifugo/commit/0f439cbe244f38cd6037e33a8b1e1b1250478fb2

мой комментарий был основан на 5 минутном рисерче информации о данной технологии, поэтому вы наверное правы.

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

Интересное решение, но мне кажется оверкил. На сколько я понял есть бэк на PHP который и должен тригерить ноду, чтобы отправить сообщение? У меня был похожий опыт только с веб сокетами, а конкретнее socket.io, нода в моём кейсе выступала в качестве прокси, хронила внутри себе структуру [{id: авторизационый хеш токена пользователя, sokcet: ссылка на сам сокет }], пыха пуляля по udp на ноду сообщение с авторизационым хешем, а нода проксировала это на фронт. Перформанс и аптайм превзошёл все ожидания, такая система споеойно держит более 400 рпс

Если вы про то, что оверкил - использовать Redis (а вместо него лучше общаться по udp), то мы просто использовали то, что бэкенд и так уже использовал для общения между некоторыми сервисами

Включение HTTP2 на стороне балансировщика разве не решает проблему ограничения кол-ва подключений?

Решает, но у нас не было HTTP2 на тот момент

А как настроено проксирование запроса на sse на ноду?

Не очень понятен вопрос.

сервер на Node.js проксирует запросы обычного API бэкенда. но соединения SSE обрабатываются на ноде и дальше не проксируются.

я так и не понял у вас что и клиент решает лезть ему в редис или нет ? и серверные прослойки? В общем в схеме не очень понятно как вы работаете с кэшем

клиент не решает лезть в Redis, клиент открывает SSE соединение. По этому событию сервер Node.js подключается к каналу Redis. Дальше при появлении сообщения в канале редиса нода отдает эти данные в уже открытое SSE соединение.

Безусловно, если клиент не инициировал SSE соединение, то сообщение отправленное в канал редиса ему отправлено не будет.

Интересно было ознакомиться.

Пару вопросов, позвольте: какой период срабатывания у hearthbeat? Сильно грузит браузер система контроля (hearthbeat и сторожевой таймер)?

У нас интервал хартбита 5 секунд, а период сторожевого таймера 10 секунд. это имперически и интуитивно подобранное значение. вопрос даже не в нагрузке на браузер, а в том, что слишком маленькие значения могут приводить к ошибкам гонки хартбита и сторожевого таймера. Мы посчитали, что для наших пользователей отсутствие SSE соединения в течение 10-15 секунд не будет проблемой.

Мы посчитали, что для наших пользователей отсутствие SSE соединения в течение 10-15 секунд не будет проблемой.

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

Есть еще один способ организации Real Time соединения, как таковой у него нет названия, но фактически это обычный Long Polling реализованный на базе протокола JSONP. Для получения данных используется тег script и длинные опросы, никаких fetch и XHR, чистый хардкор)

Кстати, а как вы победили заморозку вкладки браузером? Потому, что если SSE соединение бы улет висеть в какой-нибудь фоновой вкладки, то рано или поздно эта вкладка заморозиться хромом и тогда остальные ваши вкладки (включая активную) перестанут получать уведомления.

В этом случае замороженная вкладка перестанет отправлять хартбит, и остальные вкладки поймут, что пора решать, кто следующий откроет SSE соединение.

А если вкладка не полностью заморозилась, а у нее значительно понизился приоритет (например так себя firefox ведет). Т.е. любое событие по таймеру будет происходить со значительной задержкой (иногда до нескольких минут).

SSE позволяет передавать текст, но он может быть в gzip, например, что сильно облегчает жизнь.

Sign up to leave a comment.