Comments 62
А почему столько строк? Я честно надеялся увидеть его в одну строку. Причём, с регэкспами, разбирающими raw sockets…
Толсто.
Да вы сударь наверное и на PHP в 3 строки многопоточность делали.
> Ну что тут сказать, СЕО + информационная безопасность.
> 1994
> Ctacok
В школе проблем нет? Мама с папой знает, что ты занимаешься PHP? Если уж ты на каникулах то по-гугли на тему «perl one-liners.»
> 1994
> Ctacok
В школе проблем нет? Мама с папой знает, что ты занимаешься PHP? Если уж ты на каникулах то по-гугли на тему «perl one-liners.»
В PHP есть нормальная многопоточность? Расскажите как, а то уже второй день прибываю в шоке от способов создания многопоточной обработки в PHP
Однострочник, без raw sockets, правда))
perl -MAnyEvent::Socket -e 'tcp_server undef, 9999, sub {select($_[0]); print «Hello!\n»; close;}; AE->cv->recv'
perl -MAnyEvent::Socket -e 'tcp_server undef, 9999, sub {select($_[0]); print «Hello!\n»; close;}; AE->cv->recv'
Да тоже пока читал, кат думал, что будет строчка одна и все, а тут расписал как он все… Как-то читал статью на хабре и увидел такое, хороший совет так скажем: «Два программиста сидели и хвастались — у меня 500 000 строк кода, а второй — у меня целый миллион строк кода, но гуру кодер сказал им — у меня 500 строк кода и работает все в сотни раз лучше. Программисты долго удивлялись его коду.»
Вот и в нашем случае тоже самое, вроде можно ведь сделать так, чтобы небыло ошибок, но он делает по методу: «Явных ошибок может и не быть».
Вот и в нашем случае тоже самое, вроде можно ведь сделать так, чтобы небыло ошибок, но он делает по методу: «Явных ошибок может и не быть».
Терморектальный криптоанализ
Внезапно! %)
Хороший код, спасибо, не знал кстати про FindBin модуль, интересно.
Теперь ждём всплеск статей о написании многопоточных серверов на Ruby, Python, Erlang и т.д…
Теперь ждём всплеск статей о написании многопоточных серверов на Ruby, Python, Erlang и т.д…
А на erlang есть смысл писать что-то немногопоточное? ))
это вы уж нам расскажите, я с Erlang'ом на радостях не знаком :)
Это вы рано пишете «на радостях». Практика показывает, что как только человек освоил Erlang, то сразу начинает жалеть, что не взялся за него раньше, и писал наколеночные поделки вместо нормальных серверов :) Мозги в многопоточности он вправляет знатно.
Добавлю еще то, что на ерланге можно избегать кучи костылей, связанных с синхронизацией. После этого стремишься и в обычных языках использовать как можно меньше изменяемости.
И русской литературы по нему хрен найдешь.
Green threads есть и в перле. Просто мало кто о них знает. Так что можно точно так же забыть о синхронизации. Но мощи Эрланга это не умаляет, конечно.
Статья о написании сервера на C#. Я давно собирался написать (кармы не хватало — хабр ведь!), просто совпало.
Благодаря Perl-магии я понял, что Perl мне не нужен.
Я в свое время тоже так думал. Но потом, как-то… затянуло!
Чего только стоят модификаторы жадности квантификатора — можно пугать кого-нибудь.
Чего только стоят модификаторы жадности квантификатора — можно пугать кого-нибудь.
Что-то вы из пугливых, даже страшно подумать, что вы поймете, когда увидите Ruby-магию!
Возможно потому, что автор использовал не лучший для демонстрации пример и модуль. Такие вещи лучше показывать (иногда и использовать) на IO::Socket. И никакой принудительной магии.
Ну, у меня особой магии нет.
А вот в случае c IO::Socket придется доставать талмуды с заклинаниями и самому делать многопоточность ;).
А вот в случае c IO::Socket придется доставать талмуды с заклинаниями и самому делать многопоточность ;).
Никогда-никогда не используйте многопоточность при работе с сетью в перле. Обычно хватает non-blocking I/O — меньше граблей, быстрее работает, потребляет меньше памяти.
Не говорите никогда не использовать какую-то технологию если вам не удалось с ней сдружиться. Лично я занимаюсь крупным проектом с многопоточной сетью на Perl — главное правильно за это взяться. А связка IO::Socket+Threads показала очень хорошую производительность и отличную управляемость. И, кстати, при разработке не требуется ни талмудов ни заклинаний для обеспечения многопоточности.
Есть сторонние реализации моделей работы Net::Server. Вроде и потоки есть. Надо на CPAN смотреть.
Я прекрасно понимаю потоки. И «честные», и «перловые», и «зелёные». Всё, что обычно делается в перле через потоки, можно сделать по другому, но при этом а) проще б) не менее эффективно. Но в это сложно поверить, пока не попробуете)
А как тогда работать с несколькими запросами одновременно? Или зачем мне тогда SMP?
А зачем работать с ними одновременно? Точнее, так, — нужна latency или throughput? Ну и я за схему фронтенд+бекэнды — она сразу маштабируется, в случае чего, на несколько машин, а скорость обмена данными такая же, как и в перловых потоках.
Разве это магия?
это нюансы =)
это нюансы =)
Например, у меня уже есть рабочий прототип RADIUS-сервера, который я собираюсь использовать для собственного VPN-сервиса (Kebrum, привет!)Привет, привет. А плагин к фрирадиусу религия сделать не позволяет?
Да, именно религия.
Плагин в FreeRADIUS у меня на двух проектах. Это ужас.
Мало того, что оно любит время от времени падать в сегфолт (хорошо хоть не главный процесс, а рабочие), так это еще и забивание микроскопом гвоздями.
Конечно, FreeRADIUS хорошо тем, что у него есть туча своих плюшек, но их все отключают и используют его тупо как обертку для протокола. Ну и нахрена он тогда вообще нужен?
Плагин в FreeRADIUS у меня на двух проектах. Это ужас.
Мало того, что оно любит время от времени падать в сегфолт (хорошо хоть не главный процесс, а рабочие), так это еще и забивание микроскопом гвоздями.
Конечно, FreeRADIUS хорошо тем, что у него есть туча своих плюшек, но их все отключают и используют его тупо как обертку для протокола. Ну и нахрена он тогда вообще нужен?
Чтобы не запариваться с протоколом и не разбираться самому с MS-CHAP-авторизацией, например, а писать только логику?
С протоколом у меня работает Net::Radius::Server ;). А MS-CHAP не нужен.
Я тоже так думал, когда мы кебрум запускали. Выяснилось, что толпа народу хочет доступ с мобилок и прочей нечисти типа роутеров, куда openvpn не поставить. А падений не заметил. Скорее всего из-за того что у меня радиус с основным движком обработки запросов через сокеты общается.
Хм. Спасибо, учту.
Заодно вспомнил, что реализацию MS-CHAP на Perl я уже видел (здесь модуль, здесь использование).
Кстати, у вас кто основная аудитория? СНГ?
Заодно вспомнил, что реализацию MS-CHAP на Perl я уже видел (здесь модуль, здесь использование).
Кстати, у вас кто основная аудитория? СНГ?
У подобного подхода к многопоточным серверам на перле есть, конечно, куча плюсов, но и один большущий минус: потребление памяти (для перла + fork делается почти полная копия памяти ). Варианты с event loop требуют больше усилий, но памяти не потребляют. Хотя если нужно всего несколько потоков, то форки, наверно, лучше.
Есть идея для следующей статьи — тот же сервер, но, к примеру, на POE.
Есть идея для следующей статьи — тот же сервер, но, к примеру, на POE.
Гуглите Copy-on-Write. Это вы перепутали с потоками, которые threads.
> fork делается почти полная копия памяти
насколько я помню, в перле это реализовано немного иначе. там делается только копия измененного участка памяти
насколько я помню, в перле это реализовано немного иначе. там делается только копия измененного участка памяти
Именно, copy-on-write. perldoc.perl.org/functions/fork.html
Как правильно заметил ksurent, так и есть — с использованием Copy-on-Write. Но через некоторое время из-за беспорядка в перловых внутренностях страницы начинают копироваться. Не знаю как в современных версиях перла, но mod_perl когда-то это наглядно демонстрировал. Надо бы, конечно, поставить эксперимент…
Так получилось, что я уже ставил подобный эксперимент (правда, несколько вынужденно). У меня в проекте используется многопоточный веб-сервер с форками, и оказалось, что форки эти жутко тормозят. Единственное объяснение данному феномену, которое мне удалось найти, — что Перл при форке дёргает какие-то внутренние переменные, что приводит к копированию почти всей памяти исходного процесса в самом начале работы. При этом из-за CoW копия создаётся постранично, а не одним махом, а постраничное создание копии, как оказалось, требует на порядок больше времени, чем если бы вся память просто была скопирована каким-нибудь memcpy() (последний факт проверен написанием отдельной программы на Сях).
На всякий случай, если кому интересно, вот тут более подробная история болезни.
На всякий случай, если кому интересно, вот тут более подробная история болезни.
A bit of perl magic: POSIX::_exit
Поясняю — при завершении процесса, интерпретатор чистит за собой весь «мусор» — пробегает по всем ссылкам, уничтожает все объекты, вызывает все деструкторы. Т.е., по сути, перезаписывает всю свою память. Fail :( А _exit завершает процесс сразу, без всей этой беготни) Если не беспокоит невызов деструкторов — можно смело использовать. У меня в воркерах честный exit вызывается только в дебаге.
Поясняю — при завершении процесса, интерпретатор чистит за собой весь «мусор» — пробегает по всем ссылкам, уничтожает все объекты, вызывает все деструкторы. Т.е., по сути, перезаписывает всю свою память. Fail :( А _exit завершает процесс сразу, без всей этой беготни) Если не беспокоит невызов деструкторов — можно смело использовать. У меня в воркерах честный exit вызывается только в дебаге.
Проблема в том, что скорость завершения особо не беспокоила (да и не замерялась), проблема была в скорости инициализации. Но вообще буду иметь в виду, спасибо.
Кстати, в одном месте мне уже пришлось использовать _exit, чтобы избежать ожидания завершения процесса, запущенного через пайповый open()… Но это уже не в самом сервере, а в приложении, которое он обслуживает.
Кстати, в одном месте мне уже пришлось использовать _exit, чтобы избежать ожидания завершения процесса, запущенного через пайповый open()… Но это уже не в самом сервере, а в приложении, которое он обслуживает.
Намного более правильным решением являеться использование фреймворка AnyEvent (http://search.cpan.org/perldoc?AnyEvent::Intro )
Только как и любое поллинг каждая итерация должна занимать малое время иначе все плюсы сходят на нет
Только как и любое поллинг каждая итерация должна занимать малое время иначе все плюсы сходят на нет
+1 за AnyEvent
Быстро и удобно. Сравнивал по скорости с node.js, почти одинаково, что неудивительно, так как в бэкенде оба используют libev. Хотя AnyEvent можно переключить на другой event-loop — модули с impl.
Быстро и удобно. Сравнивал по скорости с node.js, почти одинаково, что неудивительно, так как в бэкенде оба используют libev. Хотя AnyEvent можно переключить на другой event-loop — модули с impl.
Рекомендую посмотреть в сторону POE. Достаточно удобный в использовании и отлично документированный набор библиотек.
Вот пример чат сервера:
Вот пример чат сервера:
Хабр съел ссылку poe.perl.org/?POE_Cookbook/Chat_Server
AnyEvent и POE уже упомянули. Вот еще IO::Lambda есть для любителей функционального подхода.
Спасибо за статейку, очень интересно.
Я могу ошибаться, но кажется Fork порождает процессы. А вот процессы и потоки это разные вещи. Поправьте меня если я не прав.
придерусь :)
use FindBin qw($Bin);
use lib "$Bin/../lib";
use FindBin qw($Bin);
use lib "$Bin/../lib";
В модуле Hello.pm шебанг #!/usr/bin/perl — лишний.
Sign up to leave a comment.
Многопоточный сервер на Perl? Легко!