Создайте сервер обмена мгновенными сообщениями с помощью emqtt

задняя часть

Как правило, в социальных отношениях существует два типа мгновенных сообщений: одиночный чат и групповой чат, и пользователи могут входить в систему на нескольких устройствах одновременно.

Соответствующее соотношение в основном выглядит следующим образом

отношения пользователя устройства

用户<-1---------------*->设备

Отношения группы пользователей

用户<-*---------------*->群组

Процесс отправки сообщения:

Одиночный чат: A отправляет сообщение B

A----send msg----> server ----deliver msg-->  B

Групповой чат: A отправляет сообщение Group1 (пользователи A, B, C, D)

                            |----deliver msg-->  B
A----send msg---> server -->|----deliver msg-->  C
                            |----deliver msg-->  D

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

Рассматривайте только онлайн или нет, независимо от процесса сообщения о прическе на нескольких устройствах:

Одиночный чат: A отправляет сообщение B

                            | B 在线 |---   直接  deliver msg-->  B
A----send msg----> server --|       |
                            | B 离线 |--- 等待上线 deliver msg-->  B

Групповой чат: A отправляет сообщение группе 1 (пользователь A, B онлайн, C офлайн, D онлайн)

                            |----   直接  deliver msg-->  B
A----send msg---> server -->|---- 等待上线 deliver msg-->  C
                            |----   直接  deliver msg-->  D

На самом деле рассмотрение нескольких устройств мало чем отличается от вышеописанного процесса, нужно только настроить пользователя на несколько устройств, но в контексте мобильного интернета вся модель немного отличается, в данном случае номер мобильного телефона или мобильное устройство можно в основном приравнять к пользователю.С точки зрения взаимодействия с пользователем необходимо использовать сторонние сообщения, чтобы связаться с пользователем, когда пользователь находится в автономном режиме, например, сообщения мобильного приложения, браузера и настольного приложения.Уведомления , SMS, электронная почта и т. д. Конечно, основным направлением по-прежнему является уведомление о сообщении приложения

Затем примите во внимание уведомления об офлайн-сообщениях и смоделируйте ситуацию, когда пользователь отписывается от напоминаний о сообщениях группы.

Одиночный чат: A отправляет сообщение B

                            | B 在线 |--- 直接     deliver msg   ----------->  B
A----send msg----> server --|       |
                            | B 离线 |--- 第三方触达 -----> 上线 deliver msg-->  B

Групповой чат: A отправляет сообщение в Group1 (пользователь A, B онлайн, C не напоминает офлайн, D напоминает офлайн)

                            |---- 直接                 deliver msg -->  B
A----send msg---> server -->|---- 等待上线              deliver msg -->  C
                            |---- 第三方触达 -----> 上线 deliver msg -->  D

Хорошо, разобравшись с бизнес-моделью, давайте посмотрим на протокол MQTT и функции, предоставляемые EMQTT.

Введение в mqtt и режим публикации-подписки

Принципы проектирования MQTT:

  • Оптимизировано, без добавления дополнительных функций.
  • Шаблон публикации/подписки (Pub/Sub) для облегчения передачи сообщений между датчиками.
  • Разрешить пользователям динамически создавать темы с нулевыми затратами на эксплуатацию и обслуживание.
  • Минимизируйте объем передачи для повышения эффективности передачи.
  • Примите во внимание такие факторы, как низкая пропускная способность, высокая задержка, нестабильные сети.
  • Поддерживается непрерывный контроль сеанса.
  • Помните, что вычислительная мощность клиента может быть низкой.
  • Обеспечить управление качеством обслуживания.
  • Предполагая, что данные являются независимыми, тип и формат передаваемых данных не применяются принудительно, и сохраняется гибкость

опубликовать/подписать модель

В отличие от шаблона синхронизации запроса/ответа, шаблон публикации/определения разделяет отношения между клиентом, публикующим сообщение (издателем), и клиентом (подписчиком), подписывающимся на сообщение, что означает, что издатель и подписчик не требуется. Например, вы звоните другу и ждете, пока он ответит на звонок, прежде чем вы сможете начать общение, что является типичным синхронным сценарием запроса/ответа; отправка электронной почты в список рассылки друга отличается, вы отправляете электронное письмо. • Друзья просто проверяют электронную почту, когда она свободна, что является типичным сценарием асинхронной публикации/подписки.

тема

MQTT классифицирует сообщения по темам и может фильтроваться с помощью подстановочных знаков, таких как:

  • корпус-b/этаж-5: представляет оборудование на 5-м этаже корпуса B.
  • +/этаж-5: Обозначает оборудование на 5-м этаже любого здания.
  • building-b/#: представляет все оборудование в здании B.

Вышеупомянутое взято изЗнать запись столбца MQTT

EMQ

Введение EMQ 2.0 (Erlang/Enterprise/Elastic MQTT Broker) — это сервер сообщений MQTT с открытым исходным кодом, разработанный на основе языковой платформы Erlang/OTP, поддерживающий крупномасштабные соединения и распределенные кластеры, а также режим публикации-подписки.

Полностью асинхронная архитектура

Сервер сообщений EMQ представляет собой полностью асинхронную архитектуру, основанную на платформе Erlang/OTP: асинхронная обработка TCP-соединений, асинхронная подписка на тему, асинхронная публикация сообщений. Синхронный дизайн используется только для частей с ограниченной нагрузкой на ресурсы, таких как создание TCP-соединения и выполнение транзакций базы данных Mnesia.

Сообщение MQTT передается от издателя (Publisher) к подписчику (Subscriber) и асинхронно проходит через ряд процессов Erlang Mailbox внутри сервера сообщений EMQ:

                  ----------          -----------          ----------
Publisher --Msg-->| Client | --Msg--> | Session | --Msg--> | Client | --Msg--> Subscriber
                  ----------          -----------          ----------

источникофициальный сайт emqtt

После того, как измеренный пользователь войдет на сервер emqtt, отношения подписки между пользователем и темой будут сохранены сеансом. Пока сеанс не будет очищен, пользователь сохранит текущее отношение подписки при следующем входе в систему, и сообщения QoS 1 и 2 будут сохранены на сервере после отключения пользователя.На стороне клиента, когда пользователь снова входит в систему, может быть получено предыдущее сообщение.

Реализация дизайна

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

Пользователь А:
iPhone {
Идентификатор устройства: 'device-a-iPhone'
Идентификатор пользователя: «111»
}

iPad {
Идентификатор устройства: 'device-a-iPad'
Идентификатор пользователя: «111»
}
Android {
Идентификатор устройства: «устройство-андроид»
Идентификатор пользователя: «111»
}

Пользователь Б:
{
Идентификатор устройства: 'device-b'
Идентификатор пользователя: «222»
}

Пользователь С:
{
Идентификатор устройства: 'device-c'
Идентификатор пользователя: «333»
}

Группа 1: [Пользователь A, Пользователь B, Пользователь C]

Индивидуальный чат:

Пользователи подписываются на свои собственные связанные темы, чтобы получать сообщения

A 订阅 'user/111/#'
B 订阅 'user/222/#'
C 订阅 'user/333/#'

Пользователь отправляет сообщение в чужую тему, например, A отправляет сообщение B:

A 发消息给 B     ----> 发布消息到 'user/222/inbox/111'
A 申请加 B 为好友 ----> 发布消息到 'user/222/application/111'

Групповой чат Пользователи подписываются на темы, связанные с группой, к которой они присоединились, чтобы получать сообщения

A 订阅topic ----> 'group/1/#'
B 订阅topic ----> 'group/1/#'
C 订阅topic ----> 'group/1/#'

Отправить сообщение

A 发消息到 Group1 ----> 发布消息到 'group/1/inbox/111'
B 发消息到 Group1 ----> 发布消息到 'group/1/inbox/222'
C 发消息到 Group1 ----> 发布消息到 'group/1/inbox/333'

вступай в группу, приглашай

A 申请加入群聊 Group1 ----> 发布消息到 'group/1/application/111'
B 邀请 C 加入 Group1 ----> 发布消息到 'group/1/invitation/333/from/222'

Получите приглашение (обратите внимание, что это получить, а не принять)

A 订阅topic ---->  'group/+/invitation/111/from/+'
B 订阅topic ---->  'group/+/invitation/222/from/+'
B 订阅topic ---->  'group/+/invitation/333/from/+'

Владелец группы получает заявку (обратите внимание, что принимает, а не принимает)

A 订阅topic ---->  'group/1/application/+'

Вход с нескольких устройств

A-iPhone 设备登录设置 session-id 为 device-a-iPhone 
A-iPad 设备登录设置 session-id 为 device-a-iPad
A-Android 设备登录设置 session-id 为 device-a-Android
  • Перед входом в систему вы можете определить, существует ли соответствующий сеанс.Если нет, создайте сеанс и выполните описанную выше операцию подписки.Конечно, вы также можете подписаться в соответствии с устройством.

На данный момент базовая отправка и получение выполнены.Что касается сторонней доставки офлайн-сообщений, вам необходимо разработать собственный подключаемый модуль для обработки ситуации, когда сеанс получает сообщение, но пользователь отключается.