Есть ли способ, чтобы по одному серверу отправлялось событие на пользователя, а не на вкладку?

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

Проблема в том, что каждая вкладка будет создавать отдельное соединение с сервером для запуска отправленных сервером событий, а сервер будет выполнять цикл для выполнения запроса. (если для каждого пользователя открыто 5 вкладок, то серверу нужно будет запустить 5 разных событий server-sent, чтобы ответить!)

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

Я думаю, что это будет та же идея использования WebSocket. Однако проблема со мной, использующим WebSockets, заключается в том, что каждый пользователь должен проходить проверку подлинности с использованием отправленного сервером события и не уверен, возможно ли это с помощью WebSockets. Когда пользователь входит в приложение, я генерирую sessionID, и сессия проверяет соответствие своих IP-адресов / данных агента, прежде чем ему разрешат использовать сайт.

Как я могу свести к минимуму количество подключений к Server-Sent Event до 1 на пользователя?

4 ответа

Заголовки HTTP (и, следовательно, файлы cookie) доступны серверу WebSocket при настройке подключения каждого клиента.

Однако, так как вы еще не используете WebSockets (еще?), Следующим лучшим вариантом будет ваш клиентский Javascript.

Файлы cookie доступны там, если только в файле cookie не установлен флаг HttpOnly. Это будет ваш самый надежный способ сопоставить пользователя на нескольких вкладках браузера.

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

  • Ограничить одним пользователем на соединение? Да.
  • Получить несколько вкладок, чтобы поделиться одним и тем же соединением SSE? Да, теоретически.

Разбираясь с первым пунктом: вы упомянули, что используете сеансы PHP. Файл cookie сеанса будет отправляться с каждой из ваших вкладок, поэтому при подключении первой вкладки ваш PHP-скрипт может установить что-то внутри сеанса (*), чтобы сообщить, что у вас теперь есть SSE-соединение. Когда вторая вкладка подключится, ваш PHP-скрипт будет искать эту переменную сеанса, видеть ее и возвращать код ошибки.

Что касается второго пункта, это становится проблемой связи между вкладками: первая вкладка должна иметь способ обнаружить, что вторая вкладка существует, и должна иметь способ связаться с ней, чтобы она могла пересылать сообщения SSE, которые она получает. Я верю, что HTML5 Shared Web Workers могут достичь этого, и я видел, как люди предлагали использовать его для описанного вами сценария использования SSE, но я еще не видел работающего примера.

*: не забудьте использовать session_write_close закрыть сеанс, как только ваш PHP-скрипт начнет передавать данные SSE, чтобы другие сценарии могли использовать сеанс. (Сеансы PHP по умолчанию заблокированы на время существования скрипта.)

Если пользователь аутентифицирован, то, вероятно, у вас есть какая-то запись о пользователях. Добавьте идентификатор сеанса в эту запись пользователей, чтобы на него отвечал только тот.

Похоже, вы пытаетесь предотвратить одновременное использование с теми же данными аутентификации. Лучший способ сделать это IMHO - это молча игнорировать одновременные запросы.

Это хороший вопрос и ответ на него много лет спустя, но ваш вариант использования кажется немного странным.

Опирайтесь на приведенные ниже цитаты. Мои пользователи используют несколько вкладок для использования одного и того же приложения. Ну, во-первых, ожидают ли они увидеть одни и те же данные на каждой вкладке? Я не понимаю, зачем это нужно? Если другая вкладка открыта, вы хотите беспокоиться о вкладке, которая находится в фокусе?

Теперь, если у них открыто несколько вкладок для получения различной информации, например, финансового приложения, где 1. это фондовый рынок США 2. это британский фондовый рынок 3. это азиатский фондовый рынок. Это я мог понять. Но это также исключит использование обработки размытия. Это означает, что я предпочитаю отключать соединение, если пользователь щелкает мышью с вкладки, и сообщать об этом серверу, чтобы закрыть().

Если вы этого не сделаете, тогда вы должны действительно контролировать свои тайм-ауты, потому что это приведет к большому количеству утечек памяти. Так что будьте осторожны. Пользователи будут делать все, что вы им позволите.

Один из механизмов, который вы можете использовать, — это активный сеанс. Это означает, что если пользователь щелкает вкладку, размытие, вы можете установить тайм-аут на ожидаемый период использования. Если экран является активным экраном, вы можете обновить соединение и перезапустить таймер.

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

Когда ты говоришь:

Есть ли способ добавить какую-то логику, чтобы проверить, установлено ли соединение между клиентом и отправленным сервером сценарием, используя одно и то же соединение вместо создания нового?

Что бы я сделал, если бы получение этих данных на нескольких вкладках было большой проблемой. Мне нравится фраза «Эй, вы получите одну вкладку, сэр/мам», вот и все.

я бы исследовалblurподход, который будет брать данные из открытого потока и либо добавлять их в сеанс браузера в абстракции redux или ngrx, либо в абстракции потока данных (оба имеют сложность настройки).

Это будет означать, что «если пользователь щелкает вкладку» (не активная вкладка), то по умолчанию используется поток резервных данных из потока входящих событий. Итак, отключаем основной поток и переходим к сгенерированному массиву данных, который поступает из потока. Запуск в памяти /redux/ngrx или на отдельном сервере, напримерRedisилиMongo.

У Auth0 есть хороший пример этого в статье.

Обработка восстановления соединения при событиях, отправленных сервером

В этом примере почтальон объясняет, что можно справиться с потерянным соединением и восстановить его, отслеживая отправленные сообщения, и если соединение потеряно, на сервер поступает сигнал.Last-Event-IdКоторый сообщит пользователю последнее правильное сообщение, которое было отправлено, и доставит сообщения пользователю, а также новые по порядку.

Теперь этот пример не совсем то, что вам нужно сделать, но суть та же. Сохраняйте сообщения и доставляйте их другим способом, чтобы вы могли закрыть другие вкладки, когда пользователь щелкнет их. Таким образом, у вас будет 1 соединение sse на активной вкладке, а на других вкладках будет просто запущена точная копия из какого-то другого механизма. Сохранение связи качественной и только одной.

Надеюсь, это поможет кому-то.

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

Проблема в том, что каждая вкладка будет устанавливать отдельное соединение с сервером для запуска событий, отправленных сервером, и сервер будет запускать цикл для выполнения запроса. (если для каждого пользователя открыто 5 вкладок, сервер должен будет запустить 5 разных событий, отправленных сервером, чтобы ответить!)

Есть ли способ добавить какую-то логику, чтобы проверить, установлено ли соединение между клиентом и отправленным сервером сценарием, используя одно и то же соединение вместо создания нового?

Другие вопросы по тегам