2010-05-14 2 views
36

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

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

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

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

+2

Должен ли он быть TCP? Если трафик разрежен, стоимость отслеживания всех подключений может быть необоснованно высокой. И не могли бы вы немного рассказать о том, что сделает сервер? Миллион активных подключений, которые активно не используются, кажутся мне подозрительными. – VladV

ответ

19

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

Если вы используете ОС 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 предусмотрены средства ввода-вывода ввода-вывода (см.: http://msdn.microsoft.com/en-us/magazine/cc302334.aspx), которые позволяют обслуживать многие тысячи одновременных соединений с очень небольшим количеством потоков (вчера я запускал тесты с 5000 соединениями, насыщающими ссылку на сервер с 2 потоки для обработки ввода-вывода ...). Таким образом, базовая архитектура очень масштабируема.

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

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

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

+1

Ваш EchoServerTest - это нормально, но как мы можем протестировать подключение более 64 тыс.? У клиента есть предел порта 64k – onmyway133

+1

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

+1

В Linux вы также можете использовать псевдонимы IP-адресов на клиентской машине; каждый IP-адрес даст вам дополнительные 65 тыс. клиентов. –

11

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

+0

спасибо за ответ. но лично я не думаю, что они та же проблема. то, что я хочу знать, заключается в том, как поддерживать постоянный контакт 1M-подключенных клиентов, а не как принимать их запросы на соединение или как их изменять статус соединения. спасибо в любом случае. – cow

+0

@cow: Нет ничего особенного в том, чтобы поддерживать клиентов - что заставляет вас думать, что это будет? Это далеко не самая сложная часть проблемы. – caf

+0

Что делать, если клиенты находятся в сети, где их IP-адреса могут часто меняться. Например, у меня есть телефон T-Mobile G1. Я обнаружил, что IP-адрес моего телефона часто изменяется.даже если телефон имеет TCP-соединение с каким-либо сервером вне сети T-Moble, когда нет данных, проходящих через соединение, вероятность того, что IP-адрес телефона будет изменен, большой; после изменения IP-адреса любое TCP-соединение фактически нарушено. вот почему у меня проблема. – cow

-4

EDIT: Как было отмечено в комментариях ниже, мое первоначальное утверждение, что существует предел 64K на основе количества портов неверно, однако является пределом 32K от количества розетки ручки, так что мои предлагаемый дизайн действителен.

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

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

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

+1

Несколько клиентских подключений к серверу не используют дополнительные * серверные * порты. Там будут технические ограничения, но это не количество портов. Соединения идентифицируются на стороне сервера, используя уникальный 4-кортеж (server_ip, server_port, client_ip, client_port). Возможно, вы думаете о * сокетных дескрипторах *, где появляется сокет сервера, который порождает больше дескрипторов сокетов через вызов 'accept()'. –

+0

Хм. Да, я думаю, ты прав. http://linux.die.net/man/2/accept говорит, что accept будет терпеть неудачу, если у вас закончились дескрипторы файлов, а не порты. Я взглянул в исходный код ядра Linux, и из того, что я могу сказать, максимальное количество файлов передается как int. Это, вероятно, ограничит вас дескрипторами файлов 32K, хотя это будет зависеть от платформы. Я ошибаюсь в деталях, почему TCP ограничен, но я думаю, что он по-прежнему ограничен, и UDP является приемлемой альтернативой. – DougWebb

+0

спасибо за комментарии от вас обоих. Я видел страницу c10k недели назад. Я помню, что он предлагает epoll(). Я хотел бы использовать его с UDP. howver, как я знаю, epoll не имеет отношения к UDP-серверу, который имеет только один сокет для приема, я прав? актуальна срочность чтения пакетов достаточно быстро. однако я не могу придумать, как лучше читать быстрее, чем использовать выделенный поток, чтобы читать пакеты с UDP-сокета и помещать их в очередь для использования рабочих потоков. не могли бы вы посоветовать лучшие методы? Спасибо заранее. – cow

4

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

+0

благодарит за информацию. но мое приложение не основано на Интернете. как я могу использовать APE? – cow

+0

Вы можете использовать APE без браузера. Они используют протокол по умолчанию (и вы можете создать свой собственный: http://www.ape-project.org/wiki/index.php/Protocol). Вы можете написать свою собственную библиотеку для управления соединениями с выбранным вами языком, используя их " APE Javascript framework "в качестве ссылки. – Vic

+0

еще раз спасибо. я рассмотрю протокол, чтобы проверить, хорошо ли заменить мой собственный двоично-кодированный протокол APE. – cow

0

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

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

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

0

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

Смежные вопросы