LINUX.ORG.RU

Потоки или асинхронные сокеты?


0

0

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


Зависит от логики приложения. Если основная нагрузка именно на сеть (например, раздавать статический контент), то целесообразней неблокирующие сокеты. А если сложная логика с навороченным протоколом -- частенько удобней пускать несколько тредов, а то и процессов.

swizard
()
Ответ на: комментарий от swizard

1.Это игровой сервер, второй вариант больше подходит.А по поводу fork() думаю что не лучшее из решений, ведь тогда еще понадобится механизм обмена данными между процессами.

Вопрос: Если использовать потоки, необходимо создавать для каждого клиента свой поток или просто объеденить два метода потоки и асинхронные сокеты?

T-34
() автор топика

А почему "или/или"? Сделать одну нить в цикле poll - нельзя?

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

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

Либо я Вас не так понял, либо вы меня! Разговор вообще идет о том чтобы создать не несколько нитей, а нескольок тысяч - по одному потоку на каждого клиента.

T-34
() автор топика
Ответ на: комментарий от T-34

> Разговор вообще идет о том чтобы создать не несколько нитей, а нескольок тысяч

Я думал, разговор о том, каким способом реализовывать - т.е. способ еще не выбран :)

> по одному потоку на каждого клиента.

Ну, мы же понимаем, что создавать по нити на клиента в этом случае - плохой вариант? Поэтому и предлагается гибридный вариант - несколько нитей (конфигурироемое количество), и какой-то алгоритм распределения работы между ними (основанный на цикле poll).

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

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

Еще один вопрос с количеством нитей, существует ли золотая середина, или нужно подбирать опытным путем, то количество клиентов которое будет обрабатывать один поток и вообще какое допустимо-разумное количество потоков одного процесса?

T-34
() автор топика
Ответ на: комментарий от T-34

> я не понял что Вы предлагали обрабатывать циколом.

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

> Еще один вопрос с количеством нитей, существует ли золотая середина, или нужно подбирать опытным путем

Есть мнение, что нужно создавать по одной нити на процессор. Но в данном случае под "процессором" понимается и сетевой интерфейс, и диск - в общем, всё, что может работать физически одновременно с другими "процессорами". Однако из-за того, что нить может блокироваться на некоторых "процессорах", на "процессор" можно выделить и несколько нитей.

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

Cпасибо за подробное разъеснение.

T-34
() автор топика

tailgunner прав. См. также про паттерн Реактор (Reactor) у Дугласа Шмидта. При таком кол-ве соединений если завести на каждое соединение поток - на context switch-и будет тратиться весь CPU. Количество потоков должно совпадать с кол-вом процессорных ядер.

anonymous
()
Ответ на: комментарий от tailgunner

tailgunner, anonymous (19:16:12)

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

BreadFan ★★
()
Ответ на: комментарий от BreadFan

> а можете вспомнить какую-нибудь (желательно задокументированную) реализацию такого подхода.

Нет. Но если погуглить по "Douglas Schmidt Reactor pattern", будет довольно много интересного матреиала. Первая ссылка: http://www.cs.wustl.edu/~schmidt/patterns-ace.html

tailgunner ★★★★★
()
Ответ на: комментарий от anonymous

> При таком кол-ве соединений если завести на каждое соединение поток - на context switch-и будет тратиться весь CPU. Количество потоков должно совпадать с кол-вом процессорных ядер.

переключение контекста и соотв. накладные расходы происходят тогда, когда поток исполняется. ну например, каждый поток занимается какой-то вычислительной задачей. а если он в основном спит? представьте себе диспетчер чего-то, который принимает входящее соединение, перенаправляет его в поток обработки который в свою очередь перенаправляет обработку этого соединения на другой сетевой сервер и засыпает до момента получения ответа (HTTP proxy как пример). в этом случае, будь у вас хоть N*100 потоков где N - кол-во CPU, накладные расходы на переключения контекста будут минимальны. зато реализация логики обработки единичного соединения будет тривиальной в противовес событийно-ориентированной схеме как, например, в реакторе.

это я к тому, что конечная оптимальная схема сильно зависит от конкретной задачи и входящих данных явно маловато..

// wbr

klalafuda ★☆☆
()
Ответ на: комментарий от klalafuda

> в этом случае, будь у вас хоть N*100 потоков где N - кол-во CPU, накладные расходы на переключения контекста будут минимальны.

Из врожденного занудства отмечу, что в рассматриваемом случае речь идет скорее о N*1000. Не каждая машина способна _создать_ столько нитей :)

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

> Из врожденного занудства отмечу, что в рассматриваемом случае речь идет скорее о N*1000. Не каждая машина способна _создать_ столько нитей :)

нуу.. граждане, если разработчик не в состоянии заставить свою машину создать N*1000 потоков, то о чем вообще речь? :) естественно предполагается - по крайней мере мной - что эта проблема уже решена. если она вообще была...

// wbr

klalafuda ★☆☆
()
Ответ на: комментарий от tailgunner

> Из врожденного занудства отмечу, что в рассматриваемом случае речь идет скорее о N*1000. Не каждая машина способна _создать_ столько нитей :)

ну и опять же, "5000 одновременных соединений". ну кто такое будет взграмождать на одну, пусть даже хрен знает скольки головую машину?! железки нынче дёшевы -> поставьте каскад проксей на массив обрабатывающих серверов когда на каждый из них придётся разумное количество соединений, которые он в действительности обрабатывает. IMHO такое решение будет как минимум более scalable да и дешевле к тому же.

ps: ну это так, мысли в слух..

// wbr

klalafuda ★☆☆
()
Ответ на: комментарий от klalafuda

> железки нынче дёшевы -> поставьте каскад проксей на массив > обрабатывающих серверов когда на каждый из них придётся разумное > количество соединений, которые он в действительности обрабатывает. IMHO такое решение будет как минимум более scalable да и дешевле к тому же.

В воздухе отчетливо запахло энтерпрайзами и j2ee-ями ;)

swizard
()
Ответ на: комментарий от swizard

> В воздухе отчетливо запахло энтерпрайзами и j2ee-ями ;)

ну если под enterprise в данном случае понимать что-то большое, толстое и пушистое, то почему бы и нет. согласитесь, не каждая програмулина обязана шустро обрабатывать тысячи соединений одновременно и при таких требованиях к ПО первое, на что стоит обратить внимание при его разработке - это гибкость и расширяемость продукта.

доставить пару рабочих лошадок в стойку и несколько строк в файл настроек когда система начинает проседать под нагрузкой - это дело простое и легко считаемое в плане времени и денег. а вот решение "чуть-чуть подправить код" которое потом скорее всего выльется в тотальное переписывание всего и вся - это уже тихий ужас бо очень долго, дорого и совершенно непредсказуемо...

ну и собссно почему сразу j2ee? вещь конечно хорошая, но мир клином на ней пока что не сошёлся :) меня, допустим, устраивают и классические позы a'la C/C++. "и ничего, и ничего...". впрочем, это уже дело такое - кто что знает лучше и кому что нравится больше.

// wbr

klalafuda ★☆☆
()
Ответ на: комментарий от T-34

> Еще один вопрос с количеством нитей, существует ли золотая середина, или нужно подбирать опытным путем, то количество клиентов которое будет обрабатывать один поток и вообще какое допустимо-разумное количество потоков одного процесса?

В большинстве случаев оптимальная производительность получается при количестве обрабатывающих потоков где-то между N и 2*N, где N - количество физических процессоров в машине.

Но подбирать нужно все равно опытным путем.

Вообще говоря, в идеале логика обработки должны быть достаточно отвязана от логики сетевого взаимодействия, чтобы последнее можно было заменить не трогая первое.

anonymous
()
Ответ на: комментарий от klalafuda

> ну и опять же, "5000 одновременных соединений". ну кто такое будет взграмождать на одну, пусть даже хрен знает скольки головую машину?!

Ну, например, какой-нибудь MUD прекрасно будет работать с несколькими тысячами пользователей на одной машине. Или IRC-сервер, или Jabber.

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.