`
uniseraph
  • 浏览: 83579 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

otp深入浅出之:gen_server

阅读更多
what is the gen_server ?

man 中 gen_server定义是:
引用
A behaviour module for implementing the server of a client-server relation. A generic server process (gen_server) implemented using this module will have a standard set of interface functions and include functionality for tracing and error reporting. It will also fit into an OTP supervision tree.



一个简单的echo gen_server
-module(echo).

-behaviour(gen_server).


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

-record(state, {}).

echo(Msg)->
	gen_server:call(?MODULE,{echo , Msg} ).
start_link() ->
    gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
init([]) ->
    {ok, #state{}}.

handle_call({echo , Msg}, _From, State) ->
	{reply , Msg , State };
handle_call(_Request, _From, State) ->
    Reply = ok,
    {reply, Reply, State}.
%%其他自动生成部分省略


echo gen_server代码的主干可以由模板生成,具体请参google。


运行并测试echo gen_server
         echo:start_link(),
         echo:echo("hello world").


how to start a echo gen_server ?


如上图,在主进程中的调用顺序为:echo:start_link->gen_server:start_link->gen:start->proc_lib:start_link

proc_lib:start_link中通过erlang:spawn_link创建echo进程,新进程中依次回调
gen:init_it->gen_server:init_it->echo:init,从而注入echo自己的初始化逻辑。

在gen_server:init_it中分析回调echo:init的返回值,初始化成功以后则进入循环。
init_it(Starter, Parent, Name, Mod, Args, Options) ->
    Debug = debug_options(Name, Options),
    case catch Mod:init(Args) of
        {ok, State} ->
            proc_lib:init_ack(Starter, {ok, self()}),
            loop(Parent, Name, State, Mod, infinity, Debug);
        {ok, State, Timeout} ->
            proc_lib:init_ack(Starter, {ok, self()}),
            loop(Parent, Name, State, Mod, Timeout, Debug);
        {stop, Reason} ->
            proc_lib:init_ack(Starter, {error, Reason}),
            exit(Reason);
        ignore ->
            proc_lib:init_ack(Starter, ignore),
            exit(normal);
        {'EXIT', Reason} ->
            proc_lib:init_ack(Starter, {error, Reason}),
            exit(Reason);
        Else ->
            Error = {bad_return_value, Else},
            proc_lib:init_ack(Starter, {error, Error}),
            exit(Error)
    end.




how to deal with a call ?
     gen_server:call({local,echo},{echo,"hello,world"}).

gen_server:call调用gen:call发起一个同步的消息请求,使用标签"$gen_call"作为表示,表示这是应用的消息,不是系统的消息。
call(Name, Request) ->
    case catch gen:call(Name, '$gen_call', Request) of
        {ok,Res} ->
            Res;
        {'EXIT',Reason} ->
            exit({Reason, {?MODULE, call, [Name, Request]}})
    end.


在主循环gen_server:loop中从消息队列中依次取出消息并处理,注意这是串行的,在一条消息处理完毕之前,不会处理下一条消息
loop(Parent, Name, State, Mod, Time, Debug) ->
    Msg = receive
              Input ->
                    Input
          after Time ->
                  timeout
          end,
    decode_msg(Msg, Parent, Name, State, Mod, Time, Debug, false).



gen_server:decode_msg区分不同消息类型,分别处理
decode_msg(Msg, Parent, Name, State, Mod, Time, Debug, Hib) ->
    case Msg of
        {system, From, Req} ->
            sys:handle_system_msg(Req, From, Parent, ?MODULE, Debug,
                                  [Name, State, Mod, Time], Hib);
        {'EXIT', Parent, Reason} ->
            terminate(Reason, Name, Msg, Mod, State, Debug);
        _Msg when Debug =:= [] ->
            handle_msg(Msg, Parent, Name, State, Mod);
        _Msg ->
            Debug1 = sys:handle_debug(Debug, {?MODULE, print_event},
                                      Name, {in, Msg}),
            handle_msg(Msg, Parent, Name, State, Mod, Debug1)
    end.


gen_server:handle_msg回调echo:handle_call处理应用信息,处理成功则返回loop方法。
handle_msg({'$gen_call', From, Msg}, Parent, Name, State, Mod) ->
    case catch Mod:handle_call(Msg, From, State) of
        {reply, Reply, NState} ->
            reply(From, Reply),
            loop(Parent, Name, NState, Mod, infinity, []);
        {reply, Reply, NState, Time1} ->
            reply(From, Reply),
            loop(Parent, Name, NState, Mod, Time1, []);
        {noreply, NState} ->
            loop(Parent, Name, NState, Mod, infinity, []);
        {noreply, NState, Time1} ->
            loop(Parent, Name, NState, Mod, Time1, []);
        {stop, Reason, Reply, NState} ->
            {'EXIT', R} =
                (catch terminate(Reason, Name, Msg, Mod, NState, [])),
            reply(From, Reply),
            exit(R);
        Other -> handle_common_reply(Other, Parent, Name, Msg, Mod, State)
    end;



how to deal with a cast ?

how to deal with a info ?


要注意的地方
  • 大小: 20.5 KB
分享到:
评论
3 楼 ariestiger 2009-11-16  
级别不够,看不懂
2 楼 mryufeng 2009-05-12  
图不错 gen_server其实是很复杂的 在里面做了很多安全性和稳定性的工作 还支持调试 代码更新 全局名字 supervisor等等 这些功能我们能难自己去写的对 推荐用gen_server, 比较没有大的什么性能开销。

http://blog.yufeng.info
1 楼 cbcbbcbc 2009-05-05  
不错,实战派!

相关推荐

    gen_server tasting 之超简单名称服务(续)

    在IT行业中,`gen_server`是Erlang OTP(开放电信平台)框架中的一个核心组件,它提供了一种模式化的方式来实现服务器进程。本篇博客“gen_server tasting 之超简单名称服务(续)”主要探讨了如何使用gen_server来...

    Erlang安装包,版本:otp_win64_24.1.7.exe

    otp_win64_24.1.7.exe

    pin_code_fields:Flutter软件包,将帮助您生成具有精美设计和动画的PIN码字段。 可以用于OTP或Pin码输入:nerd_face::nerd_face:

    可用于OTP或Pin码输入 :nerd_face: :nerd_face: 特征 :green_heart: 自动将下一个字段集中在键入上,将上一个字段集中在删除上 游标支持 :high_voltage: 可以设置为任意长度。 (建议3-6个字段) 文本字段的3种...

    分布式应用Erlang:Erlang_OTP_19_win64

    在OTP中,Supervisor是核心组件之一,它负责管理和监控应用程序中的进程,当某个进程崩溃时,Supervisor可以自动重启该进程,确保系统的稳定性。此外,GenServer提供了一种状态管理机制,使得进程能够存储和操作状态...

    erl:otp_src_24.0.5.tar.gz

    标题中的"erl:otp_src_24.0.5.tar.gz"指的是Erlang的源码包,其中"otp_src_24.0.5"是Erlang/OTP (Open Telecom Platform) 的24.0.5版本的源代码。Erlang是一种面向并发的、函数式的编程语言,常用于构建高可用性和...

    基于Erlang的gen_tcp聊天室代码,功能完整

    gen_tcp是Erlang OTP(开放电信平台)提供的一种行为模块,它允许程序员以面向过程的方式处理TCP连接。gen_tcp提供了创建、监听、接受和关闭TCP套接字的函数,以及发送和接收数据的基本操作。 **Erlang的并发特性**...

    gen_state_machine:OTP 19(及更高版本)中gen_statem的惯用Elixir包装器

    OTP 20(及更高版本)中gen_statem的惯用Elixir包装器。 完整文档可。 您可以在在Hex上找到该软件包。 gen_statem和此包装器之间的一个重要区别是,您在此包装器use GenStateMachine回调模式声明为use ...

    gen_server tasting 之超简单名称服务(再续)

    在IT行业中,`gen_server` 是Erlang OTP(开放电信平台)框架中的一个核心行为模块,用于构建可靠且容错的服务。它提供了一种模式,使得开发者可以编写并发、状态管理和故障恢复的服务器进程。在"gen_server tasting...

    OTP.zip_OTP_OTP .nd pudn_java otp_otp java_verify

    OTP,全称One-Time Password,是一种安全的身份验证机制,用于生成一次性使用的密码,通常...通过解压并分析“OTP.zip”中的源代码,我们可以深入了解其内部实现机制,并可能学习到如何在自己的项目中实施OTP验证系统。

    RabbitMQ系统客户端连接到RabbitMQ服务端消息通信过程1

    - `amqp_connection_sup`启动后,会创建`amqp_gen_connection`进程和`amqp_connection_type_sup`监督进程。`amqp_gen_connection`负责实际的网络连接,而`amqp_connection_type_sup`监督其他与连接相关的子进程。 ...

    otp_src_23.3.tar.gz

    OTP(Open Telephony Platform)是Erlang编程语言的核心组件之一,主要负责提供分布式计算、容错和系统监控等功能。Erlang是一种并发性极强、面向进程的编程语言,常用于构建高可用性和可扩展性的系统,尤其在电信、...

    otp_verify_java.rar_OTP_OTPVerify_TOTP_otp算法_一次性 口令

    OTP(One-Time Password)是一种基于时间、事件或挑战/应答机制的一次性密码技术,用于提高用户身份验证的安全性。OTP确保每个密码只能使用一次,从而降低了密码被重放攻击的风险。在Java环境中,我们可以使用不同的...

    erlang 聊天室

    gen_server是Erlang OTP(开放电信平台)设计模式之一,它为服务器进程提供了一个通用框架,处理请求、状态管理和错误处理。在聊天室应用中,gen_server可以被用来管理用户登录、保持用户状态、接收和转发消息。每个...

    OTP.rar_MD5 password_OTP_OTP 加密_otp算法_口令认证

    在压缩包中的“OTP.exe”很可能是一个实现OTP系统的可执行文件,用户可以通过这个程序生成和输入一次性口令。而“www.pudn.com.txt”可能是提供关于这个OTP系统更详细信息的文本文件,或者是一份使用指南。 总的来...

    rabbitMQ安装包与环境(rabbitmq-server-3.7.0+otp_win64_20.2)

    在本文中,我们将深入探讨RabbitMQ的安装过程,以及与之相关的OTP(Open Telecom Platform)环境。 首先,我们要了解OTP是什么。OTP是由Ericsson开发的一套软件开发框架,它包含了Erlang编程语言的库和工具,为构建...

    官网otp_src_21.3.tar.gz

    在windows下解压后就是otp_src_21.3.tar.gz文件,然后拷贝到服务器上进行安装即可。RabbitMQ环境所需的Erlang软件,适用RabbitMQ的版本:3.7.25 3.7.24 3.7.23 3.7.22 3.7.21 3.7.20 3.7.19

    otp_win64_24.0.zip

    OTP(Open Telecom Platform)是Erlang的核心组件,提供了一整套库、设计原则和工具,旨在帮助开发者构建高效、可靠的系统。 标题"otp_win64_24.0.zip"指的是OTP的Windows 64位版本的24.0发行版的压缩文件。这个...

    erlang OTP Design Principles之Gen中文

    本文将深入探讨Gen_Fsm的行为及其在Erlang OTP中的应用。 首先,Gen_Fsm行为的核心是一个有限状态机(FSM),它通过一系列状态(State)和事件(Event)来描述系统的行为。当系统处于某个状态S,并且接收到事件E时...

    otp_22.3_for_windows_64 和RabbitMQ-server-3.8.5安装包

    自己自学RabbitMQ整理出来的资料,windows环境下的erlang和RabbitMQ安装包,版本分别是otp_22.3_for_windows_64和rabbitmq-server-3.8.5(保证不会出现版本冲突) 在官网上下载简直是龟速,所以分享给大家便于下载,...

Global site tag (gtag.js) - Google Analytics