предисловие
счастливого Нового года всем!
Первая техническая статья в новом году обещает хорошее начало, поэтому я не бездельничал в предновогодний день три дня и надеюсь представить вам более интересный галантерейный контент.
Старые читатели должны помнить, что я поделился статьей перед Национальным праздником в прошлом году.«Проектирование системы push-уведомлений на уровне миллиона сообщений»;Хотя я разместил в тексте некоторый псевдокод, некоторые друзья все еще надеются поделиться неким исполняемым исходным кодом напрямую; пришло время заполнить дыру после стольких лет.
Структура каталогов:
Эта статья представляет собой длинное предупреждение с высокой энергией; принесите хорошую скамейку семян дыни.
Итак, на основе предыдущих я улучшил кое-какой контент, давайте взглянем на введение в этот проект:
CIM(CROSS-IM)
разработчикIM(即时通讯)
система; в то же время она предоставляет некоторые компоненты, помогающие разработчикам создавать свои собственные горизонтально масштабируемыеIM
.
с помощьюCIM
Вы можете выполнить следующие требования:
-
IM
система обмена мгновенными сообщениями. - применять к
APP
промежуточное ПО для отправки сообщений. -
IOT
ПО промежуточного слоя для прозрачной передачи сообщений в сценариях массового подключения.
Полный исходный код размещен на GitHub:GitHub.com/crossover J я…
демо
На этот раз в основном используется обмен мгновенными сообщениями, поэтому я специально записал две видеодемонстрации (групповой чат, приватный чат).
Щелкните ссылку ниже, чтобы просмотреть видеоверсию демонстрации.
YouTube | Bilibili |
---|---|
Групповой чат приватный чат | Групповой чат приватный чат |
Демонстрационная среда также была развернута в общедоступной сети.Если вы хотите попробовать ее, вы можете связаться со мной, чтобы присоединиться к внутренней бета-группе, чтобы получить учетную запись и пообщаться вместе 😋.
Архитектурный дизайн
Давайте взглянем на конкретный архитектурный проект.
-
CIM
Каждый компонент вSpringBoot
Построить. - использовать
Netty + Google Protocol Buffer
Выстраивайте низкоуровневые коммуникации. -
Redis
Храните информацию о маршрутизации, информацию об учетной записи, онлайн-статус и т. д. каждого клиента. -
Zookeeper
используется дляIM-server
Регистрация и обнаружение службы.
Все в основном состоит из следующих модулей:
cim-server
IM
сервер; для приемаclient
Соединение, прозрачная передача сообщений, отправка сообщений и другие функции.
Поддерживается кластерное развертывание.
cim-forward-route
Сервер маршрутизации сообщений; используется для обработки маршрутизации сообщений, пересылки сообщений, входа пользователей в систему, выхода пользователей из системы и некоторых операционных инструментов (получение количества онлайн-пользователей и т. д.).
cim-client
IM
Клиент; для терминала сообщений, используемого пользователем, одна команда может запускать и инициировать общение с другими (групповой чат, приватный чат); в то же время для простоты использования встроены некоторые общие команды.
блок-схема
Общий процесс также относительно прост, блок-схема выглядит следующим образом:
- клиент для
route
Инициировать вход. - Войти успешно из
Zookeeper
выберите доступныйIM-server
Вернитесь к клиенту и сохраните данные для входа и маршрутизации вRedis
. - клиент для
IM-server
Инициируйте длительное соединение и сохраните пульс после успеха. - Проходить, когда клиент отключается
route
Очистить информацию о состоянии.
Поэтому, когда мы развертываем себя, нам нужны следующие шаги:
- Создание базового промежуточного ПО
Redis、Zookeeper
. - развертывать
cim-server
, это настоящий сервер обмена мгновенными сообщениями, чтобы соответствовать требованиям производительности, он поддерживает горизонтальное расширение, нужно только зарегистрироваться на том жеZookeeper
Вот и все. - развертывать
cim-forward-route
, который является сервером маршрутизации, через который должны проходить все сообщения. Поскольку он не имеет гражданства, его также можно использоватьNginx
Прокси улучшают доступность. -
cim-client
Настоящий клиент для пользователя; после запуска он автоматически подключается к серверу обмена мгновенными сообщениями для отправки и получения сообщений с консоли.
Дополнительные сведения об использовании см.Быстрый старт.
детальный дизайн
Далее мы сосредоточимся на конкретной реализации, например, на том, как проходят групповые и частные чаты, распределяется нагрузка на сервер обмена мгновенными сообщениями, как регистрируются и обнаруживаются сервисы и так далее.
сервер обмена мгновенными сообщениями
Давайте сначала взглянем на сервер; он в основном реализует такие функции, как клиент онлайн и офлайн, а также доставку сообщений.
Первый — запустить службу:
из-заSpringBoot
встроенный, поэтому его нужно запускать при запуске приложения.Netty
Служить.
отpipline
Видно, что использованиеProtobuf
Кодек (конкретные пакеты анализируются в клиенте).
Зарегистрируйтесь, чтобы узнать
должен быть удовлетворенIM
Требования к горизонтальному расширению сервера, поэтомуcim-server
Необходимо опубликовать собственные данные в реестре.
Вот ссылка на то, что было опубликовано ранее«Получение регистрации и обнаружения службы»Есть конкретные вводные.
Поэтому после успешного запуска приложения ему необходимо зарегистрировать свои собственные данные дляZookeeper
середина.
Основная цель - преобразовать текущее приложениеip + cim-server-port+ http-port
Зарегистрироваться.
На картинке выше два, которые я зарегистрировал в демо-среде.cim-server
Экземпляр (поскольку он на сервере, отличается только порт).
Таким образом на стороне клиента (послушайте этоZookeeper
узел) может знать доступную в настоящее время служебную информацию в режиме реального времени.
Авторизоваться
когда клиент проситcim-forward-route
После завершения бизнес-проверки (точно так же, как при ежедневном входе на другие веб-сайты) в интерфейсе входа (см. ниже) клиент инициирует длительное соединение с сервером, как показано в предыдущем процессе:
В это время клиент отправит специальное сообщение, указывающее, что текущая информация для входа.
После того, как сервер его получит, ему нужноuserID
и текущийChannel
Связь каналов сохраняется.
При этом информация пользователя также кэшируется, т.е.userID
и имя пользователя.
не в сети
Когда клиент отключен, кэшированная информация должна быть очищена.
Также необходимо позвонитьroute
Сопутствующая информация об интерфейсе (см. ниже конкретные интерфейсы).
Маршрутизация мгновенных сообщений
Как видно из схемы архитектуры, уровень маршрутизации является очень важной частью, он обеспечивает рядHTTP
Сервис берет на себя клиент и сервер.
В настоящее время существуют в основном следующие интерфейсы.
интерфейс регистрации
Поскольку каждый клиент должен войти в систему, чтобы использовать его, первым шагом является регистрация.
Дизайн здесь относительно прост, непосредственно используйтеRedis
для хранения информации о пользователе; информация о пользователе также толькоID
иuserName
Вот и все.
Просто для удобстваRedis
серединаKV
Сохранено сноваVK
,такID
иuserName
Должно быть уникальным.
интерфейс входа
войти здесь иcim-server
Вход в систему отличается и носит деловой характер,
- После успешного входа необходимо определить, является ли это повторным входом (пользователь может запустить только один клиент).
- После успешного входа необходимо
Zookeeper
Получить список услуг в (cim-server
) и выбрать сервис для возврата клиенту по какому-то алгоритму. - После успешного входа в систему необходимо сохранить информацию о маршрутизации, то есть экземпляр службы, назначенный текущим пользователем, сохраняется в
Redis
середина.
Чтобы понять, что только один пользователь может войти в систему, используйтеRedis
серединаset
для сохранения данных для входа; используйтеuserID
в видеkey
, повторные входы в систему не будут записываться.
Подобно HashSet в Java, его можно только дедуплицировать и сохранить.
Получить доступный экземпляр маршрутизации также проще:
- начать с
Zookeeper
Заставьте все экземпляры службы выполнять внутренний кеш. - Опрос для выбора сервера (на данный момент есть только один алгоритм, который будет добавлен позже).
Конечно, чтобы получитьZookeeper
Вполне естественно, что перед запуском экземпляра службы вcim-server
Узел, который был ранее зарегистрирован.
Конкретный код выглядит следующим образом:
Также слушайте после запуска приложенияZookeeper
Узел маршрутизации в , и внутренний кэш обновляются, как только происходят изменения.
Здесь мы используем кеш Guava, основанный на
ConcurrentHashMap
, поэтому можно гарантировать, что清除、新增缓存
атомарность.
Интерфейс группового чата
Это реальный интерфейс сообщений, эффект в том, что один клиент отправляет сообщение, а все остальные клиенты могут его получить!
Процесс должен заключаться в том, что клиент отправляет сообщение на сервер, а сервер его получает, как описано вышеSessionSocketHolder
перебрать всеChannel
(канал), а затем отправить сообщение.
Сервер может быть одиночной машиной, но теперь это кластерная конструкция. Таким образом, все клиенты будут назначены на разные согласно предыдущему алгоритму опроса.cim-server
в экземпляре.
Следовательно, уровень маршрутизации должен играть определенную роль.
После того, как интерфейс маршрутизации получит сообщение, он сначала просматривает отношения между всеми клиентами и экземплярами службы.
Отношения маршрутизации находятся вRedis
хранятся следующим образом:
так какRedis
Однопоточный характер, когда объем данных большой, когда ключи используются для сопоставления всехcim-route:*
data, из-за чего Redis не сможет обрабатывать другие запросы.
Так что здесь вместо этого используйте команду сканирования, чтобы перебрать всеcim-route:*
.
Затем он будет вызывать сервер, на котором каждый клиент находится один за другим.HTTP
Интерфейс используется для отправки сообщений.
существуетcim-server
Реализация в следующем:
cim-server
После получения сообщения канал userID будет запрошен во внутреннем кеше, после чего останется только отправить сообщение.
онлайн пользовательский интерфейс
Это вспомогательный интерфейс, который может запрашивать информацию о текущем онлайн-пользователе.
Реализация также очень проста, то есть дедупликация, которая сохраняет состояние входа пользователя перед запросом.set
"Вот и все.
Интерфейс приватного чата
Причина, по которой говорят, что привлечение онлайн-пользователей является вспомогательным интерфейсом, на самом деле используется для помощи приватным чатам.
Как правило, предпосылка использования приватного чата должна знать, какие пользователи в настоящее время находятся в сети, и тогда вы будете знать, с кем вы хотите общаться в приватном чате.
Что-то вроде этого:
В нашем сценарии предпосылкой приватного чата является привлечение онлайн-пользователей.userID
.
Поэтому интерфейс приватного чата должен запрашивать местоположение получателя после получения сообщения.cim-server
Информация об экземпляре, последующие шаги такие же, как и в групповом чате. вызвать экземпляр получателяHTTP
Интерфейс предоставляет информацию.
Просто групповой чат — это разница между обходом всех онлайн-пользователей и отправкой только одного приватного чата.
автономный интерфейс
Когда клиент находится в автономном режиме, нам нужно сохранитьRedis
Часть информации в нем удалена (информация о маршрутизации, статус входа).
клиент обмена мгновенными сообщениями
Часть логики в клиенте уже упоминалась выше.
Авторизоваться
Первым шагом является вход в систему, который нужно вызвать при запускеroute
интерфейс входа, получитьcim-server
информацию, а затем создать соединение.
во время входа в системуroute
Интерфейс определит, является ли это повторным входом в систему, и повторный вход приведет к непосредственному выходу из программы.
Далее следует использоватьroute
возвращается интерфейсомcim-server
информация об экземпляре (ip+port
) для создания соединения.
Последним шагом является отправка сообщения о входе в систему на сервер, в котором клиент иChannel
Отношение.
пользовательский протокол
некоторые из вышеперечисленных登录报文、真正的消息报文
На самом деле они различимы в нашем пользовательском протоколе.
Поскольку он используетсяGoogle Protocol Buffer
кодек, поэтому сначала посмотрите на исходный формат.
Фактически, в настоящее время в этом протоколе есть три поля:
-
requestId
можно понимать какuserId
. -
reqMsg
это реальная новость. -
type
То есть, категория сообщения, упомянутая выше.
В настоящее время существует в основном три типа, соответствующие различным предприятиям:
сердцебиение
Чтобы поддерживать соединение между клиентом и сервером, необходимо автоматически отправлять пульс каждый раз, когда сообщение не отправляется.
Текущая стратегия состоит в том, чтобы отправлять на сервер пакет пульса каждую минуту:
Таким образом, когда сервер не получает деловое сообщение каждую минуту, он будет получатьping
Пакет сердцебиения:
встроенные команды
Клиент также имеет несколько встроенных основных команд для простоты использования.
Заказ | описывать |
---|---|
:q |
Выйти из клиента |
:olu |
Получить всю информацию о пользователе онлайн |
:all |
получить все команды |
: |
Другие команды находятся в разработке. . |
такие как ввод:q
Клиент будет закрыт, и некоторые системные ресурсы будут закрыты одновременно.
при входе:olu
(onlineUser
сокращение от ) позвонитroute
доступа ко всем пользовательским онлайн-интерфейсам.
Групповой чат
Пользоваться групповым чатом очень просто, нужно только ввести сообщение в консоли и нажать Enter.
затем позвонитroute
интерфейс группового чата.
приватный чат
То же самое верно и для приватного чата, но предпосылка заключается в том, что вам нужно активировать ключевые слова; используйтеuserId;;消息内容
Этот формат будет отправлять сообщение только определенному пользователю, поэтому обычно необходимо использовать:olu
Приобретение команд удобно для онлайн-пользователей.
обратный вызов сообщения
Чтобы удовлетворить некоторые требования к настройке, например, сообщения должны быть сохранены и так далее.
Таким образом, после того, как клиент получит сообщение, он вызовет интерфейс, в котором реализация может быть настроена.
Итак, сначала создайтеcaller
изbean
,этоbean
содержитCustomMsgHandleListener
Интерфейс, вам нужно реализовать этот интерфейс только в том случае, если вам нужно справиться с ним самостоятельно.
настраиваемый интерфейс
Поскольку я сам мало что знаю о написании интерфейсов, я не уверен, что другие большие коровы будут. Таким образом, групповой чат, приватный чат, привлечение онлайн-пользователей, обратный вызов сообщений и другие услуги (и последующие услуги) в клиенте предоставляются в виде интерфейсов.
Интеграцию страниц также удобно делать позже, нужно только настроить эти интерфейсы, не нужно заботиться о конкретной реализации.
Суммировать
cim
На данный момент это только первая версия, с множеством багов и малой функциональностью (на тестирование дернули только несколько друзей группы), однако в дальнейшем она будет дорабатываться, по крайней мере эта версия принесет некоторые идеи тем, кто которые не имеют соответствующего опыта.
Дальнейшие планы:
Полный исходный код:
Если эта статья оказалась для вас полезной, пожалуйста, перешлите ее.