рднрд╛рдЧ 1рднрд╛рдЧ рейрднрд╛рдЧ 1 рдореЗрдВ, рд╣рдордиреЗ рдПрдХ (рдереЛрдбрд╝рд╛ рдмреЗрдХрд╛рд░) mochiweb рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдмрдирд╛рдпрд╛ рдЬреЛ рд╣рд░ 10 рд╕реЗрдХрдВрдб рдореЗрдВ рдЧреНрд░рд╛рд╣рдХреЛрдВ рдХреЛ рдПрдХ рд╕рдВрджреЗрд╢ рднреЗрдЬрддрд╛ рд╣реИред рд╣рдордиреЗ рд▓рд┐рдирдХреНрд╕ рдХрд░реНрдиреЗрд▓ рдХреА рд╕реНрдерд╛рдкрдирд╛ рдХреА, рдФрд░ рдореЗрдореЛрд░реА рдЙрдкрдпреЛрдЧ рдХреА рдЬрд╛рдВрдЪ рдХреЗ рд▓рд┐рдП рдХрдИ рдХрдиреЗрдХреНрд╢рди рд╕реНрдерд╛рдкрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдЙрдкрдХрд░рдг рдмрдирд╛рдпрд╛ред рд╣рдореЗрдВ рдкрддрд╛ рдЪрд▓рд╛ рдХрд┐ рдкреНрд░рддреНрдпреЗрдХ рдХрдиреЗрдХреНрд╢рди рдХреЗ рд▓рд┐рдП рд▓рдЧрднрдЧ 45 Kb рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИред
рднрд╛рдЧ 2 рдореЗрдВ, рд╣рдо рдЕрдкрдиреЗ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЛ рдХреБрдЫ рдЙрдкрдпреЛрдЧреА рдореЗрдВ рдмрджрд▓ рджреЗрдВрдЧреЗ, рдФрд░ рдореЗрдореЛрд░реА рдХреА рдЦрдкрдд рдХреЛ рдХрдо рдХрд░реЗрдВрдЧреЗ:
тАв рд▓реЙрдЧрд┐рди / рд▓реЙрдЧрдЖрдЙрдЯ / рдПрдкреАрдЖрдИ рднреЗрдЬрдиреЗ рдХреЗ рд╕рд╛рде рдПрдХ рд╕рдВрджреЗрд╢ рд░рд╛рдЙрдЯрд░ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдирд╛;
тАв рд░рд╛рдЙрдЯрд░ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдореЛрдЪреАрд╡реЗрдм рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдЕрдкрдбреЗрдЯ рдХрд░реЗрдВ;
тАв рд╡рд┐рддрд░рд┐рдд рдПрд░реНрдЧреИрдВрдЧ рд╕рд┐рд╕реНрдЯрдо рдХреЛ рд╕реНрдерд╛рдкрд┐рдд рдХрд░рдирд╛, рдЗрд╕рд▓рд┐рдП рд╣рдо рд╡рд┐рднрд┐рдиреНрди рдиреЛрдбреНрд╕ рдкрд░ рд░рд╛рдЙрдЯрд░ рдЪрд▓рд╛ рд╕рдХрддреЗ рд╣реИрдВ;
тАв рдмрдбрд╝реА рд╕рдВрдЦреНрдпрд╛ рдореЗрдВ рд╕рдВрджреЗрд╢реЛрдВ рдХреЗ рд╕рд╛рде рд░рд╛рдЙрдЯрд░ рдкрд░реАрдХреНрд╖рдг рдЙрдкрдХрд░рдг рдмрдирд╛рдирд╛;
тАв рдореЗрдореЛрд░реА рдХреЛ рдмрдЪрд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдореЛрдЪреАрд╡рдм рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЛ рдЕрдиреБрдХреВрд▓рд┐рдд рдХрд░рддреЗ рд╣реБрдП, 24 рдШрдВрдЯреЗ рдХреЗ рд▓рд┐рдП рдореЗрдореЛрд░реА рдЙрдкрдпреЛрдЧ рдХреЛ рд╢реЗрдбреНрдпреВрд▓ рдХрд░реЗрдВред
рдЗрд╕рдХрд╛ рдорддрд▓рдм рд╣реИ рдХрд┐ рд╣рдо рд╕рдВрджреЗрд╢ рд╡рд┐рддрд░рдг рддрд░реНрдХ рдФрд░ рдореЛрдЪреАрд╡реЗрдм рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЛ рдЕрд▓рдЧ рдХрд░ рджреЗрдВрдЧреЗред рднрд╛рдЧ 1 рд╕реЗ рдмрд╛рдврд╝ рдХреА рдЙрдкрдпреЛрдЧрд┐рддрд╛ рдХреЗ рд╕рд╛рде рдорд┐рд▓рдХрд░, рд╣рдо рдФрджреНрдпреЛрдЧрд┐рдХ рдХреЗ рдХрд░реАрдм рд╕реНрдерд┐рддрд┐рдпреЛрдВ рдореЗрдВ рдЖрд╡реЗрджрди рдХреЗ рд╕рдВрдЪрд╛рд▓рди рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред
рд╕рдВрджреЗрд╢ рд░рд╛рдЙрдЯрд░ рд▓рд╛рдЧреВ рдХрд░рдирд╛
рд░рд╛рдЙрдЯрд░ API рдореЗрдВ рдХреЗрд╡рд▓ 3 рдлрд╝рдВрдХреНрд╢рди рд╣реЛрддреЗ рд╣реИрдВ:
тАв рд▓реЙрдЧрд┐рди (рдЖрдИрдбреА, рдкреАрдЖрдИрдбреА) рд╕рдВрджреЗрд╢ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХреЛ рдкрдВрдЬреАрдХреГрдд рдХрд░рддрд╛ рд╣реИ;
тАв рд▓реЙрдЧрдЖрдЙрдЯ (рдкреАрдЖрдИрдбреА) рд╕рдВрджреЗрд╢ рдкреНрд░рд╛рдкреНрдд рдХрд░рдирд╛ рдмрдВрдж рдХрд░ рджреЗрддрд╛ рд╣реИ;
тАв рднреЗрдЬреЗрдВ (Id, Msg) рдХреНрд▓рд╛рдЗрдВрдЯ рдХреЛ рд╕рдВрджреЗрд╢ рднреЗрдЬрддрд╛ рд╣реИред
рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рдПрдХ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХреЗ рд▓рд┐рдП рдЕрд▓рдЧ-рдЕрд▓рдЧ рдЖрдИрдбреА рд╕реЗ рд▓реЙрдЧ рдЗрди рдХрд░рдирд╛ рд╕рдВрднрд╡ рд╣реИред
рдпрд╣ рдЙрджрд╛рд╣рд░рдг рд░рд╛рдЙрдЯрд░ рдореЙрдбреНрдпреВрд▓ Pids рдФрд░ Ids рдХреЗ рдмреАрдЪ рджреНрд╡рд┐рджрд┐рд╢ рдирдХреНрд╢реЗ рдХреЛ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП 2 ets рддрд╛рд▓рд┐рдХрд╛рдУрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИред (#state рдкреНрд░рд╡рд┐рд╖реНрдЯрд┐ рдореЗрдВ pid2id рдФрд░ id2pid):
-module(router). -behaviour(gen_server). -export([start_link/0]). -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). -export([send/2, login/2, logout/1]). -define(SERVER, global:whereis_name(?MODULE)). % will hold bidirectional mapping between id <тАУ> pid -record(state, {pid2id, id2pid}). start_link() -> gen_server:start_link({global, ?MODULE}, ?MODULE, [], []). % sends Msg to anyone logged in as Id send(Id, Msg) -> gen_server:call(?SERVER, {send, Id, Msg}). login(Id, Pid) when is_pid(Pid) -> gen_server:call(?SERVER, {login, Id, Pid}). logout(Pid) when is_pid(Pid) -> gen_server:call(?SERVER, {logout, Pid}). init([]) -> % set this so we can catch death of logged in pids: process_flag(trap_exit, true), % use ets for routing tables {ok, #state{ pid2id = ets:new(?MODULE, [bag]), id2pid = ets:new(?MODULE, [bag]) } }. handle_call({login, Id, Pid}, _From, State) when is_pid(Pid) -> ets:insert(State#state.pid2id, {Pid, Id}), ets:insert(State#state.id2pid, {Id, Pid}), link(Pid), % tell us if they exit, so we can log them out io:format("~w logged in as ~w\n",[Pid, Id]), {reply, ok, State}; handle_call({logout, Pid}, _From, State) when is_pid(Pid) -> unlink(Pid), PidRows = ets:lookup(State#state.pid2id, Pid), case PidRows of [] -> ok; _ -> IdRows = [ {I,P} || {P,I} <- PidRows ], % invert tuples % delete all pid->id entries ets:delete(State#state.pid2id, Pid), % and all id->pid [ ets:delete_object(State#state.id2pid, Obj) || Obj <- IdRows ] end, io:format("pid ~w logged out\n",[Pid]), {reply, ok, State}; handle_call({send, Id, Msg}, _From, State) -> % get pids who are logged in as this Id Pids = [ P || { _Id, P } <- ets:lookup(State#state.id2pid, Id) ], % send Msg to them all M = {router_msg, Msg}, [ Pid ! M || Pid <- Pids ], {reply, ok, State}. % handle death and cleanup of logged in processes handle_info(Info, State) -> case Info of {'EXIT', Pid, _Why} -> % force logout: handle_call({logout, Pid}, blah, State); Wtf -> io:format("Caught unhandled message: ~w\n", [Wtf]) end, {noreply, State}. handle_cast(_Msg, State) -> {noreply, State}. terminate(_Reason, _State) -> ok. code_change(_OldVsn, State, _Extra) -> {ok, State}.
Mochiweb рдЖрд╡реЗрджрди рдЕрджреНрдпрддрди
рдорд╛рди рд▓реЗрддреЗ рд╣реИрдВ рдХрд┐ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ URL рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рдПрдХ рдкреВрд░реНрдгрд╛рдВрдХ рдЖрдИрдбреА рджреНрд╡рд╛рд░рд╛ рджрд░реНрд╢рд╛рдпрд╛ рдЧрдпрд╛ рд╣реИ, рдЬрд┐рд╕рдХреЗ рд╕рд╛рде рдпрд╣ mochiweb рд╕реЗ рдЬреБрдбрд╝рддрд╛ рд╣реИ рдФрд░ рдЗрд╕ рдкрд╣рдЪрд╛рдирдХрд░реНрддрд╛ рдХреЛ рд╕рдВрджреЗрд╢ рд░рд╛рдЙрдЯрд░ рдХреЗ рд╕рд╛рде рдкрдВрдЬреАрдХреГрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИред рд╣рд░ 10 рд╕реЗрдХрдВрдб рдореЗрдВ рдЕрд╡рд░реБрджреНрдз рд╣реЛрдиреЗ рдХреЗ рдмрдЬрд╛рдп, рд░рд╛рдЙрдЗрдХреЗ рд╕реЗ рд╕рдВрджреЗрд╢ рдкреНрд░рд╛рдкреНрдд рд╣реЛрдиреЗ рдкрд░ рдореЛрдЪреАрд╡реЗрдм рдЕрд╡рд░реБрджреНрдз рд╣реЛ рдЬрд╛рддрд╛ рд╣реИ, рдФрд░ рдХреНрд▓рд╛рдЗрдВрдЯ рдХреЛ рд╣рд░ рдЕрдиреБрд░реЛрдз рдХреЗ рд▓рд┐рдП рдПрдХ HTTP рд╕рдВрджреЗрд╢ рднреЗрдЬрддрд╛ рд╣реИ рдЬреЛ рд░рд╛рдЙрдЯрд░ рдЗрд╕реЗ рднреЗрдЬрддрд╛ рд╣реИ:
тАв рдХреНрд▓рд╛рдЗрдВрдЯ
http: // localhost: 8000 / test / 123 рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ mochiweb рд╕реЗ рдЬреБрдбрд╝рддрд╛ рд╣реИ;
тАв Mochiweb рдЖрд╡реЗрджрди рд╕рдВрджреЗрд╢ рд░рд╛рдЙрдЯрд░ рдореЗрдВ рдкрд╣рдЪрд╛рдирдХрд░реНрддрд╛ '123' рдХреЗ рд╕рд╛рде рдЗрд╕ рд╕рдВрдмрдВрдз рдХреЗ рд▓рд┐рдП рдкрд┐рдб рдкрдВрдЬреАрдХреГрдд рдХрд░рддрд╛ рд╣реИ;
тАв рдпрджрд┐ рдЖрдк '123' рдкрддреЗ рдкрд░ рд░рд╛рдЙрдЯрд░ рдХреЗ рд▓рд┐рдП рдПрдХ рд╕рдВрджреЗрд╢ рднреЗрдЬрддреЗ рд╣реИрдВ, рддреЛ рдЗрд╕реЗ рд╕рд╣реА рдореЛрдЪреАрд╡рдм рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдореЗрдВ рднреЗрдЬрд╛ рдЬрд╛рдПрдЧрд╛ рдФрд░ рдЗрд╕ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЗ рд▓рд┐рдП рдмреНрд░рд╛рдЙрдЬрд╝рд░ рдореЗрдВ рджрд┐рдЦрд╛рдИ рджреЗрдЧрд╛ред
рдпрд╣рд╛рдБ mochiconntest_web.erl рдХрд╛ рдЕрджреНрдпрддрди рд╕рдВрд╕реНрдХрд░рдг рд╣реИ:
-module(mochiconntest_web). -export([start/1, stop/0, loop/2]). %% External API start(Options) -> {DocRoot, Options1} = get_option(docroot, Options), Loop = fun (Req) -> ?MODULE:loop(Req, DocRoot) end, % we'll set our maximum to 1 million connections. (default: 2048) mochiweb_http:start([{max, 1000000}, {name, ?MODULE}, {loop, Loop} | Options1]). stop() -> mochiweb_http:stop(?MODULE). loop(Req, DocRoot) -> "/" ++ Path = Req:get(path), case Req:get(method) of Method when Method =:= 'GET'; Method =:= 'HEAD' -> case Path of "test/" ++ Id -> Response = Req:ok({"text/html; charset=utf-8", [{"Server","Mochiweb-Test"}], chunked}), % login using an integer rather than a string {IdInt, _} = string:to_integer(Id), router:login(IdInt, self()), feed(Response, IdInt, 1); _ -> Req:not_found() end; 'POST' -> case Path of _ -> Req:not_found() end; _ -> Req:respond({501, [], []}) end. feed(Response, Id, N) -> receive {router_msg, Msg} -> Html = io_lib:format("Recvd msg #~w: '~s'", [N, Msg]), Response:write_chunk(Html) end, feed(Response, Id, N+1). %% Internal API get_option(Option, Options) -> {proplists:get_value(Option, Options), proplists:delete(Option, Options)}.
рдпрд╣ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ!
рдЕрдм рдЪрд▓реЛ рд╕рдм рдХреБрдЫ рдХреНрд░рдо рдореЗрдВ рдХрд░рддреЗ рд╣реИрдВ - рд╣рдо 2 рдПрд░реНрдЧреИрдВрдЧ рд╢реЗрд▓ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗ, рдПрдХ рдореЛрдЪреАрд╡реЗрдм рдХреЗ рд▓рд┐рдП рдФрд░ рдПрдХ рд░рд╛рдЙрдЯрд░ рдХреЗ рд▓рд┐рдПред рд╕рдВрд╢реЛрдзрд┐рдд рдХрд░реЗрдВ-dev.sh рдХрд╛ рдЙрдкрдпреЛрдЧ mochiweb рд╢реБрд░реВ рдХрд░рдиреЗ рдФрд░ erl рдореЗрдВ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдЕрддрд┐рд░рд┐рдХреНрдд рдкреИрд░рд╛рдореАрдЯрд░ рдЬреЛрдбрд╝рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ:
тАв -sname n1 рдХрд╛ рдирд╛рдо erlang рдиреЛрдб 'n1'
тАв рдХрд░реНрдиреЗрд▓-рдкреЛрд▓ рдХреЛ рд╕рдХреНрд╖рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП + K рд╕рддреНрдпред
тАв + рдкреА 134217727 - рдЕрдзрд┐рдХрддрдо рдкреНрд░рдХреНрд░рд┐рдпрд╛рдУрдВ рдХреА рд╕рдВрдЦреНрдпрд╛ рдЬреЛ рдЖрдк рд╕реНрдкреЙрди рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рд╡рд╣ 32768 рд╣реИред рд╣рдореЗрдВ рдкреНрд░рддреНрдпреЗрдХ рдХрдиреЗрдХреНрд╢рди рдХреЗ рд▓рд┐рдП рдПрдХ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдореБрдЭреЗ рдирд╣реАрдВ рдкрддрд╛ рд╣реИ рдХрд┐ рд╡рд┐рд╢реЗрд╖ рд░реВрдк рд╕реЗ рдЗрд╕рдХреА рдХрд┐рддрдиреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрдЧреАред 134 217 727 - "рдореИрди рдПрд░реНрд▓" рдХреЗ рдЕрдиреБрд╕рд╛рд░ рдЕрдзрд┐рдХрддрдо рдореВрд▓реНрдпред
рдЕрдм do &&//start-dev.sh рдХрд░реЗрдВ рдФрд░ рдЖрдкрдХреЛ рдПрдХ рдЧреНрд░реАрдЯрд┐рдВрдЧ рджреЗрдЦрдирд╛ рдЪрд╛рд╣рд┐рдП: (n1 @ localhost) 1> - рдЕрдм рдЖрдкрдХрд╛ рдореЛрдЪреАрд╡реЗрдм рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ, рдФрд░ рдПрд░рд▓рд╛рдВрдЧ рдиреЛрдб рдХрд╛ рдПрдХ рдирд╛рдо рд╣реИред
рдЕрдм рдПрдХ рдФрд░ erangang рдЦреЛрд▓ рдЪрд▓рд╛рдПрдБ:
erl -sname n2
рдлрд┐рд▓рд╣рд╛рд▓, рдЙрди рджреЛ erangang рдиреЛрдбреНрд╕ рдХреЛ рдПрдХ рджреВрд╕рд░реЗ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдкрддрд╛ рдирд╣реАрдВ рд╣реИ, рдЗрд╕реЗ рдареАрдХ рдХрд░реЗрдВ:
(n2@localhost)1> nodes(). [] (n2@localhost)2> net_adm:ping(n1@localhost). pong (n2@localhost)3> nodes(). [n1@localhost]
рдЕрдм рд╕рдВрдХрд▓рд┐рдд рдХрд░реЗрдВ рдФрд░ рд░реВрдЯрд░ рд╢реБрд░реВ рдХрд░реЗрдВ:
(n2@localhost)4> c(router). {ok,router} (n2@localhost)5> router:start_link(). {ok,<0.38.0>}
рдЕрдм рдордЬрд╝реЗ рдХреЗ рд▓рд┐рдП, рдЕрдкрдиреЗ рдмреНрд░рд╛рдЙрдЬрд╝рд░ рдореЗрдВ
http: // localhost: 8000 / test / 123 рдЦреЛрд▓реЗрдВ (рдпрд╛ рдХрдВрд╕реЛрд▓ рд╕реЗ lynx --source "
http: // localhost: 8000 / test / 123 " рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВ)ред рдЙрд╕ рд╢реЗрд▓ рдХреА рдЬрд╛рдВрдЪ рдХрд░реЗрдВ рдЬрд┐рд╕рдореЗрдВ рдЖрдкрдиреЗ рд░рд╛рдЙрдЯрд░ рд╢реБрд░реВ рдХрд┐рдпрд╛ рдерд╛, рдЖрдкрдХреЛ рдпрд╣ рджреЗрдЦрдирд╛ рдЪрд╛рд╣рд┐рдП рдХрд┐ рдПрдХ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдиреЗ рд▓реЙрдЧ рдЗрди рдХрд┐рдпрд╛ рд╣реИред
рдЕрдм рдЖрдк рд░рд╛рдЙрдЯрд░ рдХреЛ рд╕рдВрджреЗрд╢ рднреЗрдЬ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ рд╡реЗ рдЖрдкрдХреЗ рдмреНрд░рд╛рдЙрдЬрд╝рд░ рдореЗрдВ рдХреИрд╕реЗ рджрд┐рдЦрд╛рдИ рджреЗрддреЗ рд╣реИрдВред рдЕрднреА рдХреЗ рд▓рд┐рдП, рдХреЗрд╡рд▓ рд╕реНрдЯреНрд░рд┐рдВрдЧреНрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВ рдХреНрдпреЛрдВрдХрд┐ рд╣рдо рдЖрдЙрдЯрдкреБрдЯ рдХреЗ рд▓рд┐рдП ~ s рдкреИрд░рд╛рдореАрдЯрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ, рдФрд░ рдкрд░рдорд╛рдгреБ рдХреЗ рдкрд░рд┐рдгрд╛рдорд╕реНрд╡рд░реВрдк рддреНрд░реБрдЯрд┐ рд╣реЛрдЧреА:
(n2@localhost)6> router:send(123, "Hello World"). (n2@localhost)7> router:send(123, "Why not open another browser window too?"). (n2@localhost)8> router:send(456, "This message will go into the void unless you are connected as /test/456 too").
рдЕрдкрдиреЗ рдмреНрд░рд╛рдЙрдЬрд╝рд░ рдХреА рдЬрд╛рдБрдЪ рдХрд░реЗрдВ, рдЖрдкрдХреЛ рдПрдХ рд╕рдВрджреЗрд╢ рдорд┐рд▓рд╛ рд╣реИ :)
рд╡рд┐рддрд░рд┐рдд рдПрд░реНрдЧреИрдВрдЧ рд╕рд┐рд╕реНрдЯрдо рдХреЛ рдЪрд▓рд╛рдирд╛
рдпрд╣ рд╡рд┐рднрд┐рдиреНрди рдорд╢реАрдиреЛрдВ рдкрд░ рдПрдХ рд░рд╛рдЙрдЯрд░ рдФрд░ рдореЛрдЪреАрд╡реЗрдм рдЪрд▓рд╛рдиреЗ рдХреЗ рд▓рд┐рдП рд╕рдордЭ рдореЗрдВ рдЖрддрд╛ рд╣реИред рдорд╛рди рд▓реЗрдВ рдХрд┐ рдЖрдкрдХреЗ рдкрд╛рд╕ рдкрд░реАрдХреНрд╖рдг рдХреЗ рд▓рд┐рдП рдХрдИ рдЕрддрд┐рд░рд┐рдХреНрдд рдорд╢реАрдиреЗрдВ рд╣реИрдВ, рддреЛ рдЖрдкрдХреЛ рд╡рд┐рддрд░рд┐рдд рдиреЛрдбреНрд╕ рдХреЗ рд░реВрдк рдореЗрдВ erlang рдЧреЛрд▓реЗ рдЪрд▓рд╛рдирд╛ рдЪрд╛рд╣рд┐рдП, рдЕрд░реНрдерд╛рдд, -sname n1 (рдФрд░ n2 рдХреЗ рд▓рд┐рдП рд╕рдорд╛рди) рдХреЗ рдмрдЬрд╛рдп nname@1@host1.example.com рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВред рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░реЗрдВ рдХрд┐ рд╡реЗ рдПрдХ рджреВрд╕рд░реЗ рдХреЛ net_adm: рдкрд┐рдВрдЧ (...) рдХреЗ рд╕рд╛рде рдКрдкрд░ рдХреЗ рдЙрджрд╛рд╣рд░рдг рдореЗрдВ рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВред
рд░рд╛рдЙрдЯрд░.рд░реЗрд▓ рдореЗрдВ рд▓рд╛рдЗрди 16 рдкрд░ рдзреНрдпрд╛рди рджреЗрдВ, рд░рд╛рдЙрдЯрд░ рдкреНрд░рдХреНрд░рд┐рдпрд╛ ('рд░рд╛рдЙрдЯрд░') рдХрд╛ рдирд╛рдо рд╡рд┐рд╢реНрд╡ рд╕реНрддрд░ рдкрд░ рдкрдВрдЬреАрдХреГрдд рд╣реИ, рдпрд╣реА рдХрд╛рд░рдг рд╣реИ рдХрд┐ рд╣рдо рд╡рд┐рддрд░рд┐рдд рдореИрдХреНрд░реЛ рдХреЛ gen_server рдХреЙрд▓реНрд╕ рдореЗрдВ рд░рд╛рдЙрдЯрд░ рдХреЗ рд╕реНрдерд╛рди рдХреА рдкрд╣рдЪрд╛рди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ, рдпрд╣рд╛рдВ рддрдХ тАЛтАЛрдХрд┐ рд╡рд┐рддрд░рд┐рдд рд╕рд┐рд╕реНрдЯрдо рдкрд░ рднреА:
-define(SERVER, global:whereis_name(?MODULE)).
рдПрдХ рд╡рд┐рддрд░рд┐рдд рдкреНрд░рдгрд╛рд▓реА рдореЗрдВ рдкреНрд░рдХреНрд░рд┐рдпрд╛рдУрдВ рдХреЗ рд▓рд┐рдП рдПрдХ рд╡реИрд╢реНрд╡рд┐рдХ рдирд╛рдо рд░рдЬрд┐рд╕реНрдЯреНрд░реА рд╕рд┐рд░реНрдл рдХрдИ рдЪреАрдЬреЛрдВ рдореЗрдВ рд╕реЗ рдПрдХ рд╣реИ рдЬреЛ рдЖрдкрдХреЛ рдЗрд░рд▓рд╛рдВрдЧ рдХреЗ рд╕рд╛рде рдореБрдлреНрдд рдореЗрдВ рдорд┐рд▓рддреА рд╣реИред
рдмрдбрд╝реА рд╕рдВрдЦреНрдпрд╛ рдореЗрдВ рд╕рдВрджреЗрд╢ рдЙрддреНрдкрдиреНрди рдХрд░реЗрдВ
рд╡рд╛рд╕реНрддрд╡рд┐рдХ рдкрд░рд┐рд╡реЗрд╢ рдореЗрдВ, рд╣рдо рдХреБрдЫ рд╕рдХреНрд░рд┐рдп рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛рдУрдВ рдФрд░ рдХрдИ рдирд┐рд╖реНрдХреНрд░рд┐рдп рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛рдУрдВ рдХреЗ рд╕рд╛рде "рд▓рдВрдмреА-рдкреВрдВрдЫ" рдЬреИрд╕рд╛ рдПрдХ рдкреИрдЯрд░реНрди рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВред рд╣рд╛рд▓рд╛рдВрдХрд┐, рдЗрд╕ рдкрд░реАрдХреНрд╖рдг рдХреЗ рд▓рд┐рдП рд╣рдо рдпрд╛рджреГрдЪреНрдЫрд┐рдХ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛рдУрдВ рдХреЛ рдЕрдВрдзрд╛рдзреБрдВрдз рдирдХрд▓реА рд╕рдВрджреЗрд╢ рднреЗрдЬреЗрдВрдЧреЗред
-module(msggen). -export([start/3]). start(0, _, _) -> ok; start(Num, Interval, Max) -> Id = random:uniform(Max), router:send(Id, "Fake message Num = " ++ Num), receive after Interval -> start(Num -1, Interval, Max) end.
рдпрд╣ рдХреЛрдб 1 рдФрд░ рдЕрдзрд┐рдХрддрдо рд╣рд░ рдЗрдВрдЯрд░рд╡рд▓ рдПрдордПрд╕ рдХреЗ рдмреАрдЪ рд░реИрдВрдбрдо рдпреВрдЬрд░ рдЖрдИрдбреА рдХреЛ рдиреНрдпреВ рдореИрд╕реЗрдЬ рднреЗрдЬреЗрдЧрд╛ред
рдпрджрд┐ рдЖрдк рд░рд╛рдЙрдЯрд░ рдФрд░ рдореЛрдЪреАрд╡реЗрдм рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдЪрд▓рд╛рддреЗ рд╣реИрдВ, рддреЛ рдЖрдк рдЗрд╕реЗ рдПрдХреНрд╢рди рдореЗрдВ рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ
: http: // localhost: 8000 / test / 3 рдФрд░ рд░рди рдкрд░ рдЬрд╛рдПрдВ:
erl -sname test (test@localhost)1> net_adm:ping(n1@localhost). pong (test@localhost)2> c(msggen). {ok,msggen} (test@localhost)3> msggen:start(20, 10, 5). ok
20 рд╕рдВрджреЗрд╢ 1 рдФрд░ 5 рдХреЗ рдмреАрдЪ рдпрд╛рджреГрдЪреНрдЫрд┐рдХ рдкрд╣рдЪрд╛рдирдХрд░реНрддрд╛рдУрдВ рдХреЛ рднреЗрдЬреЗ рдЬрд╛рдПрдВрдЧреЗ, рдкреНрд░рддреНрдпреЗрдХ 10 рдПрдордПрд╕, рдПрдХ рд╕рдВрджреЗрд╢ рдкреНрд░рддреНрдпреЗрдХред рд╢рд╛рдпрдж рдЖрдк рднрд╛рдЧреНрдпрд╢рд╛рд▓реА рд╣реИрдВ рдФрд░ рдЖрдкрдХреЛ рдХреБрдЫ рд╕рдВрджреЗрд╢ рдкреНрд░рд╛рдкреНрдд рд╣реЛрдВрдЧреЗред
рд╣рдо рдЙрдирдореЗрдВ рд╕реЗ рдХрдИ рдХреЛ рд╕рдВрджреЗрд╢реЛрдВ рдХреЗ рд▓рд┐рдП рдХрдИ рд╕реНрд░реЛрддреЛрдВ рдХреЗ рд╕рдорд╛рдирд╛рдВрддрд░ рднреА рдЪрд▓рд╛ рд╕рдХрддреЗ рд╣реИрдВред рдпрд╣рд╛рдВ 10 рдкреНрд░рдХреНрд░рд┐рдпрд╛рдУрдВ рдХрд╛ рдПрдХ рдЙрджрд╛рд╣рд░рдг рджрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рдкреНрд░рддреНрдпреЗрдХ рдиреЗ рдкреНрд░рддреНрдпреЗрдХ рд╕рдВрджреЗрд╢ рдХреЗ рдмреАрдЪ 100 рдПрдордПрд╕ рдХреА рджреЗрд░реА рдХреЗ рд╕рд╛рде рдкрд╣рдЪрд╛рдирдХрд░реНрддрд╛рдУрдВ рдХреЛ 20 рд╕рдВрджреЗрд╢ рднреЗрдЬреЗ рд╣реИрдВ:
[ spawn(fun() -> msggen:start(20, 100, 5), io:format("~w finished.\n", [self()]) end) || _ <- lists:seq(1,10) ]. [<0.97.0>,<0.98.0>,<0.99.0>,<0.100.0>,<0.101.0>,<0.102.0>, <0.103.0>,<0.104.0>,<0.105.0>,<0.106.0>] <0.101.0> finished. <0.105.0> finished. <0.106.0> finished. <0.104.0> finished. <0.102.0> finished. <0.98.0> finished. <0.99.0> finished. <0.100.0> finished. <0.103.0> finished. <0.97.0> finished.
C10K
рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рд╡реНрдпрд╛рдкрдХ рдкреИрдорд╛рдиреЗ рдкрд░ рдкрд░реАрдХреНрд╖рдг рдХреЗ рд▓рд┐рдП рд╕рднреА рднрд╛рдЧ рд╣реИрдВ; рдХреНрд▓рд╛рдЗрдВрдЯ рд╣рдорд╛рд░реЗ mochiweb рдПрдкреНрд▓рд┐рдХреЗрд╢рди рд╕реЗ рдЬреБрдбрд╝рддреЗ рд╣реИрдВ, рдЬреЛ рдЙрдиреНрд╣реЗрдВ рдПрдХ рд╕рдВрджреЗрд╢ рд░рд╛рдЙрдЯрд░ рдХреЗ рд╕рд╛рде рдкрдВрдЬреАрдХреГрдд рдХрд░рддрд╛ рд╣реИред рд╣рдо рд░рд╛рдЙрдЯрд░ рдХреЛ рднреЗрдЬрдиреЗ рдХреЗ рд▓рд┐рдП рдирдХрд▓реА рд╕рдВрджреЗрд╢реЛрдВ рдХреА рдПрдХ рдмрдбрд╝реА рдорд╛рддреНрд░рд╛ рдЙрддреНрдкрдиреНрди рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдЬреЛ рдЙрдиреНрд╣реЗрдВ рдХрд┐рд╕реА рднреА рдкрдВрдЬреАрдХреГрдд рдЧреНрд░рд╛рд╣рдХреЛрдВ рдХреЛ рднреЗрдЬреЗрдВрдЧреЗред рдЪрд▓реЛ рднрд╛рдЧ 1 рд╕реЗ рдлрд┐рд░ рд╕реЗ 10,000 рд╕рдорд╡рд░реНрддреА рдХрдиреЗрдХреНрд╢рдиреЛрдВ рдХреА рдЬрд╛рдВрдЪ рдХрд░рддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдЗрд╕ рдмрд╛рд░ рд╣рдо рдЬреБрдбрд╝реЗ рд╣реБрдП рд╕рднреА рдЧреНрд░рд╛рд╣рдХреЛрдВ рдХреЛ рдЫреЛрдбрд╝ рджреЗрдВрдЧреЗ, рдЬрдмрдХрд┐ рд╣рдо рд╕рд┐рд╕реНрдЯрдо рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдмрд╣реБрдд рд╕рд╛рд░реЗ рд╕рдВрджреЗрд╢ рдЪрд▓рд╛рддреЗ рд╣реИрдВред
рдорд╛рди рд▓реАрдЬрд┐рдП рдХрд┐ рдЖрдкрдиреЗ рдЕрдкрдиреЗ рдХрд░реНрдиреЗрд▓ рдЖрджрд┐ рдХреЛ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рднрд╛рдЧ 1 рдореЗрдВ рджрд┐рдП рдЧрдП рдирд┐рд░реНрджреЗрд╢реЛрдВ рдХрд╛ рдкрд╛рд▓рди рдХрд┐рдпрд╛ рд╣реИред рдЖрдкрдХреЗ рдкрд╛рд╕ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдПрдХ рдореЛрдЪреАрд╡реЗрдм рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдФрд░ рд░рд╛рдЙрдЯрд░ рдЪрд▓ рд░рд╣рд╛ рд╣реИ, рддреЛ рдЪрд▓реЛ рдЙрдиреНрд╣реЗрдВ рдФрд░ рдЕрдзрд┐рдХ рдЯреНрд░реИрдлрд╝рд┐рдХ рдореЗрдВ рдбрд╛рд▓ рджреЗрдВред
рдЬреБрдбрд╝реЗ рд╣реБрдП рдЧреНрд░рд╛рд╣рдХреЛрдВ рдХреЗ рдмрд┐рдирд╛, рдореЛрдЪреАрд╡реЗрдм рд▓рдЧрднрдЧ 40 рдПрдордмреА рдореЗрдореЛрд░реА рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИ:
$ ps -o rss= -p `pgrep -f 'sname n1'` 40156
рдореИрдВ рд╕рдордп рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЗрд╕ рдШреГрдгрд┐рдд рдЖрджреЗрд╢ рдХреЗ рд╕рд╛рде рдЖрдпрд╛ рдерд╛, рдореЛрдЪреАрд╡реЗрдм рдЖрд╡реЗрджрди рдХреА рд╡рд░реНрддрдорд╛рди рдореЗрдореЛрд░реА рдЙрдкрдпреЛрдЧ, рдФрд░ рд╣рд░ 60 рд╕реЗрдХрдВрдб рдореЗрдВ рд╕реНрдерд╛рдкрд┐рдд рдХрдиреЗрдХреНрд╢рди рдХреА рд╕рдВрдЦреНрдпрд╛:
$ MOCHIPID=`pgrep -f 'name n1'`; while [ 1 ] ; do NUMCON=`netstat -n | awk '/ESTABLISHED/ && $4=="127.0.0.1:8000"' | wc -l`; MEM=`ps -o rss= -p $MOCHIPID`; echo -e "`date`\t`date +%s`\t$MEM\t$NUMCON"; sleep 60; done | tee -a mochimem.log
рдпрджрд┐ рдХрд┐рд╕реА рдХреЛ рд╕рдордп рдХреЗ рд╕рд╛рде, рдХрд┐рд╕реА рдПрдХ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХреЗ рд▓рд┐рдП рдореЗрдореЛрд░реА рдЙрдкрдпреЛрдЧ рдХреЛ рдЪрд┐рддреНрд░рд┐рдд рдХрд░рдиреЗ рдХрд╛ рд╕рдмрд╕реЗ рдЕрдЪреНрдЫрд╛ рддрд░реАрдХрд╛ рдкрддрд╛ рд╣реИ, рддреЛ рдХреГрдкрдпрд╛ рдПрдХ рдЯрд┐рдкреНрдкрдгреА рдЫреЛрдбрд╝ рджреЗрдВред
рдЕрдм рдирдП erl рд╢реЗрд▓ рдореЗрдВ рднрд╛рдЧ 1 рд╕реЗ рдмрд╛рдврд╝ рдХреЛ рдЪрд▓рд╛рдПрдБ:
erl> floodtest:start("/tmp/mochi-urls.txt", 10). 100 , 10 000 . Stats: {825,0,0} Stats: {1629,0,0} Stats: {2397,0,0} Stats: {3218,0,0} Stats: {4057,0,0} Stats: {4837,0,0} Stats: {5565,0,0} Stats: {6295,0,0} Stats: {7022,0,0} Stats: {7727,0,0} Stats: {8415,0,0} Stats: {9116,0,0} Stats: {9792,0,0} Stats: {10000,0,0} ...
рдореЗрдореЛрд░реА рдЙрдкрдпреЛрдЧ рдХреА рдЬрд╛рдБрдЪ рдХрд░реЗрдВ:
Mon Oct 20 16:57:24 BST 2008 1224518244 40388 1 Mon Oct 20 16:58:25 BST 2008 1224518305 41120 263 Mon Oct 20 16:59:27 BST 2008 1224518367 65252 5267 Mon Oct 20 17:00:32 BST 2008 1224518432 89008 9836 Mon Oct 20 17:01:37 BST 2008 1224518497 90748 10001 Mon Oct 20 17:02:41 BST 2008 1224518561 90964 10001 Mon Oct 20 17:03:46 BST 2008 1224518626 90964 10001 Mon Oct 20 17:04:51 BST 2008 1224518691 90964 10001
10,000 рд╕рдорд╡рд░реНрддреА рдХрдиреЗрдХреНрд╢рди рдкрд╣реБрдВрдЪ рдЧрдП рд╣реИрдВ (рдкреНрд▓рд╕ рдореИрдВ рдлрд╝рд╛рдпрд░рдлрд╝реЙрдХреНрд╕ рдореЗрдВ рдЦреЛрд▓рд╛ рдЧрдпрд╛ рдерд╛), рдФрд░ рдореЛрдЪреАрд╡реЗрдм рдХреА рдореЗрдореЛрд░реА рдЦрдкрдд рд▓рдЧрднрдЧ 90 рдПрдордмреА (90964 KB) рд╣реИред
рдЕрдм рдХреБрдЫ рд╕рдВрджреЗрд╢ рднреЗрдЬреЗрдВ:
erl> [ spawn(fun() -> msggen:start(1000000, 100, 10000) end) || _ <- lists:seq(1,100) ]. [<0.65.0>,<0.66.0>,<0.67.0>,<0.68.0>,<0.69.0>,<0.70.0>, <0.71.0>,<0.72.0>,<0.73.0>,<0.74.0>,<0.75.0>,<0.76.0>, <0.77.0>,<0.78.0>,<0.79.0>,<0.80.0>,<0.81.0>,<0.82.0>, <0.83.0>,<0.84.0>,<0.85.0>,<0.86.0>,<0.87.0>,<0.88.0>, <0.89.0>,<0.90.0>,<0.91.0>,<0.92.0>,<0.93.0>|...]
100 рдкреНрд░рдХреНрд░рд┐рдпрд╛рдПрдВ 1 рд╕реЗ 10,000 рддрдХ рдпрд╛рджреГрдЪреНрдЫрд┐рдХ рдЖрдИрдбреА рдкрд░ 10 рд╕рдВрджреЗрд╢ рдкреНрд░рддрд┐ рд╕реЗрдХрдВрдб рдореЗрдВ рдПрдХ рд▓рд╛рдЦ рд╕рдВрджреЗрд╢ рднреЗрдЬрддреА рд╣реИрдВред рдЗрд╕рдХрд╛ рдорддрд▓рдм рд╣реИ рдХрд┐ рд░рд╛рдЙрдЯрд░ рдкреНрд░рддрд┐ рд╕реЗрдХрдВрдб 1000 рд╕рдВрджреЗрд╢реЛрдВ рдХреЛ рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд░рддрд╛ рд╣реИ, рдФрд░ рдФрд╕рддрди рд╣рдорд╛рд░реЗ рдкреНрд░рддреНрдпреЗрдХ 10 k рдЧреНрд░рд╛рд╣рдХреЛрдВ рдХреЛ рдкреНрд░рддреНрдпреЗрдХ 10 рд╕реЗрдХрдВрдб рдореЗрдВ рдПрдХ рд╕рдВрджреЗрд╢ рдкреНрд░рд╛рдкреНрдд рд╣реЛрдЧрд╛ред
рдмрд╛рдврд╝ рдХреЗ рдЙрддреНрдкрд╛рджрди рдХреА рдЬрд╛рдБрдЪ рдХрд░реЗрдВ, рдФрд░ рдЖрдк рджреЗрдЦреЗрдВрдЧреЗ рдХрд┐ рдЧреНрд░рд╛рд╣рдХреЛрдВ рдХреЛ http рд╕рдВрджреЗрд╢ рдкреНрд░рд╛рдкреНрдд рд╣реЛрддреЗ рд╣реИрдВ (рдпрд╛рдж рд░рдЦреЗрдВ рдХрд┐ рдпреЗ {NumConnected, NumClosed, NumChunksRecvd} рд╣реИрдВ):
... Stats: {10000,0,5912} Stats: {10000,0,15496} Stats: {10000,0,25145} Stats: {10000,0,34755} Stats: {10000,0,44342} ...
рдкреНрд░рддреНрдпреЗрдХ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХреЗ рд▓рд┐рдП 10 рдкреНрд░рддрд┐ рд╕реЗрдХрдВрдб рдХреЗ рдПрдХ рд▓рд╛рдЦ рд╕рдВрджреЗрд╢реЛрдВ рдХреЛ рдХрд╛рдо рдХрд░рдиреЗ рдореЗрдВ 27 рдШрдВрдЯреЗ рд▓рдЧреЗрдВрдЧреЗред рдиреАрдЪреЗ рдкрд╣рд▓реЗ 10 рдорд┐рдирдЯ рдореЗрдВ рдореЗрдореЛрд░реА рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ:
Mon Oct 20 16:57:24 BST 2008 1224518244 40388 1 Mon Oct 20 16:58:25 BST 2008 1224518305 41120 263 Mon Oct 20 16:59:27 BST 2008 1224518367 65252 5267 Mon Oct 20 17:00:32 BST 2008 1224518432 89008 9836 Mon Oct 20 17:01:37 BST 2008 1224518497 90748 10001 Mon Oct 20 17:02:41 BST 2008 1224518561 90964 10001 Mon Oct 20 17:03:46 BST 2008 1224518626 90964 10001 Mon Oct 20 17:04:51 BST 2008 1224518691 90964 10001 Mon Oct 20 17:05:55 BST 2008 1224518755 90980 10001 Mon Oct 20 17:07:00 BST 2008 1224518820 91120 10001 Mon Oct 20 17:08:05 BST 2008 1224518885 98664 10001 Mon Oct 20 17:09:10 BST 2008 1224518950 106752 10001 Mon Oct 20 17:10:15 BST 2008 1224519015 114044 10001 Mon Oct 20 17:11:20 BST 2008 1224519080 119468 10001 Mon Oct 20 17:12:25 BST 2008 1224519145 125360 10001
рдЖрдк рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ рдЖрдХрд╛рд░ рдкрд╣рд▓реЗ рд╣реА 40 рдПрдордмреА рд╕реЗ 90 рдПрдордмреА рддрдХ рдмрдврд╝ рдЧрдпрд╛ рд╣реИ рдЬрдм рд╕рднреА 10 k рдЧреНрд░рд╛рд╣рдХ рдЬреБрдбрд╝реЗ рд╣реБрдП рд╣реИрдВ, рдФрд░ рдХреБрдЫ рд╕рдордп рдмрд╛рдж 125 рдПрдордмреА рддрдХред
рдпрд╣ рдЗрдВрдЧрд┐рдд рдХрд░рдиреЗ рдпреЛрдЧреНрдп рд╣реИ рдХрд┐ рдмрд╛рдврд╝ рдХрд╛ рдЙрдкрдпреЛрдЧ рд▓рдЧрднрдЧ рдХреЛрдИ CPU рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ, msggen CPU рдХреЗ 2% рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИ, рдФрд░ рд░рд╛рдЙрдЯрд░ рдФрд░ рдореЛрдЪреАрд╡реЗрдм 1% рд╕реЗ рдХрдо рд╣реИрдВред
24 рдШрдВрдЯреЗ рдХреЗ рднреАрддрд░ рдкреВрд░рд╛ рд╣реЛрдиреЗ рдХреЗ рдмрд╛рдж рдкрд░рд┐рдгрд╛рдо
рдореЛрдЪреАрд╡рдм рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХреА рдореЗрдореЛрд░реА рдЙрдкрдпреЛрдЧ рдХреА рдирд┐рдЧрд░рд╛рдиреА рдХрд░рддреЗ рд╣реБрдП рдЖрд╡реЗрджрди рдиреЗ 24 рдШрдВрдЯреЗ рдХрд╛рдо рдХрд┐рдпрд╛ред 10,000 рдЬреБрдбрд╝реЗ рдЧреНрд░рд╛рд╣рдХ, 1000 рд╕рдВрджреЗрд╢ рдкреНрд░рддрд┐ рд╕реЗрдХрдВрдб рдпрд╛рджреГрдЪреНрдЫрд┐рдХ рдЧреНрд░рд╛рд╣рдХреЛрдВ рдХреЛ рднреЗрдЬреЗ рдЧрдПред
рдЧреНрд░рд╛рдл рдХреЛ рдЦреАрдВрдЪрдиреЗ рдХреЗ рд▓рд┐рдП gnuplot рдХреЛ рдмрд╛рдзреНрдп рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдЪрд╛рд▓ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛:
(echo -e "set terminal png size 500,300\nset xlabel \"Minutes Elapsed\"\nset ylabel \"Mem (KB)\"\nset title \"Mem usage with 10k active connections, 1000 msg/sec\"\nplot \"-\" using 1:2 with lines notitle" ; awk 'BEGIN{FS="\t";} NR

рдпрд╣ рдЧреНрд░рд╛рдлрд╝ рджрд┐рдЦрд╛рддрд╛ рд╣реИ рдХрд┐ рдореЗрдореЛрд░реА рдЙрдкрдпреЛрдЧ (10k рд╕рдХреНрд░рд┐рдп рдХрдиреЗрдХреНрд╢рди рдФрд░ 1000 msg / рд╕реЗрдХрдВрдб рдХреЗ рд╕рд╛рде) 24 рдШрдВрдЯреЗ рдХреА рдЕрд╡рдзрд┐ рдореЗрдВ 250 рдПрдордмреА рдХреЗ рднреАрддрд░ рд╕рдВрд░реЗрдЦрд┐рдд рд╣реИред рдЗрд╕ рддрдереНрдп рдХреЗ рдХрд╛рд░рдг рджреЛ рдирд┐рдЪрд▓реЗ рдЫреЛрд░ рджрд┐рдЦрд╛рдИ рджрд┐рдП рдХрд┐ рдореИрдВрдиреЗ рдмреНрдпрд╛рдЬ рдХреЗ рд▓рд┐рдП рдкреНрд░рджрд░реНрд╢рди рдХрд┐рдпрд╛:
erl> [erlang:garbage_collect(P) || P <- erlang:processes()].
рдпрд╣ рд╕рднреА рдкреНрд░рдХреНрд░рд┐рдпрд╛рдУрдВ рдХреЛ рдХрдЪрд░рд╛ рдЗрдХрдЯреНрдард╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдордЬрдмреВрд░ рдХрд░рддрд╛ рд╣реИ, рдФрд░ рд▓рдЧрднрдЧ 100 рдПрдордмреА рдореЗрдореЛрд░реА рдХреЛ рдореБрдХреНрдд рдХрд░рддрд╛ рд╣реИред рдЕрдм рд╣рдо рдореИрдиреНрдпреБрдЕрд▓ рд░реВрдк рд╕реЗ рдХрдЪрд░рд╛ рд╕рдВрдЧреНрд░рд╣ рдХреЗ рд▓рд┐рдП рдордЬрдмреВрд░ рдХрд┐рдП рдмрд┐рдирд╛ рд╕реНрдореГрддрд┐ рдХреЛ рд╕рдВрд░рдХреНрд╖рд┐рдд рдХрд░рдиреЗ рдХреЗ рддрд░реАрдХреЗ рддрд▓рд╛рд╢ рд░рд╣реЗ рд╣реИрдВред
Mochiweb рдореЗрдВ рдореЗрдореЛрд░реА рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрдо рдХрд░реЗрдВ
рдзреНрдпрд╛рди рджреЗрдВ, рдореЛрдЪреАрд╡рдм рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЗрд╡рд▓ рд╕рдВрджреЗрд╢ рднреЗрдЬрддрд╛ рд╣реИ рдФрд░ рдлрд┐рд░ рддреБрд░рдВрдд рдЙрдиреНрд╣реЗрдВ рднреВрд▓ рдЬрд╛рддрд╛ рд╣реИ, рднреЗрдЬреЗ рдЧрдП рд╕рдВрджреЗрд╢реЛрдВ рдХреА рд╕рдВрдЦреНрдпрд╛ рдХреЗ рд╕рд╛рде рд╕реНрдореГрддрд┐ рдЙрдкрдпреЛрдЧ рдореЗрдВ рд╡реГрджреНрдзрд┐ рдирд╣реАрдВ рд╣реЛрдиреА рдЪрд╛рд╣рд┐рдПред
рдореИрдВ рдПрдХ рдиреМрд╕рд┐рдЦрд┐рдпрд╛ рд╣реВрдВ рдЬрдм рдпрд╣ рдПрд░рд▓рдВрдЧ рдореЗрдореЛрд░реА рдкреНрд░рдмрдВрдзрди рдХреА рдмрд╛рдд рдЖрддреА рд╣реИ, рд▓реЗрдХрд┐рди рдореИрдВ рдпрд╣ рд╕реБрдЭрд╛рд╡ рджреЗрдиреЗ рдЬрд╛ рд░рд╣рд╛ рд╣реВрдВ рдХрд┐ рдЕрдЧрд░ рдореИрдВ рдЗрд╕реЗ рдЕрдзрд┐рдХ рдмрд╛рд░ рдХрдЪрд░рд╛ рдЗрдХрдЯреНрдард╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдордЬрдмреВрд░ рдХрд░ рд╕рдХрддрд╛ рд╣реВрдВ, рддреЛ рдпрд╣ рд╣рдореЗрдВ рдЙрд╕ рдореЗрдореЛрд░реА рдХрд╛ рдЕрдзрд┐рдХрддрд░ рд░реАрдбрд╛рдпрд░реЗрдХреНрдЯ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрдЧрд╛, рдФрд░ рдЕрдВрддрддрдГ рд╣рдореЗрдВ рдПрдХ рдЦрд╛рд▓реА рд╕рд┐рд╕реНрдЯрдо рдХреЗ рд╕рд╛рде рдЕрдзрд┐рдХ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛рдУрдВ рдХреА рд╕реЗрд╡рд╛ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрдЧрд╛ред рд╕реНрдореГрддрд┐ред
рдкреНрд░рд▓реЗрдЦрди рдХреЗ рдПрдХ рдЕрдзреНрдпрдпрди рд╕реЗ рдХреБрдЫ рдкрд░рд┐рдгрд╛рдо рдорд┐рд▓реЗ:
erlang: system_flag (fullsweep_after, рд╕рдВрдЦреНрдпрд╛)рдЧреВрдврд╝, рд▓реЗрдХрд┐рди рдпрд╣ рдХреЗрд╡рд▓ рдирдИ рдкреНрд░рдХреНрд░рд┐рдпрд╛рдУрдВ рдкрд░ рд▓рд╛рдЧреВ рд╣реЛрддрд╛ рд╣реИ рдФрд░ рд╡реАрдПрдо рдореЗрдВ рд╕рднреА рдкреНрд░рдХреНрд░рд┐рдпрд╛рдУрдВ рдХреЛ рдкреНрд░рднрд╛рд╡рд┐рдд рдХрд░рддрд╛ рд╣реИ, рди рдХреЗрд╡рд▓ рд╣рдорд╛рд░реА рдореЛрдЪреАрд╡рдм рдкреНрд░рдХреНрд░рд┐рдпрд╛рдУрдВ рдХреЛред
рдЕрдЧрд▓рд╛:
erlang: system_flag (min_heap_size, MinHeapSize)рдпрд╣ рдЙрдкрдпреЛрдЧреА рд╣реЛ рд╕рдХрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдореБрдЭреЗ рдкреВрд░рд╛ рдпрдХреАрди рд╣реИ рдХрд┐ рд╣рдорд╛рд░реЗ рдореЛрдЪреАрд╡рдм рдкреНрд░рдХреНрд░рд┐рдпрд╛рдУрдВ рдХреЛ рд╡реИрд╕реЗ рднреА рдбрд┐рдлрд╝реЙрд▓реНрдЯ рдорд╛рди рд╕реЗ рдЕрдзрд┐рдХ рдвреЗрд░ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИред рдореИрдВ рдореЛрдЪреАрд╡рдм рд╕реНрд░реЛрдд рдХреЛрдб рдХреЛ рдмрджрд▓рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╕реЗ рдмрдЪрдирд╛ рдЪрд╛рд╣реВрдВрдЧрд╛ред
рдкрд╛рд╕ рдореЗрдВ, рдореИрдВрдиреЗ рджреЗрдЦрд╛:
рдПрд░рд▓реИрдВрдЧ: рд╣рд╛рдЗрдмрд░рдиреЗрдЯ (рдореЙрдбреНрдпреВрд▓, рдлрдВрдХреНрд╢рди, рдЖрд░реНрдЧреНрд╕)рдЙрдЪрд┐рдд рд▓рдЧрддрд╛ рд╣реИ - рдЖрдЗрдП рдкреНрд░рддреНрдпреЗрдХ рд╕рдВрджреЗрд╢ рдХреЗ рдмрд╛рдж рд╕реЛрдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░реЗрдВ рдФрд░ рджреЗрдЦреЗрдВ рдХрд┐ рдХреНрдпрд╛ рд╣реЛрддрд╛ рд╣реИред
Mochiconntest_web.erl рд╕рдВрдкрд╛рджрд┐рдд рдХрд░реЗрдВ рдФрд░ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдмрджрд▓реЗрдВ:
тАв рдлрд╝рдВрдХреНрд╢рди рдХреА рдЕрдВрддрд┐рдо рдкрдВрдХреНрддрд┐ (рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛, рдЖрдИрдбреА, рдПрди) рдХреЛ рдмрджрд▓реЗрдВ рддрд╛рдХрд┐ рдпрд╣ рд╕реНрд╡рдпрдВ рдХреЛ рдХреЙрд▓ рдХрд░рдиреЗ рдХреЗ рдмрдЬрд╛рдп рд╕реНрд▓реАрдк рдореЛрдб рдореЗрдВ рдЪрд▓рд╛ рдЬрд╛рдП;
тАв рдХреЙрд▓ рд╣рд╛рдЗрдмрд░рдиреЗрдЯ () рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдкрд░ рдЕрд╡рд░реБрджреНрдз рд╣реЛрдиреЗ рдХреЗ рдмрдЬрд╛рдп рддреБрд░рдВрдд рд░рд╛рдЙрдЯрд░ рдХреЛ рдПрдХ рд╕рдВрджреЗрд╢ рднреЗрдЬрдиреЗ рдХреЗ рд▓рд┐рдП;
тАв рдлрд╝реАрдб / 3 рдирд┐рд░реНрдпрд╛рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдпрд╛рдж рд░рдЦреЗрдВред
рдЕрджреНрдпрддрд┐рдд mochiconntest_web.erl рд╕рдВрджреЗрд╢реЛрдВ рдХреЗ рдмреАрдЪ рд╣рд╛рдЗрдмрд░рдиреЗрд╢рди рдХреЗ рд╕рд╛рде:
-module(mochiconntest_web). -export([start/1, stop/0, loop/2, feed/3]). %% External API start(Options) -> {DocRoot, Options1} = get_option(docroot, Options), Loop = fun (Req) -> ?MODULE:loop(Req, DocRoot) end, % we'll set our maximum to 1 million connections. (default: 2048) mochiweb_http:start([{max, 1000000}, {name, ?MODULE}, {loop, Loop} | Options1]). stop() -> mochiweb_http:stop(?MODULE). loop(Req, DocRoot) -> "/" ++ Path = Req:get(path), case Req:get(method) of Method when Method =:= 'GET'; Method =:= 'HEAD' -> case Path of "test/" ++ IdStr -> Response = Req:ok({"text/html; charset=utf-8", [{"Server","Mochiweb-Test"}], chunked}), {Id, _} = string:to_integer(IdStr), router:login(Id, self()), % Hibernate this process until it receives a message: proc_lib:hibernate(?MODULE, feed, [Response, Id, 1]); _ -> Req:not_found() end; 'POST' -> case Path of _ -> Req:not_found() end; _ -> Req:respond({501, [], []}) end. feed(Response, Id, N) -> receive {router_msg, Msg} -> Html = io_lib:format("Recvd msg #~w: '~w' ", [N, Msg]), Response:write_chunk(Html) end, % Hibernate this process until it receives a message: proc_lib:hibernate(?MODULE, feed, [Response, Id, N+1]). %% Internal API get_option(Option, Options) -> {proplists:get_value(Option, Options), proplists:delete(Option, Options)}.
рдореИрдВрдиреЗ рдпреЗ рдмрджрд▓рд╛рд╡ рдХрд┐рдП, рдореЛрдЪреАрд╡рдм рдХреЛ рдлрд┐рд░ рд╕реЗ рдмрдирд╛рдпрд╛, рдлрд┐рд░ рд╕реЗ рд╡рд╣реА рдкрд░реАрдХреНрд╖рдг рдХрд┐рдпрд╛ред
24 рдШрдВрдЯреЗ рдХреЗ рднреАрддрд░ рдирд┐рд╖реНрдкрд╛рджрди рдХреЗ рдмрд╛рдж рдкрд░рд┐рдгрд╛рдо proc_lib: рд╣рд╛рдЗрдмрд░рдиреЗрдЯ ()

рд╣рд╛рдЗрдмрд░рдиреЗрдЯ () рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХрд╛ рдорддрд▓рдм рд╣реИ рдХрд┐ рдореЛрдЪреАрд╡реАрдм рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдореЗрдореЛрд░реА рдХреЛ 10 рдПрдордмреА рдХрдиреЗрдХреНрд╢рди рдХреЗ рд╕рд╛рде 78 рдПрдордмреА рдкрд░ рд╕рдВрд░реЗрдЦрд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рднрд╛рдЧ 1 рдореЗрдВ рджреЗрдЦреЗ рдЧрдП 450 рдПрдордмреА рдХреА рддреБрд▓рдирд╛ рдореЗрдВ рдмрд╣реБрдд рдмреЗрд╣рддрд░ рд╣реИред рд╕реАрдкреАрдпреВ рдЙрдкрдпреЛрдЧ рдореЗрдВ рдХреЛрдИ рдЙрд▓реНрд▓реЗрдЦрдиреАрдп рд╡реГрджреНрдзрд┐ рдирд╣реАрдВ рд╣реБрдИред
рдЗрд╕рд▓рд┐рдП ...
рд╣рдордиреЗ Mochiweb рдХреЗ рд▓рд┐рдП рдПрдХ рдзреВрдордХреЗрддреБ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдмрдирд╛рдпрд╛ рдЬреЛ рд╣рдореЗрдВ рдкреВрд░реНрдгрд╛рдВрдХ рдЖрдИрдбреА рджреНрд╡рд╛рд░рд╛ рдкрд╣рдЪрд╛рдиреЗ рдЧрдП рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛рдУрдВ рдХреЛ рдордирдорд╛рдиреЗ рд╕рдВрджреЗрд╢ рднреЗрдЬрдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред
24 рдШрдВрдЯреЗ рдХреЗ рд▓рд┐рдП рдкреНрд░рддрд┐ рд╕реЗрдХрдВрдб 1000 рд╕рдВрджреЗрд╢реЛрдВ рдХреЛ рдЪрд▓рд╛рдиреЗ рдХреЗ рдмрд╛рдж, 10,000 рдЬреБрдбрд╝реЗ рд╣реБрдП рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛рдУрдВ рдХреЗ рд╕рд╛рде, рд╣рдордиреЗ 80 рдПрдордмреА рдореЗрдореЛрд░реА рдпрд╛ 8 рдХреЗрдмреА рдкреНрд░рддрд┐ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЗ рдЙрдкрдпреЛрдЧ рдХреЛ рджреЗрдЦрд╛ред рд╣рдордиреЗ рдЕрдЪреНрдЫреЗ рдЧреНрд░рд╛рдлрд┐рдХреНрд╕ рднреА рдмрдирд╛рдПред
рдпрд╣ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдкреНрд░рдЧрддрд┐ рд╣реИред
рдЕрдЧрд▓реЗ рдЪрд░рдг
рднрд╛рдЧ 3 рдореЗрдВ, рдореИрдВ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛рдУрдВ рдХреА рд╕рдВрдЦреНрдпрд╛ 1 рдорд┐рд▓рд┐рдпрди рддрдХ рдмрдврд╝рд╛рдКрдВрдЧрд╛ред рдореИрдВ рдкрд░реНрдпрд╛рдкреНрдд рдореЗрдореЛрд░реА рдХреЗ рд╕рд╛рде рдПрдХ рдорд▓реНрдЯреАрдкреНрд░реЛрд╕реЗрд╕рд░ рдорд╢реАрди рдкрд░ рдкрд░реАрдХреНрд╖рдг рдЖрдпреЛрдЬрд┐рдд рдХрд░реВрдВрдЧрд╛ред рдореИрдВ 1 рдорд┐рд▓рд┐рдпрди рдХрдиреЗрдХреНрд╢рди рдХрд╛ рдЕрдиреБрдХрд░рдг рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХреБрдЫ рдЕрддрд┐рд░рд┐рдХреНрдд рдЪрд╛рд▓реЗрдВ рдФрд░ рдЕрдиреБрдХреВрд▓рди рднреА рджрд┐рдЦрд╛рдКрдВрдЧрд╛ред
рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдПрдХ рдкреНрд░рдХрд╛рд░ рдХреЗ "рдкрдм-рдЙрдк" рдкреНрд░рдгрд╛рд▓реА рдореЗрдВ рд╡рд┐рдХрд╕рд┐рдд рд╣реЛрдЧрд╛, рдЬрд╣рд╛рдВ рд╕рджрд╕реНрдпрддрд╛ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛рдУрдВ рдХреА рдЖрдИрдбреА рд╕реЗ рдЬреБрдбрд╝реА рд╣реЛрддреА рд╣реИ рдФрд░ рдЖрд╡реЗрджрди рджреНрд╡рд╛рд░рд╛ рд╕рд╣реЗрдЬреА рдЬрд╛рддреА рд╣реИред рд╣рдо рд╕рд╛рдорд╛рдЬрд┐рдХ рдиреЗрдЯрд╡рд░реНрдХ рдбреЗрдЯрд╛ рдХреЗ рдПрдХ рд╡рд┐рд╢рд┐рд╖реНрдЯ рд╕реЗрдЯ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗ: рджреЛрд╕реНрддреЛрдВред рдпрд╣ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЛ рдЕрдкрдиреА рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдЖрдИрдбреА рдХреЗ рд╕рд╛рде рд▓реЙрдЧ рдЗрди рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрдЧрд╛ рдФрд░ рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд░реВрдк рд╕реЗ рдЕрдкрдиреЗ рдХрд┐рд╕реА рдорд┐рддреНрд░ рджреНрд╡рд╛рд░рд╛ рдЙрддреНрдкрдиреНрди рдХрд┐рд╕реА рднреА рдШрдЯрдирд╛ рдХреЛ рдкреНрд░рд╛рдкреНрдд рдХрд░реЗрдЧрд╛ред