Плохая архитектура

Все, что вы хотели знать о программизме, но боялись спросить.
vg
Маньяк
Сообщения: 2803
Зарегистрирован: 29 май 2003, 22:29
Откуда: Магадан - Миссиссага

Плохая архитектура

Сообщение vg »

Недавно обсуждал вопрос об архитектуре сервера реализующего кастом команд-ориентед протокол ...
Транспорт - TCP. Мне сказали, что архитектура, когда сервер делается в первичном потоке на блокирующем прослушивающем сокете (Беркли интерфейс), и когда каждый клиент обслуживается в отдельном потоке - сакс. Было сказано, что такой софт никто не будет покупать... Было заявлено, что всё на самом деле можно сделать в одном потоке. Было сказано также, что Winsock Microsoft вообще тянет как устарелую технологию только ради поддержки старых приложений. Типа сейчас так уже не пишут. :cry:
Вот я и думаю... Как я отстал от жизни. Как же сделать так, чтобы всё работало без отдельных потоков для клиентов.

Спасибо.
ПС. Интересно мнение не только тех кто проектирует под виндовз, но *никс тоже.
Zy
Маньяк
Сообщения: 4706
Зарегистрирован: 20 янв 2005, 19:11

Сообщение Zy »

У юниксов есть каналы, которые не надо блокировать. А клиенты обрабатываются в отдельных тредах (пул тредов). И софт покупают.
vg
Маньяк
Сообщения: 2803
Зарегистрирован: 29 май 2003, 22:29
Откуда: Магадан - Миссиссага

Сообщение vg »

Zy писал(а):У юниксов есть каналы, которые не надо блокировать. А клиенты обрабатываются в отдельных тредах (пул тредов). И софт покупают.
В этом-то и прикол. Я ни как не пойму тех гуру, что сказали, мол, без тредов можно и нужно обойтись. А уж какой сокет использовать для прослушивающего сокета на серверной стороне - (блокирующий, или модный в виндовз, генерирующий ивент) - дело десятое. Выигрыш - копейки. Один фиг для клиентов нужны отдельные треды. Один пень надо с каждым клиентов "одновременно", "... а поговорить ? ...". Никак без тредов не обойтись... (уже боясь гуру, добовляю, имхо).
Аватара пользователя
ajkj3em
Маньяк
Сообщения: 2063
Зарегистрирован: 12 ноя 2006, 06:53

Re: Плохая архитектура

Сообщение ajkj3em »

vg писал(а):Недавно обсуждал вопрос об архитектуре сервера реализующего кастом команд-ориентед протокол ...
Транспорт - TCP. Мне сказали, что архитектура, когда сервер делается в первичном потоке на блокирующем прослушивающем сокете (Беркли интерфейс), и когда каждый клиент обслуживается в отдельном потоке - сакс.
не все так черно-бело, но в принципе верно. то есть скорее так - если
обработка клиентского запроса не занимает много времени, то стоит
все делать в одном потоке. причин несколько -

(а) треды не бесплатны. под линуксом тред = облегченный процесс,
так что иметь 10000 тредов на 10000 клиентов - напрашиваться на
проблемы. про пулы тредов я вообще молчу.

(б) упрощенная синхронизация в коде или отсутствие необходимости
ее как таковой -> меньше шансов налепить нетривиальных багов и
_гораздо_ проще в отладке
Было сказано, что такой софт никто не будет покупать...
если продается не сам код, а продукт, то в принципе до балды как он
написан, лишь бы работал per specifications.
Было заявлено, что всё на самом деле можно сделать в одном потоке.
зависит, но в принципе правильно. если нормируется время ответа,
то надо смотреть сколько по максимуму занимает обработка одного
запроса и какая средняя загрузка в запрос/сек.
Было сказано также, что Winsock Microsoft вообще тянет как устарелую технологию только ради поддержки старых приложений.
ну это было сказано человеком, который толком не знает winsock,
либо ты его не так понял. в winsock конечно нет поддержки epoll,
но его е**нутые WSA Events вполне нормально scale'ятся.
Как же сделать так, чтобы всё работало без отдельных потоков для клиентов.
http://www.monkey.org/~provos/libevent - немного кривовато, но представление дает

http://liboop.org - из той же оперу, вид сбоку

общая идея такая - на каждый коннекшн заводится state, сокет
регистрируется в глобальной select/poll/epoll loop и мониторится
на события. вся работа выполняется в обработчике события в
соответствии со state'ом.

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

ps. у меня сейчас бежит 2х тредовый сервер под линуксом, держит
несколько десятков тысяч клиентов. central loop - на epoll. сессии
по несколько часов, часто - дней. средняя загрузка - 30%, трафик -
около 200 kbps. второй тред - под крипто операции, первый - под
все остальное. делайте выводы.

pps. эту ссылку я по-моему уже не раз давал, она классическая по
этой тематике - http://www.kegel.com/c10k.html
vg
Маньяк
Сообщения: 2803
Зарегистрирован: 29 май 2003, 22:29
Откуда: Магадан - Миссиссага

Re: Плохая архитектура

Сообщение vg »

2 poneyhot.
Спасибо за разъяснения и ссылки. Хотя ... теперь я понимаю, что вообще ничего не понимаю в программировании :lol: (но это хорошо). Первое, что попробую в контексте - разобраться в виндовз комплетишн порт. Раньше их не использовал.
Не пойму - задам вопросы.
Спасибо.
Zy
Маньяк
Сообщения: 4706
Зарегистрирован: 20 янв 2005, 19:11

Сообщение Zy »

модный в виндовз, генерирующий ивент
Это в то же время архаичный юниксовый :-)
про пулы тредов я вообще молчу.
Почему? Это раз. А два - никто за бесплатным сыром в очередь и не выстраивался. Естественно, за треды надо платить, в чем проблема-то?
меньше шансов налепить нетривиальных багов и
_гораздо_ проще в отладке
С этмм согласен.
Аватара пользователя
ajkj3em
Маньяк
Сообщения: 2063
Зарегистрирован: 12 ноя 2006, 06:53

Сообщение ajkj3em »

Zy писал(а):
про пулы тредов я вообще молчу.
Почему? Это раз. А два - никто за бесплатным сыром в очередь и не выстраивался. Естественно, за треды надо платить, в чем проблема-то?
в ресурсах. практически ни одна операционка кроме solaris под работу
с тредами не оптимизирована. тысячи тредов, да еще и под нагрузкой,
это заведомо толкание системы в область плохо изведанного :-)

смысл в собственно пуле - это сэкономить на spawn и initialization time,
так ведь ? pre-spawning позволяет зарезирвировать системные ресурсы
(память), с тем чтобы в run-time неожиданно не случился swap'a при
spawn'e. плюс можно про-инициализироваться заранее, если архитектура
этого требует (что собственно не говорит в пользу последней, если эта
инициализация не может быть произведена основным тредом во время
стартапа).

IMO у пулов есть свое место, но оно обычно связано с подстраиванием
под ограничения существующих компонент. если система строится с
нуля или почти с нуля, то стоит стараться избегать трединга в целом
и пулов тредов в частности. если только это не демо какое-нибудь из
серии "абы работало" :-)
Zy
Маньяк
Сообщения: 4706
Зарегистрирован: 20 янв 2005, 19:11

Сообщение Zy »

это заведомо толкание системы в область плохо изведанного
Фиг ли там изведывать? Сам комп так работает - прерывания.
смысл в собственно пуле - это сэкономить на spawn и initialization time, так ведь ? pre-spawning позволяет зарезирвировать системные ресурсы (память), с тем чтобы в run-time неожиданно не случился swap'a при
spawn'e.
Отнюдь.

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

Другой пример. Допустим, есть критичное по премени выполнения приложение, которое должно, скажем, вести лог (по другому сказать: посылать сообщения в другую систему, не такую критичную, как первая). Если лог отвалится, и фиг с ним, главное, чтобы шли транзакции (либо лог не должен замедлять работу приложения). В j2ee для этого message driven beans. Что, собственно, и есть треды, которые работат на фоне, и вызывающий код не должен ждать отклика и проверять результат работы.
Аватара пользователя
ajkj3em
Маньяк
Сообщения: 2063
Зарегистрирован: 12 ноя 2006, 06:53

Сообщение ajkj3em »

Zy писал(а):
это заведомо толкание системы в область плохо изведанного
Фиг ли там изведывать? Сам комп так работает - прерывания.
система под нагрузкой работает совершенно по другому, особенно
если у нее заканчивается non-swappable memory в ядре. начинаются
проблемы со scheduler'ом, всякие linked list и hash table оказываются
плохим выбором, L1 cache trash'иться перманентно и все такое. это
вопрос того как scale'ятся структуры ядра при большом количестве
процессов или тредов. прерывания тут ни причем.
смысл в собственно пуле - это сэкономить на spawn и initialization time, так ведь ? pre-spawning позволяет зарезирвировать системные ресурсы (память), с тем чтобы в run-time неожиданно не случился swap'a при
spawn'e.
Отнюдь.

Представь, что у тебя тысячи клиентов, посылающих ассинхронные запросы разной сложности. Некоторые из них долгие и клиент может ждать их выполнения, а некоторые очень простые, и время отклика должно быть минимальным.
так что мешает запустить тред сходу, а не брать его из пула ?
Другой пример. Допустим, есть критичное по премени выполнения приложение, которое должно, скажем, вести лог (по другому сказать: посылать сообщения в другую систему, не такую критичную, как первая). Если лог отвалится, и фиг с ним, главное, чтобы шли транзакции (либо лог не должен замедлять работу приложения). В j2ee для этого message driven beans. Что, собственно, и есть треды, которые работат на фоне, и вызывающий код не должен ждать отклика и проверять результат работы.
да где же я говорил, что треды - плохо ? я говорю про пулы тредов.
понятно, что если у тебя есть две не связанные или слабо связанные
задачи, то вполне естественно их выполнять в разных тредах. другое
дело, когда есть сервер с тысячами клиентов, запускать по треду на
клиента - это убивать scalability и создавть потенциальные проблемы
с ядром.

по поводу примера сверху с запросами разной сложности - можно
сделать так, что простые запросы обрабатываются одним тредом,
сложные - другим. причем первый тред может при этом еще и
primary IO thread, то есть в нем может бежать центральный event
loop по сокетам.

коммент общего плана - любую вещь можно сделать разными
способами. как именно - дело вкуса, опыта и schedule. лично
я предпочитаю делать все на низком уровне и треды использую
строго при необходимости, когда проще отдать вопросы CPU
scheduling системе, чем заниматься этим самому.
vg
Маньяк
Сообщения: 2803
Зарегистрирован: 29 май 2003, 22:29
Откуда: Магадан - Миссиссага

Сообщение vg »

Zy хоть ты и говоришь то, что я раньше делал, но теперь, думаю, что poneyhot совершенно прав здесь. 100%
poneyhot писал(а):
Zy писал(а):
это заведомо толкание системы в область плохо изведанного
Фиг ли там изведывать? Сам комп так работает - прерывания.
система под нагрузкой работает совершенно по другому, особенно
если у нее заканчивается non-swappable memory в ядре. начинаются
проблемы со scheduler'ом, всякие linked list и hash table оказываются
плохим выбором, L1 cache trash'иться перманентно и все такое. это
вопрос того как scale'ятся структуры ядра при большом количестве
процессов или тредов. прерывания тут ни причем.
1) Я несомневаюсь, что ты писал не один сервак, поэтому не хочу учительствовать в том , что теоритически сам узнал совсем недавно... хотя на практике сталкивался давно, и, кажется, даже на этом форуме об этом пости. Постил негодуя, как один из гурей написал тривиальный пример (на асме, хотя как ты понимаешь, это совершенно дешёвый понт, можно былоб на VB и ничего бы не изменилось) мультитредового сервака с заявлением, что он тащит 5000 клиентов (каждый клиент там банально от рождения досмерти обслуживается в отдельном треде ). Бред сивой кобылы. На практике я всегда ограичивал число одновременно работающий клиентов 512. Почему? Из практике при числе клиентских тредов 1000 - сервак в состоянии сильного опьянения. Если чуть больше тредов - замирает почти всё. Почему? Потому, что, как я недавно узнал, под виндой треду выделяется мег (ред.) под стек по дефолт. Забавно? Лечится или опцией линкера или явной задачей в качесте параметра креатетред. Могу ошибаться, конечно но критичным здесь будет не тяжесть создания новыго треда при достаточной нагруженности системы, сколько банальная нехватка памяти, выделенной процессу, где эти треды обитают.

2) В свете вышесказанного, крайне неодобрительно приму теперь идею о пуле тредов. Ибо критичным как сказано будет на расходы по созданию треда, сколько ресурсы выброшенные на помойку в ожидании большего числа клиентов. :!: Прошу не путать только пул, расчитанный на архитектуру "каждому клиенту - по собственному треду", с некой гибрибной архитектурой, когда клиенту будет выделяться отдельный тред, когда это действительно нужно, например, когда сервер должен быдет выполнить затратную по времени операцию, и только после этого он вернуть данные клиенту запихивая их в сокет. Если же данные можно вернуть быстро - то надо делать это неблокирующим сокетом без всяких тредов. В последнем случае число тредов не будет равно числу клиентов. В идеале их должно быть, как мне подсказали (я в этом не понимаю) - удвоенное число устройств где выполняется код (наверное, процессоров :lol: ).

3) Ещё мне напомнили про облегчённые объекты-файберы. Но это специфика MS, кажется. Не знаю, под никсами файберов, кажется, нет.
Ну, типа заменить треды файберами. MSSQL может использовать это.

Короче, благодаря обсуждениям, я действительно увидел в том, что делал - не точто плохую архитектуру, а ужасную :lol: . Те мужики, что обсуждали со мной проблему, были правы.

РЕД. тфьу-ты 1 мегабайт, а не гиг, конечно же.
Zy
Маньяк
Сообщения: 4706
Зарегистрирован: 20 янв 2005, 19:11

Сообщение Zy »

прерывания тут ни причем.
Прерывания тут притом, что это такая же недерминированная система с асинхронными вызовами. А что там скейлится - меня мало волнует, это проблемы администрирования, а я программист. Пусть покупают другой сервер, ставят солярис и или что еще, за это им деньги платят.
так что мешает запустить тред сходу, а не брать его из пула ?
Во-первых, ты сам ответил - время на запуск. Во-вторых, если мне известна примерная нагрузка на систему, и я знаю, что у меня в каждый момент времени будут запущены, скажем, 1000 тредов, то какой мне смысл постоянно запускать одно и то же?
запускать по треду на клиента
Я нигде не говорил про тред на клиента. Я говорил, про тред на событие.
что простые запросы обрабатываются одним тредом,
сложные - другим
А кто и как будет определять, какие сложные, а какие простые?
причем первый тред может при этом еще и
primary IO thread
А если мы решим, что есть дважды праймари, тогда что?
как именно - дело вкуса
Нет, вкус - это когда пироги печешь или музвку сочиняешь.
лично
я предпочитаю делать все на низком уровне
Лично я пишу на java, поэтому не забиваю себе голову "вкусами", а делаю, как дядюшка SUN сказал. А дядюшка SUN четко разделяет работу программиста и администратора(и еще многих других работ), это даже в сертификационных вопросах по j2ee есть.

To vg:
Бред сивой кобылы.
Безусловно.
Потому, что, как я недавно узнал, под виндой треду выделяется ...
Меня такие проблемы, к счастью, не касаются.
Те мужики, что обсуждали со мной проблему, были правы.
Интересно, надолго такая уверенность?
Аватара пользователя
ajkj3em
Маньяк
Сообщения: 2063
Зарегистрирован: 12 ноя 2006, 06:53

Сообщение ajkj3em »

на джаве свет клином не сошелся знаете ли
Zy
Маньяк
Сообщения: 4706
Зарегистрирован: 20 янв 2005, 19:11

Сообщение Zy »

на джаве свет клином не сошелся знаете ли
Это вздох сожаления?
Аватара пользователя
ajkj3em
Маньяк
Сообщения: 2063
Зарегистрирован: 12 ноя 2006, 06:53

Сообщение ajkj3em »

Zy писал(а):
на джаве свет клином не сошелся знаете ли
Это вздох сожаления?
нет, это констатация факта. джава навязывает определенную модель
программирования (не как язык, а как платформа). это не означает,
что все те implementation детали, которые она при этом скрывает, не
имеют значения на других платформах и других подходах к организации
серверных систем.

(ajkj2em = poneyhot. это мой логин при постах с дивана)
vg
Маньяк
Сообщения: 2803
Зарегистрирован: 29 май 2003, 22:29
Откуда: Магадан - Миссиссага

Сообщение vg »

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

А про большое число тредов... Из практики известно. Три строчки займёт приложение, которое создаст 2000 тредов, в теле функции треда которой будет луп и sleep(100). Компьютер сильно задумается. где уж тут клиентов обслуживать.
Ответить