`
aiquantong
  • 浏览: 112735 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

erlang 学习之OTP 中 gen_server (一)

阅读更多

好记性,不如烂鼻头!!

 

说明我们的事例都是来自《erlang程序设计》第16节,但是会做我自己调整,以使其更接近OTP的标准gen_server模版本省。

 

本例分成三大部分,第一部分 是对《erlang程序设计中的代码》中简单例子进行说明;第二部分是关注如何更快速地编写一个gen_server服务;第三部分是gen_server标准实现源代码分析,看看我们还需要补充什么!!

 

现在就开始了!

ex1: server1

 

-module(server1).
-export([start/2,rpc/2]).

%%启动一个空的等待进程
start(Name, Mod) ->
    register(Name, spawn(fun() -> loop(Name,Mod, Mod:init())end)).

%远程调用接口
rpc(Name,Request) ->
    Name ! {self(),Request},
    receive 
        {Name, Response} ->
            Response
    end.
    
loop(Name,Mod,State)->
    receive 
        {From,Request}->
            %%回到具体的函数处理模块
            %%并返回 结果集 和 状态值
            {Response , State1} = Mod:handle_call(Request,State),
            %%返回到到rpc的值
            From ! {Name, Response},
            %% 采用尾递归技术来循环
            loop(Name,Mod,State1)
    end.



-module(name_server1).

%%给server1回到函数
-export([init/0,handle_call/2]).


-export([add/2,whereis/1]).

start()->server1:start(name_server,name_server1).

init()->dict:new().
    
handle_call({add,Name,Place},Dict) -> {ok,dict:store(Name,Place,Dict)};

handle_call({whereis,Name},Dict) ->{dict:find(Name,Dict),Dict}.


add(Name,Place) -> server1:rpc(name_server,{add,Name,Place}).

whereis(Name) -> server1:rpc(name_server,{whereis,Name}).

  

 ex2:server2 加入异常处理机制

-module(server2).
-export([start/2,rpc/2]).

start(Name, Mod) ->
    register(Name, spawn(fun() -> loop(Name,Mod, Mod:init())end)).

rpc(Name,Request) ->
    Name ! {self(),Request},
    receive
        {Name,crash} -> exit(rpc);
        {Name, ok, Response} -> Response
    end.
    
loop(Name,Mod,OldState)->
    receive 
        {From,Request}->
            try Mod:handle_call(Request,OldState) of
                {Response, NewState} ->
                    From ! {Name,Response},
                    loop(Name,Mod,NewState)
              %% 加入了异常处理机制 当出现则回调 terminate函数  请求      
            catch
                _:Why ->
                    From ! {Name, crash},
                    Mod:terminate(Why, OldState)
            end
    end.



-module(name_server2).

%%给server1回到函数
%%增加 中止的回调函数
-export([init/0,handle_call/2, terminate/2 ]).


-export([add/2,whereis/1]).

start()->server2:start(name_server, name_server2).

init()->dict:new().
    
%%当发生中止时 回调函数
terminate(Reason, State)->
    io:format("server caused exception ~p state ~p ~n",[Reason,State]).


handle_call({add,Name,Place},Dict) -> {ok,dict:store(Name,Place,Dict)};

handle_call({whereis,Name},Dict) ->{dict:find(Name,Dict),Dict}.


add(Name,Place) -> server2:rpc(name_server,{add,Name,Place}).

whereis(Name) -> server2:rpc(name_server,{whereis,Name}).



 

ex3: server3 加入热代码备份

%% ---
%%  Excerpted from "Programming Erlang",
%%  published by The Pragmatic Bookshelf.
%%  Copyrights apply to this code. It may not be used to create training material, 
%%  courses, books, articles, and the like. Contact us if you are in doubt.
%%  We make no guarantees that this code is fit for any purpose. 
%%  Visit http://www.pragmaticprogrammer.com/titles/jaerlang for more book information.
%%---
-module(server3).
-export([start/2, rpc/2, swap_code/2]).

start(Name, Mod) ->
    register(Name, 
	     spawn(fun() -> loop(Name,Mod,Mod:init()) end)).

rpc(Name, Request) ->
    Name ! {self(), Request},
    receive
        {Name, Response} -> Response
    end.

loop(Name, Mod, OldState) ->
    receive
	{From, {swap_code, NewCallBackMod}} ->
            %% 发送 确认信息到对应的字段
	    From ! {Name, ack},
            %% 开启新的代码处理流程循环
	    loop(Name, NewCallBackMod, OldState);
	{From, Request} ->
	    {Response, NewState} = Mod:handle_call(Request, OldState),
	    From ! {Name, Response},
	    loop(Name, Mod, NewState)
    end.


-module(name_server2).

%%给server1回到函数
%%增加 中止的回调函数
-export([init/0,handle_call/2, terminate/2 ]).


-export([add/2,whereis/1]).

start()->server3:start(name_server, name_server2).

init()->dict:new().
    
%%当发生中止时 回调函数
terminate(Reason, State)->
    io:format("server caused exception ~p state ~p ~n",[Reason, State]).


handle_call({add,Name,Place},Dict) -> {ok,dict:store(Name,Place,Dict)};

handle_call({whereis,Name},Dict) ->{dict:find(Name,Dict),Dict}.


add(Name,Place) -> server3:rpc(name_server,{add,Name,Place}).

whereis(Name) -> server3:rpc(name_server,{whereis,Name}).

%% 增加热代码替换工作
swap_code(Name, Mod) -> server3:rpc(Name, {swap_code, Mod}).

 

ex4  综合并加入 状态控制

%% ---
%%  Excerpted from "Programming Erlang",
%%  published by The Pragmatic Bookshelf.
%%  Copyrights apply to this code. It may not be used to create training material, 
%%  courses, books, articles, and the like. Contact us if you are in doubt.
%%  We make no guarantees that this code is fit for any purpose. 
%%  Visit http://www.pragmaticprogrammer.com/titles/jaerlang for more book information.
%%---
-module(server4).
-export([start/2, call/2, swap_code/2]).

start(Name, Mod) ->
    register(Name, spawn(fun() -> loop(Name,Mod,Mod:init()) end)).

swap_code(Name, Mod) -> call(Name, {swap_code, Mod}).

call(Name, Request) ->
    Name ! {self(), Request},
    receive
        {Name, crash} -> exit(rpc);
        {Name, ok, Response} -> Response
    end.

%% 加入状态判读
loop(Name, Mod, OldState) ->
    receive
	{From, {swap_code, NewCallbackMod}} ->
           case Mod:code_change(OldState) of
               {ok, _State}->
               	    From ! {Name, ok, ack},
                    loop(Name, NewCallbackMod, OldState);
               {stop, _state}->
                    From ! {Name, crash}
                end;
	{From, Request} ->
	    try Mod:handle_call(Request, OldState) of
		{reply, Response, NewState} ->
		    From ! {Name, ok, Response},
		    loop(Name, Mod, NewState);
                {noreply, NewState} ->
		    loop(Name, Mod, NewState)
	    catch
		_: Why ->
		    From ! {Name, crash},
		    Mod:terminate(Why, OldState)
	    end
    end.


-module(name_server4).

%%给server1回到函数
%%增加 中止的回调函数
-export([init/0,handle_call/2, code_change/1, terminate/2 ]).


-export([add/2,whereis/1]).

start()->server3:start(name_server, name_server4).

init()->dict:new().
    
code_change(_State)->
    {ok}.

%%当发生中止时 回调函数
terminate(Reason, State)->
    io:format("server caused exception ~p state ~p ~n",[Reason, State]).

handle_call({add,Name,Place},Dict) -> {reply,ok,dict:store(Name,Place,Dict)};

handle_call({whereis,Name},Dict) ->{reply,dict:find(Name,Dict),Dict}.


add(Name,Place) -> server4:rpc(name_server,{add,Name,Place}).

whereis(Name) -> server4:rpc(name_server,{whereis,Name}).

%% 增加热代码替换工作
swap_code(Name, Mod) -> server4:rpc(ok, Name, {swap_code, Mod}).




 

 

分享到:
评论

相关推荐

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

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

    erlang_otp_src_17.3.tar.gz

    标题中的"erlang_otp_src_17.3.tar.gz"是一个源码压缩包,包含了Erlang OTP 17.3版本的源代码。由于从官网下载可能速度较慢,这个压缩包提供了方便,用户可以直接下载并进行编译安装。 Erlang 是一种静态类型、函数...

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

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

    otp_src_21.1.tar.gz

    OTP(Open Telecommunications Platform)是Erlang编程语言的核心组件之一,它提供了一套用于构建高效、可靠和可扩展的分布式系统的工具和库。otp_src_21.1.tar.gz 是OTP的一个源代码版本,对应于Erlang的21.1版本。...

    otp_src_22.0_h.tar.gz

    OTP提供了几个设计良好的应用框架,如gen_server、gen_event、gen_fsm等,它们是基于行为模式的模块,简化了并发编程和状态管理。 5. **分布式功能** OTP支持跨节点的分布式计算,使得在多台机器上构建分布式系统...

    otp_win64_23.1.exe|otp_win64_23.1.zip

    标题中的"otp_win64_23.1.exe"是一个Erlang的Windows 64位版本的可执行安装程序,OTP(Open Telephony Platform)是Erlang的开源工具集,包含了运行Erlang虚拟机和开发分布式系统所需的各种库和服务。Erlang是一种...

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

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

    ErlangOTP 21.3.zip

    OTP是Erlang生态系统的重要组成部分,提供了许多预先设计好的行为模式(如 gen_server、gen_event 和 supervisor),这些模式使得开发者能够快速构建出符合Erlang并发哲学的应用程序。 otp_src_21.3.tar是Erlang ...

    Erlang_OTP_设计原理(含目录).pdf

    Erlang OTP设计原理是一份深入探讨Erlang/OTP(Open Telecom Platform)框架中设计模式和组织代码原则的文档。Erlang OTP作为Erlang语言的中间件平台,提供了构建可扩展和容错系统的标准方法。 文档开篇就介绍了...

    erlang 聊天室

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

    Erlang_OTP_设计原理 中文版

    1. 监督树(Supervision Trees):监督树是Erlang/OTP的核心概念之一,它是一种分层的组织结构,用于管理进程的生命周期。在这个结构中,有两类主要的进程类型:工作者进程(Worker Processes)和监督进程...

    Erlang OTP设计原理文档 中文版本

    `gen_server.html`描述的是通用服务器行为(Gen_server),它是Erlang OTP中最常用的进程行为之一。Gen_server提供了一种标准的接口来处理同步和异步请求,处理状态管理和错误处理。它们是构建复杂服务的基础,通常...

    erlang tcp_server

    1. **Erlang OTP(Open Telecom Platform)**:Erlang OTP是一个标准库,提供了强大的模块化设计和容错机制,包括行为模式如GenServer、GenEvent和Supervisor等,这些对于构建可靠的TCP服务器至关重要。 2. **...

    Erlang-OTP-API 离线查询英文全手册

    例如,`gen_server`模块是OTP行为模型之一,用于创建服务器进程,提供了一套标准的接口来实现请求处理和状态管理。 2. **错误处理和容错**:Erlang OTP强调容错性,手册中会有详细介绍如何通过进程监控(`monitor`...

    Erlang OTP并发编程实战 附书源码

    2. **gen_server行为**:gen_server是Erlang OTP中最常用的行为模式,它提供了一个通用服务器模板,支持请求-响应模型。通过gen_server,你可以创建状态管理服务器,处理同步和异步调用,同时支持定时任务和错误处理...

    Erlang实战

    - **gen_server** 是OTP中最常用的行为之一,主要用于维护状态或提供某种功能。它可以被看作是客户端/服务器架构的一种抽象。 - 用户模块需要定义一系列回调函数,如 `init/1`、`handle_call/3`、`handle_cast/2` 等...

    Erlang/OTP 中文手册(R11B)

    R11B是Erlang/OTP的一个早期版本,尽管较新版本可能包含了更多的功能和优化,但R11B中的概念和原理对于理解Erlang/OTP的基石仍然是至关重要的。手册中可能涵盖了以下内容: - R11B的改进和新增特性。 - OTP设计原则...

    基于erlang的文件存储

    2. **gen_server**:gen_server是Erlang中的一种行为(behavior),它提供了一种标准的方式来处理服务请求、状态管理和错误处理。在文件存储系统中,gen_server可能包含如下功能:接收上传请求,将文件保存到磁盘,...

Global site tag (gtag.js) - Google Analytics