OTP: gen_server的简单应用
1、确定回调模块名
2、编写接口函数
3、在回调模块里编写六个必需的回调函数
1、确定回调模块名
my_bank
2、编写接口方法
start() 打开银行
stop() 关闭银行
new_account(Who) 创建一个新账户
deposit(Who,Amount) 把钱存入银行
withdraw(Who,Amount) 把钱取出来(如果有结余的话)。
gen_server:start_link({local,Name},Mod,…) 会启动一个本地服务器。如果第一个参数是原子global,它就会启动一个能被Erlang节点集群访问的全局服务器。start_link的第二参数是Mod,也就是回调模块名。宏?MODULE会展开成模块名my_bank。
gen_server:call(?MODULE,Term)被用来对服务器进行远程过程调用。
3、编写回调方法
回调模块必需导出六个回调方法:
init/1,handle_call/3,handle_cast/2,handle_info/2,terminate/2,code_change/3.
其中的handle_call/3函数最为最重要
这个模块包含了一套简单的框架,可以填充它们来制作服务器。如果忘记定义合适的回调函数,编译器就会根据关键字-behaviour来生成警告或错误消息。start_link()函数里的服务器名(宏?SERVER)需要进行定义,因为它默认是没有定义的。
这段代码中的Reply会作为远程过程调用的返回值发挥客户端。
State 只是一个代表服务器全局状态的变量,它会在服务器里到处传递。在上面的银行模块中,这个状态不会发生变化,只是一个ETS表的索引,属于常量。
启动服务器
gen_server:start_link(Name,Mod,InitArgs,Otps) 这个调用是所有事务的起点。
它会创建一个名为Name的通用服务器,回调模块是Mod,Otps则控制通用服务器的行为。在这里可以指定消息记录、函数调试和其他行为。通用服务器通过调用Mod:init(InitArgs)启动。
初始化服务器
init(Args) -> {ok,State}|
{ok,State,Timeout}|
ignore|
{stop,Reson}
init([]) ->
{ok,#state{}}.
如果返回{ok,State},就说明我们成功启动了服务器,初始状态是State。
调用服务器
要调用服务器,客户端程序需要执行gen_server:call(Name,Request).他最终调用的回调模块里的handle_call/3.
handle_call(Request,From,State) ->
{reply,Reply,State}|
{reply,Reply,State,Timeout}|
{noreply,State}|
{noreply,State,Timeout}|
{stop,Reason,Reply,State}|
{stop,Reason,State}
Request(gen_server:call/2的第二个参数)作为handle_call/3的第一个参数重新出现。From是发送请求的客户端进程PID,State则是客户端的当前状态。
通常会返回{reply,Reply,NewState},Reply会返回客户端,成为gen_server:call的返回值。NewState则是服务器接下来的状态。
noreply会让服务器继续工作,但客户端会等待一个回复,所以服务器必需把回复的任务委派给其他进程。用适当的stop会停止服务器。
gen_server:call和handle_call之间的交互,作用是实现远程过程调用。
调用和播发
gen_server:cast(Name,Msg)则实现了一个播发(cast),也就是没有返回值得调用(实际上就是一个消息,但习惯上称它为播发来与远程过程调用相区分)。
handle_cast(Msg,State) ->
{noreply,State}|
{noreply,State,Timeout}|
{stop,Reason,State}
发给服务器的自发性消息
回调函数handle_info(Info,State)被用来处理发给服务器的自发性消息。
自发性消息是一切未经显示调用gen_server:call或gen_server:cast而到达服务器的消息。
例如:如果服务器连接到另一个进程并捕捉推出信号,就可能会突然收到一个预料之外的{‘EXIT’,Pid,What}消息。除此之外,系统里任何知道通用服务器PID的进程都可以向它发送消息。这样的消息在服务器里表现为info值。
handle_info(_Info,State) ->
{noreply,State}|
{noreply,State,Timeout}|
{stop,Reason,State}
后会有期,宝贝
服务器会因为许多原因而终止。某个以handle_开头的函数也许会返回一个{stop,Resason,NewState},服务器也可能崩溃并生成{‘EXIT',reason}。在所有这些情况下,无论他们是怎样发生的,都会调用terminate(Reason,NewState)。模板如下:
这个函数是在某个gen_server即将终止时调用的。
它应当是Module:init/1的逆操作,并进行必要的清理。
当他返回时,<mod>gen_server</mod>终止并生成原因Reason。
terminate(Reason,State) -> void().
这段代码不能返回一个新状态,因为已经终止。
但是了解服务器的终止状态非常有用。可以把状态保存到磁盘,把它放入消息发送给别的进程,或者根据应用程序的意愿丢弃它。如果想让服务期过后重启,就必须编写重启函数,由terminate/2触发。
代码更改
在服务器运行时更改它的状态。这个回调函数会在系统执行软件升级时由版本处理子系统调用。
在代码更改时转换进程状态
code_change(OldVsn,State,Extra) -> {ok,NewState}
参考引用:
Erlang程序设计(第二版)
OTP: gen_server的简单应用的更多相关文章
- erlang OTP gen_server 图解分析
http://www.hoterran.info/otp-gen_server-sourcecode 在阅读erlang的otp源码gen_server.erl的时候,一直想写点什么,用一种最好的方式 ...
- OTP gen_server
erlang behaviour小结之gen_server OTP入门 分类: Erlang2012-08-06 18:55 867人阅读 评论(0) 收藏 举报 servererlangcallba ...
- 使用Erlang和Yaws开发REST式的服务
看过那张很出名的“Apache vs. Yaws”图么?是不是在考虑你也应该使用Yaws了?这些图给人的第一印象是,Yaws在可伸缩性上具有难以置信的巨大优势,它可以扩展到80000个并行的连接,而 ...
- Mochiweb的设计分析
http://blog.csdn.net/dp0304/article/details/6994435 Web服务器的基本工作大致分3步: 接收HTTP请求: 处理HTTP请求,生成响应内容: 发送响 ...
- Erlang OTP编程初体验——gen_server和行为模式
http://blog.sina.com.cn/s/blog_3fe961ae0101k4p6.html 行为模式其实非常类似于面向对象语言中的接口,至少笔者是这么理解的.OTP行为模式将一些反复出现 ...
- Erlang 104 OTP
笔记系列 Erlang环境和顺序编程Erlang并发编程Erlang分布式编程YawsErlang/OTP 日期 变更说明 2014-12-21 A Outline, 1 A ...
- Erlang/OTP设计原则(文档翻译)
http://erlang.org/doc/design_principles/des_princ.html 图和代码皆源自以上链接中Erlang官方文档,翻译时的版本为20.1. 这个设计原则,其实 ...
- Erlang cowboy 处理简单的HTTP请求
Erlang cowboy 处理简单的HTTP请求 原文出自: Handling plain HTTP requests 处理请求的最简单的方式是写一个简单的HTTP处理器.它的模型参照Erlang/ ...
- Erlang/OTP:基于Behaviour的回调函数
原始链接:https://blog.zhustec.me/posts/erlang-otp-1-callback-based-on-behaviour OTP 是什么 OTP 的全称是开源电信平台 ( ...
- Erlang generic standard behaviours -- gen_server hibernate
hibernate 主要用于在内存空闲时,通过整理进程的stack,回收进程的heap 来达到回收内存节省资源的效果. hibernate 可用于OTP 进程以及普通进程, hibernate 的官方 ...
随机推荐
- 火山引擎 DataLeap:揭秘字节跳动数据血缘架构演进之路
更多技术交流.求职机会,欢迎关注字节跳动数据平台微信公众号,回复[1]进入官方交流群 DataLeap 是火山引擎数智平台 VeDI 旗下的大数据研发治理套件产品,帮助用户快速完成数据集成.开发.运维 ...
- CF1303F 题解
题意 传送门 有一个 \(n\times m\) 的矩阵,初始全是 \(0\).我们定义 \(a_{i,j}\) 表示矩阵中第 \(i\) 行第 \(j\) 列的元素. 如果两个格子有相邻边并且格子中 ...
- windows注册表的读
1.打开 2.读取 //打开注册表 CString CDownDlg::GetPortCom(int nmber)//读取操作表,其类型为REG_SZ { CString ans; CString r ...
- TypeError: 'int' object is not subscriptable 报错
Python中报错TypeError: 'int' object is not subscriptable 原因:整形数据中加了下标索引 例如 #python utf-8 a = 10 b = a[0 ...
- 打卡ts day01 数据类型,类
一,环境 1 新增的数据类型和部分语法,没有办法在浏览器和node 中执行,需要安装typescript 环境 安装:npm i -g typescript 成功:tsc -v 2 在浏览器中使用ts ...
- js正则匹配多行文本
原文:https://lwebapp.com/zh/post/regular-expression-to-match-multiple-lines-of-text 需求 最近有小伙伴提了个需求,想用正 ...
- Mybatis的几种传参方式
前言 单个参数 多个参数 使用索引[不推荐] 使用@Param 使用Map POJO[推荐] List传参 数组传参 总结 单个参数 单个参数的传参比较简单,可以是任意形式的,比如#{a}.#{b}或 ...
- "人生重开模拟器",10分钟轻松搭建!
人生重开模拟器是最近爆火的一款非常好玩的模拟游戏,会带你走入一个有趣的世界,开启全新的人生旅程,即"人生重开". 然而实际上,这款游戏短短在3天内上线,在百度贴吧.朋友圈.QQ群. ...
- JavaSE——subString()方法
package com.zhao.stringtest;public class Test4 { //手机号屏蔽中间四位 //subString(int beginIndex,int endIndex ...
- git 修改commit 备注
1.没有push 1.修改最后一次的提交备注 git commit --amend 输入 i 进行编辑模式,修改好以后 esc 退出编辑模式 :wq 保存并退出. 2.修改之前的备注 git reba ...