1. 程式人生 > >以我在阿里遊戲的經驗為例,談如何邊做業務邊架構重構

以我在阿里遊戲的經驗為例,談如何邊做業務邊架構重構

對一個程式設計師來說,世界上最痛苦的事情是什麼呢?

有的人會說:編碼的時候產品改需求!
有的人會說:看別人不知所云的程式碼!
有的人會說:定位一個百年不遇千年難尋的線上不定時偶爾出現的bug!
有的人會說:找不到女(男)朋友!

但我要說,這些痛苦其實都不算什麼,要麼是多花點時間去解決(比如說改需求、看程式碼),要麼是多花點心思(比如說找另一半、定位疑難bug),而我接下來說的這個事情才是最痛苦的,既要說得動老闆,也要鎮得住同行;既要技術攻關,又要協調資源;既要保證業務正常發展,又要在指定時間內完成目標。總之就是十八般武藝要樣樣精通。

這個事情就是“架構重構”,比“架構重構”還要痛苦的就是“邊做業務邊架構重構”!我們的產品形象的形容為“給飛馳的法拉利跑車換引擎”,為何這樣說呢?

首先,業務不能停,不能為了架構重構而終止業務的開發,將法拉利停下來換引擎,別人都跑遠了;

其次,業務不能出問題,不能因為架構重構導致業務無法執行,法拉利修出問題跑不了,別人也跑遠了;

第三,要根本解決問題,而不是修修補補,不是給法拉利引擎加點油,清潔一下就可以了,而是要換上新的引擎。

巧合的是,我加入UC後到現在已經做了3個系統的架構重構了(戲稱“救火隊長”),而且每個系統的特點都不一樣,過程中各種各樣的問題都遇到過,坑也踩過,也積累了一些經驗。接下來就給大家分享一下。

有的放矢

我接手的第一個系統是一個後臺系統,負責管理整個阿里遊戲的遊戲相關的資料(以下簡稱M系統),重構的主要原因是因為系統耦合了P業務獨有的資料和所有業務公用的資料,導致可擴充套件性比較差。其大概架構如下:

架構重構

舉一個最簡單的例子:資料庫中的某張表,一部分欄位是所有業務公用的“遊戲資料”,一部分欄位是“P業務系統”獨有的資料,開發的時候如果要改這張表,程式碼和邏輯都很複雜,改起來效率很低。

針對M系統存在的問題,我們的重構目標就是將遊戲資料和業務資料拆分,解開兩者的耦合,使得兩個系統都能夠獨立快速發展。

重構的方案如下:

架構重構

重構後的效果非常明顯,重構後的M系統和P業務後臺系統每月上線版本數是重構前的4倍!

我接手的第二個系統,是負責遊戲接入的核心繫統(以下簡稱S系統)。S系統是遊戲接入的核心繫統,一旦S系統故障,大量遊戲玩家就不能登入遊戲,而S系統並不具備多中心的能力,一旦主機房宕機,整個S系統業務就不可用了。其大概架構如下,可以看出資料庫主庫是全域性單點,一旦資料庫主庫不可用,兩個叢集的寫業務都不可用了:

架構重構

針對S系統存在的問題,我們的重構目標就是實現雙中心,使得任意一個機房都能夠提供完整的服務,在某個機房故障的時候,另外一個機房能夠全部接管所有業務。

重構方案如下:

架構重構

重構後系統的可用性從3個9提升到4個9,重構前最誇張的一個月有4次較大的線上故障,重構後雖然也經歷了機房交換機宕機、運營商線路故障、機櫃斷電等問題,但對業務都沒有什麼大的影響。

我接手的第三個業務系統,是屬於創新業務(以下簡稱X業務)。由於是創新業務,之前的業務快速嘗試和快速發展期間,怎麼方便怎麼操作,怎麼快速怎麼做,系統設計並未投入太多精力和時間,很多東西都塞到同一個系統中,導致到了現在已經改不動了,做一個新功能或者新業務,需要花費大量的時間來討論和梳理各種業務邏輯,一不小心就踩個大坑。X系統的架構如下:

架構重構

X系統的問題看起來和M系統比較類似,都是可擴充套件性存在問題,但其實根本原因不一樣:M系統是因為耦合了不同業務的資料導致系統可擴充套件性不足,而X系統是因為將業務相關的所有功能都放在同一個系統中,導致系統可擴充套件性不足;同時,所有功能都在一個系統中,也可能導致一個功能出問題,導致整站不可用。比如說某個功能把資料庫拖慢了,整站所有業務跟著都慢了。

針對X系統存在的問題,我們的重構目標是將各個功能拆分到不同的子系統中去,降低單個系統的複雜度。重構後的架構如下(僅僅是示例,實際架構遠比下圖複雜):

架構重構

重構後各個系統之間通過介面互動,雖然看似增加了介面的工作量,但整體來說,各系統的發展和開發速度比原來快了很多,系統也相對更加簡單,也不會出現某個子系統有問題,所有業務都有問題。

這三個系統重構的方案,現在回過頭來看,感覺是理所當然的,但實際上當時做分析和決策的時候,遠遠沒有這麼簡單。

以M系統為例,當時我們接手後遇到的問題有很多,例如:

  • 資料經常出錯;
  • M系統是單機,單機宕機後所有後臺操作就不能進行了;
  • 效能比較差,有的操作耗時好久;
  • 介面比較醜,操作不人性化;
  • 歷史上經過幾手轉接,程式碼比較混亂;
  • 業務資料和遊戲資料耦合,開發效率很低。

從這麼多問題中識別出重構的目標,並不是一目瞭然的;而如果想一下全部解決所有的這些問題,人力和時間又不夠!

所以架構重構首要的任務是從一大堆紛繁複雜的問題中識別出真正要通過架構重構來解決的問題,集中力量快速解決,而不是想著通過架構重構來解決所有的問題。否則的話,就會陷入人少事多頭緒亂的情況,團隊累死累活弄個大半年,最後發現好像什麼都做了,但每個問題都依然存在。尤其是對於剛接手一個新系統的架構師或者技術主管來說,一定要控制住“新官上任三把火”的衝動,避免攤大餅式或者運動式的重構和優化,謹記“步子大了會扯到蛋”的教訓 !

那原來發現的那些問題怎麼辦呢?當然不能放任不管。以M系統為例,我們在重構完成後,又啟動了多個優化的專案去優化這些問題,但此時的優化主要是團隊內部完成即可,和其它團隊沒有太多關聯,優化的速度是很快的。如果沒有重構就進行優化的話,每次優化都要拉一大堆關聯業務的團隊來討論方案,效率非常低下!

合縱

架構重構是大動作,持續時間比較長,而且會佔用一定的研發資源,包括開發和測試,因此不可避免的會影響業務功能的開發。因此,要想真正推動一個架構重構專案啟動,需要花費大量的精力進行遊說和溝通。注意這裡我不是指要談辦公室政治,而是指要和利益相關方溝通好,讓大家對於重構能夠達成一致共識,避免重構過程中不必要的反覆和爭執。

 道理很簡單,但如何做才是關鍵!

一般的技術同學談到架構重構的時候,就會搬出一大堆技術術語:可擴充套件性、可靠性、效能、耦合、程式碼很亂。但以我的實際經驗來看,如果和非技術同學這樣溝通,效果如同雞同鴨講,沒有技術背景的同學很難理解,甚至有可能擔心我們是在忽悠TA。例如:

技術同學說:我們系統現在的可擴充套件性太差了,改都改不動!

產品同學想:咦,可擴充套件性,和擴胸運動有關麼?擴充套件什麼呢,怎麼會改不動呢,不就是找個地方寫程式碼嘛。

技術同學說:我們的可靠性太差,現在才3個9,業界都是4個9!

專案經理想:啥是3個9,三九感冒靈?。4個9和3個9不就是差個9嘛,和可靠有什麼關係。

技術同學說:我們系統設計不合理,A業務和B業務耦合!

運營同學想:咦,耦合,蓮藕還是藕斷絲連?A業務和B業務本來就是互相依賴的呀。耦合為什麼不合理呢?

以上的樣例並無嘲笑產品運營和專案同學不懂技術的意思,而是說明有的技術術語並不是很好理解,在跨領域溝通的時候,很難達成一致共識。

除此以外,在溝通時還經常遇到的一個問題是憑感覺而不是憑資料說話。比如說:技術同學說“系統耦合導致我們的開發效率很低”,但是沒有資料,也沒有樣例,單純這樣說,其他同學很難有直觀的印象。

所以在溝通協調的時候,將技術語言轉換為通俗語言,以事實說話,以資料說話,是溝通的關鍵!

以M系統為例,我們把“可擴充套件性”轉換為“版本開發速度很慢,每次設計都要考慮是否對門戶有影響,是否要考慮對其它業務有影響”,然後我們還收集了1個月裡面的版本情況,發現有幾個版本設計階段討論1周甚至2周時間,但開發只有2天時間;而且一個月才做了4個版本,最極端的一個版本,討論2周,開發2天,然後等了1個月才和門戶系統一起上線,專案經理和產品經理一聽都被嚇到了。

以S系統為例,我們並沒有直接說可靠性是幾個9,而是整理線上故障的次數、每次影響的時長,影響的使用者,客服的反饋意見等。。。。。。然後再拿其它系統的資料一對比,無論是產品還是專案還是運營,明顯就看出系統的可靠性有問題了。

當然,如果以上技巧還不奏效,或者遇到極端情況,那就要考慮一些更加有效的手段了!比如說我們遇到一個產品人員,他認為技術優化和架構重構是研發的事情,他不關注,安排開發資源的時候也不考慮重構和優化的投入,要研發自己解決!沒辦法,只能上升到上級領導層面協調,甚至我們都放出狠話“如果你不同意安排資源進行優化,下次出故障我們就說產品不給人力進行優化和重構”。

連橫

除了以上討論的和上下游溝通協調外,有的重構還需要和其它相關或者配合的系統的溝通協調。由於大家都是做技術的,有比較多的共同語言,所以這部分的溝通協調其實相對來說要容易一些,但也不是說想推動就能推動的,主要的阻力來自“這對我有什麼好處”和“這部分我這邊現在不急”。

對於“這對我有什麼好處”這個問題,有的人會簡單理解為這是自私的表現,認為對方不顧大局,於是溝通的時候將問題人為拔高,例如“你應該站在部門的角度來考慮這個問題”、“這對公司整體利益有幫助”等等。這種溝通效果其實很差,首先是這種拔高一般都比較虛,沒法明確,不同的人理解不一樣,無法達成共識;其次是如果對公司和部門有利,但對某個小組沒用甚至不利,那麼可能是因為目前的方案不夠好,還可以考慮另外的方案。

那如何才能有效的推動呢?我們的策略是“換位思考、合作雙贏、關注長期”。簡單來說就是站在對方的角度思考,重構對他有什麼好處,能夠幫他解決什麼問題,帶來什麼收益。

以M系統為例,當時有另外一個C系統和M系統通過資料庫直連共用資料庫,我們的重構方案是要去掉兩個系統同時在底層操作資料庫,改為C系統通過呼叫M系統介面來寫入資料庫。這個方案對C系統來說,很明顯的一點就是C系統短期的改動比較大,要將10幾個讀寫資料庫的地方改為介面呼叫,剛開始C系統也是覺得重構對他們沒有什麼作用,後來我們經過分析和溝通,瞭解到C系統其實也深受目前這種架構之苦,主要體現在“資料經常出錯要排查”(因為C系統和M系統都在寫同一個資料庫,邏輯很難保證完全一致),“要跟著M系統同步開發”(因為M系統增加表或者欄位,C系統要從資料庫自己讀取出來,還要理解邏輯)、“C系統要連兩個資料庫,出問題不好查”(因為C系統自己還有資料庫)。

這些問題其實在M系統重構後都可以解決,雖然短期內C系統有一定的開發工作量,但從中長期來看,C系統肯定可以省很多事情,例如:資料問題排查主要是M系統的事情了,通過M系統的介面獲取資料,無需關注資料相關的業務邏輯等等。通過這種方式溝通協調,C系統很樂意跟我們一起做重構,而且事實也證明重構後對C系統和M系統都有很大好處。

當然如果真的出現了對公司或者部門有利,對某個小組不利的情況,那可能需要協調更高層級的管理者才能夠推動,平級推動是比較難的。

對於“這部分我們現在不急”這個問題,有的人可能會認為這是在找藉口問題,我也不排除這種可能性。但就算真的是找藉口,那也是因為大家沒有達成一致意見,可能對方不好意思直接拒絕。所以這種情況就可以參考上面“這對我有什麼好處”這個問題的處理方法來處理。

如果對方真的是因為有其它更重要的業務,此時勉為其難也不好,還是那句話:“換位思考”!因為大部分重構的系統並不是到了火燒眉毛非常緊急的時候才開始啟動的,而是有一定前瞻性的規劃,如果對方真的有其它更加重要的事情,採取等待的策略也未嘗不可,但要明確正式啟動的時間,例如3個月後開始、6月份開始,千萬不能說“以後”、“等不忙的時候”這種無法明確的時間點。

除了計劃上靈活一點,方案上也可以靈活一點:我們可以先不做這個系統相關的重構,先把其它需要重構的做完。因為大部分需要重構的系統,需要做的事情很多,分階段處理,在風險規避、計劃安排等方面更加靈活可控。

文/李運華

原文出處——聊聊架構微信公共號