使用 OpenResty 为基础的 game server 架构,请各位提意见

2,294 views
Skip to first unread message

dualface

unread,
Oct 27, 2013, 12:05:24 PM10/27/13
to open...@googlegroups.com
我们是做手游的团队,最近一款游戏有不少实时性,正好看到 OpenResty 已经支持了 WebSockets,所以基于 OpenResty 设计了一个 game server 架构。

PS: 选择 OpenResty 的原因是我们前一款游戏也是用的 OpenResty,感觉很不错(虽然最后游戏没有挣到钱)。


整体架构图:



内嵌图片 1

几点说明:

1. 因为现在版本的 cosocket 还不支持同时读写,所以我使用了这个补丁 https://github.com/aviramc/lua-nginx-module/tree/socket-changes
2. redis 是主数据库,日志类数据则存入 mysql,图里没有画出来

----

整个架构的重点有三部分:请求/响应模型,使用 redis 做消息转发,使用 job server 执行延时任务

1. 请求/响应模型

客户端通过 websockets 发送消息给服务端。每个消息都是 JSON 格式。其中包含 action 和 msgid 两个必须的参数。

- action 用于指示要调用服务端哪一个消息处理函数。例如 action = users.auth 就表示要调用服务端 UsersAction 模块的 authAction 方法。
- msgid 用于跟踪消息的执行结果,每一个从客户端发往服务端的消息都会带有一个 msgid(累加值)。当服务端的消息处理函数执行后,通过 websockets 发送消息到客户端,其中会包含请求消息中的 msgid。这样客户端就可以知道从服务端发来的消息是属于先前哪一个请求的反馈。这样模拟了 HTTP 的请求/响应模型,简化了客户端的代码实现。


2. 使用 redis 做消息转发

因为现在没有办法从外部取得一个线程的 cosocket 对象,所以也就无法直接向任意客户端发送消息。为了解决这个问题,我利用 redis 的 pub/sub 特性,实现了一个简单的消息中转机制。

每一个客户端连接到 OpenResty 后,就会创建一个子线程(ngx.thread.spawn)。这个子线程会创建一个 redis 连接,并 subscribe channel.id(连接成功的客户端都有一个自己的频道)。当有任何消息进入频道,这个子线程就通过主线程的 cosocket 对象将消息发往客户端(这里就需要前面提到的 cosocket 补丁)。


3. 使用 job server 执行延时任务

选择 beanstalkd 是因为有现成的 lua-resty-beanstalkd 模块,用起来省事儿。而且 beanstalkd 也支持延时消息,非常适合我们游戏中的需求。比如升级一个建筑物需要 10 分钟,那么我添加一个延时 10 分钟的消息到 beanstalkd 里就行了。

当一个消息倒计时结束时,就会由 worker 负责处理消息。worker 取得消息后,进行处理。如果处理后需要将更新后的数据发送到客户端,就通过 redis publish 命令来进行了。

----

整体架构还在开发,目前 1/2 都已经实现,初步测试效果还不错。下一步就是整合 beanstalkd。

由于第一次这样运用 OpenResty,所以还请各位多多提意见,看看有没有什么问题。

谢谢大家 :)



Snip20131027_17.png

smallfish

unread,
Oct 27, 2013, 9:55:48 PM10/27/13
to open...@googlegroups.com
Beanstalkd延时功能终于有人用上场景了。弱弱的问下,是采用我那个封装库还是Bakins封装的?

--


2013/10/28 dualface <dual...@gmail.com>

--
--
邮件来自列表“openresty”,专用于技术讨论!
订阅: 请发空白邮件到 openresty...@googlegroups.com
发言: 请发邮件到 open...@googlegroups.com
退订: 请发邮件至 openresty+...@googlegroups.com
归档: http://groups.google.com/group/openresty
官网: http://openresty.org/
仓库: https://github.com/agentzh/ngx_openresty
教程: http://openresty.org/download/agentzh-nginx-tutorials-zhcn.html

Snip20131027_17.png

G_will

unread,
Oct 27, 2013, 10:12:49 PM10/27/13
to open...@googlegroups.com
赞!!!

提点建议。

1. 消息部分可以使用 nanomsg 作为支撑, nanomsg 里的 pub/sub 模式天生就可以用来消息广播,而且 nanomsg 还有很多其他消息模式,很多都可以直接在游戏场景中使用。

2. 运维复杂度的问题,这个架构里涉及到好几个 deamon 程序,这些进程的维护、启动顺序、失败管理都是坑点,这里估计要仔细想想,这也是 nanomsg 的优势。

3. 还有一点就是,其实我一直很纠结,我们有客户端,我们都有 websocket 了,为啥不直接 raw tcp socket 呢?很多游戏其实用 websocket 都重,起码要打包个 websocket 客户端库。现在情况是可以永 ngx-tcp-lua-module,但是和 openresty 兼容不够好,如果春哥能搞个 tcp_by_lua 或者 pre_http_check_by_lua 就好了。




Snip20131027_17.png

YuLei Liao

unread,
Oct 27, 2013, 11:11:40 PM10/27/13
to open...@googlegroups.com
就是您封装那个,非常感谢 :)

YuLei Liao (dualface)

在 2013年10月28日,9:55,smallfish <smallf...@gmail.com> 写道:

Beanstalkd延时功能终于有人用上场景了。弱弱的问下,是采用我那个封装库还是Bakins封装的?

--


2013/10/28 dualface <dual...@gmail.com>
我们是做手游的团队,最近一款游戏有不少实时性,正好看到 OpenResty 已经支持了 WebSockets,所以基于 OpenResty 设计了一个 game server 架构。

PS: 选择 OpenResty 的原因是我们前一款游戏也是用的 OpenResty,感觉很不错(虽然最后游戏没有挣到钱)。


整体架构图:



<Snip20131027_17.png>

YuLei Liao

unread,
Oct 27, 2013, 11:19:59 PM10/27/13
to open...@googlegroups.com
raw socket要自己处理粘包,拆包等问题。websockets库相当小,所以用起来很省事儿。

这个架构就是运维麻烦。现在有一种SLG游戏的方案就是用Java做服务端,实现一个all in one的server。

Nanomsg 貌似没有现成的 lua 库吧?

YuLei Liao (dualface)

在 2013年10月28日,10:12,G_will <gwill...@gmail.com> 写道:

赞!!!

提点建议。

1. 消息部分可以使用 nanomsg 作为支撑, nanomsg 里的 pub/sub 模式天生就可以用来消息广播,而且 nanomsg 还有很多其他消息模式,很多都可以直接在游戏场景中使用。

2. 运维复杂度的问题,这个架构里涉及到好几个 deamon 程序,这些进程的维护、启动顺序、失败管理都是坑点,这里估计要仔细想想,这也是 nanomsg 的优势。

3. 还有一点就是,其实我一直很纠结,我们有客户端,我们都有 websocket 了,为啥不直接 raw tcp socket 呢?很多游戏其实用 websocket 都重,起码要打包个 websocket 客户端库。现在情况是可以永 ngx-tcp-lua-module,但是和 openresty 兼容不够好,如果春哥能搞个 tcp_by_lua 或者 pre_http_check_by_lua 就好了。


在 2013年10月28日上午12:05,dualface <dual...@gmail.com>写道:
我们是做手游的团队,最近一款游戏有不少实时性,正好看到 OpenResty 已经支持了 WebSockets,所以基于 OpenResty 设计了一个 game server 架构。

PS: 选择 OpenResty 的原因是我们前一款游戏也是用的 OpenResty,感觉很不错(虽然最后游戏没有挣到钱)。


整体架构图:



<Snip20131027_17.png>

G_will

unread,
Oct 27, 2013, 11:29:45 PM10/27/13
to open...@googlegroups.com
在 2013年10月28日上午11:19,YuLei Liao <dual...@gmail.com>写道:
raw socket要自己处理粘包,拆包等问题。websockets库相当小,所以用起来很省事儿。

这个倒是,不过我不清楚在同样的平台上,用 websocket 和 tcp socket 效率上的差距有多大,我知道这样问很不专业,应为这两个差的很多而且各种具体实现也不一样。
 

这个架构就是运维麻烦。现在有一种SLG游戏的方案就是用Java做服务端,实现一个all in one的server。

嗯,我和一些做页游后端交流过,因为他们现在的模式都是分逻辑游戏服务器的,所以在线人数规模都是设计好的,所以他们尽量做成单进程的,运维、开服、关服都是很方便的。

当然,还是和具体项目有关,如果要做大型 MMORPG 这样肯定不行。
 

Nanomsg 貌似没有现成的 lua 库吧?

有是有,不过 nanomsg 本身还处在 alpha 阶段,虽然有 zmq 的光环,但是估计有坑。
廖大可以做第一个吃螃蟹的人。

YuLei Liao

unread,
Oct 28, 2013, 12:08:48 AM10/28/13
to open...@googlegroups.com

在 2013年10月28日上午11:19,YuLei Liao <dual...@gmail.com>写道:
raw socket要自己处理粘包,拆包等问题。websockets库相当小,所以用起来很省事儿。

这个倒是,不过我不清楚在同样的平台上,用 websocket 和 tcp socket 效率上的差距有多大,我知道这样问很不专业,应为这两个差的很多而且各种具体实现也不一样。
 

效率应该没有多大差别。在我的理解,websockets在通讯上,就是帮开发者已经处理好了拆包等事情,而对于传输的方法和内容,和 raw socket 应该没有区别。


这个架构就是运维麻烦。现在有一种SLG游戏的方案就是用Java做服务端,实现一个all in one的server。

嗯,我和一些做页游后端交流过,因为他们现在的模式都是分逻辑游戏服务器的,所以在线人数规模都是设计好的,所以他们尽量做成单进程的,运维、开服、关服都是很方便的。

当然,还是和具体项目有关,如果要做大型 MMORPG 这样肯定不行。
 

因为我们游戏是 SLG 类型,所以单一 server app 应该是很方便的。但是要自己实现多进程多线程架构也不是容易的事情,对于没有历史积累的团队来说风险太大。

多个 server app 就是运维麻烦,不过写好运维脚本后应该不是大问题。



Nanomsg 貌似没有现成的 lua 库吧?

有是有,不过 nanomsg 本身还处在 alpha 阶段,虽然有 zmq 的光环,但是估计有坑。
廖大可以做第一个吃螃蟹的人。
 

呃,我就是想用现成的,哈哈

Harold.Miao

unread,
Oct 28, 2013, 1:14:04 AM10/28/13
to open...@googlegroups.com
nanomsg  可以在生产环境用了??
--

Best Regards,
Harold Miao
Snip20131027_17.png

XinQi Yang

unread,
Oct 28, 2013, 4:13:46 AM10/28/13
to open...@googlegroups.com
看玉哥提到的nanomsg 和 Beanstalkd 都在用了.
廖大的这个架构,在多用户下负载均衡是得咋个做的,比如 多个区, 或者一个区爆满的时候......在这个架构下是如何处理的?

在这样的架构下,并发能到多少? 比如一个简单逻辑的情况下. 可以到3k + 级别的么,逻辑从写redis set 后返回的情况下....





2013/10/28 Harold.Miao <miaoh...@gmail.com>



--
xinqiyang
Snip20131027_17.png

dualface

unread,
Oct 28, 2013, 1:32:41 PM10/28/13
to open...@googlegroups.com

On 2013年10月28日 Monday at 16:13, XinQi Yang wrote:

看玉哥提到的nanomsg 和 Beanstalkd 都在用了.
廖大的这个架构,在多用户下负载均衡是得咋个做的,比如 多个区, 或者一个区爆满的时候......在这个架构下是如何处理的?

在这样的架构下,并发能到多少? 比如一个简单逻辑的情况下. 可以到3k + 级别的么,逻辑从写redis set 后返回的情况下....

我们是做一个 SLG 游戏,类似二战风云那种。用户数量达到一定程度就会开新服,所以单个服的压力不会有多大。按照行业内的数据,单服同时在线峰值2K-3K就差不多了。凭感觉,这个架构满足这个要求是不会有问题的。

至于实际的数据,只有等弄得差不多的时候再来测试了。我猜测瓶颈可能会在 beanstalkd worker 那里。因为 SLG 游戏里非常多的延时类任务。这个可能多开几个 worker 进程应该能解决。

Yichun Zhang (agentzh)

unread,
Oct 29, 2013, 2:26:29 PM10/29/13
to openresty
Hello!

2013/10/27 dualface
>
> 1. 因为现在版本的 cosocket 还不支持同时读写,所以我使用了
> 这个补丁 https://github.com/aviramc/lua-nginx-module/tree/socket-changes
>

嗯,这个补丁在我的 TODO 列表中的优先级比较高,不过还需要经过一些修改才能整合进 ngx_lua 中来 :)

Best regards,
-agentzh

G_will

unread,
Oct 30, 2013, 12:01:52 AM10/30/13
to open...@googlegroups.com

关于消息转发,其实有个地方需要细究,就是应该在什么地方处理消息调度,或者简单的说就是轮询。

廖大你的这种方式,需要有一个 coroutine 不停的循环检查 redis 的 sub 接口,这样总感觉不是很好。不知道能不能把这个监听注册到 nginx 主事件调度中。这些不熟悉不知道这样想对不对。

用 nanomsg 的话,就需要一个 pub 进程,这个 pub 进程使用 epoll 本身效率很好,但是在 sub 端还是会面临与 redis 同样的问题,不过这次面对的是 nanomsg 的 socket 。

不知道这个问题应该用什么样的思路解决?
春哥也提点建议把。


在 2013年10月28日上午12:05,dualface <dual...@gmail.com>写道:
Snip20131027_17.png

dualface

unread,
Oct 30, 2013, 12:12:58 AM10/30/13
to open...@googlegroups.com
感谢 agentzh 的工作,我们才有这么好的开源项目可以运用 ^_^

--

Liao Yu Lei

dualface

unread,
Oct 30, 2013, 12:16:02 AM10/30/13
to open...@googlegroups.com

关于消息转发,其实有个地方需要细究,就是应该在什么地方处理消息调度,或者简单的说就是轮询。

廖大你的这种方式,需要有一个 coroutine 不停的循环检查 redis 的 sub 接口,这样总感觉不是很好。不知道能不能把这个监听注册到 nginx 主事件调度中。这些不熟悉不知道这样想对不对。

用 nanomsg 的话,就需要一个 pub 进程,这个 pub 进程使用 epoll 本身效率很好,但是在 sub 端还是会面临与 redis 同样的问题,不过这次面对的是 nanomsg 的 socket 。

不知道这个问题应该用什么样的思路解决?
春哥也提点建议把。

read_reply() 会阻塞这个子 thread,并不是轮训。
我想不会有效率问题的哦。

只是现在缺少一个 thread.kill 函数,不能从主 thread 里干掉这个用于监听 redis sub 的子 thread。我现在的做法是主 thread 退出前,发一个 quit 到 channel 里。子 thread 如果收到 quit 就退出。


Yichun Zhang (agentzh)

unread,
Oct 30, 2013, 1:06:06 AM10/30/13
to openresty
Hello!

2013/10/29 dualface:
>
> 只是现在缺少一个 thread.kill 函数,不能从主 thread 里干掉这个用于监听 redis sub 的子 thread。

这个 ngx.thread.kill() 函数,其实 aviramc 也提了一个补丁等待我 review,嘿嘿:

https://github.com/chaoslawful/lua-nginx-module/pull/288

我希望能把它和那个全双工的补丁一起包含进 ngx_lua 0.9.2 中去 :)

Regards,
-agentzh

YuLei Liao

unread,
Oct 30, 2013, 1:20:33 AM10/30/13
to open...@googlegroups.com
太好了,万分期待!

YuLei Liao (dualface)
qeeplay.com

cong...@gmail.com

unread,
Oct 30, 2013, 12:28:43 PM10/30/13
to open...@googlegroups.com
在 2013年10月28日星期一UTC+8上午11时29分45秒,G_will写道:


我喜欢单服的设计,因为简单,如果想和后台使用一套结构,可以使用luaj嵌入lua,luaj比lua5.1还是要快的,当然比不过luajit
毕竟单服设计已经是大路货了,技术成熟,管理方便

dualface

unread,
Oct 30, 2013, 11:53:37 PM10/30/13
to open...@googlegroups.com
嗯,把 socket server, job server 放到一个进程里确实省事儿。

--

Liao Yu Lei

Nero.Ping

unread,
Jan 18, 2014, 7:37:28 PM1/18/14
to open...@googlegroups.com

有个问题我想问一下, 对于sesssion管理你们是倾向于把session数据存放在redis中还是存放在ngx.shared.DICT中还是redis中, 我现在是把session存放在redis中, 对于高并发的情况我木有经验,对于角色扮演型的实时在线游戏我尚不知道单服平均负载能达到多少。

我觉得把session等实时型数据存放在ngx.shared.DICT中肯定会快很多,但总觉得redis在架构上更稳固,因为redis在出现故障时还能把当时的内存数据留存到硬盘上.

不知哪位经验大拿能给个建议。

Ao Xu

unread,
Jan 19, 2014, 12:12:31 AM1/19/14
to open...@googlegroups.com
web server本身最好保持无状态,方便扩展。Redis保存状态。


--
--
邮件来自列表“openresty”,专用于技术讨论!
订阅: 请发空白邮件到 openresty...@googlegroups.com
发言: 请发邮件到 open...@googlegroups.com
退订: 请发邮件至 openresty+...@googlegroups.com
归档: http://groups.google.com/group/openresty
官网: http://openresty.org/
仓库: https://github.com/agentzh/ngx_openresty
教程: http://openresty.org/download/agentzh-nginx-tutorials-zhcn.html



--
-------------------------------------------------------
XA
blog: aoxuis.me

梅晓华

unread,
Jan 5, 2016, 10:07:38 PM1/5/16
to openresty
有幸已经用Openresty做了三个手游项目了,表现很好,性能超强,感谢agentzh。
推送目前用的Push Stream,感觉还凑合。
websocket一直在考察,也用Redis的pub/sub实现过,但觉得用Redis做推送并不是太好,轮询太密可能影响性能,太稀时效不行。
觉得还是等agentzh改进了share dict再用比较好,现在先用Push Stream凑合着

个人不太建议使用beanstalkd,原因如下:
减少外部依赖,减少附加模块,降低运维成本。
防止突发事件产生密集队列,短时产生较大压力。

建筑队列这种,可以使用冷却的模式,而不是排队的模式,傲世以后应该大部分都是了。
其他需要计时排队的,也大部分可以改成记录结束时间点,客户端实时检查并调整显示,服务端根据结束时间判断是否可以执行操作。
我们包括体力增长,冷却,排队,都是这么实现的。


在 2013年10月28日星期一 UTC+8上午12:05:24,YuLei Liao写道:

Fei Ai

unread,
Jan 5, 2016, 10:23:15 PM1/5/16
to open...@googlegroups.com
你的架构中组件的选择和我们场景下的选择几乎一样,看到你前面说希望 shared dict 改进是期望在清除掉过期key的时候能被外部 lua api 感知到吗?

泡泡鱼

unread,
Jan 5, 2016, 10:31:42 PM1/5/16
to Fei Ai, openresty
无法打开图片,架构图
发自我的iPhone


------------------ 原始邮件 ------------------
发件人: Fei Ai <ai...@openresty.org>
发送时间: 2016年1月6日 11:23
收件人: openresty <open...@googlegroups.com>
主题: Re: [openresty] Re: 使用 OpenResty 为基础的 game server 架构,请各位提意见

你的架构中组件的选择和我们场景下的选择几乎一样,看到你前面说希望 shared dict 改进是期望在清除掉过期key的时候能被外部 lua api 感知到吗?
2016-01-06 11:07 GMT+08:00 梅晓华 <ziv...@gmail.com>:
有幸已经用Openresty做了三个手游项目了,表现很好,性能超强,感谢agentzh。
推送目前用的Push Stream,感觉还凑合。
websocket一直在考察,也用Redis的pub/sub实现过,但觉得用Redis做推送并不是太好,轮询太密可能影响性能,太稀时效不行。
觉得还是等agentzh改进了share dict再用比较好,现在先用Push Stream凑合着

个人不太建议使用beanstalkd,原因如下:
减少外部依赖,减少附加模块,降低运维成本。
防止突发事件产生密集队列,短时产生较大压力。

建筑队列这种,可以使用冷却的模式,而不是排队的模式,傲世以后应该大部分都是了。
其他需要计时排队的,也大部分可以改成记录结束时间点,客户端实时检查并调整显示,服务端根据结束时间判断是否可以执行操作。
我们包括体力增长,冷却,排队,都是这么实现的。


在 2013年10月28日星期一 UTC+8上午12:05:24,YuLei Liao写道:
我们是做手游的团队,最近一款游戏有不少实时性,正好看到 OpenResty 已经支持了 WebSockets,所以基于 OpenResty 设计了一个 game server 架构。

PS: 选择 OpenResty 的原因是我们前一款游戏也是用的 OpenResty,感觉很不错(虽然最后游戏没有挣到钱)。


整体架构图:




梅晓华

unread,
Jan 5, 2016, 10:42:06 PM1/5/16
to openresty
否,是agentzh说后续会支持list。

在 2016年1月6日星期三 UTC+8上午11:23:15,Fei Ai写道:

Yichun Zhang (agentzh)

unread,
Jan 5, 2016, 10:51:01 PM1/5/16
to openresty
Hello!

2016-01-05 19:07 GMT-08:00 梅晓华 <ziv...@gmail.com>:
>
> 有幸已经用Openresty做了三个手游项目了,表现很好,性能超强,感谢agentzh。
> 推送目前用的Push Stream,感觉还凑合。
> websocket一直在考察,也用Redis的pub/sub实现过,但觉得用Redis做推送并不是太好,轮询太密可能影响性能,太稀时效不行。
> 觉得还是等agentzh改进了share dict再用比较好,现在先用Push Stream凑合着。
>

可以参考朱德江的这个 PR:

https://github.com/openresty/lua-nginx-module/pull/586

另外,还是这个新合并的 ngx.semaphore API:

https://github.com/openresty/lua-nginx-module/pull/586

Regards,
-agentzh

Yichun Zhang (agentzh)

unread,
Jan 5, 2016, 10:53:10 PM1/5/16
to openresty
Hello!

2016-01-05 19:50 GMT-08:00 Yichun Zhang (agentzh):
>
> 可以参考朱德江的这个 PR:
>
> https://github.com/openresty/lua-nginx-module/pull/586
>

这个 PR 实现了 list 类型的 lua shared dict 值。

> 另外,还是这个新合并的 ngx.semaphore API:
>
> https://github.com/openresty/lua-nginx-module/pull/586
>

抱歉,复制粘贴错误,应当是

https://github.com/openresty/lua-resty-core/blob/master/lib/ngx/semaphore.md

另外,朱德江在 OpenResty Con 2015 大会上作的 OpenResty C2000K 推送系统的分享也值得一看:

优酷视频:http://v.youku.com/v_show/id_XMTQwNDUxODQzMg==.html
幻灯: http://iresty.com/download/ebook/2015_con/zhudejiang.pdf

Regards,
-agentzh

xingxing_tnt

unread,
Jan 5, 2016, 11:22:25 PM1/5/16
to open...@googlegroups.com

大赞 ! thx

高岩

unread,
Feb 23, 2016, 6:28:08 AM2/23/16
to openresty
不错,值得借鉴

朱大仙儿

unread,
Feb 23, 2016, 9:13:24 PM2/23/16
to openresty
你能支持1分钟100W的并发访问吗?





------------------

朱大仙儿

手机:18513379185
微信号:wx23456346
QQ: 23456346

天脉聚源(北京)传媒科技有限公司/互动云研发部

北京市东城区安定门东大街雍和大厦E座8层

 
 
 
------------------ Original ------------------
From:  "高岩"<crasyan...@gmail.com>;
Date:  Tue, Feb 23, 2016 07:28 PM
To:  "openresty"<open...@googlegroups.com>;
Subject:  [openresty] Re: 使用 OpenResty 为基础的 game server 架构,请各位提意见
 
不错,值得借鉴

在 2013年10月28日星期一 UTC+8上午12:05:24,YuLei Liao写道:
我们是做手游的团队,最近一款游戏有不少实时性,正好看到 OpenResty 已经支持了 WebSockets,所以基于 OpenResty 设计了一个 game server 架构。

PS: 选择 OpenResty 的原因是我们前一款游戏也是用的 OpenResty,感觉很不错(虽然最后游戏没有挣到钱)。


整体架构图:





几点说明:

1. 因为现在版本的 cosocket 还不支持同时读写,所以我使用了这个补丁 https://github.com/aviramc/lua-nginx-module/tree/socket-changes
2. redis 是主数据库,日志类数据则存入 mysql,图里没有画出来

----

整个架构的重点有三部分:请求/响应模型,使用 redis 做消息转发,使用 job server 执行延时任务

1. 请求/响应模型

客户端通过 websockets 发送消息给服务端。每个消息都是 JSON 格式。其中包含 action 和 msgid 两个必须的参数。

- action 用于指示要调用服务端哪一个消息处理函数。例如 action = users.auth 就表示要调用服务端 UsersAction 模块的 authAction 方法。
- msgid 用于跟踪消息的执行结果,每一个从客户端发往服务端的消息都会带有一个 msgid(累加值)。当服务端的消息处理函数执行后,通过 websockets 发送消息到客户端,其中会包含请求消息中的 msgid。这样客户端就可以知道从服务端发来的消息是属于先前哪一个请求的反馈。这样模拟了 HTTP 的请求/响应模型,简化了客户端的代码实现。


2. 使用 redis 做消息转发

因为现在没有办法从外部取得一个线程的 cosocket 对象,所以也就无法直接向任意客户端发送消息。为了解决这个问题,我利用 redis 的 pub/sub 特性,实现了一个简单的消息中转机制。

每一个客户端连接到 OpenResty 后,就会创建一个子线程(ngx.thread.spawn)。这个子线程会创建一个 redis 连接,并 subscribe channel.id(连接成功的客户端都有一个自己的频道)。当有任何消息进入频道,这个子线程就通过主线程的 cosocket 对象将消息发往客户端(这里就需要前面提到的 cosocket 补丁)。


3. 使用 job server 执行延时任务

选择 beanstalkd 是因为有现成的 lua-resty-beanstalkd 模块,用起来省事儿。而且 beanstalkd 也支持延时消息,非常适合我们游戏中的需求。比如升级一个建筑物需要 10 分钟,那么我添加一个延时 10 分钟的消息到 beanstalkd 里就行了。

当一个消息倒计时结束时,就会由 worker 负责处理消息。worker 取得消息后,进行处理。如果处理后需要将更新后的数据发送到客户端,就通过 redis publish 命令来进行了。

----

整体架构还在开发,目前 1/2 都已经实现,初步测试效果还不错。下一步就是整合 beanstalkd。

由于第一次这样运用 OpenResty,所以还请各位多多提意见,看看有没有什么问题。

谢谢大家 :)



Yichun Zhang (agentzh)

unread,
Feb 24, 2016, 9:47:44 PM2/24/16
to openresty
Hello!

2016-02-23 18:13 GMT-08:00 朱大仙儿:
>
> 你能支持1分钟100W的并发访问吗?
>

这个提法有些怪,因为并发度是针对某一个时刻而言的,而不是针对时间区间,这个指标不同于请求吞吐量(比如多少请求每分钟或每秒)。

BTW,朱德江做过单机 200W 并发连接的 OpenResty 测试,与时间区别无关。

Regards,
-agentzh

michael wang

unread,
Feb 25, 2016, 10:10:27 PM2/25/16
to openresty
弱弱的问一下,你画架构图使用的什么软件呀?


On Monday, October 28, 2013 at 12:05:24 AM UTC+8, YuLei Liao wrote:
我们是做手游的团队,最近一款游戏有不少实时性,正好看到 OpenResty 已经支持了 WebSockets,所以基于 OpenResty 设计了一个 game server 架构。

PS: 选择 OpenResty 的原因是我们前一款游戏也是用的 OpenResty,感觉很不错(虽然最后游戏没有挣到钱)。


整体架构图:



内嵌图片 1

rocky wu

unread,
Mar 4, 2016, 2:30:41 AM3/4/16
to openresty

廖大的分享很不错啊。

在 2013年10月28日星期一 UTC+8上午12:05:24,YuLei Liao写道:
我们是做手游的团队,最近一款游戏有不少实时性,正好看到 OpenResty 已经支持了 WebSockets,所以基于 OpenResty 设计了一个 game server 架构。

lua初学者

unread,
Mar 15, 2016, 8:12:52 AM3/15/16
to openresty
问下这个架构图是用啥软件画的?

王刚

unread,
Aug 15, 2016, 5:41:41 AM8/15/16
to openresty
廖大有更新吗?
我最近也在尝试用OR做同样的事儿
Reply all
Reply to author
Forward
0 new messages