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,"\r\n$","",[{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知识的人有帮助。

一个完整的Erlang应用的更多相关文章

  1. 如何一步一步用DDD设计一个电商网站(十)—— 一个完整的购物车

     阅读目录 前言 回顾 梳理 实现 结语 一.前言 之前的文章中已经涉及到了购买商品加入购物车,购物车内购物项的金额计算等功能.本篇准备把剩下的购物车的基本概念一次处理完. 二.回顾 在动手之前我对之 ...

  2. 【如何快速的开发一个完整的iOS直播app】(美颜篇)

    原文转自:袁峥Seemygo    感谢分享.自我学习 前言 在看这篇之前,如果您还不了解直播原理,请查看这篇文章如何快速的开发一个完整的iOS直播app(原理篇) 开发一款直播app,美颜功能是很重 ...

  3. 【如何快速的开发一个完整的iOS直播app】(采集篇)

    原文转自:袁峥Seemygo    感谢分享.自我学习 前言 在看这篇之前,如果您还不了解直播原理,请查看这篇文章如何快速的开发一个完整的iOS直播app(原理篇) 开发一款直播app,首先需要采集主 ...

  4. 【如何快速的开发一个完整的iOS直播app】(播放篇)

    原文转自:袁峥Seemygo    感谢分享.自我学习 前言 在看这篇之前,如果您还不了解直播原理,请查看上篇文章如何快速的开发一个完整的iOS直播app(原理篇) 开发一款直播app,集成ijkpl ...

  5. 【如何快速的开发一个完整的iOS直播app】(原理篇)

    原文转自:袁峥Seemygo    感谢分享.自我学习 目录 [如何快速的开发一个完整的iOS直播app](原理篇) [如何快速的开发一个完整的iOS直播app](播放篇) [如何快速的开发一个完整的 ...

  6. 一个完整的Http请求

    一个完整的http请求,通常有以下7点: 1.建立tcp连接 2.web浏览器web服务器发送请求命令 3.web浏览器发送请求头信息 4.web服务器应答 5.web服务器发送应答信息 6.web服 ...

  7. Django1.8教程——从零开始搭建一个完整django博客(一)

    第一个Django项目将是一个完整的博客网站.它和我们博客园使用的博客别无二致,一样有分类.标签.归档.查询等功能.如果你对Django感兴趣的话,这是一个绝好的机会.该教程将和你一起,从零开始,搭建 ...

  8. 第三十六课:如何书写一个完整的ajax模块

    本课主要教大家如何书写一个完整的ajax模块,讲解的代码主要跟ajax有关,而jQuery的ajax模块添加了Deferred异步编程的机制,因此对ajax的理解难度增大,还是忽略掉.但是我要讲解的代 ...

  9. 【如何快速的开发一个完整的iOS直播app】(推流篇)

    前言 在看这篇之前,如果您还不了解直播原理,请查看这篇文章如何快速的开发一个完整的iOS直播app(原理篇) 开发一款直播app,肯定需要流媒体服务器,本篇主要讲解直播中流媒体服务器搭建,并且讲解了如 ...

随机推荐

  1. 【CS Round #44 (Div. 2 only) D】Count Squares

    [链接]点击打开链接 [题意] 给你一个0..n和0..m的区域. 你可以选定其中的4个点,然后组成一个正方形. 问你可以圈出多少个正方形. (正方形的边不一定和坐标轴平行) [题解] 首先,考虑只和 ...

  2. C#正则表达式匹配HTML中的图片路径,图片地址

    C#正则表达式匹配HTML中的图片路径,图片地址 最近的项目中有个关于网页取图的功能需要我自己开发,那就是用正则表达式来匹配图片标签.       一般来说一个 HTML 文档有很多标签,比如“< ...

  3. HttpWatch--简介及使用技巧

    一 概述: HttpWatch强大的网页数据分析工具.集成在Internet Explorer工具栏.包括网页摘要.Cookies管理.缓存管理.消息头发送/接受.字符查询.POST 数据和目录管理功 ...

  4. 51NOD——N 1107 斜率小于0的连线数量

    https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1107 基准时间限制:1 秒 空间限制:131072 KB 分值: 40 ...

  5. 深入理解线程本地变量ThreadLocal

    ThreadLocal理解: 假设在多线程并发环境中.一个可变对象涉及到共享与竞争,那么该可变对象就一定会涉及到线程间同步操作,这是多线程并发问题. 否则该可变对象将作为线程私有对象,可通过Threa ...

  6. 短网址ShortUrl的算法

    场景: 我们在新浪微博上公布网址的时候.微博会自己主动判别网址.并将其转换.比如:http://t.cn/hrYnr0. 为什么要这样做的,原因我想有这样几点: 1.微博限制字数为140字一条,那么假 ...

  7. [React] Style a React component with styled-components

    In this lesson, we remove the mapping between a React component and the styles applied to it via cla ...

  8. wepy小程序实现列表分页上拉加载(1)

    使用wepy开发微信小程序商城第一篇:项目初始化 使用wepy开发微信小程序商城第二篇:路由配置和页面结构 列表页效果图: 1.新建列表页 (1)在pages里面新建一个list.wpy文件 初始代码 ...

  9. POJ 1270 Following Orders 拓扑排序

    http://poj.org/problem?id=1270 题目大意: 给你一串序列,然后再给你他们部分的大小,要求你输出他们从小到大的所有排列. 如a b f g 然后 a<b ,b< ...

  10. (转)curl 命令使用

    原文地址:http://blog.sina.com.cn/s/blog_4b9eab320100slyw.html 可以看作命令行浏览器 1.开启gzip请求curl -I http://www.si ...