Как стать автором
Обновить

Комментарии 41

Мне кажется, что вместо самописанных 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?
Да. rebar compile перекомпилит и Sync все замечательно должен подцепить. У меня все всегда работало :)
Окей, тогда сейчас проверю и обновлю статью. Спасибо.
Ковбой — очень коварное существо, высовывать его голой задницей в интернет — чревато.

1) Боится slow lorry, если кто-то об этом специально не подумал, причём в отличие от апача, который просто выедает префорки, жрёт память одним-единственным процессом, пока не приходит оом и не говорит beam.smp, «довольно».
2) Не имеет специальной защиты от postdata, то есть вместо url-encoded формочки вам зальют 20Гб (при 16 доступных памяти) и — ваш добрый эрланг всё это всосёт.
3) Не имеет защиты от излишнего числа коннектов (вариант п.1)
Была пофикшена специальная ситуация с slow lorry в середине заголовка, то есть когда метод уже передали, а заголовки нет. И slow lorry это не человек, который «ничего не передаёт» после метода, а человек, который это делает очень медленно.

что опцию --post-swap пофиксили, это хорошо.

А фикс к третьему варианту (ab с большой конкуренцией) я не вижу.
Хм… По-моему, cowboy_protocol:recv/3, используемый для получения данных из сокета, без разбору на ситуации ограничивает время их ожидания. Или я что-то путаю и некорректно понял суть проблемы?
3 — не уверен, что нет лучшего варианта, последнее время не так активно слежу за обновлениями Ковбоя (уж больно их много), но, как вариант, можно последовать совету из комментария к проблеме: github.com/extend/cowboy/issues/213#issuecomment-7427912
А посадить его под nginx?
Как самый простой вариант. Но все, как всегда, зависит от контекста. В контексте данного треда я хотел показать, что nginx не является обязательным звеном.
Мораль — что бы там на бэкенде ни крутилось, за проксирование соединений нгинксом ещё никого не уволили.
Все таки с 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, как и надо поступать в данной ситуации.
Спасибо за объяснение, думал чего-то, что ok и {error, {already_started, _}} это все что умеет возвращать application:start. Знакомлюсь с эрлангом, пока не знаю всех тонкостей. А вообще спасибо за статью отличное введение в ковбой.

Чем больше узнаю людей, тем больше я люблю эрланг!
Было бы интересно увидеть аналогичную статью, но DTL заменить на XSLT.
Я бы с радостью, но у меня на него аллергия.
Кстати, мне кажется, что ./tpl лучше убирать в ./priv
Хотя структура канонического Эрланг-приложение это подразумевает, тут все же скорее дело вкуса.
На тему горячей замены кода попробуйте вот это:
github.com/zavr/nodectl
Мы пользуемся, пока нареканий не было.
Спасибо, посмотрю. У Sync есть минусы, но плюсов, по сравнению с некоторыми рассмотренными мной ранее решениями, также хватает.
А расскажите подробнее о тех и о других, если можно. Sync никогда не использовал.
Из плюсов основных 2:
-возможность легко патчить удаленную ноду (правишь код на одной — он подхватывается на остальных)
-уведомления через 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

Затруднюсь с диагнозом. Попробуйте с гитхаба взять финальный код (git clone git://github.com/chvanikoff/webserver.git) и запустить (cd webserver && make all run) — если заработает, то ищите неточности в следовании материалам статьи, я все перед публикацией проверял. Если нет, то пишите в личку.
У вас в финальном коде
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.
У меня 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]).
Статья уже старенькая, давно стоит обновить, все руки не дойдут. Ну может сегодня вечером… :)
Да, сейчас иду по твоему тутору и, например, настройки для статики в ковбое уже по-другому задаются.

Раз уж зашла речь… У меня не находится priv_dir, сходу не подскажешь почему? :(
Разобрался с priv_dir сам.
Работающая конфигурация:
  1. Erlang/OTP 17
  2. rebar 2.6.4
  3. Рабочие версии зависимостей
    Содержимое 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"}
    	]
    ]}.
  4. Собираем и запускаем:
    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
  5. 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"}
	]
]}.

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации