(PS開(kāi)始應(yīng)用《暗時(shí)間》里提到的理論,將skynet用自己的話(huà)來(lái)總結(jié)并寫(xiě)下來(lái),這樣能充分思考并轉(zhuǎn)述為自己的記憶線索)
一、skynet設(shè)計(jì)的理解
(一)單個(gè)skynet節(jié)點(diǎn)
(1)愿景
充分利用多核。最初想法是多進(jìn)程。像咱們nodejs里多核就只能是多進(jìn)程了,因?yàn)槊總€(gè)nodejs進(jìn)程是單線程的。
多進(jìn)程是遵循unix設(shè)計(jì)哲學(xué),工具鏈形式,分拆進(jìn)程的形式來(lái)分拆模塊,減少?gòu)?fù)雜度和耦合性,方便編程及維護(hù)。
后來(lái)云風(fēng)他們發(fā)現(xiàn)lua做為嵌入式腳本,寫(xiě)邏輯時(shí)很好用的,反正如何都要用lua,而且lua提供了沙盒,這樣多進(jìn)程可以變?yōu)閱芜M(jìn)程多個(gè)沙盒,這樣綜合了多進(jìn)程和單進(jìn)程多線程的優(yōu)勢(shì)。多線程里共享資源,在同一進(jìn)程地址空間,訪問(wèn)更高效。
(2)核心功能(門(mén)房?)
很精簡(jiǎn),僅解決一個(gè)問(wèn)題。
skynet里不實(shí)現(xiàn)具體游戲邏輯,后者些放到一個(gè)一個(gè)動(dòng)態(tài)庫(kù)里(so文件)。skynet將這些so注冊(cè)到自己里邊,每個(gè)so一個(gè)永不重復(fù)的id,類(lèi)似于數(shù)據(jù)庫(kù)的autoincreament??疵枋鲞@個(gè)id是skynet自己運(yùn)行時(shí)當(dāng)次維護(hù)的,而不是模塊配置好終身的id。模塊的永久有效唯一標(biāo)示為名字,skynet提供了名字服務(wù),可以給每個(gè)模塊取一個(gè)易讀的名字。
(3)核心不解決什么問(wèn)題
skynet主張所有服務(wù)在同一OS進(jìn)程協(xié)作完成。核心里就沒(méi)管跨機(jī)通訊,單個(gè)服務(wù)的崩潰和重啟也沒(méi)管,云風(fēng)表示這些應(yīng)該由上層處理,他有責(zé)任暴露錯(cuò)誤,而不是隱藏。
這個(gè)設(shè)計(jì)的原因,游戲和操作系統(tǒng)不一樣,操作系統(tǒng)默認(rèn)不信任任何進(jìn)程,各進(jìn)程崩潰什么的不應(yīng)影響其他進(jìn)程,所以某個(gè)進(jìn)程掛了,他就安葬它,而其他進(jìn)程美好的生活。單游戲是為玩家服務(wù)的,某個(gè)環(huán)節(jié)出錯(cuò)都有可能造成玩家利益混亂,所以那里錯(cuò)了就整個(gè)流程(服務(wù)器)掛掉吧。沒(méi)有必要讓出錯(cuò)模塊被隔離開(kāi),而其他模塊卻繼續(xù)提供服務(wù)導(dǎo)出未預(yù)知行為。
上邊說(shuō)的東西應(yīng)該上層考慮,使用lua的沙盒就能做策略隔離。
(4)skynet運(yùn)行時(shí)邏輯流
skynet負(fù)責(zé)且只負(fù)責(zé)將一個(gè)數(shù)據(jù)包從一個(gè)服務(wù)發(fā)送到同一進(jìn)程的另一個(gè)服務(wù)里。發(fā)送服務(wù)直接調(diào)發(fā)送API,skynet收到數(shù)據(jù)包后,調(diào)用接受者服務(wù)的注冊(cè)的callback,即發(fā)給了接受者服務(wù)。
skynet保證在各模塊初始化時(shí)、每個(gè)獨(dú)立的callback調(diào)用時(shí),都是相互線程安全的。這樣編寫(xiě)服務(wù)的人就不需要考慮多線程的任何問(wèn)題了,只需專(zhuān)心處理給他的一個(gè)個(gè)數(shù)據(jù)包。
PS:天龍的場(chǎng)景l(fā)ua有點(diǎn)像這里的單個(gè)服務(wù)。不知天龍的跨線程切場(chǎng)景情況在這里也可以給簡(jiǎn)化為單線程?(回頭看源碼再研究這個(gè)問(wèn)題)
(5)消息調(diào)度
TODO
(6)gate和connection
TODO
(二)skynet集群
集群里最多支持255個(gè)skynet節(jié)點(diǎn),每個(gè)skynet節(jié)點(diǎn)有一個(gè)id,成為harbor id。這個(gè)id是集群層面指定,可以人為分配,也可以由一個(gè)中央服務(wù)器協(xié)調(diào)分配。
(1)集群間通信
skynet核心層紙負(fù)責(zé)在往外發(fā)消息時(shí)在source字段上加上自己的harbor id。而集群間的通信,是由單獨(dú)的harbor服務(wù)來(lái)做的。skynet將是往集群其他節(jié)點(diǎn)發(fā)的消息,就轉(zhuǎn)發(fā)到harbor內(nèi)。harbor會(huì)跟集群內(nèi)跟自己結(jié)識(shí)的skynet的harbor簡(jiǎn)歷tcp鏈接。harbor把消息發(fā)給目標(biāo)harbor。
harbor間的通信為單向的tcp管道。
master服務(wù)來(lái)同步全局的名字服務(wù)。每個(gè)skynet都會(huì)知道其他節(jié)點(diǎn)上裝配了哪些服務(wù),好路由過(guò)去。
(2)組播
TODO