主页

索引

模块索引

搜索页面

gen_server模块

Design Principles

Client-Server Principles: 1 Server VS n Client

https://img.zhaoweiguo.com/knowledge/images/languages/erlangs/erl_otp_gen_server_principle.gif

监控树模式:

init(Args) ->
  ...,
  process_flag(trap_exit, true),
  ...,
  {ok, State}.

...

terminate(shutdown, State) ->
    ..code for cleaning up here..
    ok.

Standalone Gen_Servers:

...
export([stop/0]).
...

stop() ->
    gen_server:cast(ch3, stop).
...

handle_cast(stop, State) ->
    {stop, normal, State};
handle_cast({free, Ch}, State) ->
    ....

...

terminate(normal, State) ->
    ok.
abcast/2/3

结构:

abcast(Name, Request) -> abcast
abcast(Nodes, Name, Request) -> abcast
类型:
Nodes = [Node]
Request = term()

说明:

向指定Node本地注册为Name的gen_server进程发送asynchronous请求
此函数立即返回,忽略not exist结点或不存在gen_server名
此gen_server进程调用Module:handle_cast/2方法处理此请求
: 更多请求参考:multi_call/2,3,4.
call/2/3

结构:

call(ServerRef, Request) -> Reply
call(ServerRef, Request, Timeout) -> Reply
Types
ServerRef = Name | {Name,Node} | {global,GlobalName}
  | {via,Module,ViaName} | pid()
 Node = atom()
 GlobalName = ViaName = term()
Request = term()
Timeout = int()>0 | infinity
Reply = term()
enter_loop/3/4/5

结构:

enter_loop(Module, Options, State)
enter_loop(Module, Options, State, ServerName)
enter_loop(Module, Options, State, Timeout)
enter_loop(Module, Options, State, ServerName, Timeout)

类型:

Options = [{debug,Dbgs} | {hibernate_after,HibernateAfterTimeout}]
  Dbgs = [trace | log | statistics
    | {log_to_file,FileName} | {install,{Func,FuncState}}]

作用 [1]

让一个已经存在的process进入gen_server进程中
Does not return, instead the calling process enters the gen_server process receive loop and becomes a gen_server process.
此进程必须用proc_lib[1]的启动函数启动
用户需要手动做进程初使化(包括注册名,如果指定ServerName)

此函数在做比gen_server还复杂的初始化时更加有用

警告

失败原因: 1.调用进程不是由proc_lib启动 2.指定ServerName但没有注册

multi_call/2/3/4

结构:

multi_call(Name, Request) -> Result
multi_call(Nodes, Name, Request) -> Result
multi_call(Nodes, Name, Request, Timeout) -> Result
类型:
Nodes = [Node]
Name = atom()
Request = term()
Timeout = int()>=0 | infinity
Result = {Replies,BadNodes}
 Replies = [{Node,Reply}]
  Reply = term()
BadNodes = [Node]

说明:

向每个Node上本地注册为Name的gen_server发送synchronous请求,并等待返回
Nodes默认值为: [node()|nodes()]
Timeout默认值为: infinity

警告

如其中有node不能处理monitor(如C Node或Java Node) gen_server在请求时没有启动,但在2秒内启动 此函数会等待整个超时时间,包括infinity 注: 全Erlang结点没有此问题

reply/2

结构:

reply(Client, Reply) -> Result
Types
Client - see below
Reply = term()
Result = term()

说明:

当不能使用Module:handle_call/3函数的返回值定义回复时,gen_server进程可以使用此函数显示回复
之后的就不需要handler_call的返回值了,即可使用:
{noreply, xxx}
start/start_link/3/4
start(Module, Args, Options) -> Result
start(ServerName, Module, Args, Options) -> Result
start_link(Module, Args, Options) -> Result
start_link(ServerName, Module, Args, Options) -> Result
类型:
ServerName = {local,Name} | {global,GlobalName} | {via,Module,ViaName}
Options = [Option]
   Option = {debug,Dbgs} | {timeout,Time} | {hibernate_after,HibernateAfterTimeout} | {spawn_opt,SOpts}
      Dbgs = [Dbg]
          Dbg = trace | log | statistics | {log_to_file,FileName} | {install,{Func,FuncState}}
      SOpts = [term()]
Result = {ok,Pid} | ignore | {error,Error}
   Error = {already_started,Pid} | term()

Args:

If option {timeout,Time} is present, the gen_server process is allowed to spend Time milliseconds initializing or it is terminated and the start function returns {error,timeout}.

If option {hibernate_after,HibernateAfterTimeout} is present, the gen_server process awaits any message for HibernateAfterTimeout milliseconds and if no message is received, the process goes into hibernation automatically (by calling proc_lib:hibernate/3).

If option {debug,Dbgs} is present, the corresponding sys function is called for each item in Dbgs; see sys(3).

If option {spawn_opt,SOpts} is present, SOpts is passed as option list to the spawn_opt BIF, which is used to spawn the gen_server process; see spawn_opt/2.
stop/1/3

类型:

stop(ServerRef) -> ok
stop(ServerRef, Reason, Timeout) -> ok
类型:
ServerRef = Name | {Name,Node} | {global,GlobalName}
  | {via,Module,ViaName} | pid()
Reason = term()

说明:

指定server以Reason原因exit并等待它终止.此gen_server进程会在exit前调用Module:terminate/2
Reason默认值为: normal
Timeout默认值为: infinity, 单位milliseconds

Reason为normal, shutdown, or {shutdown,Term}时会返回ok并terminate
Reason为其他时,会causes an error report to be issued using logger(3)

如果服务在指定时间内没有被terminated,则抛出timeout exception
如果此process不exist, 抛出a noproc exception
Module:init
Module:init(Args) -> Result
类型:
Args = term()
Result = {ok,State} | {ok,State,Timeout} | {ok,State,hibernate}
 | {ok,State,{continue,Continue}} | {stop,Reason} | ignore
 State = term()
 Timeout = int()>=0 | infinity
 Reason = term()

说明:

{ok,State,Timeout}
除非Timeout millisecond时间内收到请求,否则会触发timeout的info消息
{ok,State} 等于 {ok,State,infinity}
一直等待请求过来
{ok,State,hibernate}
等待消息时进入hibernate状态,通过调用proc_lib:hibernate/3
{stop,Reason} | ignore
初使化失败时,返回
code_change/3

实例:

1.reloader升级后发现每5000s reloader一次代码:
  原因: node没有重启, gen_server里面state的值没有变
  原来单位是ms,这次升级后变成s

主页

索引

模块索引

搜索页面