页游手游服务器(四)事件机制

事件机制主要用于服务器逻辑处理,形式如下:

define.Func1{Arg1=0, Arg2=‘abc'}--定义事件,Func1为事件名,Arg1=0, 指Arg1参数默认值为0,Arg2='abc'指Arg2参数默认值为0,主要用于参数类型验证

when{}

function Func1(Arg1, Arg2)

  逻辑处理1

end

 

when{Arg1=1}

function Func1(Arg1, Arg2)

  逻辑处理2

end

when函数是用来设置下面处理的触发条件

当调用Func1{Arg1=0,Arg2='XXX'}时触发逻辑1

当调用Func2{Arg1=1}时触发逻辑1,逻辑2

_calldefine('Func1', {Arg1=123, Arg2='XX'})效果等同于Func1{Arg1=123, Arg2='XX'}

在上篇说过客户端来的消息包在解析之后放在queue中,结构如:{net,funcname, funcarg}

通过调用_calldefine(funcname, funcarg),实现了客户端调用ServerNet.Func1{Arg1=123, Arg2='XXX'},调用服务器Func1事件,这样实现了RPC调用全过程,事件的机制在实现任务流程特别方便,特别适用于在不修改原来的逻辑的前提下,附加逻辑,

之后会有文章介绍事件机制实现任务流程,需要注意的是事件处理逻辑的执行顺序,实现到这儿为止只能算是较好,较方便,但不能算强健,稳定。

1个服务器最重要的是稳定,其次才算是效率,如果那的逻辑处理写错了,或者漏处理了,然后之后会发生什么,只有天知道了。
对于客户端的请求事件,一般的处理方法是,先是各种判断,然后通过,就去改内存,改数据库,给客户端发消息,记录日志等等,如下:
function func(arg1, arg2)
if 判断1不通过 then 告诉客户端条件不满足1 end
if 判断2不通过 then 告诉客户端条件不满足2 end
if 判断3不通过 then 告诉客户端条件不满足3 end
if 判断4不通过 then 告诉客户端条件不满足4 end
处理1
处理2
处理3
...
end
这种方式是最常见的方式了,有几点不好之处:
1判断可能会漏,处理中可能会出错,最后导致服务器不知道运行在状态了,服务器开发量多了之后,很难保证完全不出错
2判断必须在前,处理在后,不可避免一些逻辑代码要反复执行,代码实现看起来不太好,但是其实在效率并没有太大影响
最好的处理情况是:

对于客户端来的一个事件,如果处理出错了,或者判断请求不合法,最好的处理结果是把状态恢复到请求来之前一样,好像这个事件从来没来过一样,然后给客户端发条提示信息,在log记录下出错的tracback
这样如果某部分出了问题,也不会把数据引向不可知的程度,服务器更稳定,这种方式的局限性主要是:
1不能跨进程(多线程不考虑)
2需要有数据的恢复机制

实现思路如下:
local function beforecall(e)
sql:begin();--事务开始,lazy begin,在lua层做标记,第一次执行sql时开始事务
_calldefine(e.funcname, e.funcarg)
end

local function aftercall(e)
sql:commit();--提交事务
发送客户端事件发送
子事件入队列
end

local function errcall(e)
sql:rollback();--事务回滚
内存丢弃脏数据
发送客户端事件丢弃
子事件丢弃
end

for _, e in next, queue do
local ret = pcall(beforecall, e);
if ret then
aftercall(e)
else
errcall(e)
end
end
发送客户端事件发送或丢弃,子事件入队列或者丢弃都很简单,事务的提交和回滚也是由数据库提供的,也就是说必须要支持事务的数据库,比如mysql

posted on 2014-06-14 17:31  marcher  阅读(296)  评论(0编辑  收藏  举报

导航