分类存档: erlang

webtool允许远程访问

webtool:start().启动后,无法远程访问,查看

start(Path,Data)->{ok,Pid}|{stop,Reason}

Types:
Path = string() | standard_path
Data = [Port,Address,Name] | PortNumber | standard_data
Port = {port,PortNumber}
Address = {bind_address,IpNumber}
Name = {server_name,ServerName}
PortNumber = integer()
IpNumber = tuple(), e.g. {127,0,0,1}
ServerName = string()
Pid = pid()

Use this function to start WebTool if the default port, ip-number,servername or path can not be used.

Path is the directory where the mime.types file and WebTool's own HTML files are located. By default this is webtool-<vsn>/priv, and in most cases there is no need to change this. If Path is set to standard_path the default will be used.

If Data is set to PortNumber, the default data will be used for ip-number (127.0.0.1) and server name (localhost).

需要设置bind_address为 0,0,0,0才能远程访问。

启动方式如下:

webtool:start(standard_path,[{port,8888},{bind_address,{0,0,0,0}},{server_name,”server”}]).

第一个erlang application

1、创建目录结构 doc、ebin、include、priv、src

2、在ebin下创建应用描述文件,这里应用取名为 first_app,则创建的描述文件为first_app.app

{application, first_app,
  [{description,  "hello world,first app"},
   {id,           "first_app"},
   {vsn,          "0.1.0"},
   {modules,      [
                        first_app,
                        first_app_sup
                        ]},
   {registered,   "first_app_sup"},
   {applications, [kernel,stdlib]},
   {mod,          {first_app,[]}},
   {start_phases, []}
  ]
}.

3、下面编写 src/first_app.erl,此文件的唯一任务就是启动根监督者。

-module(first_app).

-behaviour(application).

-export([start/2,stop/1]).

start(_StartType,_StartArgs)->
        case first_app_sup:start_link() of
                {ok,Pid} -> {ok,Pid};
                Other    -> {error,Other}
        end.

stop(_State)->
        ok.

4、实现监督者 src/first_app_sup.erl

-module(first_app_sup).

-behaviour(supervisor).

-export([start_link/0,start_child/2]).

-export([init/1]).

-define(SERVER,?MODULE).
start_link()->
        supervisor:start_link({local,?SERVER},?MODULE,[]).

start_child(Value,LeaseTime)->
        supervisor:start_child(?SERVER,[Value,LeaseTime]).

init([])->
        Element={
                first_app_tcp_listener,
                        {first_app_tcp_listener,start_link,[]},
                        permanent,10000,worker,
                        [first_app_tcp_listener]
                },
        Children=[Element],
        RestartStrategy={simple_one_for_one,0,1},
        {ok,{RestartStrategy,Children}}.

5、尝试运行:

先编译为beam

erlc -o ebin src/*.erl

再运行。

在erl中输入

application:start(first_app).

注意:simple_one_for_one需要手动去调用start_child才会产生子进程。

一篇nosql内存数据库的文章

http://www.csdn.net/article/2013-04-11/2814850-877000-tps-with-erlang-and-voltdb

1、voltdb安装很简单,解压即可。

在官网上提到有几点影响性能的系统设置:

http://voltdb.com/docs/EnterpriseReleaseNotes/

 

1.1. Disable Swapping
Swapping is an operating system feature that optimizes memory usage when running multiple processes. However, memory is a critical component of the VoltDB server process. Any contention for memory, including swapping, will have a very negative impact on performance and functionality.

We recommend using dedicated servers and disabling swapping when running the VoltDB database server process. Use the swapoff command to disable swapping on Linux systems. If swapping cannot be disabled for any reason, you can reduce the likelihood of VoltDB being swapped out by setting the kernel parameter vm.swappiness to zero.

1.2. Turn off TCP segmentation offload and generic receive offload if cluster stability is a problem.
There is an issue where, under certain conditions, the use of TCP segmentation offload (TSO) and generic receive offload (GRO) can cause nodes to randomly drop out of a cluster. The symptoms of this problem are that nodes timeout — that is, the rest of the cluster thinks they have failed — although the node is still running and no other network issues (such as a network partition) are the cause.

Disabling TSO and GRO is recommended for any VoltDB clusters that experience such instability. The commands to disable offloading are the following, where N is replaced by the number of the ethernet card:

ethtool -K eth<span class="emphasis"><em>N</em></span> tso off
ethtool -K eth<span class="emphasis"><em>N</em></span> gro off

Note that these commands disable offloading temporarily. You must issue these commands every time the node reboots.

 

 

1.2. Turn off TCP segmentation offload and generic receive offload if cluster stability is a problem.
There is an issue where, under certain conditions, the use of TCP segmentation offload (TSO) and generic receive offload (GRO) can cause nodes to randomly drop out of a cluster. The symptoms of this problem are that nodes timeout — that is, the rest of the cluster thinks they have failed — although the node is still running and no other network issues (such as a network partition) are the cause.

Disabling TSO and GRO is recommended for any VoltDB clusters that experience such instability. The commands to disable offloading are the following, where N is replaced by the number of the ethernet card:

ethtool -K eth<span class="emphasis"><em>N</em></span> tso off
ethtool -K eth<span class="emphasis"><em>N</em></span> gro off

Note that these commands disable offloading temporarily. You must issue these commands every time the node reboots.

erlang gen_server 模版

今天终于理解了gen_server行为模式。

这里放一个模版,以方便自己使用:

-module(test8).

-behaviour(gen_server).

-export([start_link/0,stop_link/0]).

-export([init/1,handle_call/3,handle_cast/2,handle_info/2,terminate/2,code_change/3]).

-define(SERVER,?MODULE).

%% 不知道这个state的作用是什么
-record(state,{}).
%% 给外面调用的。

%%% ----------------------------------------------
%%% 公开的API
%%% 
%%% ----------------------------------------------

start_link()->
        gen_server:start_link({local,?SERVER},?MODULE,[],[]).
stop_link()->
        gen_server:cast(?SERVER,stop).

%%% ---------------------------------------------
%%% 私有函数
%%% ---------------------------------------------

%%% -------------------------------------------
%%% 以下是回调函数
%%% -------------------------------------------

%% Result = {ok,State} | {ok,State,Timeout} | {ok,State,hibernate}
%% | {stop,Reason} | ignore
%% 这里设置timeout为0,根据<<erlang并发编程>>描述,可以让init/1尽快结束,是一个众所周知的技巧。
init([])->
        {ok,#state{},0}.

%% Result = {reply,Reply,NewState} | {reply,Reply,NewState,Timeout}
%%  | {reply,Reply,NewState,hibernate}
%%  | {noreply,NewState} | {noreply,NewState,Timeout}
%%  | {noreply,NewState,hibernate}
%%  | {stop,Reason,Reply,NewState} | {stop,Reason,NewState}
handle_call(Request,From,State)->
        Reply=ok,
        {reply,Reply,State}.

%% Result = {noreply,NewState} | {noreply,NewState,Timeout}
%%  | {noreply,NewState,hibernate}
%%  | {stop,Reason,NewState}
handle_cast(Request,State)->
        case Request of
                stop    -> {stop,normal,State};
                _       -> {noreplay,State}
        end.

%% Result = {noreply,NewState} | {noreply,NewState,Timeout}
%%  | {noreply,NewState,hibernate}
%%  | {stop,Reason,NewState}
handle_info(Info,State)->
        {noreply,State}.
terminate(Reason,State)->
        io:format("server is stopped"),
        ok.
code_change(OldVsn,State,Extra)->
        {ok,State}.

erlang蜗牛学习中(六)

有几多日未写erlang学习代码了。

前一段时间主要做了项目的优化,有几点效果挺不错,这里略提一下。

io很耗时,日志通过udp远程写到其它服务器上,会大量减少cpu的消耗。

nosql概念在游戏开中很合适,使用json或protobuf直接存储在key-value数据库中非常方便,采用后基本上无需任何持久层的工作量。而且nosql的设计方式对某些特定场景的处理可大幅提高性能,比如:以前查询玩家的信件,直接使用sql查询,需要查询整张表,采用nosql的设计方式,在玩家中存储一个数组,里面是信件的id,可以直接根据id去查询数据。

好了,来看erlang test7

-module(test7).

-export([start/0]).

start()->
        {ok,ListenSocket} = gen_tcp:listen(8889,[binary,{packet,2},{reuseaddr,true},{active,true}]),
        listen_tcp(ListenSocket),
        gen_tcp:close(ListenSocket),
        io:format("start end.").

listen_tcp(ListenSocket)->
        {ok,Socket}=gen_tcp:accept(ListenSocket),
        spawn_link(fun()-> socket_rec(Socket) end),
        listen_tcp(ListenSocket).

socket_rec(Socket)->
        receive
                {tcp,Socket,Data}->
                        io:format("receive data ~n"),
                        socket_rec(Socket);
                {tcp_closed,Socket}->
                        io:format("tcp_closed ~n"),
                        gen_tcp:close(Socket);
                {tcp_error,Socket,Reason}->
                        io:format("tcp_error ~n"),
                        gen_tcp:close(Socket) 

        end.

test7,打开一个socket监听端口,然后开启一个线程去处理接收数据。

好了,继续测试半主动式:接一个包,设置socket为不接收状态,然后处理完包后,再继续读取数据包。

如果开启了新的线程来接收数据。别忘记调用:

controlling_process(Socket, Pid) -> ok | {error, Reason}

Types:

Socket = socket()
Pid = pid()
Reason = closed | not_owner | inet:posix()

 

Assigns a new controlling process Pid to Socket. The controlling process is the process which receives messages from the socket. If called by any other process than the current controlling process, {error, not_owner} is returned.

他的作用是把一个新的线程和这个socket绑定,这样新线程可以接收到socket的数据。

也让我困惑了两天为什么接收不到数据。

erlang工具

1、https://github.com/beamspirit/bigwig

erlang蜗牛学习中(五)

非阻塞tcp学习:

参考以下文档:

http://www.trapexit.org/Building_a_Non-blocking_TCP_server_using_OTP_principles

erlang蜗牛学习中(四)

socket,主动模式

被动模式,需要server调用recv时才读取数据。

主动模式,server使用receive来接收消息。

-module(test4).

-export([ttt/0]).

ttt()->
        {ok,Listen}=gen_tcp:listen(8888,[{packet,0},{active,true}]),
        {ok,Socket}=gen_tcp:accept(Listen),
        gen_tcp:close(Listen),
        loop(Socket).

loop(Socket)->
        receive
                {tcp,Socket,Bin} ->
                        io:format("hello tcp,~p~n",[Bin]),
                        loop(Socket);
                {tcp_closed,Socket}->
                        io:format("hello tcp_closed~n")
        end.

erlang蜗牛学习中(三)

test3.erl

理清楚了gen_server和gen_tcp之间的关系。

gen_server仅仅是一个通用模型。如果编写socket,还是需要gen_tcp。

gen_server不仅仅处理c/s,而且module之间也可以使用gen_server来进行交互处理。

 

-module(test3).

-export([ttt/0]).

ttt()->
        start_server().

start_server()->
        {ok,ListenSocket}= gen_tcp:listen(8888,[{packet,0},{active,false}]),
        {ok,Socket}=gen_tcp:accept(ListenSocket),
        {ok,_Bin}=loop(Socket,[]),
        gen_tcp:close(Socket),
        io:format("~p~n",[_Bin]).
loop(Socket,Bs)->
        case gen_tcp:recv(Socket,0) of
                {ok,Packet}->
                        io:format("ok read~p~n",[Packet]),
                        loop(Socket,[Bs,Packet]);
                {error,closed}->
                        io:format("error closed~n"),
                        {ok,Bs};
                {erorr,_Reason}->
                        io:format("error Reason~n"),
                        {ok,Bs}

        end.

erlang蜗牛学习中(二)

test2.erl

-module(test2).

-export([ttt/0]).

ttt()->
inets:start(),
case httpc:request(“http://www.baidu.com”) of
{ok,_Result}->
io:format(“hello ok”);
{error,_Reason}->
io:format(“hello error”)
end.

了解了用case来进行返回值不同的匹配。