erlang mysql:start_link_[Erlang开发之路]二十二、OTP入门

什么是OTP编程?

可以看作一个用回调函数作为参数的应用程序框架,利用gen_server模块可以实现事物语义和代码热更新,OTP是Open Telecom Platform的缩写,它能帮我们编写大型的、容错的,分布式的系统。刚看这本书的时候,joe大爷说,我们来领悟Erlang中的哲学吧,我寻思又是一些什么奇奇怪怪的东西,其实也就是想向读者表达Erlang的世界观:"一切皆为进程",进程是Erlang的基础设施,不管要完成什么功能,进程都会遵循通用的行为模式,这些进程模式可以称为模式的模式;我们直接使用进程做开发的时候会遵循这个模式,behavior的实现同样遵循进程模式.OTP behaviour包含gen_server gen_event gen_fsm supervisor.其中绝大多数情况下都是在使用gen_server,supervisor本身也是使用gen_server实现的.我们就以gen_server做为起点,逐步学习Erlang OTP.

1.gen_server模块(OTP中其中一种抽象的编程模式)

按照joe大爷的脑回路,想要深入学习一门东西并领悟精髓,就是去了解它的原理,去模仿他,类似重构,在这里我就不再把书上的代码贴出来了,我直接把我所理解的gen_server表达出来:

1.事物语义的实现

什么是事物语义呢?说实话我解释不出来,我只知道书上的代码,会截取抛出的错误,并用错误之前的上下文(书上称是服务器的状态,但我觉得上下文更符合)继续运行软件,也就是服务器时光倒退到了发生错误之前的一刻,而没发生错误的时候,时时刻刻都在更新服务器的上下文。

2.热代码更新的实现

gen_server模块自带了热更新的功能,Erlang允许程序代码在运行系统中被修改。旧代码能被逐步淘汰而后被新代码替换。在此过渡期间,新旧代码是共存的。

3.gen_server的组成

在我看来,最主要就是分为:回调函数(handle_call抽象函数的实例化)、接口函数(供用户调用)、启动\停止程序

handle_call(Recv,From,State)->{reply,Reply,newState}

%% Recv通常为tag tuple也就是带标签的元组,这样就可以重载多个回调函数,例如{action,A,B}.

%% State是旧的服务器状态,也就是我说的上下文环境

%% Reply是我们自定义的返回数据

%% newState是我们在回调函数中一系列的操作后,变更的上下文环境

handle_info(Info,State)

%% 通过这个函数可以接收一些非自发性的消息比如推出信号

terminate(Reason,State)->ok.

%% 在收到exit信号或者{stop,Reason,NewState}时会被调用

code_change(OldVsn,State,Extra)->{ok,NewState}

%% 在gen_server自动更新代码时被调用

gen_server:start_link({local|global,Name},Mod,[],[])->bool()

%% local和global的区别是前者在本机可调用,global可跨节点

%% Name是为进程注册的原子名称

%% Mod是init([])函数所在的模块名、一般回调和接口函数都在一个模块

init([])->{ok,State}

%%gen_server开始start_link的时候会调用init函数来生成一个初始化的服务器上下文环境

gen_server:call(Name,Request)->Reply

%% 这个函数我们在接口函数会用到,用来远程调用函数

%% Name是我们start_link的时候注册的名称

%% Reuqset其实就是handle_call的时候接收的Recv,带标签的元组,往往第一个原子元素就是我们的动作标识,比如写入分数:{setPoint,Who,100}

%% Reply就是我们在回调函数中的Reply自定义回复数据

gen_server:cast(Name,Request)->{noreply,State}|...

%% 这个远程远程调用函数不会接收返回值

一下贴上我自己对gen_server练习的代码:

-module(otp_server).

-export([start/0,stop/0,init/1,setPoint/2,deletePoint/1,getPoint/1,handle_call/3,handle_cast/2,handle_info/2,terminate/2,code_change/3]).

-behaviour(gen_server).

% Server Start

start()->

gen_server:start_link({local,?MODULE},?MODULE,[],[]).

init([])->

{ok,ets:new(?MODULE,[])}.%Return a new State

stop()->

gen_server:call(?MODULE,stop).

% function call

setPoint(Who,Point)->

gen_server:call(?MODULE,{set,Who,Point}).

deletePoint(Who)->

gen_server:call(?MODULE,{delete,Who}).

getPoint(Who)->

gen_server:call(?MODULE,{get,Who}).

% Handle call

handle_call({set,Who,Point},_From,TableId)->

ets:insert(TableId,{Who,Point}),

Reply={Who,set_point_success},

{reply,Reply,TableId};

handle_call({delete,Who},_From,TableId)->

case ets:lookup(TableId,Who) of

[]->

Reply={Who,this_guy_isnot_exist};

[_]->

Reply=ets:delete(TableId,Who)

end,

{reply,Reply,TableId};

handle_call({get,Who},_From,TableId)->

case ets:lookup(TableId,Who) of

[]->

Reply={Who,this_guy_isnot_exist};

[{Who,Point}]->

Reply={Who,point_is,Point}

end,

{reply,Reply,TableId};

handle_call(stop,_From,TableId)->

{stop,normal,TableId};

handle_call(_,_From,TableId)->

{reply,undefine_command,TableId}.

handle_cast(_Msg,State)->

{noreply,State}.

handle_info(_Info,State)->

{noreply,State}.

terminate(_Reason,_State)->

ok.

code_change(_OldVsn,State,_Extra)->

{ok,State}.

gen_server的内容绝不会止步于此,明日我会继续更新

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值