在《Programming Erlang》的OTP introduction章节中,作者通过循序渐进的方式,向我们展示了gen_server设计思路,现在做下总结:
在具体看gen_server之前,我们先看一个server通用框架:
在这个server里,你几乎看不到任何和具体功能相关的东西,它只提供了一个server所具备的基本框架,那它是如何运行的呢?
当我们调用start函数时,就启动了一个服务,如果服务器接收到一条消息,那么它将会把这条消息转交给Mod:handle_call或者Mod:handle_cast处理 ,然后把执行结果返回给客户端(可选),接着继续等待新消息。
从这个过程中我们不难发现,服务器实际上充当着“代理”的角色,而真正处理客户端请求的其实是另外一个Module(我们称之为:callback模块)
这样有什么好处呢? 我谈谈自己的拙见:
1.解耦,把服务器功能部分和非公能部分分离,这样可以我们就可以更加专注于服务器功能模块的编写(即callback模块)
2.复用性,如果我们希望开发一个具有新功能的server,我们可以复用现有的server框架,然后编写具有新功能的callback Module即可
现在我们看一个callback Module例子(它提供了KV存储功能)
其中init, handle_call方法是用来供server端回调的,而add,find,start方法是供客户端调用的
我们看下执行结果:
现在我们来简单分析下整个执行流程:
stroage:start() 启动了一个名为kv_server的服务,并且使用storage模块作为该服务的callback Module, 接着就阻塞在loop方法中,等待着新消息的到来....这时候,当我们调用storage:add(name, diaocow),就向kv_server发送了一条请求消息{add, name, diaocow},当kv_server接受到这条消息后,自己并没有处理,而是转交给他的callback模块storage处理,并且把处理后的结果返回给客户端,,然后继续等待着新消息...
可以看出server模块充当着代理的角色(接受客户端消息 -> 发给callback模块处理 -> 将处理结果返回给客户端),而storage模块一方面给server提供callback(真正负责处理客户端请求),另一方面给客户端提供了可以调用的接口(譬如这里的add和find接口)。
当你需要修改这个server的功能时,只需要修改callback模块即可,是不是非常方便呢 ^_^
---------------------------------------------------------------------华丽分割线-------------------------------------------------------------------
说了那么多,那么gen_server到底是什么呢? 其实它提供了类似上述理念的通用server框架,只不过比我们更加稳健,完善,如果你需要编写具有某个功能的server,使用gen_server可以让你专注于功能本身的编写,即callback模块
那如何编写一个gen_server的callback模块呢?只需三步
1.给你的callback Module起一个名字
2.确定需要向外界(客户端)提供的接口
3.实现gen_server所要求的回调接口
现在我们使用gen_server重新实现一下KV存储
运行下程序,一切ok
现在我们就详细解释下new_storage模块中每个方法的作用:
1.-behaviour(gen_server)
它表示让编译器检查,当前module是否实现了gen_server指定的所有回调接口,若我注释掉某一个回调接口(譬如code_change/3),编译时会报:
2.gen_server:start_link(ServerName, Module, Args, Options) -> Result
这个方法用来启动一个server,其中:
参数ServerName指定了服务名
参数Module指定了该server的callback模块
参数Args将作为服务初始化的启动参数(服务初始化时会调用:Module:init([Args]))
参数Options指定了一些特性参数,通常可以直接使用[]
如果服务启动成功,返回{ok, Pid}
3.Module:init([Args])
这个方法会在服务初始化时被回调,参数Args就是gen_server:start_link中倒数第二个参数,若初始化成功,该方法放回{ok, State},其中State将作为启动服务的State
4.gen_server:call(ServerRef, Request)
这个方法供callback模块向ServerRef代表的服务发送Request请求(callback模块通常会在之上再封装一层接口供客户端调用,譬如这里的add,find方法),注意该方法是一个
同步调用,它会一直等待服务器返回一个响应消息(除非等待超时,默认5s)
5.Module:handle_call(Request, From, State) -> Result
这是一个回调方法,用来处理gen_server:call(ServerRef, Request)发出的请求,其中:
Request,表示客户端请求
From,表示请求来自哪个客户端
State,表示当前服务器状态
Result为handle_call 请求处理结果,它有以下几种类型
{reply,Reply,NewState}
{reply,Reply,NewState,Timeout}
{reply,Reply,NewState,hibernate}
{noreply,NewState}
{noreply,NewState,Timeout}
{noreply,NewState,hibernate}
{stop,Reason,Reply,NewState} | {stop,Reason,NewState}
这几种返回值有什么区别呢?
如果返回的是以reply开头,那么Reply将会作为响应返回给客户端
如果返回的是以noreply开头,那么服务器将不会返回任何消息给客户端(这会导致客户端阻塞,因为客户端调用的gen_server:call方法是一个同步调用,当它发出请求后,会一直等待服务器发送响应消息,除非等待超时)
6.gen_server:cast(ServerRef, Request)
这个方法同gen_server:call(ServerRef, Request),但它最大的区别就是该调用是
异步的,它不需要等待服务器返回任何处理结果
7.Module:handle_cast(Request, State) -> Result
这个方法用来处理gen_server:cast(ServerRef, Request)发出的请求,由于不会返回结果给客户端,所以参数列表中也没有From
关于gen_server更多api,请参看:
http://www.erlang.org/doc/man/gen_server.html
otp官方文档:
http://www.erlang.org/doc/design_principles/gen_server_concepts.html
现在我们已经把gen_server设计的大体思想说了一遍,即:gen_server实现了一个通用server框架,若我们需要开发某功能,只需要按照gen_server回调接口规范,编写相应的callback Module即可
- 大小: 34.9 KB
- 大小: 23.1 KB
- 大小: 6.1 KB
- 大小: 44.3 KB
- 大小: 7.3 KB
- 大小: 4.3 KB
分享到:
相关推荐
在IT行业中,`gen_server`是Erlang OTP(开放电信平台)框架中的一个核心组件,它提供了一种模式化的方式来实现服务器进程。本篇博客“gen_server tasting 之超简单名称服务(续)”主要探讨了如何使用gen_server来...
gen_tcp是Erlang OTP(开放电信平台)提供的一种行为模块,它允许程序员以面向过程的方式处理TCP连接。gen_tcp提供了创建、监听、接受和关闭TCP套接字的函数,以及发送和接收数据的基本操作。 **Erlang的并发特性**...
7. **行为模块**:如gen_server、gen_event、gen_fsm等,是OTP设计模式的具体实现,简化了编写服务器、事件处理器和有限状态机的代码。 关于压缩包内的"otp_src_17.3",这是Erlang OTP 17.3版本的源代码目录。为了...
2. **gen_server行为**:gen_server是Erlang OTP中最常用的行为模式,它提供了一个通用服务器模板,支持请求-响应模型。通过gen_server,你可以创建状态管理服务器,处理同步和异步调用,同时支持定时任务和错误处理...
2. OTP框架:理解其模块化设计、行为(gen_server, gen_event等)、分布式应用和系统监控。 3. RabbitMQ基本概念:掌握消息队列的工作原理、交换器(exchanges)、队列(queues)、绑定(bindings)以及消费者...
`gen_server.html`描述的是通用服务器行为(Gen_server),它是Erlang OTP中最常用的进程行为之一。Gen_server提供了一种标准的接口来处理同步和异步请求,处理状态管理和错误处理。它们是构建复杂服务的基础,通常...
gen_server是Erlang OTP(开放电信平台)设计模式之一,它为服务器进程提供了一个通用框架,处理请求、状态管理和错误处理。在聊天室应用中,gen_server可以被用来管理用户登录、保持用户状态、接收和转发消息。每个...
OTP是Erlang生态系统的重要组成部分,提供了许多预先设计好的行为模式(如 gen_server、gen_event 和 supervisor),这些模式使得开发者能够快速构建出符合Erlang并发哲学的应用程序。 otp_src_21.3.tar是Erlang ...
在IT行业中,`gen_server` 是Erlang OTP(开放电信平台)框架中的一个核心行为模块,用于构建可靠且容错的服务。它提供了一种模式,使得开发者可以编写并发、状态管理和故障恢复的服务器进程。在"gen_server tasting...
OTP提供了几个设计良好的应用框架,如gen_server、gen_event、gen_fsm等,它们是基于行为模式的模块,简化了并发编程和状态管理。 5. **分布式功能** OTP支持跨节点的分布式计算,使得在多台机器上构建分布式系统...
Erlang OTP设计原理是一份深入探讨Erlang/OTP(Open Telecom Platform)框架中设计模式和组织代码原则的文档。Erlang OTP作为Erlang语言的中间件平台,提供了构建可扩展和容错系统的标准方法。 文档开篇就介绍了...
此“Erlang-OTP-API 离线查询英文全手册”是Erlang OTP的官方文档,包含了所有API的详细信息,是学习和开发Erlang OTP应用的重要资源。手册内容广泛,包括了以下几个核心部分: 1. **模块和函数**:手册详细列出了...
1. **Erlang OTP(Open Telecom Platform)**:Erlang OTP是一个标准库,提供了强大的模块化设计和容错机制,包括行为模式如GenServer、GenEvent和Supervisor等,这些对于构建可靠的TCP服务器至关重要。 2. **...
1. **模块化设计**:OTP提供了各种预定义的进程行为模式(gen_server、gen_event、gen_fsm等),便于开发者创建符合特定模式的进程,提高了代码复用和可维护性。 2. **分布式计算**:Erlang OTP支持跨节点的进程...
1. 监督树(Supervision Trees):监督树是Erlang/OTP的核心概念之一,它是一种分层的组织结构,用于管理进程的生命周期。在这个结构中,有两类主要的进程类型:工作者进程(Worker Processes)和监督进程...
其gen_server行为模式是Erlang OTP(开放电信平台)的一部分,用于构建具有状态的服务器。在这个项目中,gen_server被用来处理文件的存储和检索请求,实现文件服务的持久化状态管理。 2. **gen_server**:gen_...
例如,Gen_Server和Gen_Fsm都是Erlang OTP提供的行为模式,它们定义了处理消息的基本结构,并要求开发者实现与具体逻辑相关的回调函数。 应用(Application)在Erlang/OTP中是一个封装了代码、模块、资源文件和配置...