SNS Webgame 社群類頁面網遊開發, 自己所用的架構,以及遇到的一些問題和困惑
大家好,我第一次做伺服器的程式,之前我一直做手機客戶端,什麼WEB框架啥的都沒用過 ,遇到很多困難跟疑惑,請大家多多指教。
目前在做的一個社群頁面網遊,HTML頁面,非FLASH的,所有的互動都是基於HTTP的。
這個遊戲的邏輯比較常見,類似於SLG,玩家消耗時間採集資源(比如點一個按鈕,等5分鐘就可以採集了10個糧食),隨後製造了5個士兵,接著玩家之間可以進行PK,雙方損失N個士兵等等.
同時具有社群的常見功能,玩家之間也可以互相加好友,留言等等。 但是除了管理員,普通使用者沒有廣播的功能。也沒有專門的聊天頻道。
這個系統的特點是:
1. 使用者數可能會很多, 可能會有上百萬線上(至少所用的架構要能擴充套件到支援那麼多),並且不分割槽,大家都在同一個區。
也就是, 所有的玩家,都可以透過使用者名稱查詢到另外一個玩家的資訊,然後可以加好友或者PK。
2. PV量很大,並且資料庫操作頻繁,玩家的每個點選,都可能生成新的物件.比如生成幾個士兵,跟別人進行一場PK,會產生一條PK記錄。
我現在的設計是
瀏覽器 ----> LOAD BALANCE -----> 動態頁面伺服器 TOMCAT叢集 -----> Logic server -----> DB server
前端, 靜態的圖片,CSS什麼的,都可以交給 NGIX
動態頁面伺服器,用JSP,可以用 N臺 TOMCAT 叢集
後端, 邏輯伺服器 Logic server
資料庫 DB server , 一臺MYSQL
困惑之一: 頁面伺服器與邏輯伺服器的通訊問題
我現在的做法是,N臺 TOMCAT 透過SOCKET 連線到 邏輯伺服器, 然後傳送自定義的訊息格式;邏輯伺服器用一個執行緒維護訊息佇列,然後邏輯伺服器開啟一個執行緒,不停地處理訊息,並把結果返回對應的頁面伺服器。
然後頁面伺服器把邏輯伺服器返回的結果,翻譯成HTML返回給玩家
頁面伺服器
//
static Integer msgId = 0;
List<MyMsg> msgQueue = Collections.synchronizedList(new LinkedList());
HashMap<Integer, MyMsg> resultMap = new HashMap<Integer, MyMsg>();
public String requestHandler(HttpServletRequest hsr) {
// 一些檢查
// 根據 request 生成 msg
MyMsg msg = new MyMsg();
synchronized (msgId) {
msg.setId(msgId++);
}
msg.startTime = System.currentTimeMillis();
msgQueue.add(msg);
while (resultMap.get(msg.getMsgId()) == null) {
Thread.yield();
if (System.currentTimeMillis() > msg.startTime + 10000) {
break; // 超過 10 秒沒響應, 算超時
}
}
MyMsg result = resultMap.get(msg.getMsgId());
resultMap.remove(result);
if (result != null) {
return "翻譯result";
} else {
return "返回超時錯誤";
}
}
// 接收訊息 , 邏輯伺服器收到 MyMsg, 處理後, 會返回一個同樣 msgId 的MyMsg 給頁面伺服器, 頁面伺服器直接儲存
public void onReceiveMsg(MyMsg msg){
if (System.currentTimeMillis() > msg.startTime + 10000) {
return; // 超過 10 秒才回來, 直接丟棄
}
resultMap.put(msg.getMsgId(), msg);
}
請問這樣的設計,有沒有問題? 很多執行緒在等待自己的結果的時候,會不會造成伺服器出問題;
自己寫這些,總感覺有些不可靠, 有沒有現成的 伺服器間通訊框架,以及 訊息佇列什麼的可以直接用的?
邏輯伺服器中:
把所有收到的訊息都加入到佇列裡面,然後進行 序列處理。 這樣就省得同步什麼的了。
但這種做法,會不會造成效率損失?
一般大家做 邏輯伺服器與頁面伺服器的通訊是怎麼做的?
困惑之二
邏輯伺服器上的資料庫快取問題, 因為資料庫操作非常頻繁,所以肯定需要快取。
我現在的做法是
邏輯伺服器起三個執行緒, 一個負責邏輯處理以及資料管理, 一個負責資料庫讀取, 一個負責資料庫更新。 我沒有用 hibernate , 直接用的JDBC。
比如玩家登陸
頁面伺服器建立玩家登陸訊息 -> 邏輯伺服器 -> DB讀取執行緒讀取資料 -> 讀取到的資料,放入 資料管理程式 -> 返回玩家的資訊給 頁面伺服器
然後資料管理執行緒,定時遍歷 所有的賬戶資料(一個列表),判斷該賬戶是不是有更新,如果有更新, 則放到DB更新執行緒去更新資料庫。
我用的判斷資料是不是有更新的方法是,
在該 object 上次被更新到資料庫以後,就生成一個 saved = object.clone(), 把所有的成員物件都 clone一遍,
然後比較 當前object 與 saved 的所有成員, 看是否完全一致, 不一致,則說明有更新, 需要放到 資料庫更新執行緒去更新。
現在這種做法,
1.我感覺很麻煩, 所有的entity,都要寫 clone 方法 以及 saved與當前物件判斷更新的方法,
2.非常擔心的就是一旦伺服器突然出故障退出, 則可能會有很多賬戶的資料是過期的。只能靠日誌慢慢恢復。
3.所有的資料以及邏輯都放在一臺電腦上, 如果使用者數達到幾十上百萬以後, 會不會效能上有問題。
我後來看了一些資料庫快取的資料,比如memcache, redis ,都是類似於 hashMap 的功能, 好像是為了處理分散式系統,我的邏輯這塊,完全就在一臺機器上,所以我也不太懂怎麼把這些快取的工具應用到現在的系統中。
請大家多多指教。
目前在做的一個社群頁面網遊,HTML頁面,非FLASH的,所有的互動都是基於HTTP的。
這個遊戲的邏輯比較常見,類似於SLG,玩家消耗時間採集資源(比如點一個按鈕,等5分鐘就可以採集了10個糧食),隨後製造了5個士兵,接著玩家之間可以進行PK,雙方損失N個士兵等等.
同時具有社群的常見功能,玩家之間也可以互相加好友,留言等等。 但是除了管理員,普通使用者沒有廣播的功能。也沒有專門的聊天頻道。
這個系統的特點是:
1. 使用者數可能會很多, 可能會有上百萬線上(至少所用的架構要能擴充套件到支援那麼多),並且不分割槽,大家都在同一個區。
也就是, 所有的玩家,都可以透過使用者名稱查詢到另外一個玩家的資訊,然後可以加好友或者PK。
2. PV量很大,並且資料庫操作頻繁,玩家的每個點選,都可能生成新的物件.比如生成幾個士兵,跟別人進行一場PK,會產生一條PK記錄。
我現在的設計是
瀏覽器 ----> LOAD BALANCE -----> 動態頁面伺服器 TOMCAT叢集 -----> Logic server -----> DB server
前端, 靜態的圖片,CSS什麼的,都可以交給 NGIX
動態頁面伺服器,用JSP,可以用 N臺 TOMCAT 叢集
後端, 邏輯伺服器 Logic server
資料庫 DB server , 一臺MYSQL
困惑之一: 頁面伺服器與邏輯伺服器的通訊問題
我現在的做法是,N臺 TOMCAT 透過SOCKET 連線到 邏輯伺服器, 然後傳送自定義的訊息格式;邏輯伺服器用一個執行緒維護訊息佇列,然後邏輯伺服器開啟一個執行緒,不停地處理訊息,並把結果返回對應的頁面伺服器。
然後頁面伺服器把邏輯伺服器返回的結果,翻譯成HTML返回給玩家
頁面伺服器
//
static Integer msgId = 0;
List<MyMsg> msgQueue = Collections.synchronizedList(new LinkedList());
HashMap<Integer, MyMsg> resultMap = new HashMap<Integer, MyMsg>();
public String requestHandler(HttpServletRequest hsr) {
// 一些檢查
// 根據 request 生成 msg
MyMsg msg = new MyMsg();
synchronized (msgId) {
msg.setId(msgId++);
}
msg.startTime = System.currentTimeMillis();
msgQueue.add(msg);
while (resultMap.get(msg.getMsgId()) == null) {
Thread.yield();
if (System.currentTimeMillis() > msg.startTime + 10000) {
break; // 超過 10 秒沒響應, 算超時
}
}
MyMsg result = resultMap.get(msg.getMsgId());
resultMap.remove(result);
if (result != null) {
return "翻譯result";
} else {
return "返回超時錯誤";
}
}
// 接收訊息 , 邏輯伺服器收到 MyMsg, 處理後, 會返回一個同樣 msgId 的MyMsg 給頁面伺服器, 頁面伺服器直接儲存
public void onReceiveMsg(MyMsg msg){
if (System.currentTimeMillis() > msg.startTime + 10000) {
return; // 超過 10 秒才回來, 直接丟棄
}
resultMap.put(msg.getMsgId(), msg);
}
請問這樣的設計,有沒有問題? 很多執行緒在等待自己的結果的時候,會不會造成伺服器出問題;
自己寫這些,總感覺有些不可靠, 有沒有現成的 伺服器間通訊框架,以及 訊息佇列什麼的可以直接用的?
邏輯伺服器中:
把所有收到的訊息都加入到佇列裡面,然後進行 序列處理。 這樣就省得同步什麼的了。
但這種做法,會不會造成效率損失?
一般大家做 邏輯伺服器與頁面伺服器的通訊是怎麼做的?
困惑之二
邏輯伺服器上的資料庫快取問題, 因為資料庫操作非常頻繁,所以肯定需要快取。
我現在的做法是
邏輯伺服器起三個執行緒, 一個負責邏輯處理以及資料管理, 一個負責資料庫讀取, 一個負責資料庫更新。 我沒有用 hibernate , 直接用的JDBC。
比如玩家登陸
頁面伺服器建立玩家登陸訊息 -> 邏輯伺服器 -> DB讀取執行緒讀取資料 -> 讀取到的資料,放入 資料管理程式 -> 返回玩家的資訊給 頁面伺服器
然後資料管理執行緒,定時遍歷 所有的賬戶資料(一個列表),判斷該賬戶是不是有更新,如果有更新, 則放到DB更新執行緒去更新資料庫。
我用的判斷資料是不是有更新的方法是,
在該 object 上次被更新到資料庫以後,就生成一個 saved = object.clone(), 把所有的成員物件都 clone一遍,
然後比較 當前object 與 saved 的所有成員, 看是否完全一致, 不一致,則說明有更新, 需要放到 資料庫更新執行緒去更新。
現在這種做法,
1.我感覺很麻煩, 所有的entity,都要寫 clone 方法 以及 saved與當前物件判斷更新的方法,
2.非常擔心的就是一旦伺服器突然出故障退出, 則可能會有很多賬戶的資料是過期的。只能靠日誌慢慢恢復。
3.所有的資料以及邏輯都放在一臺電腦上, 如果使用者數達到幾十上百萬以後, 會不會效能上有問題。
我後來看了一些資料庫快取的資料,比如memcache, redis ,都是類似於 hashMap 的功能, 好像是為了處理分散式系統,我的邏輯這塊,完全就在一臺機器上,所以我也不太懂怎麼把這些快取的工具應用到現在的系統中。
請大家多多指教。
相關文章
- 面試之旅-深圳 遇到的問題和一些自己的擴充以及答案2面試
- 面試之旅-深圳 遇到的問題和一些自己的擴充以及答案1面試
- 移動端網頁版開發遇到的問題網頁
- 阿里面試中遇到的一些架構問題阿里面試架構
- 生活和開發所用到的一些工具
- 記錄一次開發中遇到的問題:Vue 重新整理頁面後,頁面空白Vue
- 頁面重構WEEX開發問題總結
- MHA架構搭建中遇到的問題架構
- iOS 開發中遇到的一些證書問題iOS
- webpack+react多頁面開發架構WebReact架構
- Docker遇到的一些問題和感想Docker
- javaweb中自己遇到的問題JavaWeb
- fastadmin自己遇到的問題AST
- 前端開發中遇到的一些問題----持續更新前端
- 使用OT開發的頁面顯示不全的問題
- docker開荒hyperf遇到的一些問題Docker
- 螢幕旋轉的適配問題以及遇到的一些坑
- Mysql主從架構搭建的時候遇到的問題MySql架構
- java建立web動態網頁遇到的問題JavaWeb網頁
- 更改windows域架構主機是遇到的問題Windows架構
- 手機端頁面在專案中遇到的一些問題及解決辦法
- 小程式開發所遇的問題以及一些小細節
- 研讀程式碼遇到的困惑---關於登陸問題
- MERGE開發中遇到的問題
- laravel開發中遇到的問題與bug修復的一些總結Laravel
- webpack+react多頁面開發(二)-終極架構WebReact架構
- 面試中遇到的一些問題面試
- 小程式遇到的一些問題
- 工作中遇到的一些問題和處理
- Vue專案開發過程中遇到的一些問題總結Vue
- Android開發過程中遇到的問題以及解決辦法 how toAndroid
- web開發的一些問題Web
- 怎麼架構自己的網站架構網站
- 開發以太坊遇到的幾個問題
- IOS日常開發中遇到的小問題iOS
- AndroidStudio Java開發遇到的問題AndroidJava
- React開發中遇到的問題總結React
- 開發中遇到的float double精度問題