賴勇浩(http://laiyonghao.com)
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伺服器端的技術與一些工具。
在庫的方面,他建議庫應該與商務邏輯分開存放,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人同時線上。
在 2012 年 1 月,珠三角技術沙龍(http://techparty.org/)廣州站上,我再次炒了這鍋冷飯,但是因為時間較為充裕,同樣的投影片我講了雙倍的時間,在上海講了 45 分鐘,而在廣州則講了一個 91 分鐘的版本。這次的沙龍也有視頻,所以我覺得值得在部落格上記錄下來,給更多人觀看、探討和交流。以下是這兩次報告的資料地址:
幻燈: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