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

Затем, в прекрасный солнечный летний день, подходит руководитель проекта и говорит:

«Нам нужно создать MVP для чат-системы всего за один месяц!»

Это хаос! Вроде бы что-то очень сложное всего за месяц работы. Некоторые вопросы начинают возникать:

  • Какие требования?
  • Как оценить усилия?
  • Как создать простое приложение для чата, которое собирает ценность?

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

После обширных исследований и отсутствия решения голос с небес говорит:

«Почему бы не создать свою собственную архитектуру?»

Это просто MVP! Нам нужно протестировать проект, прежде чем думать о масштабируемости, верно? Именно тогда мы решили реализовать эту архитектуру с помощью WebSockets. Вот разбивка того, что мы придумали.

Проект

Нашей отправной точкой была базовая архитектура, состоящая из Back-end с Python и Django, с использованием базы данных PostgreSQL и ReactJS и Redux во Front-end. Помня о маленьких шагах, мы подумали о создании системы чата без операций в реальном времени, другими словами, просто о CRUD сообщений. После моделирования базы данных у нас осталось всего две таблицы: Чат и Сообщение. Простой!

Когда база данных готова, мы создали все конечные точки, необходимые для связи с Front-end. Наш API стал очень простым, всего две конечные точки: /chats и /chats/:idChat/messages, со следующими HTTP-действиями:

  • POST: / api / v1 / chats / - создает новый чат между двумя пользователями.
  • GET: / api / v1 / chats / - выводит список всех чатов, к которым принадлежит авторизованный пользователь.
  • POST: / api / v1 / chats /: idChat / messages / - добавляет новое сообщение в определенный чат.
  • GET: / api / v1 / chats /: idChat / messages / - перечисляет все взаимодействия между пользователями в определенном чате.

Во Front-end мы создали с Redux два хранилища: одно для чатов, а другое для сообщений, точно отражающих то, что было получено от API. Для связи между Редукторами потребовалось четыре действия:

  • CREATE_CHAT: отправляет вызов POST в / chats / и объединяет новый чат в магазине.
  • GET_ALL_CHATS: отправляет вызов GET в / chats / и добавляет возвращенные чаты в магазин.
  • SEND_MESSAGE: отправляет вызов POST в / chats /: idChat / messages / и добавляет новое сообщение в магазин.
  • GET_ALL_MESSAGES: отправляет вызов GET в / chats /: idChat / messages / и добавляет возвращенные сообщения в хранилище.

На изображении выше представлена ​​реализация после первого этапа проекта. Благодаря этому мы уже могли вести разговоры между двумя пользователями. Однако нам нужно было обновить страницу, чтобы получать новые сообщения.

Думая о реальном времени

Чтобы преобразовать приложение в архитектуру реального времени, нам нужно было добавить два ключевых элемента: структуру данных с возможностью публикации / подписки и сервер WebSocket.

Для Pub / Sub мы выбрали Redis - хранилище структур данных в памяти с открытым исходным кодом (под лицензией BSD), используемое в качестве базы данных, кеша и брокера сообщений, поскольку наша команда была хорошо знакома с ним. Этот инструмент имеет первостепенное значение для работы нашей новой архитектуры, позволяя почти мгновенно публиковать сообщения без ущерба для производительности нашей веб-службы.

Чтобы прослушать публикации Redis и создать сервер WebSocket, мы решили создать микросервис с использованием NodeJS. При инициализации он создает WebSocket, используя библиотеку socket.io, подписываясь как слушатель Redis.

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

После добавления этих двух частей наша архитектура выглядит так:

Пришло время исправить проблему обновления страницы, что сделает нашу беседу более плавной. Для этого нам потребовалась двунаправленная связь между сервером и клиентом. Согласно нашей архитектуре, теперь нам просто нужно добавить библиотеку socket.io на стороне Front-end и подключить ее к микросервису. Благодаря этому мы могли иметь постоянное соединение между клиентом и сервером, позволяя им получать и отправлять сообщения в любой момент.

На стороне Back-end мы добавили две вещи: соединение с Redis и публикацию сообщения после его сохранения в базе данных. Для структуры Front-end мы только что создали новое действие с именем ADD_MESSAGE_FROM_SOCKET и компонент <WebSocket />.

Действие несет простую ответственность за добавление сообщений, полученных в правильном хранилище. Компонент взял на себя роль создания / удаления соединения с WebSocket и прослушивания порта. Когда он получает новое сообщение через WebSocket, он просто вызывает действие ADD_MESSAGE_FROM_SOCKET.

Были приняты важные решения:

  • За соединение WebSocket с клиентом не должен отвечать веб-сервер.
  • Сообщения следует сохранять в PostgreSQL и публиковать в Redis.
  • Клиент мог получать новые сообщения только через WebSockets, вставка новых сообщений по-прежнему будет происходить через HTTP.

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

Подведение итогов

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

Первоначально опубликовано на сайте cheesecakelabs.com 27 апреля 2017 г.