LINUX.ORG.RU

Сеть IP — когда писать программы лень

 


2

6

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

>>> Подробности

★★★

Проверено: Shaman007 ()
Последнее исправление: Silent (всего исправлений: 1)
Ответ на: комментарий от A-234

fork/exec - это не очень хорошее проектирование. Когда для выполнение очень простого и популярного действия нужно городить copyonwrite, всякие оптимизации и прочее - это не очень хорошо. В виндах это делается стандартно через параметры к CreateProcess

farafonoff ★★
()
Ответ на: комментарий от A-234

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

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

А под оффтопиком аналога нет потому что fork не подходит для гуи, ему есть лучшая замена в виде потоков. Люди из мс это поняли и сделали CreateThread и CreateProcess

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

по факту к апачу идет нагрузкой php

К nginx идет какой-то /другой/ php? Разница в том, что в первом случае php крутится внутри Апача в несколько потоков, а во втором php fork()-ается в несколько робочих процессов снаружи от процесса nginx.

Как бы Апач должен делать fcgi под nginx как стоячего, если ты нам не гонишь: всё же дешевые нити против богомерзких форков и unix-ipc.

baka-kun ★★★★★
()
Ответ на: комментарий от KennyMinigun

Почему? Дайте ссылку на почитать

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

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

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

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

и все это хуже nginx…

…который не использует нити. Зато использует множество процессов и unix-ipc между ними.

baka-kun ★★★★★
()
Ответ на: комментарий от farafonoff

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

Если использовать разделяемую память, то процессы лучше за счёт явного размещения разделяемых объектов в отдельной области, если использовать message passing — то процессы на порядки лучше масштабируются, легко расползаясь по разным серверам.

Упавший дочерний процесс может доставить немало весёлых минут, но только если падает постоянно. Упавший поток => смерть всего приложения. Всегда.

Я и говорю, с процессами всё просто, надёжно, быстро и масштабируемо — скукотищщщаааа, никакой движухи.

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

Да в общем эти ограничения меня вполне устраивают :)

A-234 ★★★★★
()
Ответ на: комментарий от farafonoff

для создания демона нужно написать много шаманского кода с форками и закрытием дескрипторов

Не так уж и много:

if ((pid = fork()) > 0) exit(0);
A-234 ★★★★★
()
Ответ на: комментарий от farafonoff

И получают все проблемы с синхронизацией и безопасностью, но ценой падения производительности.

«Проблемы с безопасностью» отгребают как раз тредовые приложения. Они, внезапно, не могут просто взять и уйти на пониженый уровень привилегий. А отфоркнутый child - может. Простейший пример - какая-нибудь самба или ftp. Или почтовый сервер, который через procmail складывает почту в мэйлбоксы. Или ещё круче - где требутеся ограничение ресурсов.

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

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

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

no-dashi ★★★★★
()
Ответ на: комментарий от farafonoff

А под оффтопиком аналога нет потому что fork не подходит для гуи, ему есть лучшая замена в виде потоков.

Не «лучшая замена», а «единственная замена». И вообще, UI-приложения и демоны это два параллельных измерения, что хорошо для одного, то превращается в полный п...ц для другого.

Для примера - тот же самый Apache + PHP. Казалось бы - самое время сделать Apache весь насквозь нитиевый, и PHP пускать в нитях, это же ведь так круто и быстро, верно? А теперь посмотрим на многоюзерский хостинг, подумаем и скажем - да ну её на.уй эту многонитиевость, пусть уж лучше многопроцессовым будет, там хоть такого песца с привилегиями не будет.

no-dashi ★★★★★
()
Ответ на: И "да" и "нет". от anonymous

но вот форкаться это немного более дорого для системы

Да почти пофиг, если заранее. Ну, на самом деле, если мы пишем HTTP-сервер и не очень-то доверяем запускаемым процессам/модулям, то разумнее форкаться, если нас интересует стабильность. Т.е. выбор определяется не только скоростью создания нового процесса/нити, но и другими факторами.

Да, можно создавать 100к тредов в секунду, но всего лишь 20к форков, но нужно ли? Если процессор вдруг начинает тратить заметное время на создание/убиение процессов/тредов, то надо менять уже подход. Реально, выбор форк/нить относится скорее к необходимому удобству IPC, удобно ли делать мьютексы и условные перменные или можно выкрутиться разделяемой памятью.

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

Посмотрите на виндовые службы, например

Посмотрел, это оно?

Думаю сравнивать простоту, в данном случае, излишне. Пример из моего предыдущего поста можно ведь еще упростить ;)

A-234 ★★★★★
()
Ответ на: комментарий от baka-kun

Причем в древние времена linux fork() был относительно дороже, чем в солярке или bsd.

Не путаешь с vfork?

Casus ★★★★★
()
Ответ на: комментарий от A-234

Не так уж и много:

Хахаха!!! Понимаю, когда в школе предлагают подобное детям, чтобы не парились, но в продакшн так низзя. Где-то была моя переписка с SolarDiz-ом про то, как правильно. Ну и про setsid() прочитай.

Casus ★★★★★
()
Ответ на: комментарий от A-234

Скорей всего, тебе хотели предложить посмотреть на impersonate token и прочее (там примерно на три страницы вызовов чтобы сменить привилегии нити), а также всяческие хитровые...ые коллбэки передаваемые друг другу родителськой нитью и дочереней, плюс свистопляски до состояние полный п...ц когда ВНЕЗАПНО надо что-то достать из родительского контекста, и поменять так, чтобы никто из сосеей не заметил :-)

no-dashi ★★★★★
()
Ответ на: комментарий от farafonoff

Автор разморозился. суперсервер уже давно никто не использует, как и fork(), а также юниксовый ipc.

Ну почему же. Я дома очень даже использую.
На нем exim, samba, ftp, tftp, еще по мелочи.
Зачем мне чтобы все эти демоны постоянно болтались в памяти.

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

Не путаешь с vfork?

Не, не путаю: vfork() родителя замораживает до execve() или завершения потомка. Помню, я тогда как раз пытался понять, почему сервер в интернете одинаково работает, а на локалхосте линукс сливает FreeBSD 2.2.7.

baka-kun ★★★★★
()

По моему никто из спорщиков не обратил внимание на то, что это: «Ремейк 3.08 от 27.04.2012г. статьи, опубликованной в 2002 году». Тоесть статья отражает положение вещей, больше относящееся к тем временам.

bbk123 ★★★★★
()
Ответ на: комментарий от A-234

Ты отвечал на вопрос о запуске демона, а привёл не самый корректный способ запуска потомка. Про setsid() уже прочитал?

Casus ★★★★★
()
Ответ на: комментарий от baka-kun

FreeBSD 2.2.7.

Если склероз мне не врёт, это примерно 97г. Могу поверить вполне. Но в те временя на фре нельзя было запустить скотский оракл так же просто, как на линуксе, это и предопределило мой выбор в пользу линукса ;)

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

Если этот демон стартует init'ом то пофигу.

A-234 ★★★★★
()
Ответ на: Из пещеры! Бегом! от anonymous

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

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

Если склероз мне не врёт, это примерно 97г.

Да, где-то так. До девальвации точно.

Но в те временя на фре нельзя было запустить скотский оракл так же просто, как на линуксе

Скотский 7.3, если мне не изменяет память, Женя Кузаков запускал на фряхе. Позднее линуксовая восьмерка на 3-CURRENT работала даже лучше.

PS. Веселое было время. :)

baka-kun ★★★★★
()
Ответ на: комментарий от farafonoff

Все эти проблемы есть только в восьмеричных правах. В виндах настройки прав намного более тонкие.

Дебил. С тобой можно будет разговаривать, когда научишься различать РАЗДЕЛЕНИЕ привилегий и КОЛИЧЕСТВО возможных привилегий.

no-dashi ★★★★★
()
Ответ на: комментарий от farafonoff

shared хостинг - пережиток 90х. v{d,p}s и облака - технологии будущего

Ыыыы... Моя плакать. Даешь каждому юзеру под его <?php print «Hello World\n»; ?> по виртуалке с 4 ядрами, 2GB RAM и 8GB HDD. И каждому приложению каждого юзера - тоже!!!

no-dashi ★★★★★
()
Ответ на: комментарий от farafonoff

Все эти проблемы есть только в восьмеричных правах. В виндах настройки прав намного более тонкие.

Чё ты тогда на лоре делаешь?

На микрософт.ком сидеть надо.

mirr0r
()
Ответ на: комментарий от baka-kun

Скотский 7.3, если мне не изменяет память, Женя Кузаков запускал на фряхе.

Надо будет Женьку спросить. Насколько я помню, с фряхой были какие-то конкретные трудности у 7.3, пока не изобрели способ линковки оракла с его библиотеками для скотины на родной системе. Правда, тогда речь про линукс была, но на фряхе могло тоже сработать, до этого «открытия» приходилось использовать ibcs2. Потом вышел 8-й нативный для линукса и про скотский можно было смело забыть. Аркаша Юдин, помнится, очень радовался, что линуксовый оракл на фре лучше работает, чем на линуксе.

PS. Веселое было время. :)

Дык! ;)

Casus ★★★★★
()
Ответ на: комментарий от A-234

В чем конкретно некорректность состоит?

Да какая разница? Ты же демонов из инита пускаешь, значит сам умный, разберёшься.

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

Причина такой реакции мне не ясна. Ну да ладно, надеюсь у тебя все в порядке.

A-234 ★★★★★
()
Ответ на: комментарий от Orlusha

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

Вот надежды на её освобождение были задушены, да.

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

Да и не спорю...

из всего названного зоопарка хорошо живут только sockets, mmap, pipes. Остальное лучше не трогать - трупниной воняет. Семафоры медленные (по сравнению с pthread mutex), сигналы deprecated (не безопасно с точки зрения разделяемых библиотек, например), shm ограничены в количестве (ограничение на всю систему) message queues медленные. pthreads заменяют все это намного более эффективными механизмами общей памяти и атомарных операций.

Всё верно. Но механизмов (именно юниксовых) выше крыши, а вот тут выступавший оратор говорил что они волею Божию помре... Слава Богу что в отличие от оффтопа мы имеем возможность выбора.

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

Ммм... Не всегда.

Но сигналы плохи сами по себе (очень медленные).

Они не всегда медленные. Всё зависит от реализации механизма сигналов. В том же QNX, при наличии hard real-time, они вельми шустры. С введением POSIX 1003.1b всё стало несколько легче в системах, которые поддерживают данное расширение стандарта. Там были определены:

Timers: periodic timers, delivery is accomplished using POSIX signals
Priority scheduling: fixed priority preemptive scheduling with a minimum of 32 priority levels
Real-time signals: additional signals with multiple levels of priority
Semaphores: named and memory counting semaphores
Memory queues: message passing using named queues
Shared memory: named memory regions shared between multiple processes
Memory locking: functions to prevent virtual memory swapping of physical memory pages

Подробнее — http://www.eetimes.com/electronics-news/4133374/POSIX-in-Real-Time Стартовая точка для раскопок под Linux — http://rhdv.home.xs4all.nl/posix.html

Так что, не контуженному в башку «сычу-наСильнику» есть из чего выбрать соответствующий инстрУмент. ;) Плюсовцы — на отдых. :)))

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

Хе...

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

Хе-хе-хе... А вот тут всё плохо. И именно в части продакшона. Вот в чём дело — если у Вас сервис реализован именно таким образом, то получится, что (продолжаем пример с http) что при обращении по tcp/80, суперсервер xinitd скажет запросу — «погодь, я ща тут на винте найду и загружу обработчик» (примерно так). Т.е., как-раз для продакшона этот подход не гож. Он годен когда Вы хотите например при обращении к tcp/80 запустить (пусть будет опять-таки например) ping 192.168.1.1 (или что возжелается). Пример звизданутый, я понимаю, но вот идея именно в этом.

С переходом на SysV-init оно всё по-проще. Организовать нормальный запуск не сложно. Создать нормальный демон — то же. За то не будет проблем при переносе кода из девелопмента в продакшн. «В Англии ружья кирпичом не чистят...» тьфу ты! В продакшоне так сервера не запускают. )))

Впрочем, если очень хочется, то я не против.

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

ЫЫЫ!

Вот понадобилось мне в программе запустить и прочитать вывод системного скрипта. Ничего проще и универсальнее fork/exec лично я придумать не могу.

man popen(3), не? Да, он там сам как-то fork()/exec() сделает. И... что? Нет, ну можно конечно и извратиться... :)

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

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

Создание демона? «Шесть шагов». http://www.netzmafia.de/skripten/unix/linux-daemon-howto.html Закрыть три дескриптора и создать новый процесс... Мелочи.

Сравни с созданием сервиса под оффтоп.

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

Да почти пофиг, если заранее.

Если префоркнутый, то да. Но вот беда в том, что при создании сетевых вещей этот подход не всегда работает. Да и можно прогиммороиться от души с использованем механизма epoll_*. Было как-то раз «веселье». Ну его на фиг.

Реально, выбор форк/нить относится скорее к необходимому удобству IPC, удобно ли делать мьютексы и условные перменные или можно выкрутиться разделяемой памятью.

Да.

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

Jaaa... Jaaa...

Ыыыы... Моя плакать. Даешь каждому юзеру под его <?php print «Hello World\n»; ?> по виртуалке с 4 ядрами, 2GB RAM и 8GB HDD. И каждому приложению каждого юзера - тоже!!!

Ich немношшечко рыдайтен то же... ))))) Самое смешное что они верят в то, что их «облака-белогривые лошадки» будут написаны кем-то другим, кто не столкнётся с этими всеми проблемами... ))))

anonymous
()
Ответ на: ЫЫЫ! от anonymous

popen - халява для девочек :) Не является popen заменой fork/exec, разве что вы мне расскажете как узнать pid порожденного процесса. На самом деле, я бы использовал popen но запускать один шелл из под другого да еще с такими ограничениями. Не вижу смысла в этом вызове вообще.

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

P.S. Еще один момент - stdout вы прочитаете, а как быть с stderr?

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

Сервис под оффтоп в 100 раз круче. Он может сообщать об ошибках запуска, автоматически перезапускаться, автоматически работать от нужного пользователя. В линуксе для этого пишется куча кода на множестве языков программирования (init/init scripts)

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