Pull to refresh

Comments 62

А почему столько строк? Я честно надеялся увидеть его в одну строку. Причём, с регэкспами, разбирающими raw sockets…
Да вы сударь наверное и на PHP в 3 строки многопоточность делали.
> Ну что тут сказать, СЕО + информационная безопасность.
> 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 не угасла.
Да тоже пока читал, кат думал, что будет строчка одна и все, а тут расписал как он все… Как-то читал статью на хабре и увидел такое, хороший совет так скажем: «Два программиста сидели и хвастались — у меня 500 000 строк кода, а второй — у меня целый миллион строк кода, но гуру кодер сказал им — у меня 500 строк кода и работает все в сотни раз лучше. Программисты долго удивлялись его коду.»

Вот и в нашем случае тоже самое, вроде можно ведь сделать так, чтобы небыло ошибок, но он делает по методу: «Явных ошибок может и не быть».
Терморектальный криптоанализ

Внезапно! %)
По-моему, такие вещи как раз-таки внезапно и бывают ;).
Хороший код, спасибо, не знал кстати про FindBin модуль, интересно.

Теперь ждём всплеск статей о написании многопоточных серверов на Ruby, Python, Erlang и т.д…
А на erlang есть смысл писать что-то немногопоточное? ))
это вы уж нам расскажите, я с Erlang'ом на радостях не знаком :)
Это вы рано пишете «на радостях». Практика показывает, что как только человек освоил Erlang, то сразу начинает жалеть, что не взялся за него раньше, и писал наколеночные поделки вместо нормальных серверов :) Мозги в многопоточности он вправляет знатно.
Добавлю еще то, что на ерланге можно избегать кучи костылей, связанных с синхронизацией. После этого стремишься и в обычных языках использовать как можно меньше изменяемости.
Этому способствует куча языков, например, Haskell, Common Lisp, Scheme, Erlang и т.д. Хотя мутабельность везде так или иначе присутствует, но они учат избегать её и связанных с ней костылей.
И русской литературы по нему хрен найдешь.
Green threads есть и в перле. Просто мало кто о них знает. Так что можно точно так же забыть о синхронизации. Но мощи Эрланга это не умаляет, конечно.
Статья о написании сервера на C#. Я давно собирался написать (кармы не хватало — хабр ведь!), просто совпало.
Это очень удачное стечение обстоятельств ;)
Благодаря Perl-магии я понял, что Perl мне не нужен.
Я в свое время тоже так думал. Но потом, как-то… затянуло!
Чего только стоят модификаторы жадности квантификатора — можно пугать кого-нибудь.
Что-то вы из пугливых, даже страшно подумать, что вы поймете, когда увидите Ruby-магию!
Возможно потому, что автор использовал не лучший для демонстрации пример и модуль. Такие вещи лучше показывать (иногда и использовать) на IO::Socket. И никакой принудительной магии.
Ну, у меня особой магии нет.
А вот в случае c IO::Socket придется доставать талмуды с заклинаниями и самому делать многопоточность ;).
Никогда-никогда не используйте многопоточность при работе с сетью в перле. Обычно хватает non-blocking I/O — меньше граблей, быстрее работает, потребляет меньше памяти.
Не говорите никогда не использовать какую-то технологию если вам не удалось с ней сдружиться. Лично я занимаюсь крупным проектом с многопоточной сетью на Perl — главное правильно за это взяться. А связка IO::Socket+Threads показала очень хорошую производительность и отличную управляемость. И, кстати, при разработке не требуется ни талмудов ни заклинаний для обеспечения многопоточности.
Есть сторонние реализации моделей работы Net::Server. Вроде и потоки есть. Надо на CPAN смотреть.
Я прекрасно понимаю потоки. И «честные», и «перловые», и «зелёные». Всё, что обычно делается в перле через потоки, можно сделать по другому, но при этом а) проще б) не менее эффективно. Но в это сложно поверить, пока не попробуете)
А как тогда работать с несколькими запросами одновременно? Или зачем мне тогда SMP?
А зачем работать с ними одновременно? Точнее, так, — нужна latency или throughput? Ну и я за схему фронтенд+бекэнды — она сразу маштабируется, в случае чего, на несколько машин, а скорость обмена данными такая же, как и в перловых потоках.
Нужно тупо успевать обрабатывать пакеты.

Насчет frontend & backend — это Вы куда-то не туда попали. Это не HTTP.
Разве это магия?
это нюансы =)
Например, у меня уже есть рабочий прототип RADIUS-сервера, который я собираюсь использовать для собственного VPN-сервиса (Kebrum, привет!)
Привет, привет. А плагин к фрирадиусу религия сделать не позволяет?
Да, именно религия.
Плагин в FreeRADIUS у меня на двух проектах. Это ужас.
Мало того, что оно любит время от времени падать в сегфолт (хорошо хоть не главный процесс, а рабочие), так это еще и забивание микроскопом гвоздями.
Конечно, FreeRADIUS хорошо тем, что у него есть туча своих плюшек, но их все отключают и используют его тупо как обертку для протокола. Ну и нахрена он тогда вообще нужен?
Чтобы не запариваться с протоколом и не разбираться самому с MS-CHAP-авторизацией, например, а писать только логику?
С протоколом у меня работает Net::Radius::Server ;). А MS-CHAP не нужен.
Я тоже так думал, когда мы кебрум запускали. Выяснилось, что толпа народу хочет доступ с мобилок и прочей нечисти типа роутеров, куда openvpn не поставить. А падений не заметил. Скорее всего из-за того что у меня радиус с основным движком обработки запросов через сокеты общается.
В основном — да. Пытаемся выходить на запад, но там дичайшая конкуренция.
Мы идем сразу больше на Китай и арабов. Так что можно будет сотрудничать.
У подобного подхода к многопоточным серверам на перле есть, конечно, куча плюсов, но и один большущий минус: потребление памяти (для перла + fork делается почти полная копия памяти ). Варианты с event loop требуют больше усилий, но памяти не потребляют. Хотя если нужно всего несколько потоков, то форки, наверно, лучше.

Есть идея для следующей статьи — тот же сервер, но, к примеру, на POE.
Гуглите Copy-on-Write. Это вы перепутали с потоками, которые threads.
> fork делается почти полная копия памяти

насколько я помню, в перле это реализовано немного иначе. там делается только копия измененного участка памяти
Как правильно заметил ksurent, так и есть — с использованием Copy-on-Write. Но через некоторое время из-за беспорядка в перловых внутренностях страницы начинают копироваться. Не знаю как в современных версиях перла, но mod_perl когда-то это наглядно демонстрировал. Надо бы, конечно, поставить эксперимент…
Так получилось, что я уже ставил подобный эксперимент (правда, несколько вынужденно). У меня в проекте используется многопоточный веб-сервер с форками, и оказалось, что форки эти жутко тормозят. Единственное объяснение данному феномену, которое мне удалось найти, — что Перл при форке дёргает какие-то внутренние переменные, что приводит к копированию почти всей памяти исходного процесса в самом начале работы. При этом из-за CoW копия создаётся постранично, а не одним махом, а постраничное создание копии, как оказалось, требует на порядок больше времени, чем если бы вся память просто была скопирована каким-нибудь memcpy() (последний факт проверен написанием отдельной программы на Сях).

На всякий случай, если кому интересно, вот тут более подробная история болезни.
A bit of perl magic: POSIX::_exit
Поясняю — при завершении процесса, интерпретатор чистит за собой весь «мусор» — пробегает по всем ссылкам, уничтожает все объекты, вызывает все деструкторы. Т.е., по сути, перезаписывает всю свою память. Fail :( А _exit завершает процесс сразу, без всей этой беготни) Если не беспокоит невызов деструкторов — можно смело использовать. У меня в воркерах честный exit вызывается только в дебаге.
Проблема в том, что скорость завершения особо не беспокоила (да и не замерялась), проблема была в скорости инициализации. Но вообще буду иметь в виду, спасибо.

Кстати, в одном месте мне уже пришлось использовать _exit, чтобы избежать ожидания завершения процесса, запущенного через пайповый open()… Но это уже не в самом сервере, а в приложении, которое он обслуживает.
Намного более правильным решением являеться использование фреймворка AnyEvent (http://search.cpan.org/perldoc?AnyEvent::Intro )
Только как и любое поллинг каждая итерация должна занимать малое время иначе все плюсы сходят на нет
+1 за AnyEvent
Быстро и удобно. Сравнивал по скорости с node.js, почти одинаково, что неудивительно, так как в бэкенде оба используют libev. Хотя AnyEvent можно переключить на другой event-loop — модули с impl.
Рекомендую посмотреть в сторону POE. Достаточно удобный в использовании и отлично документированный набор библиотек.
Вот пример чат сервера:
Спасибо, посмотрю. Я несколько раз натыкался на него, но как-то не нашел времени разобраться.
AnyEvent и POE уже упомянули. Вот еще IO::Lambda есть для любителей функционального подхода.
Спасибо за статейку, очень интересно.
Я могу ошибаться, но кажется Fork порождает процессы. А вот процессы и потоки это разные вещи. Поправьте меня если я не прав.
придерусь :)

use FindBin qw($Bin);
use lib "$Bin/../lib";
Спасибо, не знал.
Статью уже править не буду, но Ваш пост для себя сохраню.
В модуле Hello.pm шебанг #!/usr/bin/perl — лишний.
Sign up to leave a comment.

Articles