Добрый день. Подскажите пожалуйста, что привильней использовать для реализации паралельного обслуживания tcp соединений. Предпологамое количество подключенных и активных клиентов до 5000, возможно и выше.
Зависит от логики приложения. Если основная нагрузка именно на сеть (например, раздавать статический контент), то целесообразней неблокирующие сокеты. А если сложная логика с навороченным протоколом -- частенько удобней пускать несколько тредов, а то и процессов.
1.Это игровой сервер, второй вариант больше подходит.А по поводу fork() думаю что не лучшее из решений, ведь тогда еще понадобится механизм обмена данными между процессами.
Вопрос: Если использовать потоки, необходимо создавать для каждого клиента свой поток или просто объеденить два метода потоки и асинхронные сокеты?
Либо я Вас не так понял, либо вы меня! Разговор вообще идет о том чтобы создать не несколько нитей, а нескольок тысяч - по одному потоку на каждого клиента.
> Разговор вообще идет о том чтобы создать не несколько нитей, а нескольок тысяч
Я думал, разговор о том, каким способом реализовывать - т.е. способ еще не выбран :)
> по одному потоку на каждого клиента.
Ну, мы же понимаем, что создавать по нити на клиента в этом случае - плохой вариант? Поэтому и предлагается гибридный вариант - несколько нитей (конфигурироемое количество), и какой-то алгоритм распределения работы между ними (основанный на цикле poll).
Ну вообщем да, изначально разговор шел о способе, но исключительно асинхронные сокеты отпали. Огромное количество процессов несомненно смущает, прошу прощения за деревянность, я не понял что Вы предлагали обрабатывать циколом.
Еще один вопрос с количеством нитей, существует ли золотая середина, или нужно подбирать опытным путем, то количество клиентов которое будет обрабатывать один поток и вообще какое допустимо-разумное количество потоков одного процесса?
> я не понял что Вы предлагали обрабатывать циколом.
Нить ждет прибытия данных из сети в цикле на poll, вычитывает их неблокирующим чтением, и, когда запрос вычитан полностью, выбирает из пула рабочих нитей одну и отправляет ей готовый запрос.
> Еще один вопрос с количеством нитей, существует ли золотая середина, или нужно подбирать опытным путем
Есть мнение, что нужно создавать по одной нити на процессор. Но в данном случае под "процессором" понимается и сетевой интерфейс, и диск - в общем, всё, что может работать физически одновременно с другими "процессорами". Однако из-за того, что нить может блокироваться на некоторых "процессорах", на "процессор" можно выделить и несколько нитей.
tailgunner прав. См. также про паттерн Реактор (Reactor) у Дугласа Шмидта. При таком кол-ве соединений если завести на каждое соединение поток - на context switch-и будет тратиться весь CPU. Количество потоков должно совпадать с кол-вом процессорных ядер.
> При таком кол-ве соединений если завести на каждое соединение поток - на context switch-и будет тратиться весь CPU. Количество потоков должно совпадать с кол-вом процессорных ядер.
переключение контекста и соотв. накладные расходы происходят тогда, когда поток исполняется. ну например, каждый поток занимается какой-то вычислительной задачей. а если он в основном спит? представьте себе диспетчер чего-то, который принимает входящее соединение, перенаправляет его в поток обработки который в свою очередь перенаправляет обработку этого соединения на другой сетевой сервер и засыпает до момента получения ответа (HTTP proxy как пример). в этом случае, будь у вас хоть N*100 потоков где N - кол-во CPU, накладные расходы на переключения контекста будут минимальны. зато реализация логики обработки единичного соединения будет тривиальной в противовес событийно-ориентированной схеме как, например, в реакторе.
это я к тому, что конечная оптимальная схема сильно зависит от конкретной задачи и входящих данных явно маловато..
> Из врожденного занудства отмечу, что в рассматриваемом случае речь идет скорее о N*1000. Не каждая машина способна _создать_ столько нитей :)
нуу.. граждане, если разработчик не в состоянии заставить свою машину создать N*1000 потоков, то о чем вообще речь? :) естественно предполагается - по крайней мере мной - что эта проблема уже решена. если она вообще была...
> Из врожденного занудства отмечу, что в рассматриваемом случае речь идет скорее о N*1000. Не каждая машина способна _создать_ столько нитей :)
ну и опять же, "5000 одновременных соединений". ну кто такое будет взграмождать на одну, пусть даже хрен знает скольки головую машину?! железки нынче дёшевы -> поставьте каскад проксей на массив обрабатывающих серверов когда на каждый из них придётся разумное количество соединений, которые он в действительности обрабатывает. IMHO такое решение будет как минимум более scalable да и дешевле к тому же.
> железки нынче дёшевы -> поставьте каскад проксей на массив > обрабатывающих серверов когда на каждый из них придётся разумное > количество соединений, которые он в действительности обрабатывает. IMHO такое решение будет как минимум более scalable да и дешевле к тому же.
В воздухе отчетливо запахло энтерпрайзами и j2ee-ями ;)
> В воздухе отчетливо запахло энтерпрайзами и j2ee-ями ;)
ну если под enterprise в данном случае понимать что-то большое, толстое и пушистое, то почему бы и нет. согласитесь, не каждая програмулина обязана шустро обрабатывать тысячи соединений одновременно и при таких требованиях к ПО первое, на что стоит обратить внимание при его разработке - это гибкость и расширяемость продукта.
доставить пару рабочих лошадок в стойку и несколько строк в файл настроек когда система начинает проседать под нагрузкой - это дело простое и легко считаемое в плане времени и денег. а вот решение "чуть-чуть подправить код" которое потом скорее всего выльется в тотальное переписывание всего и вся - это уже тихий ужас бо очень долго, дорого и совершенно непредсказуемо...
ну и собссно почему сразу j2ee? вещь конечно хорошая, но мир клином на ней пока что не сошёлся :) меня, допустим, устраивают и классические позы a'la C/C++. "и ничего, и ничего...". впрочем, это уже дело такое - кто что знает лучше и кому что нравится больше.
> Еще один вопрос с количеством нитей, существует ли золотая середина, или нужно подбирать опытным путем, то количество клиентов которое будет обрабатывать один поток и вообще какое допустимо-разумное количество потоков одного процесса?
В большинстве случаев оптимальная производительность получается при количестве обрабатывающих потоков где-то между N и 2*N, где N - количество физических процессоров в машине.
Но подбирать нужно все равно опытным путем.
Вообще говоря, в идеале логика обработки должны быть достаточно отвязана от логики сетевого взаимодействия, чтобы последнее можно было заменить не трогая первое.