1. 程式人生 > >[Erlang 0020]網頁遊戲分線到不分線

[Erlang 0020]網頁遊戲分線到不分線

     這一年來可以明顯看到一個變化:網頁遊戲分線從標配逐漸變成了可選,越來越多的遊戲開始不分線;當初為什麼要分線?現在為什麼又不分線?技術上面臨著什麼挑戰?僅僅是技術問題麼?

術語解釋

    不同的技術實現"一條線"的概念也不盡相同,我們使用的Erlang實現,這裡的一條線對應Erlang的一個VM.

為什麼要分線?

     可以通過比較來回答這個問題:所有玩家都在同一條線上 VS 同樣數量的玩家被分配在多條線;如果所有玩家(假定1000人)都在一條線上首先同一場景的玩家數就會比較高,特別是一些遊戲的熱點區域比如副本入口,主城中心,傳送門等等,當然同屏人數也會高;伺服器端對應相關場景的廣播壓力,和業務邏輯的運算壓力都集中在一條線上。而進行了分線之後,相當於把玩家做了分流,同一場景以及同屏的人數都會減少,一方面伺服器端單條線的運算壓力下降了,另一方面客戶端的同屏人數也降了下來;

   分線實際上幫伺服器端和客戶端都減輕了壓力,特別是很長一段時間內Flash客戶端的同屏人數一直有人數限制,多數遊戲能做到100多人,不會超過200人;這實際上是木桶理論中的短板,即使伺服器端能做到不分線,客戶端也支撐不了那麼高的同屏;(當然現在這個問題已經有了突破)

   總結一下,為什麼分線:分擔運算壓力 同屏人數限制

分線對設計的影響

    分線實際上是突破技術瓶頸支撐更多玩家的方案,一旦分線自然就會帶來"換線"和"跨線"的問題;所謂換線,就是玩家顯示的從一條線路切換到另一條線路;不在同一條線的玩家就屬於"跨線";玩家一個在1線,一個在2線,他們要交易怎麼辦?組隊呢?聊天呢?戰鬥呢?即使是忽略掉互動的因素,只看一個玩家,這一個玩家上線應該選擇哪條線?如果玩家在戰鬥,交易,掛機等狀態下能夠換線麼?在這些狀態下下線然後上線怎麼處理?

   本質上換線實際上是玩家資料從一個Erlang節點遷移到另一個Erlang節點,有一個銷燬和重建的過程;而跨線是兩個玩家的資料在不同的Erlang節點內。

   一部分解決方案是來自於策劃,會有一些遊戲狀態的互斥,比如不允許跨線交易,不允許在修煉狀態換線,等等;另外一方面就要在做設計的時候充分考慮分線了:

    玩家不在一條線怎麼辦?玩家當前能不能換線?玩家在當前這個狀態換線了怎麼辦?玩家下線之後再上線怎麼辦?我這個服務是全域性的應該怎麼辦?......

    具體技術實現上,Erlang做這個有先天優勢,啟動多個節點,設計一個閘道器節點做負載均衡;做水平擴充套件是很容易的。

分線血淚

   可以發現分線的設計需要在完成某一個功能的同時考慮到多條線的情況,會增加問題的複雜度;我不知道有多少採取分線策略的遊戲曾經因為分線栽過跟頭,我們就差點因為分線的一個bug把遊戲經濟系統搞死;事情大概經過:

   某週日23點左右 運營的同事告訴我遊戲內有玩家金幣異常

   23:30左右到公司  封號,分析日誌,發現金幣來源應該是玩家交易,排除伺服器被攻擊可能

   0點左右  封鎖了交易的所有協議,停服更新

   1點左右 發現還有一處可能出現問題的地方 再次更新

   2點 從玩家日誌庫抓取異常玩家的資料做分析 發現玩家金幣成倍增長2 4 8 16 32 64 也就是說,金幣被”複製了“,但是玩家怎麼做到的?是自己和自己交易麼?分析程式碼雖然缺少這個防護,但是交易使用的SQL也保證了他得不到收益。

   3:00 ~5:00 在本地測試環境,反覆模擬各種情況下的交易,答案:當時遊戲存在一個分線選擇的bug導致玩家可以同時登陸兩條線,玩家使用兩個賬號反覆登陸換線,然後進行交易就可以把金幣通過交易複製;  

    6點左右補丁做好熱更新第一個版本

    7點左右客戶端補丁也做了分發

   第二天運營提交了相關賬號的修復規則,一個遊戲的充值有一個前提保證就是遊戲內的經濟系統穩定,一旦出現刷金幣之類的事情搞亂了經濟系統,這個遊戲服也就死掉了;

為什麼不分線了?

    首先分線的種種限制,比如跨線不能交易等等增加了玩家操作步驟,需要玩家先選擇換線;另外,分線分流玩家分散了壓力也分散了人氣,顯得遊戲不熱鬧;

    其次在Flash同屏問題已經有了優化方案,可以看一下現在非常火爆的神魔遮天,它的同屏人數遠遠超出了100的限制;觀察一下神魔遮天的處理,當一個區域聚集了很多人的時候,它並不是一下全部渲染出來,而是一個一個渲染出來的;還有一些客戶端的優化策略,這些方案的組合結果就是同屏人數可以更多;

怎麼實現?

    有的不分線是通過拆分遊戲的功能模組實現的,比如把場景運算放在單獨的erlang節點,以功能為單位拆分成多個節點分擔壓力;一旦壓力上去就可以通過增加對應的功能節點來緩解壓力;實際上是換了一種分擔壓力的方式,對於客戶端和玩家這些都是透明的。

   我們從分線到不分線更困難一些,之前所有的邏輯都是在一個節點內完成,很難按照功能拆分遊戲,那將是顛覆性的。諮詢立濤,他給我們的建議是隻開一條線,開啟SMP,單線支撐2000~3000人應該沒有問題。

   Erlang SMP VM比普通Erlang VM要慢那麼一點點,但是可以充分發揮多核優勢 摘錄一點資料:

   從OTP R12B開始,如果作業系統報告有多於1個的CPU(或者核心)VM的SMP版本會自動啟動,並且根據CPU或者核心的數量啟動同樣數量的排程器。

    沒有SMP支援的Erlang VM只有1個執行在主處理執行緒中的排程器。該排程器從執行佇列(run-queue)中取出可以執行的Erlang程序以及IO任務,而且因為只有一個執行緒訪問他們所以無須鎖定任何資料。而帶有SMP支援的Erlang VM可以有一個或多個排程器,每個執行在一個執行緒中。排程器從同一個公共執行佇列中取出可執行的Erlang程序和IO任務。在SMP VM中所有的共享資料結構都會由鎖進行保護,執行佇列就是這樣一個由鎖保護的資料結構。

   實踐過程中,我們還是採取了一個折中的方案,只要玩家在一條線上不超過閾值,就只開啟這一條線,客戶端也沒有線路選擇的功能,如果超過閾值,就開啟新線路,並通知客戶端顯示選線功能;

僅僅是技術問題麼?

   從分線到不分線不僅僅是技術問題,策劃同樣要做調整,比如遊戲內的一些容易堆積玩家的區域要想辦法分散壓力,比如增加入口,修改NPC位置等等;還有一些數值限制也需要重新考慮,比如一個活動分線模式最多隻允許30個玩家參與,不分線了這個限制就要改掉否則大部分玩家都參與不了這個活動。

   單服最高線上超過3000人怎麼辦?首先現在遊戲平臺能推到這個線上的情況都很少了;其次如果超過這個值,一般都是開啟新服,也就是通過運營手段而非技術手段解決這個問題。

  從分線到不分線,下一站是什麼?一個世界?

  對於開發者,下一戰又是什麼?

2012-09-06 更新

堅強☆2002  22:38:52
有一個問題: 就現在開服導量的情況以及一機多服的開服模式 是不是可以不用考慮分線,直接在一個Erlang節點內搞定所有邏輯就OK 如果特別火爆,也不是從技術的角度去解決問題,而是開新服?
現在海賊那邊在設計新專案架構 遇到這個問題
chenglitao  22:40:12
嗯,都是不分線了。峰值通過高配置機器解決。
不要考慮任何分散式,程式碼就是簡單,便於維護,模組化就好。
堅強☆2002  22:42:08
而且我覺得這方面神魔做出了好的榜樣 客戶端同屏現在也不是問題了 束縛更少了
chenglitao  22:42:25
嗯,是的,現在都問題不大了。
堅強☆2002  22:42:56
ok 明白了