erlang进程池框架poolboy的例子

在hottub和poolboy之间纠结,后来发现hottub在子进程crash以后,重启会有问题,尝试用了下poolboy,发现可以满足需求,在此记录下

poolboy官网的和pgsql结合的例子在我这边总是崩溃,提示invalid child spec,无奈,google后,在某个角落找到一个可以跑的例子,改了下,贴一下备忘

 

新建工程rebar-creator create-app pool_test

config.erl

-module(config).

-compile(export_all).
-export([]).

get_pool_name()->
  test_pool.

get_pool_args()->
  PoolArgs = [{name, {local, get_pool_name()}},
    {worker_module, test_worker},
    {size, 5},
    {max_overflow, 10}],
  PoolArgs.

get_worker_args()->
  test_work_args.

 

pool_sup.erl

-module(pool_sup).

-behaviour(supervisor).

-export([start_link/0]).
-export([init/1]).

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

init([]) ->

  RestartStrategy = one_for_one,
  MaxRestarts = 100,
  MaxSecondsBetweenRestarts = 10,

  SupFlags = {RestartStrategy, MaxRestarts, MaxSecondsBetweenRestarts},

%%   Restart = permanent,
  Restart = transient,
  Shutdown = 5000,
  Type = supervisor,

  Child = {worker_sup, {worker_sup, start_link, []},
    Restart, Shutdown, Type, [worker_sup]},
  Children = [Child],
  {ok, {SupFlags, Children}}.

 

pool_test_app.erl

-module(pool_test_app).

-behaviour(application).

-compile(export_all).

start(_StartType, _StartArgs) ->
  pool_sup:start_link().

stop(_State) ->
  ok.

get_worker() ->
  poolboy:checkout(test_pool).

info(Pid) ->
  gen_server:call(Pid, {info}).

crash(Pid) ->
  gen_server:call(Pid, {crash}).

 

test_worker.erl

-module(test_worker).
-behaviour(gen_server).
-behaviour(poolboy_worker).

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

-record(state, {}).

start_link([Args]) ->
  gen_server:start_link(?MODULE, [Args], []).

init([Args]) ->
  io:format("working thread init ~p,~p~n", [self(), Args]),
  process_flag(trap_exit, true),
  {ok, #state{}}.

handle_call({info}, _From, State) ->
  io:format("info~n"),
  {reply, _Reply = ok, State};
handle_call({crash}, _From, State) ->
  1 = 2,
  {reply, _Reply = ok, State};
handle_call(_Request, _From, State) ->
  {reply, _Reply = ok, State}.

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

handle_info({'EXIT', _Pid, Reason}, State) ->
  io:format("exit reason ~p~n", [Reason]),
  case Reason of
    normal ->
      io:format("normal exit trapped~n"),
      {stop, normal, State};
    other ->
      io:format("other exit trapped~n"),
      {noreply, State}
  end;
handle_info(_Info, State) ->
  {noreply, State}.

terminate(_Reason, _State) ->
  io:format("terminate ~p,~p,~p~n", [_Reason, _State, self()]),
  ok.

code_change(_OldVsn, State, _Extra) ->
  {ok, State}.

 

worker_sup.erl

-module(worker_sup).
-behaviour(supervisor).
-export([start_link/0, init/1]).


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

%% {ok,{{one_for_one,1000,3600},
%% [{test_pool,{poolboy,start_link,
%% [[{name,{local,test_pool}},
%% {worker_module,test_worker},
%% {size,5},
%% {max_overflow,10}],
%% [test_work_args]]},
%% permanent,5000,worker,
%% [poolboy]}]}}

%init返回的策略里面的回调函数是poolboy,start_link,所以,不需要手工去启动poolboy
init([]) ->
  Name = config:get_pool_name(),
  PoolArgs = config:get_pool_args(),
  WorkerArgs = config:get_worker_args(),

  PoolSpec = poolboy:child_spec(Name, PoolArgs, [WorkerArgs]),

  ChildSpecs = [PoolSpec],
  {ok, {{one_for_one, 1000, 3600}, ChildSpecs}}.

 

大概就这样,子进程crash了自动重启,pool crash了也自动重启。满足需求了

你可能感兴趣的:(erlang)