天天看點

Firefly遊戲伺服器學習筆記 4———— master 子產品介紹

(子產品的介紹方法都是先說大體功能,在撿一些細節詳細讨論。)

master 類很簡單,就3個函數,一個init,設定配置資訊,并調用masterapp,然後還有一個循環啟動子程序的start函數。

這裡隻有masterapp函數值得我們關注。

代碼如下:

36     defmasterapp(self):

 37         config = json.load(open(self.configpath,'r'))

 38         mastercnf = config.get('master')

 39         rootport = mastercnf.get('rootport')

 40         webport = mastercnf.get('webport')

 41         masterlog = mastercnf.get('log')

 42         self.root = PBRoot()

 43         rootservice = services.Service("rootservice")

 44         self.root.addServiceChannel(rootservice)

 45         self.webroot = vhost.NameVirtualHost()

 46         self.webroot.addHost('0.0.0.0','./')                                                                       

 47         GlobalObject().root = self.root

 48         GlobalObject().webroot = self.webroot

 49         ifmasterlog:

 50             log.addObserver(loogoo(masterlog))#日志處理

 51         log.startLogging(sys.stdout)

 52         import webapp

 53         import rootapp

 54         reactor.listenTCP(webport,DelaySite(self.webroot))

 55         reactor.listenTCP(rootport,BilateralFactory(self.root))

實際上我不喜歡這種編碼風格,感覺有點亂,有些過度使用import和python的修飾符。

仔細看,這裡首先通過config.json讀取配置資訊,然後根據配置資訊,起一個pb.root,和一個webserver,然後給pb.root 加一個services,這個services類是個非常重要的類,貫穿整個系統。我們下面會詳細介紹它。這裡還通過import  webapp 和修飾符@xxx的方法來實作給webserver添加stop 和reload 2個child。實作的功能,我前面其實已經是說過。就是在浏覽器裡面輸入http://localhost:9998/stop或者http://localhost:9998/reload來調用對于的類。具體實作的方法是:

webroot = vhost.NameVirtualHost()

 webroot.putChild(cls.__name__, cls()) ;       

這個vhost.NameVirtualHost().putChild()函數也是twisted的函數,和前面pb.root一樣,大家如果等不及我後面的解說可以自己google到twisted網站,上面有詳細的doc、samples。

由于看的實在不習慣(可能自己是python、server的新手),是以我就自己按照功能實作改了一下結構,如下,希望大家對比可以更加清晰。(我改動後的所有代碼都會抽空上傳到github。位址為:https://github.com/chenee如果沒有說明我還沒來得及上傳,在等等,或者直接M我要。)

22classMaster:

 23     def__init__(self, configpath, mainpath):

 24         """

 25         """

 26         self.configpath = configpath

 27         self.mainpath = mainpath

 28

 29         config = json.load(open(self.configpath,'r'))

 30         mastercnf = config.get('master')

 31         self.rootport = mastercnf.get('rootport')

 32         self.webport = mastercnf.get('webport')

 33         self.masterlog = mastercnf.get('log')

 34

 35     def__startRoot(self):

 36         root = PBRoot("rootservice")

 37         GlobalObject().root = root

 38         reactor.listenTCP(self.rootport,BilateralFactory(root))

 39

 40

 41     def__startWeb(self):

 42         webroot = vhost.NameVirtualHost()

 43         webroot.addHost('0.0.0.0','./')

 44         GlobalObject().webroot = webroot

 45         webapp.initWebChildren()                                                                                    

 46         reactor.listenTCP(self.webport,DelaySite(webroot))

 47

 48

 49     defstartMaster(self):

50

 51         self.__startRoot()

 52         self.__startWeb()

 53

 54         if self.masterlog:

 55             log.addObserver(loogoo(self.masterlog))#日志處理

 56         log.startLogging(sys.stdout)

 57

 58         #reactor.run()

 59

 60     defstartChildren(self):

 61         """

 62         """

 63         print"startchildren ......"

 64         config = json.load(open(self.configpath,'r'))

 65         sersconf = config.get('servers')

 66         for sernamein sersconf.keys():

 67             cmds ='python %s %s %s' % (self.mainpath,sername, self.configpath)

 68             subprocess.Popen(cmds, shell=True)

 69         reactor.run()  

我把原先通過addServiceChannel()添加services的過程放到PBRoot類的__init__裡面了,這樣改動也适合後面其它子產品,反正root邏輯上肯定是需要一個services的。而且這個services就是普通services。(後面還會提到一些services的子類)

另外,把原先通過import webapp 加用修飾類實作的putChild()功能,直接寫到一個注冊函數裡面。

45   webapp.initWebChildren()                                                                                     

                         addToWebRoot(stop)

                         addToWebRoot(reloadmodule)

改動以後的功能和原先一模一樣,改動後的代碼對我等新手來說可以清晰的看到master子產品的結構

OK,下面我們來看剛才提到的services。用戶端所有的指令最終都是通過services的    

             callTarget(self,targetKey,*args,**kw) 函數來分發。

比如client端發一條編号為01的指令,或者一條“login”指令,server端到底執行什麼處理函數,就是通過services來實作的,具體實作實際上就是在services類裡面通過

          self._targets= {} # Keeps track of targets internally

這個字典來儲存指令ID/名稱 和具體指令實作函數的對應關系。

注冊、和登出這個對應關系的函數為services類的:mapTarget() 、unMapTarget()。

每個子產品(master,gate,net。。。)都有對應的services,但是可能不止一個。

子產品之間提供服務,也是通過實作一個services執行個體,并注冊一批相應處理函數來實作的。

OK,到這裡master基本介紹完畢。

由于master的webserver功能比較簡單,而且和系統的其它子產品基本無關。大家可以通過twisted官網的DOC和sample來了解,我就不贅述了。

API:

http://twistedmatrix.com/documents/10.2.0/api/twisted.web.vhost.NameVirtualHost.html

Twisted Web In 60 Seconds:

https://twistedmatrix.com/documents/current/web/howto/web-in-60/index.html

下篇文章我盡力介紹twisted的PB(Perspective Broker,透明代理)