server processes with timeout

I have to implement erlang gen_server processes which are alive for hours. But after timeout gen_server process should be killed. These processes are started dynamically so dynamical supervising is used. The idea is to use timer:apply_after() on process init. So init of gen_server process looks like that

init(Time) -> 
   timer:apply_after(Time, my_supervisor, kill_child, [self()]),
   % do other init things
   ok.

I'm a bit new to erlang so the question is does this approach is fine or it has some drawbacks? Is there a better solution?

Thanks!


I would do something different:

init([]) ->
    erlang:send_after(Time, self(), timeout_shutdown),
    {ok, #state{}}.

handle_info(timeout_shutdown, State) ->
    {stop, normal, State};
...

This way, the process gracefully shuts down itself, without the need for the supervisor to kill it. Better, you can declare the child as transient in the supervisor, so it doesn't get restarted.


You might want to consider using erlang:send_after/3 and react to the message in your gen_server with handle_info:

Creating timers using erlang:send_after/3 and erlang:start_timer/3 is much more efficient than using the timers provided by the timer module. The timer module uses a separate process to manage the timers, and that process can easily become overloaded if many processes create and cancel timers frequently (especially when using the SMP emulator).

The functions in the timer module that do not manage timers (such as timer:tc/3 or timer:sleep/1), do not call the timer-server process and are therefore harmless.

http://www.erlang.org/doc/efficiency_guide/commoncaveats.html


you can try this code: the process worker1 shutdown itself every second, the process worker2 shutdown itself every two seconds. You just need load the two beam, and run super:start_link(). super:main(). super:start_link(). super:main(). in erl shell.

This is supervosor:

-module(super).
-behaviour(supervisor).
%% API
-export([start_link/0]).
-export([stop/0]).
-export([main/]).
%% Supervisor callbacks
-export([init/1]).

-define(SERVER, ?MODULE).

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

init([]) ->
    RestartStrategy = simple_one_for_one,
    MaxRestarts = 1000,
    MaxSecondsBetweenRestarts = 3600,

    SupFlags = {RestartStrategy, MaxRestarts, MaxSecondsBetweenRestarts},

    Restart = permanent,
    Shutdown = 2000,
    Type = worker,

    AChild = {worker, {worker, start_link, []},
          Restart, Shutdown, Type, [worker]},
    {ok, {SupFlags, [AChild]}}.

main() ->
    add_worker(worker1, 1000),
    add_worker(worker2, 2000).

add_worker(WorkerName, Time) when is_atom(WorkerName)->
    supervisor:start_child(?SERVER, [WorkerName, Time]).
stop() ->
    exit(whereis(?SERVER), shutdown).

This is gen_server:

-module(worker).
-behaviour(gen_server).
%% API
-export([start_link/2]).

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

-define(SERVER, ?MODULE). 

-record(state, {}).

start_link(WorkerName, Time) ->
    io:format("server: ~p start!~n", [WorkerName]),
    gen_server:start_link({local, WorkerName}, ?MODULE, [WorkerName, Time], []).

init([WorkerName, Time]) ->
    erlang:send_after(Time, self(), {WorkerName, timeout_shutdown}),
    {ok, #state{}}.


handle_call(_Request, _From, State) ->
    Reply = ok,
    {reply, Reply, State}.


handle_cast(_Msg, State) ->
    {noreply, State}.

handle_info({WorkerName, timeout_shutdown}, State) ->
    io:format("server: ~p timeout_shutdown!~n", [WorkerName]),
    {stop, normal, State}.

terminate(_Reason, _State) ->
    ok.

code_change(_OldVsn, State, _Extra) ->
    {ok, State}.
链接地址: http://www.djcxy.com/p/38248.html

上一篇: Erlang Dynamic supervisor启动gen

下一篇: 服务器进程超时