Комментарии 41
Мне кажется, что вместо самописанных
лучше использовать встроенный в rebar плагин и поправить rebar.config как-то так:
c_tpl/0, c_tpl/1, c_tpl/2
лучше использовать встроенный в rebar плагин и поправить rebar.config как-то так:
{plugins,[rebar_erlydtl_compiler]}.
{deps, [
{cowboy, ".*", {git, "https://github.com/extend/cowboy.git", {branch, "master"}}},
{sync, ".*", {git, "git://github.com/rustyio/sync.git", {branch, "master"}}},
{mimetypes, ".*", {git, "git://github.com/spawngrid/mimetypes.git", {branch, "master"}}},
{erlydtl, ".*", {git, "git://github.com/evanmiller/erlydtl.git", {branch, "master"}}}
]}.
{erlydtl_opts,[
{compiler_options,[debug_info]},
[
{doc_root, "tpl"},
{out_dir, "ebin"},
{source_ext, ".dtl"},
{module_ext, "_dtl"}
]
]}.
Спасибо, не знал о такой возможности. А как после изменения шаблона его перекомпилировать? Простой rebar compile сделает это «на живую»? И справится ли с этим Sync?
Ковбой — очень коварное существо, высовывать его голой задницей в интернет — чревато.
1) Боится slow lorry, если кто-то об этом специально не подумал, причём в отличие от апача, который просто выедает префорки, жрёт память одним-единственным процессом, пока не приходит оом и не говорит beam.smp, «довольно».
2) Не имеет специальной защиты от postdata, то есть вместо url-encoded формочки вам зальют 20Гб (при 16 доступных памяти) и — ваш добрый эрланг всё это всосёт.
3) Не имеет защиты от излишнего числа коннектов (вариант п.1)
1) Боится slow lorry, если кто-то об этом специально не подумал, причём в отличие от апача, который просто выедает префорки, жрёт память одним-единственным процессом, пока не приходит оом и не говорит beam.smp, «довольно».
2) Не имеет специальной защиты от postdata, то есть вместо url-encoded формочки вам зальют 20Гб (при 16 доступных памяти) и — ваш добрый эрланг всё это всосёт.
3) Не имеет защиты от излишнего числа коннектов (вариант п.1)
1 и 3 было пофикшено здесь: github.com/extend/cowboy/commit/a013becc66b50db038c1f7f3539040b4482bba18
2 пофикшено здесь: github.com/extend/cowboy/commit/84d7671e91bb2dee2081172dbf651860134ae75e
2 пофикшено здесь: github.com/extend/cowboy/commit/84d7671e91bb2dee2081172dbf651860134ae75e
Была пофикшена специальная ситуация с slow lorry в середине заголовка, то есть когда метод уже передали, а заголовки нет. И slow lorry это не человек, который «ничего не передаёт» после метода, а человек, который это делает очень медленно.
что опцию --post-swap пофиксили, это хорошо.
А фикс к третьему варианту (ab с большой конкуренцией) я не вижу.
что опцию --post-swap пофиксили, это хорошо.
А фикс к третьему варианту (ab с большой конкуренцией) я не вижу.
Хм… По-моему, cowboy_protocol:recv/3, используемый для получения данных из сокета, без разбору на ситуации ограничивает время их ожидания. Или я что-то путаю и некорректно понял суть проблемы?
3 — не уверен, что нет лучшего варианта, последнее время не так активно слежу за обновлениями Ковбоя (уж больно их много), но, как вариант, можно последовать совету из комментария к проблеме: github.com/extend/cowboy/issues/213#issuecomment-7427912
3 — не уверен, что нет лучшего варианта, последнее время не так активно слежу за обновлениями Ковбоя (уж больно их много), но, как вариант, можно последовать совету из комментария к проблеме: github.com/extend/cowboy/issues/213#issuecomment-7427912
Мораль — что бы там на бэкенде ни крутилось, за проксирование соединений нгинксом ещё никого не уволили.
Все таки с web frameworks на эрланге все плохо. Столько ерунды надо руками писать.
Ковбой — это не фреймворк, а сервер. Фреймворк — это, например, Chicago Boss.
Да какая разница. Хочешь написать приложение, то либо берешь сервер и делаешь руками убивая кучу времени, либо фреймворк типа чикагы, где лютый оверкилл и ты опять же тратишь время на то, что бы выкинуть половину ненужного говна. Более-менее посередине нитроген, к которому все никак ни одной db не прикрутят.
В общем по сравнению с тем что есть на питоне — грустно.
В общем по сравнению с тем что есть на питоне — грустно.
Под конкретную задачу — конкретное решение.
Фреймворки плохо, ибо ограничивают в средствах.
Библиотеки (втч) аксепторы — хорошо, ибо есть много что готового, но это готовое, ты прозрачно можешь заменить на свое.
Фреймворки плохо, ибо ограничивают в средствах.
Библиотеки (втч) аксепторы — хорошо, ибо есть много что готового, но это готовое, ты прозрачно можешь заменить на свое.
В каких средствах меня ограничивает pyramid например? Но даже если это и так, то бывает когда это не главное. Главное быстро писать что хочешь. Вот тут fw и замечательно пригождается.
Главное быстро
Да, но как понимаю, в этом случае подойдет что угодно, втч «замечательные проекты на php». На тему быстро — требуется время на изучение фреймворка. Во некоторых подобных случаях удобнее и быстрее решить свою конкретную задачу руками.
Фремворки, кроме того, не всегда прозрачны (если, фреймворк написали не вы сами). Времени на понимание и отладку может уйди безумно много. А может и не уйти.
Про pyramid ничего сказать не смогу, — не пользовался.
А вот та же самая Django:
- ограничение на схему бд;
- крайне тяжело адаптировать к существующей базе;
- сложно адаптировать к существующей инфраструктуре;
- не удобно, и не всегда возможно оптимизировать;
- есть проблемы с потокобезопасностью, не всегда ясно как их разруливать;
- ...
писать что хочешь.
Опять зависит от того, что Вы конкретно хотите.
Не всегда задача авторов фреймворка совпадает и вашей текущей задачей.
Очень хорошо изучать подходы, а не их конкретные реализации. И потом использовать в своих проектах.
А зачем в webserver.erl в функции ensure_started делать pattern-matching если не зависимо от результата вызывается ensure_started(Apps)?
Потому что он может не отматчить вернувшееся от application:start(App) значение (например — {error, {not_started, _}}) и тогда мы упадем в функции ensure_started, как и надо поступать в данной ситуации.
Было бы интересно увидеть аналогичную статью, но DTL заменить на XSLT.
Кстати, мне кажется, что
./tpl
лучше убирать в ./priv
На тему горячей замены кода попробуйте вот это:
github.com/zavr/nodectl
Мы пользуемся, пока нареканий не было.
github.com/zavr/nodectl
Мы пользуемся, пока нареканий не было.
Спасибо, посмотрю. У Sync есть минусы, но плюсов, по сравнению с некоторыми рассмотренными мной ранее решениями, также хватает.
А расскажите подробнее о тех и о других, если можно. Sync никогда не использовал.
Из плюсов основных 2:
-возможность легко патчить удаленную ноду (правишь код на одной — он подхватывается на остальных)
-уведомления через Growl (хотя вроде еще какие-то есть для тех, кто не пользует Growl)
Из минусов основных тоже 2:
-не умеет апгрейдить код из вложенных директорий (например — если есть модули во вложенных в src/ директориях, то они не будут обновляться на лету). Давно собираюсь посмотреть, да попатчить (или разобраться, как его научить этому), но все никак руки не дойдут.
-не особо понятно, как интегрировать свои дополнительные действия на апгрейд кода (допустим применимо к данной статье я бы хотел при обновлении src/webserver_app.erl дергать webserver:update_routes/0), тут снова упираемся в то, что надо патчить сорцы как-то.
-возможность легко патчить удаленную ноду (правишь код на одной — он подхватывается на остальных)
-уведомления через Growl (хотя вроде еще какие-то есть для тех, кто не пользует Growl)
Из минусов основных тоже 2:
-не умеет апгрейдить код из вложенных директорий (например — если есть модули во вложенных в src/ директориях, то они не будут обновляться на лету). Давно собираюсь посмотреть, да попатчить (или разобраться, как его научить этому), но все никак руки не дойдут.
-не особо понятно, как интегрировать свои дополнительные действия на апгрейд кода (допустим применимо к данной статье я бы хотел при обновлении src/webserver_app.erl дергать webserver:update_routes/0), тут снова упираемся в то, что надо патчить сорцы как-то.
У меня выдаёт:
Erlang R15B01 (erts-5.9.1) [source] [64-bit] [smp:2:2] [async-threads:0] [kernel-poll:false]
Eshell V5.9.1 (abort with ^G)
1>
=INFO REPORT==== 24-Apr-2013::20:30:50 ===
application: webserver
exited: {bad_return,
{{webserver_app,start,[normal,[]]},
{'EXIT',
{{badmatch,
{error,
{shutdown,
{child,undefined,
{ranch_listener_sup,http_listener},
{ranch_listener_sup,start_link,
[http_listener,100,ranch_tcp,
[{port,8008}],
cowboy_protocol,
[{env,
[{dispatch,
[{'_',[],
[{[],[],index_handler,[]},
{'_',[],notfound_handler,[]}]}]}]}]]},
permanent,5000,supervisor,
[ranch_listener_sup]}}}},
[{webserver_app,start,2,
[{file,«src/webserver_app.erl»},{line,20}]},
{application_master,start_it_old,4,
[{file,«application_master.erl»},{line,274}]}]}}}}
type: temporary
{«init terminating in do_boot»,{{case_clause,{error,{bad_return,{{webserver_app,start,[normal,[]]},{'EXIT',{{badmatch,{error,{shutdown,{child,undefined,{ranch_listener_sup,http_listener},{ranch_listener_sup,start_link,[http_listener,100,ranch_tcp,[{port,8008}],cowboy_protocol,[{env,[{dispatch,[{'_',[],[{[],[],index_handler,[]},{'_',[],notfound_handler,[]}]}]}]}]]},permanent,5000,supervisor,[ranch_listener_sup]}}}},[{webserver_app,start,2,[{file,«src/webserver_app.erl»},{line,20}]},{application_master,start_it_old,4,[{file,«application_master.erl»},{line,274}]}]}}}}}},[{webserver,ensure_started,1,[{file,«src/webserver.erl»},{line,29}]},{webserver,start,0,[{file,«src/webserver.erl»},{line,16}]},{init,start_it,1,[]},{init,start_em,1,[]}]}}
Crash dump was written to: erl_crash.dump
после попытки запустить
soif@LubuntuVM:~/webserver$ erl -pa ebin deps/*/ebin -s webserver
Erlang R15B01 (erts-5.9.1) [source] [64-bit] [smp:2:2] [async-threads:0] [kernel-poll:false]
Eshell V5.9.1 (abort with ^G)
1>
=INFO REPORT==== 24-Apr-2013::20:30:50 ===
application: webserver
exited: {bad_return,
{{webserver_app,start,[normal,[]]},
{'EXIT',
{{badmatch,
{error,
{shutdown,
{child,undefined,
{ranch_listener_sup,http_listener},
{ranch_listener_sup,start_link,
[http_listener,100,ranch_tcp,
[{port,8008}],
cowboy_protocol,
[{env,
[{dispatch,
[{'_',[],
[{[],[],index_handler,[]},
{'_',[],notfound_handler,[]}]}]}]}]]},
permanent,5000,supervisor,
[ranch_listener_sup]}}}},
[{webserver_app,start,2,
[{file,«src/webserver_app.erl»},{line,20}]},
{application_master,start_it_old,4,
[{file,«application_master.erl»},{line,274}]}]}}}}
type: temporary
{«init terminating in do_boot»,{{case_clause,{error,{bad_return,{{webserver_app,start,[normal,[]]},{'EXIT',{{badmatch,{error,{shutdown,{child,undefined,{ranch_listener_sup,http_listener},{ranch_listener_sup,start_link,[http_listener,100,ranch_tcp,[{port,8008}],cowboy_protocol,[{env,[{dispatch,[{'_',[],[{[],[],index_handler,[]},{'_',[],notfound_handler,[]}]}]}]}]]},permanent,5000,supervisor,[ranch_listener_sup]}}}},[{webserver_app,start,2,[{file,«src/webserver_app.erl»},{line,20}]},{application_master,start_it_old,4,[{file,«application_master.erl»},{line,274}]}]}}}}}},[{webserver,ensure_started,1,[{file,«src/webserver.erl»},{line,29}]},{webserver,start,0,[{file,«src/webserver.erl»},{line,16}]},{init,start_it,1,[]},{init,start_em,1,[]}]}}
Crash dump was written to: erl_crash.dump
после попытки запустить
soif@LubuntuVM:~/webserver$ erl -pa ebin deps/*/ebin -s webserver
Затруднюсь с диагнозом. Попробуйте с гитхаба взять финальный код (
git clone git://github.com/chvanikoff/webserver.git
) и запустить (cd webserver && make all run
) — если заработает, то ищите неточности в следовании материалам статьи, я все перед публикацией проверял. Если нет, то пишите в личку.У вас в финальном коде
а в тексте статьи
Падает из-за отсутствия квадратных скобок в lists:append(["/", Filetype, "/[...]"])
Static = fun(Filetype) ->
{lists:append(["/", Filetype, "/[...]"]), cowboy_static, [
{directory, {priv_dir, webserver, [list_to_binary(Filetype)]}},
{mimetypes, {fun mimetypes:path_to_mimes/2, default}}
]}
а в тексте статьи
Static = fun(Filetype) ->
{lists:append("/", Filetype, "/[...]"), cowboy_static, [
{directory, {priv_dir, webserver, [list_to_binary(Filetype)]}},
{mimetypes, {fun mimetypes:path_to_mimes/2, default}}
]}
end,
Падает из-за отсутствия квадратных скобок в lists:append(["/", Filetype, "/[...]"])
Проблема решилась установкой пакета R16B от Erlang Solutions (по умолчанию в Убунту ставится R15B).
Спасибо за статью!
Спасибо за статью!
Rebar может сам компилить шаблоны, erlydtl_opts описывается в rebar.config.
У меня
{«init terminating in do_boot»,{{case_clause,{error,{not_started,cowlib}}},[{webserver,ensure_started,1,[{file,«src/webserver.erl»},{line,26}]},{webserver,start,0,[{file,«src/webserver.erl»},{line,13}]},{init,start_it,1,[]},{init,start_em,1,[]}]}}
Помогло дописать в
erl -pa ebin deps/*/ebin -s webserver
падает с ошибкой (установлен Erlang 17.1){«init terminating in do_boot»,{{case_clause,{error,{not_started,cowlib}}},[{webserver,ensure_started,1,[{file,«src/webserver.erl»},{line,26}]},{webserver,start,0,[{file,«src/webserver.erl»},{line,13}]},{init,start_it,1,[]},{init,start_em,1,[]}]}}
Помогло дописать в
webserver.erl
ссылку на cowlib
:-define(APPS, [crypto, ranch, cowlib, cowboy, webserver]).
Работающая конфигурация:
От себя добавлю, что нагуглить мануал на работающий “Hello Erlang” на cowbow практически невозможно. Не работает ничего нигде. Всё протухло. Но Erlang всё равно неимоверно крут.
- Erlang/OTP 17
- rebar 2.6.4
- Рабочие версии зависимостейСодержимое rebar.config
{plugins, [rebar_erlydtl_compiler]}. {deps, [ {cowboy, "1.0.4",{git, "git://github.com/extend/cowboy", {tag, "1.0.4"}}}, {sync, ".*", {git, "git://github.com/rustyio/sync.git", {branch, "master"}}}, {mimetypes, ".*", {git, "git://github.com/spawngrid/mimetypes.git", {branch, "master"}}}, {erlydtl, "0.9.4",{git, "git://github.com/erlydtl/erlydtl.git", {tag, "0.9.4"}}} ]}. {erlydtl_opts, [ {compiler_options, [debug_info]},[ {doc_root, "tpl"}, {out_dir, "ebin"}, {source_ext, ".dtl"}, {module_ext, "_tpl"} ] ]}.
- Собираем и запускаем:
rm -fr ./deps && make clean && make && make run
Один варнинг, но всё заработает:
Compiled src/binomial_heap.erl /[censored]/webserver/deps/eunit_formatters/src/eunit_progress.erl:31: Warning: type dict/0 is deprecated and will be removed in OTP 18.0; use use dict:dict/0 or preferably dict:dict/2
- Profit
От себя добавлю, что нагуглить мануал на работающий “Hello Erlang” на cowbow практически невозможно. Не работает ничего нигде. Всё протухло. Но Erlang всё равно неимоверно крут.
И мой тоже неправильный. Оказалось, что статика не работает.
Содержимое rebar.config
{plugins, [rebar_erlydtl_compiler]}.
{deps, [
{cowboy, "0.8.6",{git, "git://github.com/extend/cowboy",
{tag, "0.8.6"}}},
{sync, ".*", {git, "git://github.com/rustyio/sync.git", {branch, "master"}}},
{mimetypes, ".*", {git, "git://github.com/spawngrid/mimetypes.git", {branch, "master"}}},
{erlydtl, "0.9.4",{git, "git://github.com/erlydtl/erlydtl.git",
{tag, "0.9.4"}}}
]}.
{erlydtl_opts, [
{compiler_options, [debug_info]},[
{doc_root, "priv/tpl"},
{out_dir, "ebin"},
{source_ext, ".dtl"},
{module_ext, "_tpl"}
]
]}.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
Web-сервер на базе Cowboy