部落格搬家啦——為了更好地經營部落格,本人已經將部落格遷移至www.ijavaboy.com。這裡已經不再更新,給您帶來的不便,深感抱歉!這篇文章的新地址:點擊我
兩個多月沒有更新部落格了,那是因為剛進入一個新的領域,瘋狂地學習並工作。這兩個月,對於我來說,是一次新的旅程。從之前的Android開發,一不小心溜入遊戲伺服器端的開發。現在,終於有了一點閑暇,記錄一下這兩個月中學到的和領悟到的知識。
兩個月前,進入一家做互連網3D產品的創業公司,而我負責的,正是伺服器端的開發。和傳統的3D遊戲不同,這裡沒有複雜的遊戲邏輯,只專註於產品需要的功能,用戶端中不外乎使用者的登陸和聊天等功能。而伺服器端主要的任務就是處理使用者的登陸登出和各種資訊的同步。之前的一個月,學習了SmartFoxServer引擎,同時一併學習了下Unity3D引擎(因為用戶端使用的是這個,學這個主要是為了可以很好地和用戶端配合)。
一直到幾個星期前,當老大說要支援高達200000個使用者同時線上的時候,才知道SFS2X試用版最多隻可以支援100個使用者,幾經周折破解了SFS2X,消除了這個限制。但是,就算消除了限制,讓一台機子同時處理200K個使用者同時線上並操作,最後的結果只有一個——它將活活累死!於是,到SFS官方論壇和網站上尋求答案,雖然英文馬馬虎虎,但還可以表情達意,最終得知Terracotta是個好東東。而且官方有一個SmartFoxServer1.6和Terracotta整合的文檔。
正當我興緻突起,準備大幹一場的時候,無意中被當頭一棒——SmartFoxServer2X明確表態,從2X起,SmartFoxServer不再支援Terracotta叢集。花了好幾個晝晝夜夜,在其官方論壇上用那生硬的English發帖詢問,結果終於得到證實,2X開始真的不支援或者不再提倡使用Terracotta來叢集。再次看到1.6的那份官方叢集文檔的最後一句:
Finally the future releases of SmartFoxServer will move towards a tighter integration with Terracotta,
to provide even more distributed services out of the box, and further simplify the development
我不禁啞然!
後來,翻閱了大量了官方論壇上的文章,卻又找到官方人員的相關言論說,可以按照1.6思想的來使用Terracotta完成SFS的叢集。於是,我決定嘗試一把...
寫好了叢集擴充的代碼,當想要測試一把的時候,才發現,怎樣讓Terracotta識別SFS2X呢?也就是怎樣將SFS2X作為Terracotta叢集的用戶端來啟動呢?
下載了1.6的叢集的Demo,看到了它是使用了一個新的bat檔案來啟動的。看了下這個檔案,其中含有Terracotta的啟動包,終於明白了,原來如此。於是將其拷貝到
SFS2X的啟動bat檔案中,成功實現將SFS2X加入到Terracotta叢集中。通過Terracotta Developer Console也可以看到串連上的用戶端。
興奮之餘,將寫好的SFS2X叢集擴充Demo打了個jar包放到了SFS2X中,又寫了個測試的Client,結果一運行,報了一個大大的異常,從異常資訊看出,這個和ClassLoader有關。
之前學習SFS2X的時候,看到過官方介紹過2X中使用了新的ClassLoader機制。核心SFS2X使用SystemClassLoader載入,每一個擴充使用一個新的ClassLoader進行載入,這樣是為了方便應用擴充的熱部署。但是,這個熱部署我倒不太願意用,現在又因為這個鳥東東和Terracotta叢集有了衝突。
從Terracotta的官方論壇中又再次得知,載入Terracotta中共用資料的ClassLoader必須命名,Terracotta就是根據ClassLoader的名稱來完成不同JVM之間相同資料的同步。
這下徹底死了個翹翹,難道註定了無法實現SFS2X和Terracotta的整合嗎?心有不甘。。。
這時,一個強烈的念頭湧上心頭,SmartFoxServer2X不是用java寫的嘛,反編譯你的源碼,殊死一搏吧。
這個時候,發現其代碼並沒有進行加密,心中大喜。反編譯後的代碼清楚無比,看到了在載入每個擴充的時候,其都定義了一個URLClassLoader來完成擴充的載入。那麼我現在就需要替換掉這個URLClassLoader,而使用自己的定義的ClassLoader。
於是引入Terracotta和SmartFoxServer相關的jar包,重新實現了個命了名的ClassLoader,讓這個ClassLoader完成擴充的載入。
打成jar包,替換掉原來的jar包,運行起來,OK!測試通過,叢集終於實現。
實現叢集的目的,主要是為了分擔負載和容錯。那麼現在如何?負載平衡成為一個關鍵,看了很多關於負載平衡的資料,基本是基於Http請求的負載平衡。但是,對於像SmartFoxServer一樣的遊戲伺服器端引擎來說,其使用的往往是Tcp或者Udp協議。而我們知道,Http協議是無狀態的,使用者的每一次請求都可以做到負載平衡。而Tcp或者Udp使用的是長串連的形式,使用者一旦和某個物理機器串連了,那麼直到他主動退出或者這個物理機器上的SmartFoxServer出現故障,否則其在登陸中所發出的每一次請求都是在同一個TCP或者UDP串連中完成的。那麼如何?SFS2X的負載平衡呢?
有兩個思路:
1、用戶端維護一個伺服器端可用的SFS2X節點的列表,然後每次請求的時候隨即擷取一個進行串連,如果請求逾時或者失敗,則再重新選擇一個嘗試串連。但是這個方案不能根據負載狀況進行請求。
2、就是外加一個負載平衡伺服器,這個伺服器作為一個普通的Web Server。可以使用Tomcat或者Apache等。他主要的功能就是負責維護每個SFS2X節點的負載情況(每個節點上登陸的使用者數)和可用的SFS2X節點資訊。當一個用戶端請求登陸SFS2X伺服器的時候,其首先發送Http請求到這個WebServer,這個WebServer會查詢並返回當前所有可用的節點和每個節點對應的負載資訊。然後,用戶端根據返回的資料,選擇一個負載最小的節點進行串連。但是這個方案,這個單點的WebServer容易成為整個系統的瓶頸,同時可能成為單點故障。但是這個可以使用傳統的負載平衡技術來避免這些問題。
第一個基本排除,採用第二個。但是第二個又引發一個問題。就是負載平衡伺服器和SFS2X叢集如何完成資料的同步。是每個SFS2X節點每隔一定的時間將串連到原生使用者數等資訊發送到一個儲存媒介,這樣,負載平衡伺服器每次只需要查詢這個儲存媒介就可以了。但是,這個會成為瓶頸嗎?
I DON'T KNOW,JUST TEST IT!