OTP Design Principles: Gen_Server Behaviour

本文介绍了OTP框架下的Gen_Server行为设计原则,包括客户端-服务器模型的应用、Gen_Server的启动方式、同步请求与异步请求的处理方法以及如何优雅地关闭Gen_Server。此外还详细解释了Gen_Server模块中的回调函数及其作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

OTP Design Principles: Gen_Server Behaviour

1,Client-Server原则
client-server模型由一个中心服务器和任意多的客户端组成
该模型主要用来做资源管理操作,不同的客户端共享一个通用的资源,服务器负责管理该资源

2,例子
[code]
-module(ch3).
-behaviour(gen_server).

-export([start_link/0]).
-export([alloc/0, free/1]).
-export([init/1, handle_call/3, handle_cast/2]).

start_link() ->
gen_server:start_link({local, ch3}, ch3, [], []).

alloc() ->
gen_server:call(ch3, alloc).

free(Ch) ->
gen_server:cast(ch3, {free, Ch}).

init(_Args) ->
{ok, channels()}.

handle_call(alloc, _From, Chs) ->
{Ch, Chs2} = alloc(Chs),
{reply, Ch, Chs2}.

handle_cast({free, Ch}, Chs) ->
Chs2 = free(Ch, Chs),
{noreply, Chs2}.
[/code]

3,启动Gen_Server
ch3:start_link():
[code]
start_link() ->
gen_server:start_link({local, ch3}, ch3, [], []) => {ok, Pid}
[/code]
gen_server:start_link/4启动一个新进程并连接它,新进程为一个gen_server
1)第一个参数指定gen_server名字,{local, ch3}表示在本地注册一个gen_server进程为ch3
2)第二个参数指定callback module为ch3,在这里接口方法和callback方法都放在一个module里,这是一个好的编程实践
3)第三个参数指定init方法的参数
4)第四个参数为options
如果名字注册成功,新的gen_server进程调用callback方法ch3:init([]),返回{ok, State}
gen_server:start_link是同步的,直到gen_server初始化并且可以接收请求才返回,gen_server:start_link由supervisor启动,它是supervision tree的一部分
gen_server:start启动一个单独的进程,gen_server:start不是supervision tree的一部分,它没有supervisor

4,同步请求——Call
同步请求alloc()由gen_server:call/2实现:
[code]
alloc() ->
gen_server:call(ch3, alloc).
[/code]
ch3是gen_server的名字,alloc是实际的请求
该请求会发送一条消息给gen_server,请求接受以后,gen_server调用handle_call(Request, From, State)并返回{replay, Replay, State1}

5,异步请求——Cast
异步请求free(Ch)由gen_server:cast/2实现
[code]
free(Ch) ->
gen_server:cast(ch3, {free, Ch}).
[/code]
ch3是gen_server的名字,{free, Ch}是真正的请求
callback方法为handle_cast(Request, State),返回{noreply, State1}.

6,关闭
6.1 在Supervision Tree中
如果gen_server是supervision tree的一部分,则不需要stop方法。gen_server会被supervisor自动关掉。
如果需要在关闭gen_server之前做清理工作,那么shutdown strategy必须为一个timeout并且必须在gen_server的init方法中设置捕获exit信号
gen_server将在关闭时调用callback方法terminate(shutdown, State):
[code]
init(Args) ->
...,
process_flag(trap_exit, true),
...,
{ok, State}.
...
terminate(shutdown, State) ->
..code for cleaning up here..
ok.
[/code]

6.2 单独的Gen_Servers
如果gen_server不是supervision tree的一部分,那么定义一个stop方法会比较有用:
[code]
...
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.
[/code]
callback方法处理stop请求,然后返回{stop, normal, State1},norma指定这是一个正常的关闭,State1为gen_server的state的新的值
这将使得gen_server调用terminate(normal, State1),然后优雅的关闭服务器

7,处理其他消息
如果gen_server可以接受除了请求外的其他消息,那么callback方法handle_info(Info, State)必须实现来处理它们
例如gen_server连接到supervisor以为的其他进程并捕获到exit信号,这时就会接受一个exit消息
[code]
handle_info({'EXIT', Pid, Reason}, State) ->
..code to handle exits here..
{noreply, State1}.
[/code]

补充:gen_server exports and callbacks
[code]
gen_server module callback module
gen_server:start_link -------> Module:init/1
gen_server:start
gen_server:call -------------> Module:handle_call/3
gen_server:multi_call
gen_server:cast -------------> Module:handle_cast/2
gen_server:abcast
gen_server:replay
gen_server:enter_loop
Module:handle_info/2
Module:terminate/2
Module:code_change/3
[/code]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值