揭秘LOL背後的IT基礎架構丨產品而非服務

TF中文社群發表於2020-04-08

歡迎來到Tungsten Fabric使用者案例系列文章,一起發現TF的更多應用場景。“揭秘LOL”系列的主人公是Tungsten Fabric使用者Riot Games遊戲公司,作為LOL《英雄聯盟》的開發和運營商,Riot Games面臨全球範圍複雜部署的挑戰,讓我們一起揭秘LOL背後的“英雄們”,看他們是如何執行線上服務的吧。

作者:Nicolas Tittley和Ala Shiban(文章來源:Riot Games)譯者:TF編譯組


這個長系列的文章,探討並記錄了Riot Games如何開發、部署和運營後端基礎架構的歷程。我們是Riot 開發體驗團隊的軟體架構師兼產品經理Nicolas Tittley和Ala Shiban。我們團隊負責幫助Riot開發人員在玩家所處的任何地方構建、部署和運營遊戲,同時專注於雲無感(cloud-agnostic)平臺,這些平臺使遊戲的發行和運營變得更加輕鬆。

在過去的兩年前的一篇文章中,Maxfield Stewart介紹了有關開發生態系統,以及當時使用的許多工具。這裡我們將更新一些最新的內容,包括面臨的新挑戰,如何解決問題,以及我們從中學到的東西。

快速回顧


我們強烈建議您回過頭閱讀以前的文章,但是如果您想直接閱讀本文,這裡有一個超級精簡版本來幫您趕上進度。

Riot使用裸金屬和雲基礎架構的組合來在全球範圍內執行後端系統。這些後端系統被分散到不同的地理位置,基於完全不同的部署,執行著允許玩家與LOL《英雄聯盟》互動的整套服務。像大多數遊戲的後端系統一樣,LOL後端開始時作為一個整體,由專門的運營團隊來負責運營。隨著時間的推移,Riot逐漸擁抱了DevOps實踐和基於微服務的體系架構。 本系列的第一篇文章做了詳細介紹,為了幫助我們的開發人員更快地服務玩家,Riot大量依賴於Docker容器這種打包服務,並開始在叢集排程程式中執行它們。直到 最近一篇文章,討論了為實現此目的而使用的許多工具。

執行效果如何?


非常牛,但,痛並快樂著。

在上篇文章發表之時( 編者按:發表時間為2017年12月 ),我們運營著5000多個生產容器。這個數字並沒有停止增長,今天,僅在Riot自主運營的區域(Riot-operated regions),我們就執行了14,500多個容器。Riot的開發人員喜歡為玩家創造新事物,當他們越容易編寫、部署和運營服務,他們就越能創造出令人興奮的新體驗。

開發團隊以真正的DevOps方式,擁有並負責他們的服務。他們建立了工作流來部署、監視和運營那些服務,當他們找不到所需的東西時,就乾脆自己發明再造。對於開發人員來說,這是一個非常自由的時期,他們很少遇到無法自行解決的問題。

但慢慢地,我們開始注意到一些令人擔憂的趨勢。每個月的QA和負載測試環境變得越來越不穩定。我們不得不花費更多的時間,來查詢錯誤的配置或過時的依賴關係。這些孤立的事件並不是關鍵,但總的來說,它們耗費了團隊很多時間和精力——我們更願意將其花費在創造玩家價值上。

更糟糕的是,在非Riot自主運營的分片區域(non-Riot shards),不僅開始出現類似的困難,而且還爆出一系列其它問題。合作伙伴們必須與越來越多的開發人員進行對接,並採用越來越多的微服務,每種微服務都有不同的方式,彼此各不一樣。現在,運營人員必須比以往更加努力,以創造出有效且穩定的分片區域。在這些非Riot自主運營的分片區域,問題發生率要高得多,直接原因就是微服務的實時版本不相容,或者其它類似的跨界問題。

Riot的DevOps現狀


在討論如何解決打包、部署和運營之前,讓我們花一點時間來探討Riot的執行環境。這些都不是Riot所獨有的,但所有這些細節的重疊,都說明了我們是如何組織起來,以便為所有玩家提供價值的。

開發者模式


Riot的工程師們喜歡自己建造東西!為了幫助他們做到這一點,我們採用了強大的DevOps思維方式。團隊建立並擁有了自己的後端服務,確保對其提供支援,並在服務表現不如預期時進行分流。總的來說,Riot工程師很高興能夠實現快速迭代,也很樂意對自己的實時服務負責。這是一個非常標準的DevOps設定,Riot並沒有在任何方面逆勢而上。

有狀態分片模式


由於歷史原因、規模性問題,以及法律方面你的因素,Riot產品的後端系統按照分片的方式進行組織。其中,生產分片通常在地理位置上靠近目標受眾。這樣做有許多好處,包括改進的延遲問題,更好的匹配性,有限的故障域,以及清晰的非高峰時間視窗(可在其中執行維護操作)。當然,我們還在內部和外部執行著許多開發和QA分片,例如《英雄聯盟》公開測試服(PBE)。
 
揭秘LOL背後的IT基礎架構丨產品而非服務

運營模式


這是事情變得更加複雜的地方。儘管Riot是開發者,但出於合規性和專有技術的原因,我們與一些本地運營商合作以提供一些服務分片。實際上,這意味著Riot的開發人員必須打包分片的每個元件,將其交付給運營人員,並指導他們如何部署、配置和運營所有分片。Riot的開發人員不會自己去操作、訪問甚至檢視這些分片。(編者按:文中的分片邏輯可以理解成分塊分割槽域的定義)

迭代解決方案


嘗試1-新的聯盟部署工具


我們第一次嘗試改善情況,就採取了全新的方法,嘗試利用開源元件和最少Riot定製功能,來推進Riot的部署和運營工作。儘管這項工作成功地部署了完整的《英雄聯盟》分片,但工具的設計方式並沒有達到開發人員和運營人員的期望。團隊表達了對工具的不滿——這種工具被證明對運營來說太難採用,對開發者來說太受約束。

因此,在第一個分片部署後,我們就做出了痛苦的決定——讓這些工具退役。這看起來好像很激進,但由於所有團隊仍然擁有自己維護的部署系統並且尚未完全過渡,因此我們能夠快速淘汰新的工具。

嘗試2-更多流程


由於第一次嘗試並不如預期的成功,我們轉向傳統,透過新增流程來達到要求。廣泛的溝通,明確的釋出日期,文件化的流程,變更管理會議和儀式,以及永遠存在的電子表格,在某種程度上取得了一點點進展,但始終感覺不佳。團隊喜歡他們的自由DevOps,巨大的變化量和變化速度,都使他們的工作更加繁重。儘管合作伙伴的情況有所改善,但我們仍未達到所期望的運營水準。

嘗試3-後設資料


我們決定嘗試另一種方法。之前我們一直將開發人員作為工具的主要受眾,現在則開始研究針對於合作伙伴的運營人員,部署/運營系統將如何工作。我們精心設計了一種工具,允許開發人員向其Docker容器的打包微服務新增標準化後設資料,例如所需的配置和擴充套件特性。這帶來了進步,運營人員可以採用更加標準化的方式來理解所需的服務配置和部署特性,並且在日常運營中減少對開發人員的依賴。

此時,本地和合作夥伴運營站點的故障率、事件率和額外的停機時間都有所改善,但我們仍然頻繁遇到部署和運營故障,這些故障本來都是可以避免的。

嘗試4-Riot的應用程式和環境模式


我們最終採用了一種新方法,將關注點從個人服務轉移到了整個產品。我們建立了一個高階別的宣告性規範,以及可對其執行操作的工具集,讓規範和工具變得與眾不同。在詳細介紹之前,我們先來看一下前三次的嘗試中出了什麼問題。

反思錯誤之處


部署和運營的是產品,而非服務


儘管擁抱DevOps和微服務給我們帶來了許多好處,但它建立了一個危險的反饋環路。開發團隊建立微服務,對其進行部署、運營,並對其效能負責。這意味著他們為自己最佳化了日誌、度量標準和流程,並且通常很少考慮其服務能否為其他人所理解,包括沒有開發背景甚至工程能力的人。

隨著開發人員建立出越來越多的微服務,運營整體產品變得非常困難,並導致越來越多的失敗。最重要的是,Riot的流動團隊結構,使一些微服務的所有權變得不清晰,很難在分流時搞清楚應該與誰聯絡,從而導致出現很多屬性錯誤的頁面。越來越多的異構微服務、部署流程和組織變更,使得合作伙伴地區的運營團隊不知所措。

搞清楚“為什麼”


我們檢查了Riot運營區域和非Riot運營區域的故障,並將故障頻率的差異提煉為一項關鍵的觀察結果:

允許不連續的變更流進入分散式系統最終將導致可預防的事件。

當團隊希望跨邊界進行協調時,就會開始發生故障,因為依賴關係需要將釋出與多個更改捆綁在一起。團隊要麼使用人工流程來建立釋出週期,透過專案管理儀式協調發布,要麼臨時釋出較小規模的釋出更改,導致團隊在找出相容版本的過程中陷入混亂。

兩者各有其優缺點,但是在大型組織中往往會崩潰。想象一下,數十個團隊需要以協調的方式,連續交付代表共享產品的數百個微服務,並且允許這些微服務使用不同的開發實踐。更糟的是,對於合作伙伴來說,嘗試應用這些流程非常困難,他們的操作人員缺乏關於各個部分如何組合起來的上下文。

新解決方案:Riot的應用程式和環境模型


鑑於先前的嘗試未能產生預期的結果,我們決定透過建立一個自用固有對的(opinionated)宣告性規範來消除部分狀態操縱,該宣告性規範可以捕獲整個分散式產品——環境。環境包含完全指定、部署、配置、執行和運營一組分散式微服務所需的所有宣告性後設資料,這些微服務共同代表一種產品,並且是完整且不變的版本。我們之所以選擇“環境”這個名字,是因為它是Riot 最不會過度使用的一個詞。命名實在是一件難事。

隨著遊戲《符文之地傳奇》LOR的釋出,我們證明了可以描述整個的微服務遊戲後端(包括遊戲伺服器),並使其在Riot自主運營地區以及全球合作伙伴的資料中心中,作為產品進行部署、執行和運營。我們還展示了實現這一目標的能力,同時改善了已經廣受喜愛的DevOps方法的優勢。

對什麼進行規定描述(OPINIONATED ON WHAT)


該規範描述了服務捆綁包或環境之間的層次關係。
 

捆綁到環境規範中的應用程式規範

宣告性與高等級

宣告性規範的好處之一是它易於操作。對於合作伙伴的運營人員,他們的其中一個困難,就是無法理解、調整和潛在地自動化整個遊戲後端的部署方式。規範的宣告性性質,意味著它不需要工程師具有指令碼或程式設計專業知識,就可以對規範中的大多數內容進行更改。

保持規範的高等級,有助於將遊戲後端的定義與基礎實現脫鉤。這使我們能夠在對遊戲工作室影響最小的情況下,從名為Admiral的內部編排器/排程程式,遷移到基於Mesos的排程程式,以及考慮遷移到Kubernetes。它還使我們的合作伙伴運營人員可以在需要時交換其基礎架構元件。例如,它允許運營人員可以使用不同的指標聚合系統,而不需要更改微服務工具。

不可變與版本化

我們發現,要在快速發展的DevOps世界中有效部署和運營,使用共享語言來引用服務和環境至關重要。版本控制服務和環境及其關聯的後設資料,使我們能夠確保所有位置都部署了正確的版本。它使我們的合作伙伴運營人員可以確定地知道正在執行哪個版本,並且回傳給我們。此外,當應用於整個環境時,它提供了一組眾所周知的服務,可以對其進行質量檢查並標記為“好”。這種捆綁消除了在向合作伙伴傳達新版本時遺失依賴項的任何可能性。

使這些版本不可變,可以確保我們維持這種通用語言。當相同版本的服務被部署在兩個不同的分片中,我們現在也可以確定它們是完全相同的。

專注於運營

鑑於我們的目標是提高合作伙伴運營人員服務玩家的水平,我們很快意識到,部署軟體只是第一步。瞭解如何對實時系統進行分類、運營和維護,是同樣重要的事情。

從歷史上看,我們非常依賴於執行手冊。手冊由開發人員維護,並取得了不同程度的成功,他們記錄了從必需的配置值到高等級體系架構的所有內容。為了使合作伙伴運營人員具備配置和操作每種服務所需的全部知識,我們決定將這些執行手冊中包含的儘可能多的資訊帶到服務規範的最前面。這大大減少了合作伙伴地區投入新服務的時間,並確保他們在微服務更新時被告知所有重要變化。

如今,合作伙伴運營人員可以使用該規範來了解有關操作後設資料的資訊,包括所需/可選配置、擴充套件特性、維護操作,重要指標/警報定義、部署策略,服務間依存關係,以及越來越多的其它有用資訊。

處理分片差異


當然,分片不是彼此完全相同的副本。儘管我們希望使它們儘可能地接近,但總有一些配置必須有所不同。資料庫密碼、支援的語言、擴充套件引數,以及特定的調整引數必須隨每個分片而變化。為了支援該模式,我們的工具使用分層的覆蓋系統部署環境規範,使運營人員可以專門化特定的部署,同時仍然知道它們都源自已知的良好版本。讓我們看看它是如何工作的!

應用案例


一個簡單的遊戲後端可以包括兩個環境,一個用於遊戲伺服器,另一個用於元遊戲服務(排行榜,匹配系統等)。元遊戲環境由多種服務組成:排行榜、匹配系統、比賽歷史等等。每個服務都包含一個或多個Docker映像,從概念上講,它們等效於Kubernetes容器。對於所有環境,相同的層次結構都是正確的,並且從哲學上講,每一個環境都毫無例外地封裝了在任何受支援的基礎架構或雲上部署、執行和運營的遊戲後端所需的一切,及其所有的依賴項。

該規範還包括執行和運營整個環境所需的所有後設資料。不斷增長的集合包括配置、機密、指標、警報、文件、部署及rollout策略、入站網路限制,以及儲存、資料庫和快取要求。

下面我們有一個示例,演示在兩個區域中進行兩個假設的遊戲分片部署。您可以看到它們都由元遊戲環境和遊戲伺服器環境組成。在歐洲分片中的遊戲伺服器產品環境,落後於美國分片中的同類遊戲環境。這為遊戲和運營團隊提供了描述和比較不同遊戲分片部署的通用語言。每個環境中不斷增加的服務數量可以保持簡單性,從而可以可靠地部署數十個分片。
遊戲分片部署示例

我們的下一步:延遲感知排程


我們希望能夠描述服務之間的預期和可接受的延遲,並使工具針對基礎區域和較低階別的PaaS服務進行最佳化,使其能夠滿足這些需求。這將導致某些服務位於同一個機架、主機或雲區域中,而不是允許它們分佈在其它服務中。

由於遊戲伺服器和支援服務的效能特點,這件事與我們高度相關。Riot已經是一家多雲公司,有我們自己的資料中心,也有AWS以及合作伙伴的雲,但是我們依靠靜態設計的拓撲。紙牌遊戲和射擊遊戲具有不同的配置檔案,不必針對一、兩種情況的最佳化進行手工拓撲,從而節省了工程師們的時間,使他們可以專注在遊戲上面。

最後的話


我們在執行遊戲過程中面臨著穩定性下降的問題,主要是來自合作伙伴經營的遊戲分片。工具開發團隊捆綁了開源部署工具,並將後設資料新增到了容器中,而遊戲團隊則實施了集中釋出流程。這些方法可以解決症狀,但不能解決導致問題的根本原因,這意味著我們未能達到目標水準。

我們最終採用的解決方案引入了一個新規範,該規範捕獲了整個遊戲後端的所有拓撲、層次結構和後設資料及其所有依賴項。這種方法之所以有效,是因為它帶來了繫結容器的一致的版本釋出,它們之間互動方式的依賴關係,以及啟動和操作整個遊戲所需的所有支援後設資料。而不可變性帶來了確定性的部署和可預測的操作。

作為一個平臺團隊,我們的目標是挑選能夠產生良性迴圈的系統和構建模組,在這樣的良性迴圈中,功能開發工作自然會帶來易於操作的產品。將DevOps模式的敏捷性與易於操作的整個產品相結合是長期組織敏捷性的關鍵。我們的環境捆綁方法直接改善了運營指標,更重要的是提高了玩家體驗的質量。我們很高興看到業界其他人士如何解決類似的問題。我們已經看到了來自CNCF(雲原生計算基金會)和大型雲供應商(例如Microsoft開放應用程式模式規範)的想法和專案。希望其中一些專案能夠取代我們自己制定的規範,並朝著全行業解決方案邁進。

在以後的文章中,我們還將更詳細地探討Riot規範,介紹示例,並討論設計中的權衡以及Riot特定的快捷方式。

謝謝閱讀!如果您有任何疑問,非常歡迎與我們取得聯絡。



·END·


更多“揭秘LOL”系列文章


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69957171/viewspace-2684936/,如需轉載,請註明出處,否則將追究法律責任。

相關文章