В современном технологическом мире WhatsApp является важным приложением для обмена сообщениями, которое связывает миллиарды людей по всему миру. Архитектура WhatsApp разработана таким образом, чтобы обеспечить надежную и эффективную передачу сообщений между пользователями в любой точке мира. Согласно последним данным, WhatsApp насчитывает более 2,7 миллиарда активных пользователей ежемесячно в более чем 180 странах. Предполагается, что к 2025 году это число достигнет 3,14 миллиарда.
Требования
Функциональные
- Общение: Система должна поддерживать один на один и групповые беседы между пользователями.
- Подтверждение: Система должна поддерживать подтверждение доставки сообщений, такие как отправлено, доставлено и прочитано.
- Обмен: Система должна поддерживать обмен медиафайлами, такими как изображения, видео и аудио.
- Хранение чатов: Система должна поддерживать постоянное хранение сообщений чата, когда пользователь не в сети, до успешной доставки сообщений.
- Пуш-уведомления: Система должна уметь уведомлять оффлайн пользователей о новых сообщениях, как только их статус становится онлайн.
Нефункциональные
- Низкая задержка: Пользователи должны иметь возможность получать сообщения с низкой задержкой.
- Согласованность: Сообщения должны доставляться в том порядке, в котором они были отправлены. Более того, пользователи должны видеть одинаковую историю чата на всех своих устройствах.
- Доступность: Система должна быть высокодоступной. Однако доступность может быть скомпрометирована в интересах согласованности.
- Безопасность: Система должна быть защищена с помощью сквозного шифрования. Сквозное шифрование гарантирует, что только две общающиеся стороны могут видеть содержание сообщений. Никто посредине, даже WhatsApp, не должен иметь доступ.
Высокоуровневый дизайн
На абстрактном уровне высокоуровневый дизайн состоит из сервера чата, отвечающего за коммуникацию между отправителем и получателем. Когда пользователь хочет отправить сообщение другому пользователю, оба подключаются к серверу чата. Оба пользователя отправляют свои сообщения на сервер чата. Затем сервер чата отправляет сообщение другому предполагаемому пользователю и также сохраняет сообщение в базе данных.
Примечание: Отправитель и получатель не обязательно подключены к одному и тому же серверу чата / серверу WebSocket.
- Пользователь А и пользователь В создают канал связи с сервером чата.
- Пользователь А отправляет сообщение на сервер чата.
- Получив сообщение, сервер чата отправляет подтверждение пользователю А.
- Сервер чата отправляет сообщение пользователю В и сохраняет сообщение в базе данных, если статус получателя не в сети.
- Пользователь В отправляет подтверждение серверу чата.
- Сервер чата уведомляет пользователя А о том, что сообщение успешно доставлено.
- Когда пользователь В читает сообщение, приложение уведомляет сервер чата.
- Сервер чата уведомляет пользователя А о том, что пользователь В прочитал сообщение.
Подробный дизайн
Подключение к серверу WebSocket
В WhatsApp каждое активное устройство подключено к серверу WebSocket через протокол WebSocket. Сервер WebSocket поддерживает открытое соединение со всеми активными (онлайн) пользователями. Поскольку одного сервера недостаточно для обработки миллиардов устройств, должно быть достаточно серверов для обработки миллиардов пользователей. Задача каждого из этих серверов — предоставить порт каждому онлайн-пользователю. Отображение между серверами, портами и пользователями хранится в менеджере WebSocket, который находится на вершине кластера хранилища данных. В данном случае это Redis.
Отправка или получение сообщений
Менеджер WebSocket отвечает за:
Поддержание соответствия между активным пользователем и портом, назначенным пользователю. Каждый раз, когда пользователь подключается к другому серверу WebSocket, эта информация обновляется в хранилище данных. userId<>server:port
Оба пользователя подключены к одному и тому же серверу
Если оба пользователя подключены к одному и тому же серверу, вызов менеджера WebSocket избегается.
Оба пользователя подключены к разным серверам
Сервер WebSocket, связанный с пользователем А, определяет WebSocket, к которому подключен пользователь В, через менеджер WebSocket. Если пользователь В в сети, менеджер WebSocket отвечает серверу WebSocket пользователя А, что пользователь В подключен к его серверу WebSocket.
Одновременно сервер WebSocket отправляет сообщение в службу сообщений и сохраняется в базе данных Mnesia, где оно обрабатывается в порядке поступления (FIFO). Как только эти сообщения доставляются получателю, они удаляются из базы данных.
Если пользователь В не в сети, сообщения сохраняются в базе данных Mnesia. Как только они появляются в сети, все сообщения, предназначенные для пользователя В, доставляются через пуш-уведомление. В противном случае эти сообщения удаляются навсегда через 30 дней.
Оба пользователя (отправитель и получатель) общаются с менеджером WebSocket, чтобы найти сервер WebSocket друг друга. Рассмотрим случай, когда между обоими пользователями может быть непрерывный разговор. Таким образом, к менеджеру WebSocket поступает много вызовов. Чтобы минимизировать задержку и уменьшить количество этих вызовов к менеджеру WebSocket, каждый сервер WebSocket кеширует информацию о недавних разговорах о том, какой пользователь подключен к какому серверу WebSocket.
Отправка или получение медиафайлов
Обычно серверы WebSocket легковесные и не поддерживают сложную логику, такую как обработка отправки и получения медиафайлов. У нас есть другая служба под названием служба активов, которая отвечает за отправку и получение медиафайлов.
- Медиафайл сжимается и шифруется на стороне устройства.
- Сжатый и зашифрованный файл отправляется в службу активов для хранения файла в хранилище blob. Служба активов назначает ID, который сообщается отправителю. Служба активов также поддерживает хеш для каждого файла, чтобы избежать дублирования контента в хранилище blob. Например, если пользователь хочет загрузить изображение, которое уже есть в хранилище blob, изображение не будет загружено. Вместо этого тот же ID передается получателю.
- Служба активов отправляет ID медиафайлов получателю через службу сообщений. Получатель скачивает медиафайл из хранилища blob, используя ID.
- Контент загружается на CDN, если служба активов получает большое количество запросов на какой-то конкретный контент.
Поддержка групповых сообщений
Серверы WebSocket не отслеживают группы, потому что они отслеживают только активных пользователей. Однако в группе некоторые пользователи могут быть онлайн, а другие — оффлайн. Для групповых сообщений за доставку сообщений каждому пользователю в группе отвечают следующие три основных компонента:
- Обработчик групповых сообщений
- Служба групповых сообщений
- Kafka
Допустим, пользователь А хочет отправить сообщение в группу с каким-то уникальным ID — например, Group/A
. Следующие шаги объясняют поток сообщения, отправленного в группу:
- Поскольку пользователь А подключен к серверу WebSocket, он отправляет сообщение в службу сообщений, предназначенное для
Group/A
. - Служба сообщений отправляет сообщение в Kafka с другой конкретной информацией о группе. Сообщение сохраняется там для дальнейшей обработки. В терминологии Kafka группа может быть темой, а отправители и получатели — производителями и потребителями соответственно.
- Теперь наступает ответственность групповой службы. Групповая служба хранит всю информацию о пользователях в каждой группе в системе. Она имеет всю информацию о каждой группе, включая идентификаторы пользователей, идентификатор группы, статус, значок группы, количество пользователей и так далее. Эта служба находится на вершине кластера баз данных MySQL с несколькими вторичными репликами, распределенными географически. Также существует сервер кеша Redis для кеширования данных с серверов MySQL. Географически распределенные реплики и кеш Redis помогают снизить задержку.
- Обработчик групповых сообщений общается со службой групп, чтобы получить данные пользователей Group/A.
- На последнем шаге обработчик групповых сообщений следует тому же процессу, что и сервер WebSocket, и доставляет сообщение каждому пользователю.
Архитектура WhatsApp — оценка
Низкая задержка
Можно минимизировать задержку системы на разных уровнях: это можно сделать с помощью географически распределенных серверов WebSocket и связанных с ними кешей. Мы можем использовать кластеры кеша Redis поверх кластеров баз данных MySQL. Мы можем использовать CDN для частого обмена документами и медиаконтентом.
Согласованность
Система также обеспечивает высокую согласованность сообщений с помощью очереди сообщений FIFO с строгим порядком. Однако для упорядочивания сообщений потребуется, чтобы Sequencer предоставлял ID с соответствующими механизмами вывода причинности каждому сообщению. Для оффлайн пользователей база данных Mnesia хранит сообщения в очереди. Сообщения отправляются позже по порядку после того, как пользователь выходит в онлайн.
Доступность
Систему можно сделать высокодоступной, если у нас достаточно серверов WebSocket и производить репликацию данных на нескольких серверах. Когда пользователь отключается из-за какой-либо неисправности сервера WebSocket, сессия воссоздается через балансировщик нагрузки с другим сервером. Более того, сообщения хранятся на кластере Mnesia согласно модели репликации первичный-вторичный, что обеспечивает высокую доступность и надежность.
Безопасность
Система также предоставляет механизм сквозного шифрования, который обеспечивает безопасность переписки между пользователями.
Резюме
В этой главе мы разработали мессенджер WhatsApp. Во-первых, мы определили функциональные и нефункциональные требования вместе с оценкой ресурсов, критически важных для проектирования. Во-вторых, мы сосредоточились на высокоуровневом и подробном дизайне архитектуре WhatsApp, где описали различные компоненты, отвечающие за разные сервисы. Наконец, мы оценили нефункциональные требования и выделили некоторые компромиссы в дизайне.
Эта задача проектирования показала, что мы можем оптимизировать общие вычислительные ресурсы для конкретных случаев использования. WhatsApp оптимизировал свой программный стек для обработки значительно большого количества подключений на стандартных серверах.
Добавить комментарий
Для отправки комментария вам необходимо авторизоваться.