Здравствуйте, Lazy Cjow Rhrr, Вы писали:
LCR>Ну я надеюсь, я достаточно подробно пояснил, почему я считаю, что Эрланг невозможен под jvm/.net? Хочу правильно поставить акцент: я не отрицаю возможность lightweight библиотеки, я всего лишь навсего очень-очень сильно сомневаюсь, что она может составить конкуренцию Эрлангу на _его_ поле боя и на смежных площадях:
Уважаемые коллеги, обсуждающие, как аналогичные задачи можно успешно решать за счет очередей сообщений и пулов потоков. Мне кажется, вы недооцениваете одной важной вещи, которую предоставляет поход Erlang-а. Если упустить ее из виду, то очередь сообщений действительно может
успешно использоваться (равно как и язык ассемблера в умелых руках). Разница всего лишь в цене и в возможностях.
А предоставляет Erlang такую штуку, как возможность оформить какую-либо автономную операцию в виде самостоятельного процесса. И наплодить таких процессов
сотни тысяч. И не иметь с этим делом большого геморроя, прибивая за просто так любой процесс и очень дешево порождая новый процесс. И все это в террариуме, в котором копошатся тысячи и тысячи процессов.
В качестве примера возьмем гипотетическую доставку подписчикам RSDN текстов новых постов в виде e-mail сообщений (пример актуальный кстати, т.к. изрядный процент сообщений теряется). Предположим, что процедура доставки одного сообщения одному абоненту оформляется в виде самостоятельного процесса. Он использует механизм гарантированной доставки, повторяя попытки отсылки сообщения с возрастающим тайм-аутом после каждой неудачи. После N неудачных попыток процесс просто завершает свою работу ("на нет и суда нет"). Реализовать такой процесс в виде одного for-а не составляет труда (извините, пример не на Erlang-е, а на псевдо-языке):
deliver_message( post, recipient )
{
for(i = 0; i != N; ++i )
{
result = try_deliver( post, recipient );
if( ok != result )
{
// Если временная проблема доставки, то есть
// смысл повторить ее позже.
if( can_be_delivered_later( result ) )
sleep( (i+1)*TIMEOUT );
else
// Если SMTP сервера нет или он говорит, что
// такого получателя нет, то просто прекращаем
// дальнейшие попытки.
die( post, recipient, THESE_STUPID_BEES_MAKE_INVALID_HONEY );
}
else
// Сообщение отправлено.
die( post, recipient, HAVE_A_NICE_DAY );
}
Функция die может помечать в базе, что сообщение на данного абонента доставлять больше не нужно (для корректного продолжения работы после рестартов).
Создать такой процесс и отладить его -- нет проблем, все весьма тривиально. Причем run-time Erlang-а гарантирует, что система не ляжет, даже если в ней одновременно будут крутиться, скажем 500K таких процессов.
А вот альтернативные решения требуют несколько больших усилий. Самый простой вариант -- рескан с каким-то периодом базы в поиске пар сообщение/абонент, которым нужно произвести доставку. Но для того, чтобы протестировать его под нагрузкой придется сильно попотеть, набивая тестовую БД и имитируя различные исходы доставки сообщения. А так же верификации результатов тестирования.
Чуть более сложный вариант -- организация каждой пары сообщение/абонент в виде объекта. Этот объект ставится в очередь. Когда какая-то из нитей рабочего пула извлекает такой объект, она выполняет очередную попытку доставки, затем анализирует разультат доставки и принимает решение о том, что делать дальше. Здесь нужно придумывать, как ставить в очереди "отложенные" объекты, время повторной доставки которых далеко "в будущем" -- ведь вытащив такую заявку из вершины очереди рабочая нить должна понять, что еще рано, вернуть объект обратно и заснуть "до лучших" времен. Нужно самим делать механизм "прибивания" рабочих нитей которые из-за каких-то сбоев в функции try_deliver не возвращаются из обрабоки очередного сообщения.
Вот как-то так. Или я что-то не правильно про Erlang понял?