Мне нужно реализовать архитектуру, которая может обслуживать 3 миллиона устройств GPS, отправляющих обновления / предупреждения о местоположении (каждые 10 секунд) в нашу систему для обработки.
Особенности: 1) TCP-связь. 1) Долгоживущие связи (~ 12 часов в день). Изменяйте только при изменении их IP-адреса. 2) GPRS-связь. 3) Простой разбор данных и хранение в базе данных.
В настоящее время у нас есть базовая система (Active-Pasive), обрабатывающая ~ 50K соединений на одном сервере с использованием Netty Framework для Java NIO.
Я думал об увеличении количества серверных узлов, скажем, по одному на каждые ~ 100 тыс. Соединений. Проблема в том, что у меня может быть только несколько общедоступных IP-адресов или одно имя хоста для подключения этих клиентов, поэтому мне нужен прокси для управления запросами.
Может ли Haproxy управлять нагрузкой в 3 миллиона TCP-сессий в той или иной конфигурации, или мне нужен аппаратный балансировщик нагрузки, или их комбинация.
Также netty - хороший выбор, или я могу справиться с большей нагрузкой на сервер приложений с помощью какой-либо другой инфраструктуры / технологии.
Я не могу говорить о конкретном дизайне любого из двух рассматриваемых вами решений. Однако я могу объяснить дизайн, который может быть реализован в программном обеспечении и может масштабироваться до миллионов TCP-соединений на одном IP-адресе при развертывании на достаточном количестве стандартных машин.
Прежде всего, IP-адрес может быть передан любому пулу машин, отвечающих за обработку входящих пакетов.
Для того, чтобы это работало, между этими машинами должна быть возможность связи. Таким образом, каждый должен иметь индивидуальный IP-адрес, поскольку эти одноадресные IP-адреса не используются для связи с вашими клиентами, они могут быть адресами RFC 1918 или IPv6, так что у вас будет достаточно адресов для связи между вашими машинами.
Когда пакет получен, IP-адрес и порт клиента ищутся в таблице на машине, получившей пакет. Если он найден, запись в таблице указывает, какой бэкэнд должен обрабатывать пакет. Затем принимающая машина инкапсулирует пакет в туннель к этому бэкэнду.
Если запись не найдена, то IP-адрес и порт клиента хешируются, чтобы создать два (для избыточности) индекса в распределенной хеш-таблице. Все машины должны использовать одну и ту же хеш-функцию, чтобы это работало.
Если пакет был SYN-пакетом, то принимающая машина выбирает серверную часть и отправляет информацию на две машины, выбранные хешем, а также сохраняет ее в своей собственной таблице. Это происходит параллельно с пересылкой пакета на бэкэнд.
Если пакет не был SYN-пакетом, он сохраняется на принимающей машине, при этом у двух машин (параллельно) запрашивается, какой сервер должен его обработать. Как только возвращается первый ответ, указывающий, куда должен быть отправлен пакет, пакет пересылается на бэкэнд, а отображение на бэкэнд сохраняется в локальной таблице и отправляется на другую из двух машин, выбранных хешем.
Бэкэнд должен быть настроен таким образом, чтобы публичный IP-адрес был назначен фиктивному интерфейсу (в Linux есть фиктивный сетевой драйвер для такого рода целей). Интерфейсы, которые фактически используются для маршрутизации пакетов, должны иметь одноадресные адреса. Таким образом, стек TCP на бэкэнде с радостью принимает TCP-подключения к общедоступному адресу, но не будет использовать его для подключений, которые он инициировал сам.
Ответы из серверной части просто отправляются с общедоступным IP-адресом в качестве исходного адреса без прохождения через пул anycast (этот подход известен как прямой возврат сервера или DSR).