好记性,不如烂鼻头!!
说明我们的事例都是来自《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}).
分享到:
相关推荐
在IT行业中,`gen_server`是Erlang OTP(开放电信平台)框架中的一个核心组件,它提供了一种模式化的方式来实现服务器进程。本篇博客“gen_server tasting 之超简单名称服务(续)”主要探讨了如何使用gen_server来...
标题中的"erlang_otp_src_17.3.tar.gz"是一个源码压缩包,包含了Erlang OTP 17.3版本的源代码。由于从官网下载可能速度较慢,这个压缩包提供了方便,用户可以直接下载并进行编译安装。 Erlang 是一种静态类型、函数...
gen_tcp是Erlang OTP(开放电信平台)提供的一种行为模块,它允许程序员以面向过程的方式处理TCP连接。gen_tcp提供了创建、监听、接受和关闭TCP套接字的函数,以及发送和接收数据的基本操作。 **Erlang的并发特性**...
OTP(Open Telecommunications Platform)是Erlang编程语言的核心组件之一,它提供了一套用于构建高效、可靠和可扩展的分布式系统的工具和库。otp_src_21.1.tar.gz 是OTP的一个源代码版本,对应于Erlang的21.1版本。...
OTP提供了几个设计良好的应用框架,如gen_server、gen_event、gen_fsm等,它们是基于行为模式的模块,简化了并发编程和状态管理。 5. **分布式功能** OTP支持跨节点的分布式计算,使得在多台机器上构建分布式系统...
标题中的"otp_win64_23.1.exe"是一个Erlang的Windows 64位版本的可执行安装程序,OTP(Open Telephony Platform)是Erlang的开源工具集,包含了运行Erlang虚拟机和开发分布式系统所需的各种库和服务。Erlang是一种...
在IT行业中,`gen_server` 是Erlang OTP(开放电信平台)框架中的一个核心行为模块,用于构建可靠且容错的服务。它提供了一种模式,使得开发者可以编写并发、状态管理和故障恢复的服务器进程。在"gen_server tasting...
OTP是Erlang生态系统的重要组成部分,提供了许多预先设计好的行为模式(如 gen_server、gen_event 和 supervisor),这些模式使得开发者能够快速构建出符合Erlang并发哲学的应用程序。 otp_src_21.3.tar是Erlang ...
Erlang OTP设计原理是一份深入探讨Erlang/OTP(Open Telecom Platform)框架中设计模式和组织代码原则的文档。Erlang OTP作为Erlang语言的中间件平台,提供了构建可扩展和容错系统的标准方法。 文档开篇就介绍了...
gen_server是Erlang OTP(开放电信平台)设计模式之一,它为服务器进程提供了一个通用框架,处理请求、状态管理和错误处理。在聊天室应用中,gen_server可以被用来管理用户登录、保持用户状态、接收和转发消息。每个...
1. 监督树(Supervision Trees):监督树是Erlang/OTP的核心概念之一,它是一种分层的组织结构,用于管理进程的生命周期。在这个结构中,有两类主要的进程类型:工作者进程(Worker Processes)和监督进程...
`gen_server.html`描述的是通用服务器行为(Gen_server),它是Erlang OTP中最常用的进程行为之一。Gen_server提供了一种标准的接口来处理同步和异步请求,处理状态管理和错误处理。它们是构建复杂服务的基础,通常...
1. **Erlang OTP(Open Telecom Platform)**:Erlang OTP是一个标准库,提供了强大的模块化设计和容错机制,包括行为模式如GenServer、GenEvent和Supervisor等,这些对于构建可靠的TCP服务器至关重要。 2. **...
例如,`gen_server`模块是OTP行为模型之一,用于创建服务器进程,提供了一套标准的接口来实现请求处理和状态管理。 2. **错误处理和容错**:Erlang OTP强调容错性,手册中会有详细介绍如何通过进程监控(`monitor`...
2. **gen_server行为**:gen_server是Erlang OTP中最常用的行为模式,它提供了一个通用服务器模板,支持请求-响应模型。通过gen_server,你可以创建状态管理服务器,处理同步和异步调用,同时支持定时任务和错误处理...
R11B是Erlang/OTP的一个早期版本,尽管较新版本可能包含了更多的功能和优化,但R11B中的概念和原理对于理解Erlang/OTP的基石仍然是至关重要的。手册中可能涵盖了以下内容: - R11B的改进和新增特性。 - OTP设计原则...
2. **gen_server**:gen_server是Erlang中的一种行为(behavior),它提供了一种标准的方式来处理服务请求、状态管理和错误处理。在文件存储系统中,gen_server可能包含如下功能:接收上传请求,将文件保存到磁盘,...