2011 年 12 月初,首届 PyCon China 会议在上海召开,我受邀作了题为《Python 于 Webgame 的应用》的报告,其中的主体思想在 InfoQ 记者丁雪丰先生写的稿件(http://www.infoq.com/cn/articles/pycon-2011-first-in-china)中有完备的描述,在此我直接引用了:
……赖勇浩带来的《Python之于Webgame的应用》, 他先推荐了两个自己比较喜欢的演讲内容,一个是洪强宁的《Python于Web 2.0网站的应用》,另一个则是沈葳的《Python编程艺术》,两人恰好都是大会第一天的演讲嘉宾。赖勇浩在演讲中介绍了Webgame服务器端的技术与一些工具。在 2012 年 1 月,珠三角技术沙龙(http://techparty.org/)广州站上,我再次炒了这锅冷饭,但是因为时间较为充裕,同样的幻灯片我讲了双倍的时间,在上海讲了 45 分钟,而在广州则讲了一个 91 分钟的版本。这次的沙龙也有视频,所以我觉得值得在博客上记录下来,给更多人观看、探讨和交流。以下是这两次报告的资料地址:
在库的方面,他建议库应该与业务逻辑分开存放,lib就放在site-packages中;不要手写配置脚本setup.py,尽量使用工具生成,PasteScript提供了创建、安装、测试、部署、运行等众多功能;可以使用pbp.skels来生成众多代码,比如生成命名空间包;在部署时,一定要有一个纯净的Python环境,这时可以使用virtualenv。
插件方面,主要是善用setuptools,以棋牌游戏为例,游戏插件可以分为接口与实现两部分,接口中主要是房间进程交互、通用功能(例如踢人)、计时器管理、定义接口,实现中主要是实现接口、实现业务逻辑,实现部分可以不接触网络编程,不接触数据库。对插件感兴趣的还可以学习一下Trac Component Architecture。
游戏和I/O有着密不可分的关系,Node.js的作者说过:I/O needs to be done differently.他也同意这一观点,只是不太认同Node.js的实现方式,Node.js的改变太多,他认为接口应该尽可能与以前一样,但是底层的实现方式则应该与Node.js类似。从目前来看,Coroutine将成为趋势,可以考虑使用gevent,它在libevent之上通过greenlet提供了一套API。另外也可以参考沈葳的eurasia。
其他方面,赖勇浩建议在通信时使用二进制协议,比如Google的protobuf,他们自己开发了一个名为abu.RPC的通信框架,使用了protobuf、libevent和greenlet,因此可以实现更小的数据量、更快的传输和同步API,支持并行管线和双向调用特性。受到Falcon语言(这是一门开源的多范式语言)的启发,开发了python-message,实现了进程内的发布订阅,应用于任务、邮件、好友等子系统内。此外,还做了些小组件,比如absolute32来实现一些标准库的封装。目前,他所开发的纯Python游戏服务器,单台8核8G内存,可以承受最高1500人同时在线。
幻灯:http://www.slideshare.net/laiyonghao/python-webgame-10452102
录像(上海45分钟版):http://e.gensee.com/v_3df867_14
录像(广州91分钟版):http://v.youku.com/v_playlist/f16785412o1p4.html
================================
以下内容为幻灯片的文本,纯为通过搜索引擎吸引流量用,请无视。
--------------------------------
Python 于 webgame 的应用 — Presentation Transcript
1. Python 于 web-game 的应用 赖勇浩(http://laiyonghao.com) 2011.12.04 1
2. 自我介绍• 网游从业超过 6 年 • 天下盛境• 曾在网易、江苏盛典 – 团队建设 – 项目管理 (广州)等公司工作 – 服务器端• 珠三角技术沙龙 – 通信与安全• 赖勇浩的编程私伙局 • 斩魂 – pv 1,000,000+ – 服务器端 – csdn blog top100 – AI• twitter/weibo/42qu/CP • 幻想三国、疯狂石头 yUG/gzlug 和泡泡游戏等 2
3. 启发于……http://slidesha.re/aGrXfY http://slidesha.re/fQhtkL 3
4. 以我经历的项目为蓝本,向大家讲述 web-game 服务器端技术与工具 源于项目,高于项目。 4
5. 项目介绍1• 天下盛境 – 横版卷轴 – 动作类网页游戏• 0505u.com• 服务器端完全使 用 Python 开发• 2010.08~现在 5
6. 项目介绍2• 棋牌OnWeb – QQgame copy cat• http://qp-demo.laiyonghao.com/client/• 服务器端完全使用 Python 开发• 2009.01~2009.03 6
7. library 7
8. Python 在 Python 项目中的位置 C/C++ Python lua C/C++ lua Python 8
9. 大中型 Python 项目 9
10. 大中型 Python 项目 10
11. 大中型 Python 项目 11
12. lib 应该在 Lib/site-packages 目录 12
13. 要整这么复杂吗? 13
14. 就一个 setup.py 而已…… • 避免手写 setup.py • 如何建立命名空间包 14
15. 神器 paster • http://pypi.python.org/ pypi/PasteScript • 创建、安装、测试、 部署、运行 • Many different kinds of projects have created skeletons for their projects (Pylons, TurboGears, ZopeSkel, and others). • http://pypi.python.org/ pypi/PasteDeploy 15
16. 基本用法 16
17. pbp.skels• http://pypi.python.org/pypi/pbp.skels• pbp.skels is a collection of templates to speed up the creation of standardized, boiler-plate code. 17
18. • paster create -t pbp_package my.package 18
19. http://lucasmanual.com/mywiki/PythonPaste 编写自己的 templates, commands 19
20. 开发、测试、打包、更新• python setup.py develop• python setup.py test• python setup.py bdist• python setup.py sdist --formats=gztar,zip• python setup.py register• python setup.py upload 20
21. virtualenv• http://pypi.python.org/pypi/virtualenv• Virtual Python Environment builder• 《Python于Web 2.0网站的应用》介绍过了 21
22. plugin 22
23. what is the difference between plugin and library?• A plugin extends the capabilities of a larger application.• A library is a collection of subroutines or classes used to develop software.• http://stackoverflow.com/a/2792342 23
24. 以《棋牌OnWeb》为例…… 24
25. 到后台看看…… 25
26. 神器 setuptools 26
27. setup.pyentry_points="""# -*- Entry points: -*-[qipaionweb.games]doudizhu = doudizhu.game_impl:GameImpl""" 27
28. def get_game_impl_class(game_name): group = qipaionweb.games prj = game_name return pkg_resources.load_entry_point( prj, group, game_name) 28
29. 接口与实现• game_interface • game_impl – 与房间进程交互 – 实现接口 – 通用功能(踢人) – 实现业务逻辑 – 计时器管理 – 不接触网络 – 定义接口 – 不接触数据库 – 单线程 29
30. 进阶:Trac Component Architecture• trac.core.ComponentManager• trac.core.Component• trac.core.ExtensionPoint• trac.core.Interface http://trac.edgewall.org/wiki/TracDev/ComponentArchitecture http://trac.edgewall.org/wiki/TracDev/PluginDevelopment 30
31. 参考:ulipad• http://code.google.com/p/ulipad/source/bro wse/trunk/modules/Mixin.py• 另一种 plugin 机制 31
32. I/O 32
33. I/O needs to be done differently. 33
34. I/O needs to be done differently. 34
35. 35
36. http://s3.amazonaws.com/four.livejournal/20091117/jsconf.pdf 36
37. This is how I/O should be done.def sign_in(username, password): result = db.query(select ...) if len(result) == 1: token = game.sign_in(...) return token 2 DB 1 3 6 sign_in 4 5 game 7 37
38. 协程才是未来! 38
39. gevent 39
40. gevent = libevent + greenlet 40
41. libevent• 提供指定文件描述符事件发生时调用 回调函数的机制• timeouts, signals 41
42. greenlet• green thread – user space – pseudo-concurrently – scheduled by VM – http://wikipedia.org/wiki/Green_threads• greenlet = pythons green thread 42
43. echo server• from gevent.server import • if __name__ == __main__: StreamServer • server =• def echo(socket, address): StreamServer((0.0.0.0, 6000), echo)• fileobj = socket.makefile() • print (Starting echo server• while True: on port 6000)• line = fileobj.readline() • server.serve_forever()• if not line:• break• if line.strip().lower() == quit:• print ("client quit")• break• fileobj.write(line)• fileobj.flush() 43
44. 参考:eurasia• http://code.google.com/p/eurasia/ 44
45. protocol 45
46. google protobuf• http://code.google.com/p/protobuf/• 协议描述语言• C++、java、Python and more 46
47. RPC 47
48. abu.RPC = gevent + protobuf 48
49. abu.RPC• 更小(得益于 google protobuf)• 更快(得益于 libevent)• 同步API(利益于 greenlet)• 并行管线• 双向调用 49
50. 并行管线http://wiki.msgpack.org/display/MSGPACK/Design+of+RPC 50
51. echo serverfrom abu.rpc import Server, send_returnimport echo_pb2 as echoclass EchoService(echo.EchoService): @send_return def echo(self, controller, request, done): return requestserver = Server((0.0.0.0, 1008),(EchoService(),))print serving...server.serve_forever() 51
52. publish-subscribe 52
53. import message • hello, lai.def hello(context, name): print hello, %s.%namemessage.sub(greet, hello)message.pub(greet, lai) 53
54. python-message• http://pypi.python.org/pypi/message• 进程内的 publish-subscribe 机制• 受 falcon 编程语言启发而写• http://www.slideshare.net/laiyonghao/pyth onmessage010• 应用于任务、邮件、好友等子系统 54
55. utils 55
56. absolute32• http://pypi.python.org/pypi/absolute32• [-2**31, 2**31-1]• ubuntu 10.04 LTS 32-bit/64-bit• python 2.6/3.1• hash• add• crc• adler 56
57. 谢谢。 Q&Ahttp://laiyonghao.com 57