Как сохранить миллион одновременных TCP-соединений? - PullRequest
40 голосов
/ 14 мая 2010

Я должен разработать сервер, который должен обслуживать миллионы клиентов, которые одновременно связаны с сервером через TCP.

Трафик данных между сервером и клиентами будет редким, поэтому проблемы пропускной способности можно игнорировать.

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

Кто-нибудь знает, как это сделать, и какое аппаратное / программное обеспечение необходимо (при наименьших затратах)?

Ответы [ 6 ]

20 голосов
/ 14 мая 2010

Какие операционные системы вы рассматриваете для этого?

Если вы используете ОС Windows и используете что-то более позднее, чем Vista, у вас не должно возникнуть проблем со многими тысячами соединений на одном компьютере. Я провел тесты (здесь: http://www.lenholgate.com/blog/2005/11/windows-tcpip-server-performance.html) на машине с Windows Server 2003 с низкой спецификацией и легко установил более 70 000 активных TCP-соединений. Некоторые ограничения ресурсов, влияющие на количество возможных соединений, были значительно сняты в Vista (см. здесь: http://www.lenholgate.com/blog/2005/11/windows-tcpip-server-performance.html) и, таким образом, вы, вероятно, сможете достичь своей цели с помощью небольшого кластера машин. Я не знаю, что вам понадобится перед ними для маршрутизации соединений.

Windows предоставляет средство под названием I / O Completion Ports (см .: http://msdn.microsoft.com/en-us/magazine/cc302334.aspx), которое позволяет обслуживать многие тысячи одновременных соединений с очень небольшим количеством потоков (вчера я проводил тесты с 5000 соединениями, насыщающими ссылку на сервер с 2-мя потоками для обработки ввода-вывода ...). Таким образом, базовая архитектура очень масштабируема.

Если вы хотите запустить несколько тестов, у меня есть несколько свободно доступных инструментов в моем блоге, которые позволяют вам подключать простой эхо-сервер, используя многие тысячи соединений ( 1 ) и ( 2 *). 1016 *) и некоторый бесплатный код, который вы могли бы использовать, чтобы начать работу ( 3 )

Вторая часть вашего вопроса, из ваших комментариев, более сложная. Если IP-адрес клиента продолжает меняться, и между вами и теми, кто предоставляет NAT, нет ничего, что могло бы дать вам согласованный IP-адрес, тогда их соединения, без сомнения, будут разорваны и их необходимо будет восстановить. Если клиенты обнаруживают, что это соединение разрывается при изменении их IP-адреса, они могут повторно подключиться к серверу, а если нет, то я бы предложил, чтобы клиенты периодически опрашивали сервер, чтобы они могли обнаружить потерю соединения и воссоединиться. Сервер ничего не может сделать здесь, так как он не может предсказать новый IP-адрес, и он обнаружит, что старое соединение не удалось, когда он попытается отправить данные.

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

11 голосов
/ 14 мая 2010

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

4 голосов
/ 14 мая 2010

Я сталкивался с APE Project Некоторое время назад. Кажется, мечта сбылась. Они могут поддерживать до 100 тысяч одновременно работающих клиентов на одном узле. Распределите их по 10 или 20 узлам, и вы сможете обслуживать миллионы. Идеально подходит для RESTful приложений. Возможно, нужно поискать глубже для любого общего пространства имен. Недостатком является то, что это автономный сервер, в дополнение к веб-серверу. Этот сервер, конечно, с открытым исходным кодом, поэтому любые расходы связаны с аппаратным обеспечением / Интернет-провайдером.

1 голос
/ 27 мая 2012

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

TCP - единственный вариант, и он также доставит вам головную боль. Большинство маршрутизаторов забывают маршрут и / или сбрасывают соединение через несколько минут, поэтому вашему клиент-серверному коду придется отправлять «keep aive» довольно часто.

Я рекомендую настроить «сниффер», чтобы увидеть, как телефонные компании поддерживают связь с вашим смартфоном благодаря своей технологии «push». Скопируйте все, что они делают, потому что этот материал работает !

0 голосов
/ 17 января 2014

Как упоминал Грег, проблема, которую вы описываете, это C10K (или, скорее, «C1M» в вашем случае) Недавно я создал простой эхо-сервер TCP на linux, который очень хорошо масштабируется с количеством сеансов (хотя проверено только до 200 000), используя очередь epoll . На BSD у вас есть нечто подобное, называемое kqueue. Вы можете проверить код , если хотите. Надеюсь, это поможет и удачи!

0 голосов
/ 14 мая 2010

РЕДАКТИРОВАТЬ: Как отмечено в комментариях ниже, мое первоначальное утверждение, что существует ограничение в 64 КБ, основанное на количестве портов, неверно, однако составляет ограничение 32 КБ на количество сокетов . обрабатывает , поэтому мой предложенный дизайн действителен.

С типичным дизайном сервера TCP / IP вы ограничены в количестве одновременных открытых соединений, которые вы можете иметь. У сервера есть один порт прослушивания, и когда клиент подключается к нему, сервер делает вызов на прием, и это создает новый сокет на случайном порту для остальной части соединения.

Для обработки более чем 64K одновременных соединений, я думаю, вам нужно использовать UDP вместо этого. Для прослушивания сервера нужен только один порт, и вам нужно управлять соединениями, используя 32-битный идентификатор клиента в пакетных данных вместо отдельного порта для каждого клиента. 32-разрядный идентификатор клиента может быть IP-адресом клиента, и клиент может прослушивать на известном UDP-порту сообщения, возвращаемые с сервера. Этот порт будет единственным, который должен быть открыт на брандмауэре.

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

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