Я пытаюсь создать приложение для обмена мгновенными сообщениями. Клиенты будут не только отправлять сообщения, но и часто отправлять аудио. И я решил использовать соединение через веб-сокет для связи с клиентами. Это быстро и позволяет отправлять двоичные данные.
Основная идея состоит в том, чтобы получить сообщение от client1 и уведомить об этом client2. Но вот в чем дело. Мое приложение будет работать на GAE. А что, если сокет client1 открыт на server1, а client2 открыт на < em>сервер2. Эти серверы не знают о клиентах друг друга.
У меня есть одна идея, как это решить, но я уверен, что это дерьмовый способ. Я собираюсь использовать какую-то связь между серверами (например, JMS или открыть другое соединение через веб-сокет между серверами, сейчас это не имеет значения).
Но это наверняка приведет к катастрофе. Я даже не могу представить, как часто эти серверы будут разговаривать друг с другом. Для каждого сообщения сервер1 должен уведомлять сервер2, сервер2 > должен уведомить client2. Но все становится еще хуже, когда в игру вступает серверN.
Еще один способ, которым я вижу это, — это Firebase. Но он ограничивает размер сообщения до 4 КБ. Поэтому я не могу отправлять аудио через него. В качестве решения я могу уведомить клиента о новом звуке, и он отправится за ним на мой сервер.
Надеюсь, я ясно объяснил проблему. Кто-нибудь знает, как это решить? Или, может быть, есть другие способы создания таких приложений?
связь через веб-сокет между клиентами в распределенной системе
Ответы (2)
Если вы строите кластер обмена сообщениями и ожидаете, что взаимодействующие клиенты будут подключаться к разным экземплярам сервера, то связь между сервером и сервером неизбежна. Хотя обычно это не проблема.
- Во-первых, если вы не используете балансировку нагрузки, ваши клиенты будут подключаться к одному и тому же серверу в среднем 50% времени (в случае 2 серверов).
- Во-вторых, каналы внутри центра обработки данных являются быстрыми и бесплатными во всех известных общедоступных облаках.
- В-третьих, вы часто можете сделать что-то умное на внешнем интерфейсе, чтобы убедиться, что два клиента, которые могут обмениваться данными, подключаются к одному и тому же серверу. Например, направьте всех клиентов из одной страны на один и тот же сервер, используя балансировку нагрузки DNS.
Вторая часть вопроса касается передачи больших медиафайлов. Обычно рекомендуется отправлять его вне диапазона - хранить на сервере и передавать только ссылку на него. Как кто-то предложил в комментарии, сохраните аудио на сервере и просто отправьте сообщение типа «аудио доступно, возьмите его отсюда ...». Вам не нужно опрашивать сервер для этого. Просто извлеките его один раз, когда клиент-получатель запрашивает его.
В общем, похоже, что вы пытаетесь изобрести велосипед. Просто используйте что-нибудь с полки.
- Пусть все клиенты подключаются к нескольким серверам, и каждый сервер сохраняет эти метаданные.
- Централизованная система, такая как zookeeper, хранит информацию об активных серверах.
Когда клиент c1 отправляет сообщение клиенту c2:
- the message is received by a server (say s1, we can add lad balancer to distribute incoming requests)
- s1 будет транслировать эту информацию на все остальные серверы, чтобы узнать, к какому серверу подключен клиент c2 ИЛИ лучше использовать последовательное хеширование, которое решает, к какому серверу клиент может подключиться, и в этом подходе широковещательное сообщение не требуют
- соответствующие ответы сервера серверу s1 (скажем, s2)
- теперь s1 отправляет сообщение m на s2 и сервер s2 клиенту c2
Минусы описанного выше подхода:
Каждый сервер будет иметь соединение с n-1 серверами, создавая ячеистую топологию.
Централизованная система (zookeeper) становится единой точкой отказа (что решаемо)
Такие приложения, как Whatsapp, G-Talk, используют XMPP и TCP/IP.