Я работаю над одним приложением чата [все для всех] в Elixir, используя OTP Genserver и получаю сообщения от js-клиента, когда пользователь регистрируется со своими именами в качестве первого этапа. Теперь я просто немного не уверен, как лучше всего хранить эти имена на моем сервере эликсира и отправлять регулярные обновления клиенту со списком пользователей в сети или в хранилище базы данных. Пожалуйста, предложите лучший подход.
Интернет-пользователи хранят эликсир
Ответы (2)
Я согласен с bitwalker, что ETS подходит.
Вот краткое изложение того, что я сделал в производстве. Это был не чат-сервер, а пуш-сервер с парой тысяч пользователей, подключающихся через долгий опрос. Отправляемые данные были разделены примерно на 50 категорий, и пользователи могли выбирать, какие из них им нужны. В часы пик сервер отправлял новые сообщения каждые 2 секунды и обрабатывал > 2000 запросов в секунду.
По сути, я сохранил gen_server
для каждого пользователя, где я хранил ожидающие сообщения и конфигурацию пользователя (в основном список выбранных каналов). Это было полезно при длительном опросе, поскольку данные пользователя отделены от запроса пользователя, поэтому данные остаются, пока запросы являются временными. Однако я думаю, что этот подход также хорош для постоянных подключений, таких как веб-сокеты, поскольку время от времени могут возникать отключения, а сохранение более стабильных данных пользователя дает вам возможность возобновить работу после повторного подключения.
Очевидно, что при поступлении запроса вам нужно найти специфический для пользователя процесс, и для этого хорошо подходит ETS, поскольку у вас нет узкого места в одном процессе. Вместо ручной работы с ETS я бы рекомендовал использовать gproc в сочетании с via
кортежами. По сути, при запуске пользовательского gen_server вы можете указать name: {:via, :gproc, {:n, :l, key}}
, где key
— это некоторый пользовательский ключ (произвольный термин), который вы создаете на основе вашего внутреннего идентификатора пользователя (:n
и :l
указывают уникальное имя на локальном узле). Затем вы можете использовать тот же кортеж via
при выполнении вызовов/кастов, а gen_server
будет использовать gproc
для поиска соответствующего процесса.
Наконец, вам нужна логика тайм-аута/отключения для очистки пользовательских процессов. В моем случае я просто завершал процесс пользователя, если не было активности веб-слоя (конечный пользователь не приходил за данными в течение некоторого времени). Gproc автоматически удалит записи для завершенного процесса из своей внутренней таблицы ETS. Вероятно, лучше всего контролировать пользовательские процессы в соответствии со стратегией temporary
.
Я понимаю, что все это все еще немного расплывчато, но я надеюсь, что это имеет какой-то смысл. Имейте в виду, что это не окончательный шаблон (конечно, такого не бывает), но я думаю, что это разумная первая попытка.
Вы также можете взглянуть на веб-фреймворк Phoenix, в котором есть интересная функция публикации и подписки в формеTopics
. Я еще не пробовал это сам, но это кажется интересным и может даже упростить некоторые вещи, которые я обсуждал выше, или, по крайней мере, помочь в отправке уведомлений из чата всем пользователям.
Звучит как хороший пример использования ETS.
Более простым подходом может быть использование агента для хранения информации о онлайн-пользователях, но это во многом зависит от того, что вам нужно от выбранного вами механизма хранения.