Как написать самый производительный сервер под WinSock 2.2, WinXP?

Тема в разделе "WASM.WIN32", создана пользователем microprogs, 23 окт 2008.

  1. microprogs

    microprogs New Member

    Публикаций:
    0
    Регистрация:
    26 фев 2006
    Сообщения:
    54
    Собственно Сабж. На компе Core2 Duo T7500 + 2Gb RAM. Сервер в LAN, Ethernet 100Mbit/s
    Поизучав сокеты я написал кучу клиентов, кучу серверов, но все они производительностью не блещат :dntknw:
    может конечно я много хочу... я хочу выжать максимум из сервера, а именно:
    1. Максимально возможно число клиентов, больше 1000 и больше и больше, если это возможно....
    2. Чтобы сервер занимал по возможности ВСЮ полосу пропускания...
    3. Чтобы сервер довольно быстро реагировал на запросы клиентов...
    4. Чтобы сервер довольно много мог прокачивать трафика от каждого клиента туда и обратно, причем делать это максимально быстро....

    под п.2 и п.4 я понимаю тот факт, что если у нас один клиент - то между ним коннект 100MBit/s, если 2 - 50MBit/s, если 4 - 25MBit/s и т.д....
    Я понимаю, что идеальных вещей не бывает...

    Но попробовав реализовать такой сервер у меня ничего хорошего не получилось, а именно:
    1. даже при одном клиенте отжиралось менее 50MBit/s, хотя я гнал много трафика в расчете на 100MBit/s, соотвественно уже на одном клиенте использование не всей полосы пропускания, что же ждать от 10, 100, 1000 клиентов?
    Поставил тут же прогу для проверки скорости сети - дык смотрю опять в виндовый диспетчер загруженности сети - 100%, то есть все 100MBit... значит можно, просто я что-то не так делаю...
    2. Оба ядра загружены полностью при клиентах ~300 :dntknw:

    Мои проблемы наверное исходят из неверной концепции проектирования сервера???
    Пока я разобрал 4 варианта работы с сокетами (* - это вариант, над которым я не просто думал, но и написал прогу для тестирования):

    4 варианта:
    *1. Юзать блокирующие сокеты, каждого клиента - в новый поток + Синхронизация на потоках через WaitForSingleObject
    *2. Юзать не блокирующие сокеты + синхронизация WSAAnyncSelect на сообщениях WM_xxx, один поток
    3. Юзать не блокирующие сокеты + синхронизация WSAEventSelect на Event'ах, один поток
    4. Юзать не блокирующие сокеты в одном потоке + читать через select массив состояний всех сокетов


    может есть еще какие-то более умные способы?
    Может есть ссылки/статьи/исходники/примеры того, КАК ПРАВИЛЬНО ПИСАТЬ ВЫСОКОПРОИЗВОДИТЕЛЬНЫЙ СЕРВЕР под WinXP?

    Кто че хорошего/плохого скажет про способы 1,2,3,4?
    Если комбинировать 1 и 4, хорошая идея?

    WinSock функции .....Ex (с постфиксом Ex) реально помогают повысить производительность, как пишет Соломон/Русинович, или не сильно они влияют на проблему?

    При реализации способа п.2 у меня была загрузка канала = 30Mbit/s (1/3 канала - ужасно), в сервере одновременно обрабатывалось 3-10 клиентов, не более, все остальные тупо в очереди ожидания....

    п.1. - в сервер "одновременно" 300 клиентов, на каждого примерно равномерная скорость, но общая суммарная скорость равна ~50Mbit/s, не забивает весь канал :dntknw: Еще проблема - винда очень не хотела, чтобы моя прога создавала больще 2000 потоков...
    да и создание потока - вещь архи затратная... нужно выделить стек ядра + стек юзера + еще блок прочей хрени...
    может в этом случае спасут волокна?, но как???
    У способа проблема - он ограничен сверху числом потоков, которые винда разрешит создать проге, он отжирает не весь канал....


    З.Ы. Не ботал еще QoS, поможет ли оно мне, или это ваще не в тему?
     
  2. l_inc

    l_inc New Member

    Публикаций:
    0
    Регистрация:
    29 сен 2005
    Сообщения:
    2.566
    microprogs
    Порты завершения. Создаёте потоков, сколько захотите, а соединения будут распределяться по созданному количеству автоматически.
     
  3. microprogs

    microprogs New Member

    Публикаций:
    0
    Регистрация:
    26 фев 2006
    Сообщения:
    54
    пасибо за совет)
    читаю...
    кстати вариант на русском нашел (может эта тема форума будет полезна не только мне...):
    http://www.gamedev.ru/community/mmorpg/articles/?id=6
     
  4. microprogs

    microprogs New Member

    Публикаций:
    0
    Регистрация:
    26 фев 2006
    Сообщения:
    54
    Ага п.2. c WSAAsyncSelect и WM_xxx мессаги ф топку, получается, из него архи нельзя выжать максимум...
    Мессаги штука медленная, гораздо эффективнее юзать WSAEventSelect....

    Если нет возражений, то я убираю п.2. ваще как вариант производительного сервера....


    Текущие достойные соперники на роль MAX производительности (сугубо мое имхо, не окончательное, экспериментально, ибо пока еще читаю, думаю, экспериментирую)...
    1. п1. + п.4 = Много потоков, каждый поток рулит массивом сокетов через select.
    2. п.3 + много потоков = Много потоков, каждый поток на WSAшных Event'ах рулит массивом сокетов.
    3. Порты завершения (пока еще читаю, вникаю, уже начинает нравится :), но другие два варианта пока еще не убираю...)

    Вроде так, других "кандидатов" нет???

    Кстати, а что насчет волокон?
    Есть несозревшая мысля, что они тоже помогут... есть наметки, но и проблемы, пока не придумал как...
     
  5. microprogs

    microprogs New Member

    Публикаций:
    0
    Регистрация:
    26 фев 2006
    Сообщения:
    54
    Где найти нормальный рабочий пример клиента и сервера на портах завершения?
    Все что я находил - это слова авторов - дескать iocp - самый сложные объект винды, и далее кривой код, который либо ваще не работает, либо держит токо одного клиента...

    Если линк на какой-нить реальный пример, скажем сервер держащий 10000 коннектов через iocp???
     
  6. Dian

    Dian Member

    Публикаций:
    0
    Регистрация:
    19 июн 2008
    Сообщения:
    222
    Может и боян, но всё таки статейка в тему:
    http://www.rsdn.ru//article/baseserv/threadpool.xml

    Кода, к сожалению, не прилагается
     
  7. Explode Sense

    Explode Sense New Member

    Публикаций:
    0
    Регистрация:
    21 июл 2006
    Сообщения:
    130
    Адрес:
    Russia
    *насчёт потоков - по умолчанию выделяется 1 мб для стека потока (при указанном 0<x<1мб). Есть способ уменьшить кол-во выделяемой памяти по умолчанию, но лучше не ориентироваться на сервер с кучей тредов - это одна большая грабля, которая будет постоянно за Вами бегать и долбить по носу (при этом изрядно кушая цп на переключении м\д потоками).
     
  8. SUMASBROD

    SUMASBROD Member

    Публикаций:
    0
    Регистрация:
    8 май 2007
    Сообщения:
    64
    Кстати очень неплохо про выбор архитектуры сервера написано в книге
    Network Programming for Microsoft Windows / Anthony Jones, Jim Ohlund.--2nd ed
    Как раз там есть глава про масштабируемые приложения использующие WinSock, со сводной табличкой, в которой четко просматривается, что рулят Overlapped модель и порты завершения (Completion Port Model)
    Там количество соединений было порядка 10-50к =)
    Примеры кода там тоже есть. Не знаю только, переведена ли она на русский.
     
  9. Aspire

    Aspire New Member

    Публикаций:
    0
    Регистрация:
    19 май 2007
    Сообщения:
    1.028
    SUMASBROD
    Переведена: http://rapidshare.com/files/157134129/______-__________________________Microsoft_Windows.2002.pdf
     
  10. microprogs

    microprogs New Member

    Публикаций:
    0
    Регистрация:
    26 фев 2006
    Сообщения:
    54
    Я согласен с этим утверждением, ибо при 1000 клиентов переключение м/д контекстами 1000 потоков - это убийственно :)
    Поэтому в своих утверждениях я предполагаю, что есть фиксированное множество потоков - экспериментально, скажем 50...
    Они время от времени засыпают/просыпаются, но потоков 50, значит большое кол-во клиентов выруливается либо на каждый потока массив сокетов и select, либо на каждый поток массив WSA'шных Event'ов...

    Имхо, при грамотной реализации IOCP порвер эти два способа.
    Но при неграмотной реализации может быть равноценно, а может быть и хуже.
    У меня пока хуже...
    А на WSA'шных Event'ах + небольшой пул потоков 1000 клиентов вытягиваю... но этого мне мало...
    и канал по прежнему не забит на 100% :dntknw:((
     
  11. microprogs

    microprogs New Member

    Публикаций:
    0
    Регистрация:
    26 фев 2006
    Сообщения:
    54
    За Оланда и Энтони Джонса спасибо)

    Более близко к истине, пока читаю....
     
  12. microprogs

    microprogs New Member

    Публикаций:
    0
    Регистрация:
    26 фев 2006
    Сообщения:
    54
    Кстати, если я не ошибаюсь, после беглого просмотра исходника последнего апача под винды я увидел, что он тоже юзает, IOCP...
    Но он еще юзает select и Ивенты, но никогда не юзает WSAAsyncSelect...
    May be, я на правильном пути... Ушел читать...
     
  13. ECk

    ECk Member

    Публикаций:
    0
    Регистрация:
    9 апр 2004
    Сообщения:
    454
    Адрес:
    Russia
    Что есть и что работает:
    1. один поток
    2. FIONBIO & select & FIONREAD(с объявленным перед winsock.h MAX_FD_SET >= 4096)
    3. Finite state machine

    Таким образом, совершенно неважно, сколько у тебя клиентов висит (отдавая части хоть всем подряд канал юзается на ура). 5к коннектов дают полную нагрузку канала и не более 5% использования ЦПУ.
    Касательно нагрузки - коннекты идут по SSL на базе schannel (не сказать, что сильно легкие задачи в плане нагрузки ЦПУ), но за счет временнОго разделения одного потока - все в пределах нормы.
    Относительно числа потоков по числу клиентов - было и такое первоначально, однако потом отказался как от зла :) (число потоков когда было 1970, когда 1900, но не более 2к). При этом, дело вовсе не в памяти под стек - дело было в размере NonPagedPool (в котором выделяются структуры под потоки). Если он превышен (а под создание потоков NonPagedPoolMustSucceed не используется) - поток новый просто не создается. Данный факт был проверен указанием фиксированного размера стека на поток в районе 4кб (что не укладывается в объяснение о числе потоков согласно МСДН).
     
  14. Explode Sense

    Explode Sense New Member

    Публикаций:
    0
    Регистрация:
    21 июл 2006
    Сообщения:
    130
    Адрес:
    Russia
    ECk
    Не понимаю тогда, почему STACK_SIZE_PARAM_IS_A_RESERVATION со стеком, скажем 512k, даёт возможность создать уже, 3k потоков и более?

    add
    "фиксированного размера стека на поток в районе 4кб"
    Без указания флага STACK_SIZE_PARAM... размер стека потока в Вашем случае всё равно был 1 мб (_зарезервированой_ виртуальной памяти).
     
  15. ECk

    ECk Member

    Публикаций:
    0
    Регистрация:
    9 апр 2004
    Сообщения:
    454
    Адрес:
    Russia
    Фактическая в ущерб логической многопоточность в данном смысле существенно ухудшает работу вообще за счет оверхеда при переключениях потоков (не считая того, что ради освобождения пространства под стек многочисленных потоков будут идти сплошные сбросы и выгрузы в своп и из него) - плюс к тому, за счет того, что архитектурно пакеты доставляются в NDIS исключительно в DPC - большим количеством потоков, которые надо переключать между собой, косвенно замедляется доставка входящих пакетов.
    Хотя это кому как нравится (FSM бесспорно сложнее модели Socket Per Thread).
    При обсуждении создания пауков для индексации веб страниц в поисковиках Microsoft Research например, усираются, что такая модель (Socket Per Thread) куда как лучше чем применяемая Гуглом логическая многопоточность a la FSM.
    Вообще, наверное лучше почитать Стивенса и не изобретать велосипед (если, конечно, время на собственный опыт не жаль).
     
  16. microprogs

    microprogs New Member

    Публикаций:
    0
    Регистрация:
    26 фев 2006
    Сообщения:
    54
    Как я понял, ваши 1., 2., 3. - это про одну реализацию сервера.
    1. - а если мой случай Core 2 Duo, или чей-то случай Cure 2 Quad, тогда соответсвенно ваша программа будет работать еще лучше, если создать соотвественно 2, или 4 потока.
    2., 3. - прошу подробнее, например Finite state machine мне говорит только об одном - Конечный Автомат (КА), и более ни о чем не говорит, кроме как возникновения в голове некоторого switch'а....


    5К клиентов + полная загрузка канала - это меня очень радует.... Ибо пока у меня не было полной загрузки канала, и клиентов сейчас не более 1000...

    SSL мне ваще не нужен в 99% случаев....

    Можно пример исходника сервера + клиента?
     
  17. ECk

    ECk Member

    Публикаций:
    0
    Регистрация:
    9 апр 2004
    Сообщения:
    454
    Адрес:
    Russia
    microprogs
    Совершенно верно.
    В случае установки ThreadAffinity на отдельные ядра отдельным потокам.
    Именно.
    Пример делался в рамках коммерческого проекта, поэтому исходники дать не могу.
     
  18. microprogs

    microprogs New Member

    Публикаций:
    0
    Регистрация:
    26 фев 2006
    Сообщения:
    54
    Все таки не пойму как получилось 5К подключений... :dntknw:

    Вот нашел пример Echo-сервера на IOCP, он на моей тачке выдает от силы 4000 коннектов, дальше не держит...
    Все таки не пойму, где обещанные 50 000 коннектов, тут даже 5К нету...
     
  19. ECk

    ECk Member

    Публикаций:
    0
    Регистрация:
    9 апр 2004
    Сообщения:
    454
    Адрес:
    Russia
    нужно посмотреть параметр MaxUserPort в реестре.
    http://technet.microsoft.com/en-us/library/cc758002.aspx
    По умолчанию там от 1024 до 5000, поэтому получается около 4к коннектов (каждый коннект = новый порт)
    Можно установить 0xFFFF туда и будет коннектов больше.
    При этом, если сразу по 4к сокетов коннектить (в режиме клиента) - на втором цикле сокеты перестанут открываться (ввиду того, что только что отключенные сокеты находятся какое-то время в ожидании прихода пакетов по закрытии).
    Чтобы этого не было можно звать shutdown(SD_BOTH) - тогда сокеты можно юзать повторно практически сразу.