как создать приложение мессенджер

Разработка мессенджера для Андроид и iOS

WhatsApp, Telegram, Skype

Разработка мессенджера для смартфонов или сайта может стать успешным стартапом. Уже сейчас мессенджеры занимают первое место по количеству скачиваний в мире.

как создать приложение мессенджер. 1 reiting populiarnosti messengerov. как создать приложение мессенджер фото. как создать приложение мессенджер-1 reiting populiarnosti messengerov. картинка как создать приложение мессенджер. картинка 1 reiting populiarnosti messengerov.

Исследование компании SimilarWeb: в 168 странах мессенджеры лидируют по количеству скачиваний.

В 2016 году в мире было 1,58 млрд пользователей мессенджеров. По данным Портала статистики Statista к 2021 году эта цифра вырастет до 2,48 млрд. А это уже треть населения Земли. Так что, возможно, уже сейчас имеет смысл создать свой мессенджер на Андроид или iOS.

Стоит ли создавать еще одно приложение messenger?

У каждого пользователя на телефоне установлены два-пять мессенджеров. Все они используются в той или иной степени.

как создать приложение мессенджер. 3 image screen s istochnika. как создать приложение мессенджер фото. как создать приложение мессенджер-3 image screen s istochnika. картинка как создать приложение мессенджер. картинка 3 image screen s istochnika.

Статистика роста количества пользователей мессенджеров показывает: потенциал у приложений для обмена сообщениями есть. Но при запуске стартапа нужно быть готовым к конкуренции. Разработка мессенджера для iOs или на Andriod начинается с правильной постановки задачи и подбора инструментов. Так мы получим приложение, которое удовлетворит потребности пользователей.

Как создать мессенджер, востребованный пользователями

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

Наш подход к разработке архитектуры мессенджера

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

В WOXAPP мы проектируем и разрабатываем архитектуру по принципам Clean architecture.

Чистая архитектура, описанная Робертом Мартином, позволяет спроектировать гибкую и масштабируемую систему.

В современном программном обеспечении это распространенная практика, но достичь Clean architecture получается не у всех. В своей работе мы придерживаемся ряда определенных принципов и получаем ожидаемый результат. На рисунке новая архитектура, которую презентовал Google. C помощью этого подхода и наших собственных доработок мы реализовываем чистую архитектуру на Android.

как создать приложение мессенджер. 5 image clean architecture. как создать приложение мессенджер фото. как создать приложение мессенджер-5 image clean architecture. картинка как создать приложение мессенджер. картинка 5 image clean architecture.

Гибкость, масштабируемость и тестируемость

В процессе работы мы делаем так, чтобы архитектура делилась на автономные слои. Тогда бизнес-логика, представление и объекты данных разделены и могут меняться независимо друг от друга. Вне зависимости от размеров системы такой подход сохраняет ее гибкость, масштабируемость (масштабирование количества функций) и тестируемость.

Масштабируемым делаем не только код, но и саму инфраструктуру системы.

Производительность приложения

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

В процессе работы думаем о задаче клиента и с этим подходим к выбору инструментов.

Как правило, программируем на PHP. Этот язык программирования используется в Whatsapp, Facebook, Stackoverflow. PHP не уступает остальным языкам по производительности и способен выдержать высокие нагрузки. Плюс этого языка в том, что после выполнения задачи ресурсы сервера высвобождаются, а правильно построенная архитектура и хороший стек технологий перекрывают недостатки языка.

Стоимость разработки проекта на PHP в разы дешевле, чем на языках типа Java, Python. В то же время приложение не уступает по производительности.

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

Работа с большим количеством пользователей и большими нагрузками

В работе используем платформу NodeJS. Как показывает наш опыт, эта платформа подходит для создания чатов и мобильных приложений. NodeJS хорошо устроена и позволяет строить высоконагруженные системы. С коробки чат на NodeJS способен выдержать нагрузку в 10 000 подключений.

Разработка мессенджера для Android или iOS под данную платформу требует использовать Java Script. Этот язык популярен, поэтому найти разработчиков не проблема.

Таблицы базы данных хранят JSON-документы, допускающие любой уровень вложенности. У каждого документа прописан уникальный для таблицы-родителя первичный ключ «id». Ссылаясь на ключ, получаем документ. Каждая функция ReQL-запроса работает с данными, полученными из предыдущей функции цепочки. Это позволяет строить более гибкую архитектуру высоконагруженных проектов и не думать о сложности структур данных.

как создать приложение мессенджер. 7 infographica visheizlozhennogo. как создать приложение мессенджер фото. как создать приложение мессенджер-7 infographica visheizlozhennogo. картинка как создать приложение мессенджер. картинка 7 infographica visheizlozhennogo.

Разработка интерфейса мессенджера

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

Источник

Простой клиент-сервер на Android (интернет-мессенджер)

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

Поехали. Многие мобильные приложения (и не только) используют архитектуру клиент-сервер. Общая схема, думаю, понятна.

как создать приложение мессенджер. 72ff3cc1380e4a05a3a22a614b2d0bfd. как создать приложение мессенджер фото. как создать приложение мессенджер-72ff3cc1380e4a05a3a22a614b2d0bfd. картинка как создать приложение мессенджер. картинка 72ff3cc1380e4a05a3a22a614b2d0bfd.

Уделим внимание каждому элементу и отметим:

как создать приложение мессенджер. b0aeddc9d49e4525966d138e485db8f0. как создать приложение мессенджер фото. как создать приложение мессенджер-b0aeddc9d49e4525966d138e485db8f0. картинка как создать приложение мессенджер. картинка b0aeddc9d49e4525966d138e485db8f0.

Клиент, установленный на устройстве А, посылает сообщение для клиента, установленного на устройстве Б. И наоборот. Сервер играет роль связующего звена между устройством А и Б… С, Д… и т.д. Также он играет роль «накопителя» сообщений, для их восстановления, на случай удаления на одном из клиентских устройств.

Для хранения сообщений используем SQL БД как на сервере, так и на устройствах-клиентах (в принципе, вся работа клиентов интернет-мессенджеров и сводится к постоянной синхронизации локальной и удаленной БД с сообщениями). Дополнительно, наш интернет-чат будет уметь стартовать вместе с запуском устройства и работать в фоне. Взаимодействие будет происходить путем HTTP запросов и JSON ответов.

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

Делаем сервер

Для реализации «сервера», нам нужно зарегистрироваться на любом хостинге, который дает возможность работы с SQL и PHP.

Создаем пустую SQL БД, в ней создаем таблицу.

Структура запросов к api:

Клиентская часть

Теперь структура Android приложения:

как создать приложение мессенджер. 6898c53f8075409ba4d2137fd223d685. как создать приложение мессенджер фото. как создать приложение мессенджер-6898c53f8075409ba4d2137fd223d685. картинка как создать приложение мессенджер. картинка 6898c53f8075409ba4d2137fd223d685.

В фоне работает FoneService.java, который, в отдельном потоке, каждые 15 секунд делает запрос на сервер. Если ответ сервера содержит новые сообщения, FoneService.java записывает их в локальную БД и отправляет сообщение ChatActivity.java о необходимости обновить ListView, с сообщениями. ChatActivity.java (если она в этот момент открыта) получает сообщение и обновляет содержимое ListView из локальной БД.

Отправка нового сообщения из ChatActivity.java происходит сразу на сервер, минуя FoneService.java. При этом наше сообщение НЕ записывается в локальную БД! Там оно появится только после получения его назад в виде ответа сервера. Такую реализацию я использовал в связи с важным нюансом работы любого интернет-чата — обязательной группировкой сообщений по времени. Если не использовать группировку по времени, будет нарушена последовательность сообщений. Учитывая, что клиентские приложения просто физически не могут быть синхронизированы с точностью до миллисекунд, а возможно будут работать даже в разных часовых поясах, логичнее всего будет использовать время сервера. Так мы и делаем.

Создавая новое сообщение, мы передаем запросом на сервер: имя автора сообщения, имя получателя сообщения, текст сообщения. Получая эту запись назад, в виде ответа сервера, мы получаем то, что отправляли + четвертый параметр: время получения сообщения сервером.

Источник

Как создать свой мессенджер: ответы на популярные вопросы

Время чтения: 7 минут

как создать приложение мессенджер. 01 site ru 3. как создать приложение мессенджер фото. как создать приложение мессенджер-01 site ru 3. картинка как создать приложение мессенджер. картинка 01 site ru 3.

Если вы сомневаетесь нужно в ли ступать на территорию разработки мессенджеров, просто взгляните на последние цифры. В 2021 году приложением Facebook Messenger пользуются 1,3 миллиарда человек во всем мире, а WhatsApp есть на телефоне у 2 миллиардов пользователей (¼ часть населения земли, на секунду).

Хорошая новость заключается в том, что у большинства установлено сразу несколько приложений, поэтому все перечисленные компании не конкурируют между собой, а дополняют друг друга. Например, WeChat популярен в основном в азиатских странах, а Slack используют 12 миллионов человек для коммуникации внутри компаний. Аналитики ожидают, что количество активных пользователей будет только расти, а рынок приложений для обмена сообщениями будет цвести и пахнуть.

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

Ключевые функции мессенджеров

Must-have функции

Авторизация

Для пользователя регистрация не должна занимать больше, чем две минуты. Чтобы ускорить процесс, мы рекомендуем добавить интеграции с социальными сетями, регистрацию по номеру телефона или адресу электронной почты. После этого юзеры смогут выбрать фотографию профиля и имя. В некоторых приложениях, например, в Telegram, есть дополнительная функция, которая скрывает номер телефона от других, также в мессенджере можно создавать сразу несколько профилей. Например, рабочий и личный, или российский и заграничный, если вы живете на две страны.

Доступ к контактам

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

как создать приложение мессенджер. 02 site eng 3. как создать приложение мессенджер фото. как создать приложение мессенджер-02 site eng 3. картинка как создать приложение мессенджер. картинка 02 site eng 3.

Обмен сообщениями

как создать приложение мессенджер. 03 site eng 2. как создать приложение мессенджер фото. как создать приложение мессенджер-03 site eng 2. картинка как создать приложение мессенджер. картинка 03 site eng 2.

Обмен файлами

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

Push-уведомления

Как создать свой мессенджер без функции уведомлений? Это невозможно! В эпоху, когда мы так боимся пропустить что-то важное, пользователи обязаны немедленно знать, что они получили новое сообщение. Наверняка, каждый из нас хоть раз сходил с ума, ожидая обратную связь от потенциального работодателя — не нам вас убеждать в том, насколько важны push-уведомления в чатах 🙂

Защита данных

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

Nice-to-have функции

Звонки

Чат-боты

Эта функция привлечет бизнес-клиентов в ваше приложение-чат. Не пугайтесь слова «Боты». Чат-бот — это всего лишь автоматическое программное обеспечение, которое поддерживает онлайн-связь с клиентами, отправляет автоматические сообщения и помогает с ответами на часто задаваемые вопросы. Они также могут позвать человека, если вопрос пользователя пришелся роботу «не по зубам».

как создать приложение мессенджер. 04 site eng 1. как создать приложение мессенджер фото. как создать приложение мессенджер-04 site eng 1. картинка как создать приложение мессенджер. картинка 04 site eng 1.

Как создать свой мессенджер, который принесет прибыль?

Как найти надежного разработчика?

Проверить команду разработчиков «на прочность» можно в два шага:

Помимо этого, для стартапа важно соблюдать бюджет и сроки. Поэтому мы искренне советуем выбрать того, кто разрабатывает приложения на React Native. Почему? Сейчас объясним.

React Native — это фреймворк, который был создан Facebook 5 лет назад. Код приложений пишется на JavaScript – одном из самых популярных языков программирования во всем мире. Есть 3 основных преимущества работы с компанией, которая работает на React Native.

JavaScript. Этот язык — один из самых распространенных среди разработчиков, поэтому вы сможете найти подрядчика для разработки вашего приложения быстро и безболезненно.

Нативные UI-элементы. Компании Facebook принадлежат бесконечные библиотеки нативных UI-элементов для интерфейса. Как это поможет вашей бизнес-идее? Очень просто — это означает, что ваше будущее приложение функционировать как нативное. Производительность мессенджера будет такой же, как если бы вы разработали его на Java или Swift.

Мы работаем с React Native последние 4 года и еще ни разу не разочаровались. Фреймворк позволяет нам создавать MVP (минимально-жизнеспособный продукт)для наших клиентов за 3 месяца. Это означает, что вы придете к нам с идеей, и через 90 дней у вас будет рабочая версия продукта, которую можно тестировать, собирать обратную связь и показывать потенциальным инвесторам.

Сколько стоит создать приложение-мессенджер?

Вот мы и дошли до самой важной части статьи — той, которая про стоимость и сроки. Разработка мессенджера – сложный процесс, в котором участвует команда разработчиков, дизайнеров, проектных менеджеров и QA-специалистов. Выбросить кого-то из команды и при этом сделать крутой продукт нельзя 🙂

Мы подробно рассказали о том, как создать свой мессенджер и как его можно монетизировать. Теперь давайте посчитаем, сколько это стоит!

как создать приложение мессенджер. Tinder ru. как создать приложение мессенджер фото. как создать приложение мессенджер-Tinder ru. картинка как создать приложение мессенджер. картинка Tinder ru.

Key in your e-mail address to get a full breakdown of the estimation with all details

Thank you! You will be contacted soon!

Итого

Источник

«Хочу как Дуров»: пишем простой мессенджер

Авторизуйтесь

«Хочу как Дуров»: пишем простой мессенджер

как создать приложение мессенджер. messengermini. как создать приложение мессенджер фото. как создать приложение мессенджер-messengermini. картинка как создать приложение мессенджер. картинка messengermini.

В последнее время растёт популярность приложений для обмена сообщениями. Пользователи предпочитают мессенджеры, потому что они позволяют взаимодействовать в режиме реального времени. В этой статье мы разберём процесс создания простого приложения для обмена мгновенными сообщениями. Не будем сильно углубляться в нюансы разработки: мы напишем рабочий мессенджер, который в дальнейшем можно будет улучшить.

Статья подойдёт состоявшимся программистам и тем, кто только интересуется, как войти в IT.

Используемые технологии и инструменты

Подготовка

Структура будущего приложения выглядит примерно так:

как создать приложение мессенджер. 1 bdJ5lKSWXS 40D9TJ9dNA 1. как создать приложение мессенджер фото. как создать приложение мессенджер-1 bdJ5lKSWXS 40D9TJ9dNA 1. картинка как создать приложение мессенджер. картинка 1 bdJ5lKSWXS 40D9TJ9dNA 1.

Установите Node.js и MongoDB. Кроме того, нам понадобится библиотека AngularJS, скачайте её и скопируйте в папку lib каталога Client.

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

Серверная часть

Шаг 1. Запуск проекта

Перейдите в каталог Server и выполните команду:

Она запустит новый проект.

Укажите все необходимые сведения. В результате будет создан файл package.json примерно следующего вида:

Шаг 2. Установка зависимостей

Выполнение этих команд установит необходимые зависимости и добавит их в package.json :

Выглядеть они будут примерно так:

Шаг 3. Создание сервера

Создадим сервер, который обслуживает порт 3000 и возвращает HTML-файл при вызове. Для инициализации нового соединения сокету нужно передать HTTP-объект. Событие connection будет прослушивать входящие сокеты, каждый сокет будет выпускать событие disconnect, которое будет вызвано при отключении клиента. Мы будем использовать следующие функции:

Создайте сервер с именем server.js . Он должен:

В результате ваш сервер будет выглядеть примерно так:

Клиентская часть

Создайте файлы index.html в каталоге Client, style.css в каталоге CSS и app.js в каталоге js.

Client/index.html

Пусть это будет простой HTML-код, который получает и отображает наши сообщения.

Включите скрипты socket.io-client и angular.js в ваш HTML:

socket.io служит для нас клиентом. Он по умолчанию подключается к хосту, обслуживающему страницу.

В результате index.html должен выглядеть примерно так:

CSS/style.css

Чтобы придать нашей странице внешний вид окна чата, добавим немного стилей. Вы можете использовать любую CSS-библиотеку. Получим следующее:

js/app.js:

Создайте Angular-приложение и инициализируйте соединение сокета. Для этого нужны следующие функции:

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

В результате app.js будет выглядеть примерно так:

Запуск приложения

Перейдите в папку с server.js и запустите команду:

Сервер начнет работу на порте 3000. Чтобы в этом убедиться, перейдите по ссылке в браузере:

Ваш собственный мессенджер готов!

Что можно улучшить?

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

Установите Mongoose или MongoDB для работы с базами данных Mongo:

Можете ознакомиться с документацией по их использованию: mongoose и mongodb.

Схема должна получиться примерно следующего вида:

Собеседникам могут быть присвоены следующие статусы:

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

Неплохо было бы реализовать для пользователя функционал сохранения сообщений в дополнительные коллекции. Пусть каждый её объект содержит сообщение, отправителя, получателя и время. Спроектируйте вашу базу данных в соответствии с конкретными потребностями и методами обработки сообщений.

Также вы можете создать REST API для обслуживания клиента. Например, конечную точку, отправляющую домашнюю страницу, из которой пользователи могут выполнять другие запросы.

Некоторые из возможных конечных точек API:

Вот какой мессенджер получился у автора статьи:

как создать приложение мессенджер. 1. как создать приложение мессенджер фото. как создать приложение мессенджер-1. картинка как создать приложение мессенджер. картинка 1.

как создать приложение мессенджер. 1 HRqQTX ACCAlU2UQ9PNaGg. как создать приложение мессенджер фото. как создать приложение мессенджер-1 HRqQTX ACCAlU2UQ9PNaGg. картинка как создать приложение мессенджер. картинка 1 HRqQTX ACCAlU2UQ9PNaGg.

Внешний вид приложения

Исходный код приложения можно найти на GitHub.

Источник

Как я свой мессенджер писал

Одним вечером, после очередного расстраивающего дня, наполненного попытками наладить баланс в своей игре, я решил, что мне срочно требуется отдых. Переключусь на другой проект, быстренько его сделаю, верну на место скатившуюся за время разработки игры самоооценку и с новыми силами возьму игру штурмом! Главное выбрать проект nice and relaxing… Написать свой месседжер? Ха! How hard can it be?

Код можно посмотреть здесь.

как создать приложение мессенджер. bcwavbn h0r3vgv8zzhdkaq09y. как создать приложение мессенджер фото. как создать приложение мессенджер-bcwavbn h0r3vgv8zzhdkaq09y. картинка как создать приложение мессенджер. картинка bcwavbn h0r3vgv8zzhdkaq09y.как создать приложение мессенджер. . как создать приложение мессенджер фото. как создать приложение мессенджер-. картинка как создать приложение мессенджер. картинка .

Краткая предыстория

До начала работы над мессенджером почти год корпел над мультиплеерной онлайн Line Tower Wars игрой. Программирование шло хорошо, всё остальное (баланс и визуал в особенности) — не очень. Внезапно оказалось, что сделать игру и сделать увлекательную игру (увлекательную для кого-то помимо самого себя) — две разные вещи. После года мытарств мне нужно было отвлечься, поэтому я решил попробовать свои силы в чём-то другом. Выбор пал на мобильную разработку, а именно, Flutter. Слышал множество хороших вещей про Flutter, да и дарт после недолгих экспериментов мне понравился. Решил написать свой собственный мессенджер. Во-первых, хорошая практика по реализации и клиента, и сервера. Во-вторых, будет что-то весомое положить в портфолио для поиска работы, я как раз нахожусь в процессе.

Запланированный функционал

Выбор языка

С выбором языка долго не думал. Сначала был соблазн использовать дарт и для клиента, и для сервера, но более детальная инспекция показала, что доступных драйверов для дарт не очень много, а те что есть не внушают особого доверия. Хотя не поручусь говорить о текущем моменте, возможно ситуация улучшилась. Так что выбор мой пал на C#, с которым я работал в Unity.

Архитектура

Начал с продумывания архитектуры. Конечно, учитывая что моим мессенджером скорее всего будут пользоваться 3 с половиной человека, можно было бы не заморачиваться с архитектурой вообще. Берёшь и делаешь как в бесчисленных туториалах. Вот нода, вот монго, вот вебсокеты. Готово. И Firebase где-то тут. Но так не интересно. Я решил делать мессенджер, способный легко горизонтально скейлиться, будто ожидаю миллионы одновременных клиентов. Однако так как опыта в этой сфере у меня не было никакого, пришлось всё познавать на практике методом ошибок и снова ошибок.

как создать приложение мессенджер. image loader. как создать приложение мессенджер фото. как создать приложение мессенджер-image loader. картинка как создать приложение мессенджер. картинка image loader.

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

Ниже будет подробное описание отдельных компонентов.

Frontend Server

Ещё до того как я взялся делать игру, меня увлекла концепция асинхронного однопоточного сервера. Эффективно и без потенциальных race’ов — о чем ещё можно просить. С целью разобраться, как такие сервера устроены, я стал копаться в модуле asyncio языка python. Увиденное решение показалось мне очень изящным. Если кратко, то решение на псевдокоде выглядит так.

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

Frontend сервера реализованы именно так. Они все однопоточные и асинхронные. Поэтому для максимальной производительности нужно запускать столько серверов на одной машине сколько у неё имеется ядер (4 на картинке).

Frontend сервер читает сообщение от клиента и, основываясь на коде сообщения, отправляет его в один из топиков кафки.

Кафка имеет несколько применений, но я использую его как брокер сообщений по типу RabbitMQ. В кафке есть топики. Топик служит в качестве логического представления коллекции, в которую мы можем писать и на которую все заинтересованные клиенты могут подписываться (в моем случае authentication backend сервера подписываются на топик authentication, например). Почему логического? Потому что топик не является каким-то неделимым юнитом, каждый топик состоит из одного или более партишн (partition). Когда мы отправляем сообщение в топик, оно попадает в один из партишн. Мы можем либо явно указать партишн, либо довериться алгоритму, который определит в какой партишн отправить сообщение. Например, отправлять все сообщения с одинаковым ключом в один и тот же партишн (сообщения могут, но не обязаны, иметь ключ, а так же заголовки (headers)).

Зачем такие сложности? Зачем делить топик на партишн? Партишн служит в качестве единицы параллелизации. Несколько потребителей (consumer) могут подписаться на один и тот же топик (образуя группу consumer’ов), и тогда кафка (по умолчанию) распределит все партишн равномерно между ними. Если, скажем, у нас топик с двумя партишн, на который подписано 2 клиента, кафка распределит каждому клиенту по одному партишн. Если партишн 3 — одному из клиентов достанется 2. Кафка умеет детектить добавление новых партишн и новых клиентов и автоматически перераспределять партишн в случае необходимости.

Frontend сервер отправляет сообщение в кафку без ключа (когда нет ключа, кафка просто отправляет сообщения в партишн по очереди). Из топика сообщение вытаскивает один из соответствующих backend серверов. Сервер обрабатывает сообщение и… что дальше? А что дальше зависит от типа сообщения.

Окей, звучит не очень сложно, но для того чтобы отправить сообщение какому-либо клиенту нам нужно: 1) узнать с каким frontend сервером этот клиент соединён (ведь мы не выбираем с каким конкретно сервером клиент соединятся, за нас решает балансировщик); 2) передать сообщение от backend сервера нужному frontend серверу; 3) собственно, отправить сообщение клиенту.

Для реализации пунктов 1 и 2 я решил использовать отдельный топик («frontend servers» топик). Разделение authentication, session и call топиков на партишн служит как механизм параллелизации. Видим что session сервера сильно загружены? Просто добавляем парочку новых партишн и session серверов, и кафка сделает перераспределение нагрузки за нас, разгружая имеющиеся session сервера. Разделение же «frontend servers» топика на партишн служит как механизм маршрутизации.

Каждому frontend серверу соответствует один партишн «frontend servers» топика (с таким же индексом, что и сам сервер). То есть серверу 0 — партишн 0 и тд. Кафка даёт возможность подписаться не только на определённый топик, но и на определённый партишн определённого топика. Все frontend сервера на стартапе подписываются на соответствующий партишн. Таким образом backend сервер получает возможность отправить сообщение конкретному frontend серверу, отправив сообщение в определённый партишн.

Окей, теперь, когда клиент присоединяется, нужно просто сохранять где-то пару UserId — Frontend Server Index. При дисконнекте — удалять. Для этих целей подойдёт любое из многих in-memory key-value бд. Я выбрал редис.

* На самом деле процесс чуть сложнее чем я описал. Можете ознакомиться в исходном коде.

Псевдокод frontend сервера

В коллбэке ожидание ответа отменяется и начинается отправка серверной ошибки. Если же ответ от backend сервера получен, коллбэк ничего не делает.

Использовать await Task.WhenAny(answerReceivedTask, Task.Delay(x)) нет возможности, так как код после Task.Delay выполняется на потоке из пула.

* При написании статьи я вдруг осознал, что мы можем не передавать deliveryHandler в метод Produce или просто игнорировать все ошибки кафки (клиенту всё равно будет отправлена ошибка по таймауту, который я описал ранее) — тогда весь наш код будет однопоточным. Теперь думаю, как лучше сделать.

Backend Server

По сравнению с frontend сервером, интересных моментов здесь практически нет. Все backend сервера работают одинаково. На стартапе сервер подписывается на топик (authentication, session или call в зависимости от роли), и кафка назначает ему один или более партишн. Сервер получает сообщение из кафки, обрабатывает и обычно посылает в ответ одно или более сообщений. Почти реальный код:

Кафка гарантирует at least once delivery, что означает, что сообщения не будут потеряны и будут доставлены в большинстве случаев один раз (иногда возможна повторная доставка сообщения). Это достигается за счёт того, что кафка для каждого партишн каждого топика хранит последний подтвержённый (commited) оффсет. Скажем, один consumer вытащил из назначенного ему партишн сообщение с оффсетом 16, обработал его, закоммитил 16й оффсет, вытащил следующее сообщение, но во время обработки вдруг умер, не сделав коммит. Кафка назначит его партишн какому-то другому consumer’у из той же группы consumer’ов и начнёт доставлять ему сообщения из данного партишн, начиная с оффсета 16 + 1 (последний подтверждённый оффсет + 1). Таким образом сообщение 17 не будет потеряно. Кафка может либо коммитить оффсеты автоматически каждые N миллисекунд, либо полностью передать контроль над коммитами пользователю.

Как видно, мы итерируем по ворк юнитам, находим последний завершённый к данному моменту юнит, после которого нет незавершённых, и коммитим соответствующий ему оффсет. Такой цикл позволяет нам избежать «дырявых» коммитов. Например, если у нас в данный момент 4 ворк юнита ( 0: Finished, 1: Not Finished, 2: Finished, 3: Finished ), мы можем закоммитить только 0й юнит, так как, если закоммитим сразу 3й, это может привести к потенциальной потере 1го, если вдруг сервер умрёт прямо сейчас.

Сервисы довольно тривиальны. Вот, например, какой код выполняется, когда юзер отправляет новое сообщение:

База данных

Большая часть функционала сервисов, вызываемых backend серверами, — это просто добавление новых данных в бд и обработка уже имеющихся. Очевидно, как база данных устроена и как мы ей оперируем играет очень важное значение для мессенджера, и тут мне бы хотелось сказать, что я подошёл к вопросу выбора бд очень тщательно после внимательного изучения всех вариантов, но это не так. Я просто выбрал CockroachDb, потому что он обещает много при минимуме усилий и имеет совместимый с postgres синтаксис (я работал с постгрес раньше). Были мысли использовать Кассандру, но в конце концов решил остановиться на чём-то знакомом. Я никогда раньше не работал ни с кафкой, ни с рэббитом, ни с Flutter и дарт, ни с WebRtc, поэтому решил не тащить ещё и Кассандру, так как боялся утонуть во всём множестве новых для меня технологий.

Из всех частей моего проекта дизайн базы данных — вещь, в которой я сомневаюсь больше всего. Я не уверен, что решения, которые я принял, действительно, хорошие решения. Всё работает, но можно было сделать лучше. Например, есть таблицы ShareRooms (так я называю чаты) и ShareItems (так я называю сообщения). Так вот все юзеры, входящие в какую-то комнату, записаны в jsonb поле этой комнаты. Это удобно, но явно очень медленно, так что скорее всего переделаю на использование внешних ключей. Или, например, таблица ShareItems хранит все сообщения. Что тоже удобно, но так как ShareItems является одной из самых нагруженных таблиц (постоянные select и insert ), возможно стоит создавать новую таблицу для каждой комнаты или что-то в этом роде. Кокроач раскидывает записи по разным нодам, соответственно, нужно тщательно продумывать куда какая запись пойдёт, чтобы добиться максимальной производительности, а я этого не делал. В общем, как можно понять из всего вышесказанного, базы данных не самое моё сильное место. Прямо сейчас я вообще тестирую всё на постгрес, а не кокроач, потому что так меньше нагрузки на мою рабочую машину, она и так бедная от нагрузок скоро взлетит. Благо код для постгрес и кокроач разнится совсем немного, так что переключаться не составляет труда.

Сейчас я нахожусь в процессе изучения, как, собственно, кокроач работает (как происходит mapping между SQL и key-value (кокроач использует RocksDb под капотом), как он распределяет данные между нодами, реплицирует и тд). Стоило, конечно, изучить кокроач перед тем как использовать его, но лучше поздно чем никогда.

Flutter

Долгое время я работал над серверной частью и использовал простые консольные клиенты для теста, так что даже не создавал Flutter проект. А когда создал, думал, что серверная часть была сложной частью, а приложение это так, фигня, за пару дней разберусь. Пока работал над сервером, пару раз создавал Hello World’ы на флаттер, чтобы прочувствовать фреймворк, и, так как мессенджеру не требуется какой-то замысловатый UI, думал, что полностью готов. Так вот UI, действительно, фигня, но реализация функционала доставила мне проблем (и ещё доставит, так как не всё готово).

State management

Самая популярная тема. Есть тысяча способов управлять состоянием, и рекомендуемый подход меняется раз в полгода. Сейчас мэйнстримом является provider. Лично я для себя выбрал 2 способа: bloc и redux. Bloc (Business Logic Component) для управления локальным состоянием и redux для управления глобальным.

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

Ну а про redux и так все всё знают, так что и говорить нечего. Тем более я его вырезал из приложения 🙂 Использовал для управление аккаунтом, но затем, поняв что в данном случае преимуществ над блоком особых нет, вырезал, чтобы не тащить лишнее. Но в целом считаю redux полезной вещью для управления глобальным состоянием.

Самая мучительная часть

Изображения

В данный момент можно отправлять текст, текст + изображения и просто изображения. Отправка видео ещё не реализована. Изображения немного ужимаются и сохраняются в Firebase storage. В самом сообщении передаются ссылки. По получении сообщения клиент скачивает изображения, генерирует миниатюры и сохраняет всё на файловую систему. В базу записываются пути к файлам. Кстати, генерация миниатюр — единственный код, выполняемый на отдельном треде, так как это compute-heavy операция. Я просто запускаю один воркер-поток, скармливаю ему изображение и в ответ получаю миниатюру. Код предельно прост, так как дарт даёт удобные абстракции для работы с потоками.

Также используется Firebase auth, но только для авторизации доступа к Firebase storage (чтобы юзер не мог, скажем, залить профильную картинку кому-то другому). Вся остальная авторизация осуществляется через мои серверы.

Формат сообщений

Здесь вы наверное ужаснётесь, так как я использую обычные массивы байтов. Json отпадает, потому что требуется эффективность, а про protobuf я не знал, когда начинал. Использование массивов требует большой аккуратности, потому что один неправильный индекс и всё пойдёт наперекосяк.

Первые 4 байта — длина сообщения.
Следующий байт — код сообщения.
Следующие 16 байт — идентификатор запроса (uuid).
Следующие 40 байт — токен авторизации.
Остальная часть сообщения.

Длина сообщения требуется, так как я не использую http или вебсокеты, или какой-то другой протокол, который обеспечивает разделение одного сообщения от другого. Мои frontend сервера видят только потоки байтов, и они должны знать, где одно сообщение заканчивается, и начинается другое. Есть несколько способов разделять сообщения (например, использовать какой-то никогда не встречающийся в сообщениях символ в качестве разделителя), но я предпочёл указывать длину, так как этот способ самый простой, хоть он и влечёт за собой оверхед, так как большинству сообщений хватает и одного байта для указания длины.

Идентификатор запроса присутствует в большинстве сообщений, но не во всех. Он выполняет 2 функции: по этому идентификатору клиент устанавливает соответствие между отправленным запросом и полученным ответом (если клиент отправил сообщения А, Б, В в таком порядке, это не означает, что ответы тоже придут по порядку). Вторая функция — избежание дупликатов. Как было сказано ранее, кафка гарантирует at least once delivery. То есть в редких случаях сообщения всё-таки могут быть продублированы. Добавив в нужную таблицу базы данных колонку RequestIdentifier с unique ограничением, мы можем избежать вставки дупликата.

Токен авторизации — это UserId (8 байт) + 32 байта HmacSha256 подпись. Не думаю, что здесь стоит использовать Jwt. Jwt это примерно в 7-8 раз больший размер ради получения чего? У меня юзеры не имеют никаких claims, поэтому простая подпись hmac’ом годится. Авторизации через другие сервисы нет и не планируется.

Аудио и видео звонки

Забавно, что реализацию аудио и видео звонков я сознательно откладывал, так как был уверен, что проблем не оберусь, а на деле это оказалось одной из самых легких в реализации фич. По крайней мере базовый функционал. Вообще просто добавление WebRtc в приложение и получение первого сеанса видеосвязи заняло всего несколько часов, и, о чудо, первый же тест увенчался успехом. До этого я думал, что работающий с первого раза код — это миф. Обычно первый тест новой фичи всегда проваливается из-за какой-нибудь тупой ошибки вроде «добавил сервис, но не зарегистрировал его в DI-контейнере».

WebRtc — это технология, позволяющая установить peer-to-peer соединение между двумя устройствами, и, в случае если peer-to-peer соединение невозможно, помогающая соединить устройства через сервер. Это не какая-то библиотека, где вы вызываете пару функций, и всё настраивается автоматически за вас. Установка соединения является довольно вовлечённым процессом, но при этом не очень сложным.

Сам сеанс связи в большинстве случаев происходит без участия сервера (peer-to-peer), но для того чтобы установить связь, требуются 3 разных сервера (серверы не обязательно должны быть физически разными, подразумеваются 3 разные роли. Один и тот же сервер в теории может выполнять все 3 функции).

Первый и самый простой — stun сервер. Мы отправляем stun серверу сообщение, и его задача — прочитать Source IP и Source Port пакета и отправить эту информацию обратно, но уже в теле пакета. Для чего это требуется? Прямо сейчас вы скорее всего сидите за каким-то роутером. У роутеров есть внутренний и внешний IP адреса. Когда вы отправляете пакет на какой-то сайт, роутер, получив от вас пакет, заменяет его Source IP и Source Port на свой внешний IP и какой-то сгенерированный порт и делает запись в таблицу NAT вида [ Source IP | Source Port | Router External IP | Router Port ]. Когда роутер получает пакет откуда-то снаружи, он сравнивает Dest IP и Dest Port полученного пакета с колонками Router External IP и Router Port таблицы NAT, и, либо находит соответствующие Source IP — Source Port и пересылает пакет нужному устройству, либо отбрасывает пакет. Важно тут то, что, чтобы пакет попал к вам на устройство, он сначала должен пройти через роутер, а, чтобы пройти через роутер, должна быть соответствующая запись в NAT таблице. Уже сам простой факт отправки сообщения stun серверу генерирует запись в NAT таблице. А в ответ от stun сервера мы получаем пару Router External IP — Router Port. Эта пара — публичный адрес нашего устройства. Отправляя пакеты на данный адрес, устройства «извне» смогут пройти через NAT (NAT traversal) благодаря тому, что нужная запись в таблицу NAT была сделана, когда мы отправили запрос stun серверу.
* Некоторые NAT сложнее, и обойти их не так просто. Собственно, если бы всё было просто, то WebRtc бы и не требовался.

Второй сервер — turn. Это сервер, через который происходит передача потоков между клиентами, когда реальный peer-to-peer невозможен. Fallback сервер. Намного сложнее в реализации, и, в теории, не обязателен, но крайне желателен, потому что peer-to-peer соединение возможно далеко не всегда. Есть свободная реализация turn сервера — coturn, но я его ещё не поднимал.

Третий сервер — сигнальный. Без него тоже в теории можно обойтись, но на практике нет. Этот сервер может быть реализован как угодно, нет никакого специального протокола. Его функция — просто передавать разную конфигурирующую информацию от одного устройства другому и обратно. Эта конфигурирующая информация нужна для установки соединения. Без него возможно обойтись, потому что информацию вы можете передать из уст в уста, например, или используя другой мессенджер 🙂 В передаваемых данных нет ничего особенного — числа и строки.

В WebRtc есть 3 типа сигнальных сообщений: offer, answer и candidate. Инициатор звонка отправляет offer другой стороне через сигнальный сервер, получает в ответ answer, и обе стороны отправляют друг другу кандидатов. Кандидатов может быть много, и, по сути, это такой процесс переговоров, где стороны решают какую транспортную конфигурацию использовать. Возможных транспортных конфигураций (маршрутов от одного устройства к другому) может быть несколько, выбирается наилучший.

Сама по себе технология WebRtc устанавливает соединение и занимается передачей потоков туда-обратно, но это не фреймворк для создания полноценных звонков. Под звонком я подразумеваю сеанс связи с возможностью отменить, отклонить и принять вызов, а также положить трубку. Плюс нужно дать знать звонящему, если другая сторона уже занята. А также реализовать мелочи вроде «ждать ответа на вызов N секунд, затем сбросить». Если просто внедрить WebRtc в приложение в голом виде, то при входящем звонке камера и видео будут спонтанно включаться, что, конечно, неприемлемо.

В чистом виде WebRtc обычно подразумевает как можно более скорую отправку кандидатов другой стороне, чтобы переговоры начались как можно быстрее, что логично. В моих тестах кандидаты принимающей стороне вообще всегда начинали приходить ещё даже до того как придёт offer. Такие «ранние» кандидаты нельзя отбрасывать, их нужно запоминать, чтобы потом, когда придёт оффер, и RTCPeerConnection будет создан, добавить их в соединение. Тот факт, что кандидаты могут начать приходить ещё до оффера, а также некоторые другие причины, делают реализацию полноценных звонков нетривиальной задачей. Что делать, если нам звонят сразу несколько юзеров? Нам будут приходить кандидаты от всех, и, хотя мы можем отделить кандидатов одного юзера от другого, становится неясно каких кандидатов отбрасывать, потому что мы не знаем чей оффер придёт раньше. Также будут проблемы, если нам начинают приходить кандидаты и затем оффер в момент, когда мы сами кому-то звоним.

Текущее состояние и дальнейшие планы

Поиск по QR-коду, неожиданно, довольно проблематично реализовать, потому что почти все плагины для скана кода, которые я пробовал, отказываются заводиться либо работают некорректно. Но, думаю, здесь проблемы будут решены. А за реализацию поиска по геолокации я пока ещё не брался. В теории особых проблем быть не должно.

Уведомления в процессе реализации, как и отправка видео.

Что ещё нужно сделать?

И много всего по-мелочи, вроде конкатенации строк вместо использования StringBuilder ‘а, Dispose не везде вызывается, где должен, и тд и тп. В общем, обычное состояние проекта в процессе разработки. Всё вышеперечисленное решаемо, но есть одна фундаментальная проблема, о которой я вообще не думал до последнего момента, потому что вылетело из головы — мессенджер должен работать даже когда приложение не открыто, а мой — не работает. Если честно, решение этой задачи пока не приходит мне в голову. Тут, видимо, не обойтись без нативного кода.

Я бы оценил готовность проекта в 70%.

Итоги

Полгода прошло с момента начала работы над проектом. Совмещал с парт-тайм работой и делал большие перерывы, но всё равно сил и времени ушло прилично. Планирую реализовать все заявленные фичи + добавить что-нибудь необычное вроде крестиков-ноликов или шашек прямо в комнате. Безо всякой причины, просто потому что интересно.

Если есть какие-то вопросы, пишите. Почта есть на гитхаб.

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *