zoukankan      html  css  js  c++  java
  • Erlang cowboy 入门参考

    http://blog.csdn.net/ubuntu64fan/article/details/40542549

    本文翻译自:

    http://ninenines.eu/docs/en/cowboy/HEAD/guide/getting_started/

    我没有按原文逐句翻译。仅仅是我自己的理解,力求简单明了。本文程序在RHEL6.4上写成并运行,参考下面的文章,安装Erlang:

    erlang在redhat上的安装

    1 引言

    Erlang不仅仅是一门语言,更是一个操作平台。Erlang开发者很少写单独的模块,而是写库和程序,然后把它们打包在一起进行发布。一个产品发布包含Erlang虚拟机和所有用来运行的程序,因此可以直接成为产品。Cowboy是Erlang编写的WebServer,提供Http,Https,WebSocket,TCP等各种高性能服务框架。本文将说明如何安装Cowboy,写第一个程序并发布。通过阅读本文,读者可以了解发布你的第一个Cowboy程序的全部内容。

    2 开始第一个产品

    当我们要开发一个程序(产品),我们希望用一个工程去管理它。代码构建,打包,发布等一系列行为。做Java开发使用的是Eclipse+Maven+Ant等工具。做Erlang开发可以使用Gnu Make。由于每个工具所完成的功能都类似,因此推荐使用下面这个Make模板。

    https://github.com/ninenines/erlang.mk

    下面开始我们的第一个Erlang工程。创建一个hello_erlang的目录,进入这个目录:

    1. $ mkdir hello_erlang && cd hello_erlang  

    下载erlang.mk文件。这是erlang工程的构建脚本。关于这个脚本的细节可以在各位成为erlang专家的时候去理解。

    1. $ wget --no-check-certificate https://raw.githubusercontent.com/ninenines/erlang.mk/master/erlang.mk  

    之后我们会看到目录下多了一个文件:erlang.mk。然后我们就可以生成我们的程序,同时生成发布版本(bootstrap,bootstrap-rel是target):

    1. $ make -f erlang.mk bootstrap bootstrap-rel  

    现在就可以构建我们的工程,生成发布版本:

    1. $ make  

    这个命令会花费较长时间执行完毕。然后启动运行产品程序:

    1. $ ./_rel/hello_erlang_release/bin/hello_erlang_release console  

    输入下面的命令可以看到运行的进程,其中包括:hello_erlang_sup。这个是我们的程序的督程(supervisor)。

    1. (hello_erlang@127.0.0.1)1> i().  


    现在这个程序什么也没做,接下来我们给它添加Cowboy依赖,然后把它变成一个简单的HelloWorld程序。整个过程就是如下样子:

    1. [root@rhel64-origin workspace]# mkdir hello_erlang  
    2. [root@rhel64-origin workspace]# cd hello_erlang/  
    3. [root@rhel64-origin hello_erlang]# ls  
    4. [root@rhel64-origin hello_erlang]# wget --no-check-certificate https://raw.githubusercontent.com/ninenines/erlang.mk/master/erlang.mk  
    5. --2014-10-28 17:42:55--  https://raw.githubusercontent.com/ninenines/erlang.mk/master/erlang.mk  
    6. Resolving raw.githubusercontent.com... 103.245.222.133  
    7. Connecting to raw.githubusercontent.com|103.245.222.133|:443... connected.  
    8. WARNING: certificate common name “www.github.com” doesn’t match requested host name “raw.githubusercontent.com”.  
    9. HTTP request sent, awaiting response... 200 OK  
    10. Length: 20522 (20K) [text/plain]  
    11. Saving to: “erlang.mk”  
    12.   
    13. 100%[======================================================>] 20,522      --.-K/s   in 0.04s  
    14.   
    15. 2014-10-28 17:42:55 (473 KB/s) - “erlang.mk” saved [20522/20522]  
    16.   
    17. [root@rhel64-origin hello_erlang]# ls  
    18. erlang.mk  
    19. [root@rhel64-origin hello_erlang]# make -f erlang.mk bootstrap bootstrap-rel  
    20. [root@rhel64-origin hello_erlang]# make  
    21.  ERLC   hello_erlang_app.erl hello_erlang_sup.erl  
    22.  APP    hello_erlang.app.src  
    23.  GEN    distclean-relx-rel  
    24. --2014-10-28 17:43:08--  https://github.com/erlware/relx/releases/download/v1.0.2/relx  
    25. Resolving github.com... 192.30.252.131  
    26. Connecting to github.com|192.30.252.131|:443... connected.  
    27. HTTP request sent, awaiting response... 302 Found  
    28. Location: https://s3.amazonaws.com/github-cloud/releases/9900098/f6fcb596-e38d-11e3-9e8b-c953e4c1e42a?response-content-disposition=attachment%3B%20filename%3Drelx&response-content-type=application/octet-stream&AWSAccessKeyId=AKIAISTNZFOVBIJMK3TQ&Expires=1414489636&Signature=adyKnn8IPqauqWSnsXhJTc2vBio%3D [following]  
    29. --2014-10-28 17:43:12--  https://s3.amazonaws.com/github-cloud/releases/9900098/f6fcb596-e38d-11e3-9e8b-c953e4c1e42a?response-content-disposition=attachment%3B%20filename%3Drelx&response-content-type=application/octet-stream&AWSAccessKeyId=AKIAISTNZFOVBIJMK3TQ&Expires=1414489636&Signature=adyKnn8IPqauqWSnsXhJTc2vBio%3D  
    30. Resolving s3.amazonaws.com... 54.231.244.0  
    31. Connecting to s3.amazonaws.com|54.231.244.0|:443... connected.  
    32. HTTP request sent, awaiting response... 200 OK  
    33. Length: 743699 (726K) [application/octet-stream]  
    34. Saving to: “/root/workspace/hello_erlang/relx”  
    35.   
    36. 100%[======================================================>] 743,699      147K/s   in 5.0s  
    37.   
    38. 2014-10-28 17:43:19 (145 KB/s) - “/root/workspace/hello_erlang/relx” saved [743699/743699]  
    39.   
    40. ===> Starting relx build process ...  
    41. ===> Resolving OTP Applications from directories:  
    42.           /root/workspace/hello_erlang/ebin  
    43.           /usr/local/lib/erlang/lib  
    44. ===> Resolving available OTP Releases from directories:  
    45.           /root/workspace/hello_erlang/ebin  
    46.           /usr/local/lib/erlang/lib  
    47. ===> Resolved hello_erlang_release-1  
    48. ===> Including Erts from /usr/local/lib/erlang  
    49. ===> release successfully created!  

    3 cowboy安装

    为了使我们的hello_erlang使用cowboy,我们需要修改2个文件:Makefile和src/hello_erlang.app.src。修改后的Makefile如下:

    1. PROJECT = hello_erlang  
    2. DEPS = cowboy  
    3. include erlang.mk  

    我们在src/hello_erlang.app.src文件中添加cowboy,这让我们的程序发布时自动将cowboy打包。有些仅仅是开发阶段的依赖不必要添加在这里(applications[...])。修改后的文件如下:

    1. {application, hello_erlang, [  
    2.         {description, "Hello Erlang!"},  
    3.         {vsn, "0.1.0"},  
    4.         {modules, []},  
    5.         {registered, []},  
    6.         {applications, [  
    7.                 kernel,  
    8.                 stdlib,  
    9.                 cowboy  
    10.         ]},  
    11.         {mod, {hello_erlang_app, []}},  
    12.         {env, []}  
    13. ]}.  

    现在我们运行make命令,cowboy就被自动加入到产品中,当然它什么也没做。输出如下:

    1. [root@rhel64-origin hello_erlang]# make  
    2. --2014-10-28 17:53:58--  https://raw.githubusercontent.com/ninenines/erlang.mk/master/packages.v2.tsv  
    3. Resolving raw.githubusercontent.com... 103.245.222.133  
    4. Connecting to raw.githubusercontent.com|103.245.222.133|:443... connected.  
    5. WARNING: certificate common name “www.github.com” doesn’t match requested host name “raw.githubusercontent.com”.  
    6. HTTP request sent, awaiting response... 200 OK  
    7. Length: 7115 (6.9K) [text/plain]  
    8. Saving to: “/root/workspace/hello_erlang/.erlang.mk.packages.v2”  
    9.   
    10. 100%[======================================================>] 7,115       --.-K/s   in 0.001s  
    11.   
    12. 2014-10-28 17:54:06 (12.6 MB/s) - “/root/workspace/hello_erlang/.erlang.mk.packages.v2” saved [7115/7115]  
    13.   
    14. Initialized empty Git repository in /root/workspace/hello_erlang/deps/cowboy/.git/  
    15. remote: Counting objects: 7063, done.  
    16. remote: Total 7063 (delta 0), reused 0 (delta 0)  
    17. Receiving objects: 100% (7063/7063), 5.26 MiB | 530 KiB/s, done.  
    18. Resolving deltas: 100% (4198/4198), done.  
    19. make[1]: Entering directory `/root/workspace/hello_erlang/deps/cowboy'  
    20. DEPPKG=$(awk 'BEGIN { FS = " " }; $1 == "cowlib" { print $2 " " $3 " " $4 }' /root/workspace/hello_erlang/.erlang.mk.packages.v2;) VS=$(echo $DEPPKG | cut -d " " -f1); REPO=$(echo $DEPPKG | cut -d " " -f2); COMMIT=$(echo $DEPPKG | cut -d " " -f3);        if [ "$VS" = "git" ]; then git clone -n -- $REPO /root/workspace/hello_erlang/deps/cowlib; cd /root/workspace/hello_erlang/deps/cowlib && git checkout -q $COMMIT; else exit 78; fi  
    21. Initialized empty Git repository in /root/workspace/hello_erlang/deps/cowlib/.git/  
    22. remote: Counting objects: 202, done.  
    23. remote: Total 202 (delta 0), reused 0 (delta 0)  
    24. Receiving objects: 100% (202/202), 87.64 KiB | 100 KiB/s, done.  
    25. Resolving deltas: 100% (119/119), done.  
    26. DEPPKG=$(awk 'BEGIN { FS = " " }; $1 == "ranch" { print $2 " " $3 " " $4 }' /root/workspace/hello_erlang/.erlang.mk.packages.v2;) VS=$(echo $DEPPKG | cut -d " " -f1); REPO=$(echo $DEPPKG | cut -d " " -f2); COMMIT=$(echo $DEPPKG | cut -d " " -f3);         if [ "$VS" = "git" ]; then git clone -n -- $REPO /root/workspace/hello_erlang/deps/ranch; cd /root/workspace/hello_erlang/deps/ranch && git checkout -q $COMMIT; else exit 78; fi  
    27. Initialized empty Git repository in /root/workspace/hello_erlang/deps/ranch/.git/  
    28. remote: Counting objects: 905, done.  
    29. Receiving objects: 100% (905/905), 288.85 KiB | 170 KiB/s, done.  
    30. remote: Total 905 (delta 0), reused 0 (delta 0)  
    31. Resolving deltas: 100% (532/532), done.  
    32. make[2]: Entering directory `/root/workspace/hello_erlang/deps/cowlib'  
    33.  ERLC   cow_http_te.erl cow_http.erl cow_http_hd.erl cow_date.erl cow_mimetypes.erl cow_multipart.erl cow_qs.erl cow_cookie.erl cow_spdy.erl  
    34.  APP    cowlib.app.src  
    35. make[2]: Leaving directory `/root/workspace/hello_erlang/deps/cowlib'  
    36. make[2]: Entering directory `/root/workspace/hello_erlang/deps/ranch'  
    37.  ERLC   ranch_acceptors_sup.erl ranch_conns_sup.erl ranch_server.erl ranch_tcp.erl ranch.erl ranch_acceptor.erl ranch_listener_sup.erl ranch_app.erl ranch_protocol.erl ranch_ssl.erl ranch_sup.erl ranch_transport.erl  
    38.  APP    ranch.app.src  
    39. make[2]: Leaving directory `/root/workspace/hello_erlang/deps/ranch'  
    40.  ERLC   cowboy_router.erl cowboy_rest.erl cowboy_http_handler.erl cowboy_sup.erl cowboy_websocket_handler.erl cowboy_static.erl cowboy_sub_protocol.erl cowboy_websocket.erl cowboy.erl cowboy_app.erl cowboy_handler.erl cowboy_loop_handler.erl cowboy_protocol.erl cowboy_bstr.erl cowboy_clock.erl cowboy_http.erl cowboy_spdy.erl cowboy_req.erl cowboy_middleware.erl  
    41.  APP    cowboy.app.src  
    42. make[1]: Leaving directory `/root/workspace/hello_erlang/deps/cowboy'  
    43.  APP    hello_erlang.app.src  
    44.  GEN    distclean-relx-rel  
    45. ===> Starting relx build process ...  
    46. ===> Resolving OTP Applications from directories:  
    47.           /root/workspace/hello_erlang/ebin  
    48.           /root/workspace/hello_erlang/deps  
    49.           /usr/local/lib/erlang/lib  
    50. ===> Resolving available OTP Releases from directories:  
    51.           /root/workspace/hello_erlang/ebin  
    52.           /root/workspace/hello_erlang/deps  
    53.           /usr/local/lib/erlang/lib  
    54. ===> Resolved hello_erlang_release-1  
    55. ===> Including Erts from /usr/local/lib/erlang  
    56. ===> release successfully created!  

    4 监听连接

    当一个客户端请求到来,我们需要根据请求内容将请求分发(dispatch)到处理器(handler)。因此我们需要一个路由表(dispatch list),cowboy根据路由表分发请求到对应的处理模块程序。然后我们让cowboy开始监听连接。

    编辑Erlang程序源代码文件:src/hello_erlang_app.erl,修改start/2函数,最后的src/hello_erlang_app.erl如下:

    1. -module(hello_erlang_app).  
    2. -behaviour(application).  
    3.   
    4. -export([start/2]).  
    5. -export([stop/1]).  
    6.   
    7. start(_Type, _Args) ->  
    8.     Dispatch = cowboy_router:compile([  
    9.         {'_', [{"/", hello_handler, []}]}  
    10.     ]),  
    11.     cowboy:start_http(my_http_listener, 100, [{port, 8080}],  
    12.         [{env, [{dispatch, Dispatch}]}]  
    13.     ),  
    14.     hello_erlang_sup:start_link().    
    15.   
    16. stop(_State) ->  
    17.     ok.  

    现在我们把根路由"/"定义到hello_handler,下面我们就需要为此写这个处理器。

    5 处理请求

    cowboy具有处理各种请求的特色,例如:REST,WebSocket等。这里我们使用一个简单的HTTP处理器。我们使用处理器模板生成这个处理器:

    1. $ make new t=cowboy_http n=hello_handler  

    这将创建src/hello_handler.erl代码文件。打开它,修改成下面的样子(只修改了init/3):

    1. -module(hello_handler).  
    2. -behaviour(cowboy_http_handler).  
    3.   
    4. -export([init/3]).  
    5. -export([handle/2]).  
    6. -export([terminate/3]).  
    7.   
    8. -record(state, {  
    9. }).  
    10.   
    11. init(_, Req, Opts) ->  
    12.     Req2 = cowboy_req:reply(200,  
    13.         [{<<"content-type">>, <<"text/plain">>}],  
    14.         <<"Hello Erlang!">>,  
    15.         Req),  
    16.     {ok, Req2, Opts}.  
    17.   
    18. handle(Req, State=#state{}) ->  
    19.     {ok, Req2} = cowboy_req:reply(200, Req),  
    20.     {ok, Req2, State}.  
    21.   
    22. terminate(_Reason, _Req, _State) ->  
    23.     ok.  

    6 构建并运行

    1. $ make  
    2. $ ./_rel/hello_erlang_release/bin/hello_erlang_release console  

    在浏览器中打开:http://your-ip-addr:8080/,显示如下:

    7 总结

    cowboy这个框架和nodejs很像。erlang的语法有点生疏,但是erlang比nodejs不知道强多少倍。erlang是C写的,nodejs的底层是C++,可见多数C++写的产品最后都不如C写的,这是偶然么?“一只鸟长得像鸭子,叫声像鸭子,走路也像鸭子,那它就是鸭子!”

  • 相关阅读:
    19牛客暑期多校 round2 H 01矩阵内第二大矩形
    NOIP2017滚粗记
    Left 4 Dead 2(求生之路2) 游戏打不开 游戏闪退 的一种可能性以及解决方法
    Luogu P1156 垃圾陷阱
    Luogu P1376 机器工厂
    Luogu P1842 奶牛玩杂技
    Luogu P1880 石子合并
    Luogu P1441 砝码称重(fj省选)
    Luogu P1077 摆花
    Luogu P1282 多米诺骨牌
  • 原文地址:https://www.cnblogs.com/fvsfvs123/p/4210866.html
Copyright © 2011-2022 走看看