• 一个完整的Erlang应用


    http://blog.chinaunix.net/uid-25876834-id-3308693.html

    这里介绍构建一个完整的Erlang/OTP应用的例子,最后还给出了一个在实际生成环境中,如何启动应用的才能方便运维人员维护和部署的实例。例子摘自 《Manning.Erlang.and.OTP.in.Action》(国内目前已经有中文版发行)。

    关于该应用例子中,代码和配置文件中的基本的概念的解释我这里就省略了。
     
    一个完整而简单的基于tcp的rpc 应用为例,一个应用包括:
     
    1、元数据文件 tcp_rpc.app

    点击(此处)折叠或打开

    1. {application,tcp_rpc,
    2.  [{description,"RPC Server for Erlang and OTP in action"},
    3.   {vsn, "0.1.0"},
    4.   {modules,[tr_app,
    5.             tr_sup,
    6.             tr_server]},
    7.   {registered, [tr_sup]},
    8.   {applications, [kernel, stdlib]},
    9.   {mod, {tr_app, []}}
    10. ]}.
    2、应用启动模块 tr_app.erl

    点击(此处)折叠或打开

    1. -module(tr_app).
    2. -behaviour(application).
    3. %% --------------------------------------------------------------------
    4. %% Include files
    5. %% --------------------------------------------------------------------
    6. %% --------------------------------------------------------------------
    7. %% Behavioural exports
    8. %% --------------------------------------------------------------------
    9. -export([
    10.      start/2,
    11.      stop/1
    12.         ]).
    13. %% --------------------------------------------------------------------
    14. %% Internal exports
    15. %% --------------------------------------------------------------------
    16. %% -export([]).
    17. %% ====================================================================!
    18. %% External functions
    19. %% ====================================================================!
    20. %% --------------------------------------------------------------------
    21. %% Func: start/2
    22. %% Returns: {ok, Pid} |
    23. %% {ok, Pid, State} |
    24. %% {error, Reason}
    25. %% --------------------------------------------------------------------
    26. start(_Type, _StartArgs) -> 
    27.     case tr_sup:start_link() of
    28.     {ok, Pid} -> 
    29.      {ok, Pid};
    30.     Error ->
    31.      {error,Error}
    32.     end.
    33. %% --------------------------------------------------------------------
    34. %% Func: stop/1
    35. %% Returns: any
    36. %% --------------------------------------------------------------------
    37. stop(_State) ->
    38.     ok.
    3、顶层监督模块 tr_sup.erl

    点击(此处)折叠或打开

    1. -module(tr_sup).
    2. -behaviour(supervisor).
    3. -export([start_link/0]).
    4. -export([
    5.      init/1
    6.         ]).
    7. -define(SERVER, ?MODULE).
    8. start_link() ->
    9.     supervisor:start_link({local, ?SERVER}, ?MODULE, []).
    10. init([]) ->
    11.     Server = {tr_server, 
    12.              {tr_server,start_link,[]},
    13.              permanent, 2000, worker, [tr_server]},
    14.     {ok,{
    15.          {one_for_one,0,1}, 
    16.          [Server]
    17.         }
    18.     }.
    4、服务器模块 tr_server.erl

    点击(此处)折叠或打开

    1. %%%-------------------------------------------------------------------
    2. %%% @author <龙二>
    3. %%% @copyright (C) 2012, 
    4. %%% @doc RPC over TCP server. This module defines a server process that 
    5. %%% listens for incoming TCP connections and allows the user to
    6. %%% execute RPC commands via that TCP stream.
    7. %%% @end
    8. %%% Created : 2 Jul 2012 by <emacs>
    9. %%%-------------------------------------------------------------------
    10. -module(tr_server).
    11. -include_lib("eunit/include/eunit.hrl"). %% Eunit单元测试
    12. -behaviour(gen_server).
    13. %% API
    14. -export([
    15.          start_link/1,
    16.          start_link/0,
    17.          get_count/0,
    18.          stop/0
    19.          ]).
    20. %% gen_server callbacks
    21. -export([init/1,handle_call/3,handle_cast/2,handle_info/2,
    22.          terminate/2,code_change/3]).
    23. -define(SERVER,?MODULE).
    24. -define(DEFAULT_PORT,1055).
    25. -record(state,{port,lsock,request_count = 0}).
    26. %%%===================================================
    27. %%% API
    28. %%%===================================================
    29. %%----------------------------------------------------
    30. %% @doc Starts the server.
    31. %%
    32. %% @spec start_link(Port::integer()) -> {ok,Pid}
    33. %% where
    34. %% Pid = pid()
    35. %% @end
    36. %%----------------------------------------------------
    37. start_link(Port) ->
    38.     gen_server:start_link({local,?SERVER},?MODULE,[Port],[]).
    39. %% @spec start_link() -> {ok,Pid}
    40. %% @doc Calls 'start_link(Port)' using the default port
    41. start_link() ->
    42.     start_link(?DEFAULT_PORT).
    43. %%----------------------------------------------------
    44. %% @doc Fetches the number of requests made to this server
    45. %% @spec get_count() -> {ok,Count}
    46. %% where
    47. %% Count = integer()
    48. %% @end
    49. %%----------------------------------------------------
    50. get_count() ->
    51.     gen_server:call(?SERVER,get_count).
    52. %%----------------------------------------------------
    53. %% @doc Stops the server
    54. %% @spec stop() -> ok
    55. %% @end
    56. %%----------------------------------------------------
    57. stop() ->
    58.     gen_server:cast(?SERVER,stop).
    59. %%%===================================================
    60. %%% gen_server callbacks
    61. %%%===================================================
    62. init([Port]) ->
    63.     {ok,LSock} = gen_tcp:listen(Port,[{active,true}]),
    64.     %% 0 is timeout value
    65.     %% a atom msg 'timeout' will be generate
    66.     %% handle_info/2 will handle this msg immediately when init/1 finished
    67.     {ok,#state{port = Port,lsock = LSock},0}. 
    68. handle_call(get_count,_From,State) ->
    69.     {reply,{ok,State#state.request_count},State}.
    70. handle_cast(stop,State) ->
    71.     {stop,normal,State}.
    72. %% handle_info/2: handle tcp,port,timeout msg 
    73. handle_info({tcp,Socket,RawData},State) ->
    74.     do_rpc(Socket,RawData),
    75.     RequestCount = State#state.request_count,
    76.     {noreply,State#state{request_count = RequestCount + 1}};
    77. handle_info(timeout,#state{lsock = LSock} = State) ->
    78.     {ok,_Sock} = gen_tcp:accept(LSock),
    79.     {noreply,State}.
    80. terminate(_Reason,_State) ->
    81.     ok.
    82. code_change(_OldVsn,State,_Extra) ->
    83.     {ok,State}.
    84. %%%===================================================
    85. %%% Internal functions
    86. %%%===================================================
    87. do_rpc(Socket,RawData) ->
    88.     try
    89.         {M,F,A} = split_out_mfa(RawData),
    90.         Request = apply(M,F,A),
    91.         gen_tcp:send(Socket,io_lib:fwrite("~p~n",[Request]))
    92.     catch
    93.         _Class:Err ->
    94.             gen_tcp:send(Socket,io_lib:fwrite("~p~n",[Err]))
    95.     end.
    96. split_out_mfa(RawData) ->
    97.      MFA = re:replace(RawData," $","",[{return,list}]),
    98.     {match,[M,F,A]} =
    99.         re:run(MFA,
    100.              "(.*):(.*)s*\((.*)s*\)s*.s*$",
    101.              [{capture,[1,2,3],list},ungreedy]),
    102.     {list_to_atom(M),list_to_atom(F),args_to_terms(A)}.
    103. args_to_terms(RawArgs) ->
    104.     {ok,Toks,_Line} = erl_scan:string("[" ++ RawArgs ++ "]. ",1),
    105.     {ok,Args} = erl_parse:parse_term(Toks),
    106.     Args.
    5、启动整个应用的开启模块 tr.erl

    点击(此处)折叠或打开

    1. -module(tr).
    2. -export([start/0]).
    3. %%
    4. %% API Functions
    5. %%
    6. %% 启动应用
    7. start() ->
    8.     case application:start(tcp_rpc) of
    9.         ok ->
    10.             ok;
    11.         Msg ->
    12.             {failur, Msg}
    13.     end.
    14. %% 关闭应用
    15. stop() ->
    16. case application:stop(tcp_rpc) of
    17. ok ->
    18. ok;
    19. Msg ->
    20. {failure, Msg}
    21. end.
     
    6、启动脚本 start_tr.sh (windows下为start_tr.bat)

    点击(此处)折叠或打开

    1. erl -pa ebin -name tr@127.0.0.1 -setcookie tr -s tr start
    2. chmod +x start_tr.sh
    3. windows下的话,需要将erl这个程序加入到环境变量,否则就要使用绝对路径来应用erl程序
      
    7、编译代码可以通过:
    erlc -o ebin src/*.erl
    或者利用Emakefile

    点击(此处)折叠或打开

    1. { ["src/*"]
    2.     , [     
    3.         {outdir, "./ebin"}]
    4. }.

    配合 erl -make 来编译这个应用。

     
    8、启动。因为我们写了启动脚本和启动模块,所以不需要进入到erlang shell 里面启动这个应用,可以直接通过执行 start_tr.sh 来启动。
     
    这里给出一个完整又简单的例子,希望可以对刚接触OTP知识的人有帮助。
    1.     , [     
    2.         {outdir, "./ebin"}]
    3. }.
    配合 erl -make 来编译这个应用。
     
    8、启动。因为我们写了启动脚本和启动模块,所以不需要进入到erlang shell 里面启动这个应用,可以直接通过执行 start_tr.sh 来启动。
     
    这里给出一个完整又简单的例子,希望可以对刚接触OTP知识的人有帮助。
  • 相关阅读:
    怎样用Lodrunner测试WAP站点的性能(两种解决方案)
    LR测试登陆后进行的操作时 绕过登录
    单元测试 模块接口测试
    一个分布式服务器集群架构方案
    利用loadrunner代理方式,录制手机APP脚本
    安卓开发环境安卓
    安卓自动化测试(2)Robotium环境搭建与新手入门教程
    安卓自动化测试(1)安卓自动化测试原理概念
    HTML框架
    HTML5表单提交与PHP环境搭建
  • 原文地址:https://www.cnblogs.com/fvsfvs123/p/4136897.html
Copyright © 2020-2023  润新知