《魔獸世界》

工程師的工坊:重新打造安其拉抗戰準備

Blizzard Entertainment

戰爭即將開打。在本月稍早的時候,其中一個大家最期待的《魔獸世界》經典版事件正式上線,也就是安其拉的抗戰準備。整個經典版的伺服器不分部落聯盟,大家同心協力一起貢獻資源以開啟大門並解鎖安其拉團隊副本。遙想當年,流沙之戰首次(也是唯一一次)在 2006 年登場的時候,每個伺服器都有上千名玩家趕赴希利蘇斯親身參與或現場目睹一片混亂的戰場。玩家的熱情完全超出遊戲開發團隊的想像,一切發生得又急又快,我們來不及做足準備。伺服器很快就過載,許多玩家在為期 12 個小時的期間內,只能不斷反覆經歷登入失敗和連線中斷的過程,然後我們的工程師才終於透過快速修正排除了這個問題,讓玩家得以重新連線。雖然我們在活動期間成功穩定住了伺服器的運行狀態,並從中學習到了不少經驗,但我們認為還有機會能夠再做得更好。十五年後的今天,我們已經準備好替《魔獸世界》經典版重新打造出《魔獸世界》歷史上最史詩磅礡的其中一個事件,並著重心力在優化伺服器以排除戰鬥延遲和伺服器當機的問題,同時也會讓希利蘇斯能夠容納更多的玩家(玩家數量上限為該事件在 2006 年首次登場時的兩倍)。

在這篇文章中,我們要向各位介紹我們是如何重新打造這個萬眾矚目的事件。首先,我們會探討我們使用自動化玩家和壓力測試來決定臨界點以及手動研擬優化方案的過程;也會說明我們是如何透過軟體來克服硬體所解決不了的問題;更會分享我們是怎麼在不影響到《魔獸世界》經典版遊戲體驗的情況下,成功策劃出伺服器很少當機的全球事件。

重新打造第二次大戰「流沙之戰」

我們在思考該怎麼安排這個事件時,為自己訂立了三個必須達成的目標:解決連鎖當機的問題、提高指定區域的玩家數量上限、決定當延遲值達到多少時要把玩家傳送到希利蘇斯外面。在我們詳細說明我們是如何最大化伺服器運行效能之前,必須要先來瞭解一下我們在開發過程中碰到了哪些阻礙,分別是:《魔獸世界》經典版程式碼資料庫的限制、人數管理方案的運作機制,以及這些項目對遊戲帶來的影響。

阿努比薩斯入侵艾澤拉斯

突破極限

現代版《魔獸世界》的基礎是建立在 15 年前所推出的原版遊戲的程式碼資料庫之上。自從遊戲問世以來,我們開發出許多新的現代方法來處理《決戰艾澤拉斯》高玩家人數的問題,其中成效最顯著的就是伺服器鏡像功能。相較於 2006 年當時的情況,鏡像功能可以讓《魔獸世界》伺服器在遊戲中容納更多玩家。《決戰艾澤拉斯》中,我們使用鏡像功能來複製區域(例如:祖達薩),藉此讓伺服器在達到玩家人數上限時,還能夠乘載更多玩家。此舉能把玩家分散到同一區域的多個不同版本中,進而解決了延遲問題;玩家與遊戲之間的互動是最佔據 CPU 效能的內容,因為玩家會不斷傳送大量封包給伺服器,以確保自己可以分毫不差地四處移動並施放法術。此外,鏡像功能也減緩了潛在的延遲問題;當玩家數量超過上限時,玩家在進入新區域的過程中就有可能會遇到這種延遲問題。乍聽之下好像很簡單,但實則不然:《魔獸世界》經典版的製作理念是要忠實地重現出原版遊戲 1.12 版的樣貌,也就是說,各種奇葩的遊戲內容都必須保留下來。當你在進入新的區域時,鏡像功能偶爾會導致你的獵物(例如:敵方玩家或敵方 NPC)突然消失。如果在遊戲中加入鏡像功能,那麼好幾年前那種追至區域邊界獵殺玩家與 NPC 的懷舊場面就無法被重現出來。因此,我們需要想出一個解決辦法,在不影響原版遊戲體驗的情況下,讓伺服器依舊能夠容納更多的玩家,而且玩家不會因為嚴重的延遲而玩不下去。

為了要解決這個問題,我們決定採用「分層」機制,也就是直接複製整個區域(例如:東部王國),藉此來管理玩家人數與延遲問題,同時又能保存原版遊戲在當年的原始樣貌,讓玩家能夠再次透過放風箏的方法把世界首領帶到其他區域,也能夠一路追殺敵方玩家至區域邊界的地方,而不用擔心對方會因為鏡像功能的關係而跑到別的地方去。不過,分層機制的設計原理,並不能作為一勞永逸的解決方案。因為原版遊戲 1.12 版並沒有採用鏡像功能也沒有採用分層機制,因此我們答應玩家只會在《魔獸世界》經典版新內容推出之初使用分層機制,之後會隨著玩家越來越平均分散在遊戲世界的各個地方,慢慢移除掉這個機制。在少數情況下,我們還是會因為在線玩家人數過多的關係而採用分層機制(例如:北美的費琳娜);但自從遊戲推出以來,我們針對各個伺服器採用分層機制的頻率確實有越來越低的趨勢。在醞釀了整整 15 年之後,安其拉之戰可謂是《魔獸世界》經典版最受矚目的事件之一,如果沒有分層機制的輔助,我們預計在遊戲內容剛推出的時候,絕大多數的玩家都會集中出現在同一區域(起始區域除外)。如果沒有分層機制或鏡像功能的技術協助控制玩家人數,我們就必須訴諸創意並迅速採取行動。

聚集在銅鑼處的玩家

手動打造令人永生難忘的遊戲體驗

我們開始尋找不採用分層機制或鏡像功能處理玩家人數問題的解套方法,做法是:生成無頭客戶端(自動化玩家),引導這些玩家模仿真實玩家的行為,例如:施放法術、跟 NPC 戰鬥、在區域境內四處移動。這可以讓我們迅速瞭解到,當好幾千名玩家在同一區域中與遊戲互動時,伺服器的運行效能將會是如何。在經過這些模擬之後,我們安排志願者進行壓力測試,藉此掌握真實玩家的行為以及真實玩家與虛擬電腦之間的行為差異。此舉能夠協助我們判斷臨界點,並釐清當玩家人數過高時,伺服器的哪幾段程式碼會出現最嚴重的問題。我們針對伺服器的幀數時間進行了仔細評估,藉此辨識出程式碼容不容易導致伺服器失去回應(也稱作卡死)。

接下來要做的事情是,分析影響伺服器效能的因素;如此一來,我們才能把這個艱鉅的任務拆散成有辦法實際執行的目標。我們所遇到的是多項式難題,這種指數型的問題沒辦法依靠運行速度更快的硬體來加以解決。因此,我們只好手動選擇要多麼頻繁地將哪些資料傳送給玩家,藉此來對效能進行優化。在這邊舉個例子說明:假設有 20 個玩家不斷繞圈圈跳躍。伺服器會透過傳送封包(資料交付項目)的方式,把每個玩家所採取的動作傳送給其他 19 名玩家。如果有 20 個玩家,伺服器就必須處理 380 個封包(總玩家數 20 人 * 接收者 19 人 = 380 個封包)。當有更多玩家在同一個區域裡採取動作時,這個問題會以指數的速度惡化。如果我們把人數提高至 500 人,伺服器就必須傳送 249,500 個封包。如果我們把人數提高至 1,500 人,伺服器就必須接收 2,248,500 個封包。根據玩家所採取的動作,每一秒都會有好多封包不斷在玩家與伺服器之間往來;請注意,在上述例子中,玩家僅僅採取了一個動作。伺服器所接收到的封包越多,就會需要越多時間來進行處理;光是要解決一名玩家的封包需求就已經很不容易了,更遑論還有其他好幾位玩家得顧。在這個問題急遽惡化之後,伺服器就會開始瀕臨卡死邊緣。相較於 2006 年當時的情況,《魔獸世界》經典版的每個伺服器都擁有更多的玩家人數,所以我們預計必須要能夠在大門附近容納比以往都還要更多的玩家才行。

優化伺服器效能

我們的伺服器經過特殊設計,一旦出現卡死的狀況就會直接當機並重新啟動,所以我們明白一定要盡全力去降低伺服器處理資料的所需時間。在經過測試之後,我們發現跟角色移動指令有關的處理過程,是導致伺服器負荷過重的第一個主要元兇。我們開始針對「面向」(顯示角色模組面朝的方向)這件事降低封包的傳輸量,只有當玩家開始、停止或使用鍵盤操控角色移動的時候,才會傳送封包。在玩家人數過多的時候,網路延遲已經是必然的結果,如果此時 CPU 還得花時間去傳送面向封包這種不怎麼重要的東西,遊戲玩起來會更卡頓。因此,不如就乾脆直接停止傳送這種封包。我們決定降低移動指令封包的傳送頻率,藉此讓同一區域能夠容納更多玩家。請留意,我們的目標是找到伺服器當機之前的臨界點,並力求讓盡可能多的玩家可以同時出現在希利蘇斯。畢竟,跟完全無法登入並操控角色比起來,缺少幾個動作封包已經算很不錯的了。我們也開始節流優先順序較低的資料。當玩家採取「較不重要」的動作時,其封包的傳送頻率會低於「更為重要」的動作。我們發現許多訊息都會不分重要層級高低同時傳送,因此針對程式碼進行了優化,讓遊戲只會以更低的頻率批次傳送較不重要的資訊給玩家。

增益效果和減益效果是影響伺服器效能的第二個主要元凶。增益效果和減益效果會頻繁地出現在遊戲中的各個角落,有戰鬥發生的地方尤其如此。雖然這個問題乍看之下好像沒什麼大不了的,但是當玩家密集地群聚在一起時,這類的資訊就必須在各個玩家之間互相傳送。跟節流低優先順序的資料類似,我們會以批次傳送的方式來處理增益效果和減益效果的資料,這樣才不需要在短時間內接連傳送多個封包給多個玩家。

管理玩家人數

除了優化伺服器以因應單一區域內出現更多玩家的這件事情以外,我們也知道絕對沒辦法把整個伺服器的所有玩家全部塞到希利蘇斯裡面(人數將會超過原版《魔獸世界》1.12 版伺服器乘載上限的兩倍)。我們必須做出艱難的抉擇,並限制玩家的進出,藉此來管制這個區域境內的玩家人數。我們決定只允許等級 60 的角色進入希利蘇斯,且一旦玩家人數達到上限,就會阻止符合資格的角色繼續進入這個區域。這樣的限制是正確的決定,因為希利蘇斯的這個事件是遊戲後期內容,而且低等級的角色也依然可以在其他區域參與抗戰準備,比方說殺死遊蕩在貧瘠之地的阿努比薩斯(設計給等級 20 至等級 30 玩家體驗的遊戲內容)。我們所遇到的第二個阻礙是,我們知道同一區域最多可以容納多少玩家還不至於導致伺服器當機,但我們並不確定應該要把玩家人數降低至多少,才能夠讓效能與玩家人數之間的比率達到最佳值。在測試的過程中,我們發現最佳的玩家人數大概介於 1,500 人左右(係指角色之間彼此重疊的狀態下)。不過,因為這個事件涉及整個區域的關係,因此當玩家分散開來之後,效能問題將會被降至最低。

這個事件預計會在所有區域展開,所以我們必須確保這個事件在各個分層中都能夠運作。也就是說,當某個分層中有玩家持權杖敲響銅鑼時,同一伺服器的其他全部分層的事件也應該同步展開。這個事件必須要靠玩家互動才能觸發,因此我們希望同一伺服器各個分層的所有人都能夠看見持有權杖的玩家。這衍生出了一個很有趣的問題,因為伺服器之間必須要互相傳送原先不會傳送的資訊。我們必須在各個伺服器之間編譯並傳送封包(可能涉及到上千名玩家),這樣才能確保每個分層的資料能夠同步,這一點會使情況變得複雜。

於是,我們在推出荊棘谷釣魚大賽的同時,開始著手開發這項技術,並在稍晚的時候將其套用至奧妮克希亞、奈法利安、祖爾格拉布和撕裂世界增益效果。等我們認定這項技術已經成熟之後,我們開始在安其拉之戰的事件中測試這項技術以及其他技術。

希利蘇斯的部落玩家

實驗解決方案

到這裡,我們已經順利排除主要的技術阻礙,並透過幾個方式優化伺服器效能,是時候來測試看看開發成果了。我們把原先 10 小時的戰爭縮短成只有一個小時的簡略版。

在第一次的壓力測試中,我們幾乎讓所有玩家同時進入該區域,看看會發生什麼狀況。伺服器所容納的玩家數量一度逼近 1.12 版當時玩家數量上限的 150%。不過,就在此時,我們的測試伺服器當機了。我們針對區域所能容納的最大玩家人數,原先就已經設定了較寬鬆的高門檻,結果沒想到最終結果還是超出了這樣的門檻。在經過一番調查之後,我們發現負責讓玩家進出這個區域的程式碼,屬於沒有辦法同時處理多個玩家的佇列。也正是因為如此,玩家才無法被傳送出這個區域,而且會在飛行的過程中卡住很長一段時間。我們讓伺服器恢復運作並繼續進行壓力測試,同時不斷對程式碼做出調整。我們慢慢調低玩家人數,直到遊戲的延遲狀況來到尚可接受的狀態;與此同時,該區域所能容納的最高玩家人數,還是遠遠超過其他任何一個區域。因為伺服器當機的關係,原本預計一個半小時就能夠結束的事件,最後花了整整四個小時才落幕。

我們在一個禮拜之後,進行了第二次壓力測試。我們藉著這次機會,確認了優化結果是否有成功。在載入壓力測試之後,我們立刻發現改善出現成效:玩家在飛往希利蘇斯的路上不再會被卡住!我們順利收集到足夠的資料,並以此判斷出讓希利蘇斯同時容納多少玩家較為合適。在經過這兩次的測試之後,我們決定採納能夠在延遲與伺服器穩定性這兩者之間取得最佳平衡的玩家人數。這兩次的測試都算成功,因為我們順利驗證了優化的成果,並在經過反覆調整之後確立了區域的玩家人數上限。

在艾澤拉斯的其他地方採用同樣的伺服器解決方案

我們原本的計畫是,只在流沙之戰期間把優化內容套用至希利蘇斯。在我們確定這些優化內容可以安全無虞地發布至全球之後,我們在 1.13.5 版中把優化內容套用到了整個遊戲。在抗戰準備的號角吹響之後,玩家開始繳回補給品,並大量收割蟲子的屍體。玩家人數遽增的現象不只發生在希利蘇斯,各大主城和不少其他區域也出現了類似的情況。這些優化內容能幫助遊戲體驗變得更加流暢,並讓大規模的 PvP 戰鬥得以在艾澤拉斯的各個地方上演。部分玩家甚至還召喚出了世界首領桑德蘭,藉此來把其他陣營趕出蜂巢。

雖然大門開啟的事件還沒發生,但部分伺服器已經遇到了抗戰準備的進度停滯不前的奇怪錯誤。部分伺服器完成抗戰準備的速度過快,導致每次繳回資源的時候,邏輯運作都會出現競爭條件的問題,使得為期五天的計時器無法開始倒數。這個極端案例發生的機率相當小,所以我們手動修復了發生該問題的伺服器,並順利排除相關的遊戲錯誤,伺服器在完成抗戰準備的過程中將不會再遇到這個問題。

在開啟大門的抗戰準備落幕且經過五天之後,我們開始監控中國伺服器(全世界第一個開啟大門的伺服器)的遊戲情況。中國第一個敲響銅鑼的伺服器是「奧羅」。我們在監控分層玩家人數的過程中,發現各個分層的玩家主要都聚集在希利蘇斯。在事件剛開放的時候,有上千名玩家同時在線,多個分層都處於爆滿狀態,這是我們前所未見的盛況。雖然遊戲中有出現明顯的延遲問題,但是在第一波中國伺服器開放遊玩的過程中,我們的伺服器從頭到尾都沒有當機。

敲響銅鑼!

在 8 月 4 日當天,我們發現北美有多個伺服器都已經準備好在伺服器重置完成之後的短時間內敲響銅鑼。我們藉由 GM 帳號和觀察工具,主動逐一監控這些伺服器的狀況,以便處理玩家可能會遇到的任何問題。伺服器開放以及事件開跑的過程都沒有出現錯誤。持有權杖的玩家獲得了羨煞眾人的黑色其拉作戰坦克坐騎,玩家也能順利迎戰更巨大的蟲子,我們對於遊戲運行的穩定度感到很滿意。我們在等待第一個重置後伺服器完成五天等待期間的過程中,發現到一個重大問題:伺服器重啟之後,事件不會接續先前的進度。這也就表示,萬一伺服器當機或重啟,事件的所有進度都會遺失。雖然這個問題早在《魔獸世界》經典版開發之初就已經存在,但是因為遊戲中很少有事件會在伺服器重啟之後還接續先前進度的關係,所以時至今日依然沒有獲得解決。雖然遊戲團隊順利在短時間內排除掉這個問題,但是我們絕對不能讓任何一個伺服器重啟,直到我們在不影響玩家進行遊戲的情況下實裝修正內容並在資料庫裡面妥為記錄所有抗戰準備的現有狀態為止。


有些人可能會說,正是因為伺服器會當機的關係,才能夠呈現出當年的安其拉之戰為人所熟悉的那種混亂場面。雖然伺服器不會再當機,但是經過我們的積極努力,遊戲體驗的穩定度有所提升,而且每個伺服器的希利蘇斯都能夠同時容納 1,500 名左右的在線玩家,這未嘗不是另一種混亂場面。我們希望經典版的玩家能夠體驗到 10 小時不中斷的遊戲事件,並在安其拉之戰當中跟盡可能多的其他玩家一起留下美好回憶。雖然過程中仍然有幾個伺服器當機,但我們有順利在短時間內就讓這幾個伺服器恢復運作。這些伺服器在短短幾分鐘之類就完全恢復運作並重新上線,而且後續都沒有再次出現當機的狀況。

全世界有超過 4,000 名玩家成為聖甲蟲領主,隨著各個伺服器不斷累積抗戰準備的進度,這樣的人數也還在持續上升當中。自從安其拉抗戰準備展開以來,經典版的刺激程度和激戰場面令人拍案叫絕,感謝挺身而出參加第二次大戰「流沙之戰」的所有玩家!