90%產品服務化,細說豆瓣的5年變革之路">90%產品服務化,細說豆瓣的5年變革之路

分類:IT技術 時間:2017-09-30

背景

今天主要分享下微服務中的Auto Scale,豆瓣2005年3月上線,是一家歷史比較悠久的互聯網公司,主要覆蓋文化綜合領域的Web、APP等各種產品,現在有豆瓣讀書、豆瓣電影、豆瓣音樂等等。

〓 豆瓣簡介

在技術方面,豆瓣主要的開發語言是python和Golang,豆瓣擁有自研私有雲平臺Douban App Engine(以下簡稱“DAE”),上面托管豆瓣網所有應用使用配置來描述應用:應用依賴MQ、Daemon,以及Cron,這樣開發者使用一個配置文件就可以描述對資源的所有需求,平臺拿到描述文件後可以在上面做需要的資源管配。

〓 Douban App Engine

在DAE上會統一調度所有資源,產品開發人員不必關心具體的機器設備,比如無需關心某個業務線需要配備多少臺物理機器,所有資源由平臺統一調配,所有開發流程,從提交PR到測試,上線是一套統一流程。

〓 現狀

豆瓣從2012年開始做服務化,主要因為隨著產品線越來越多,單體應用已經無法滿足豆瓣對開發效率的需求,因此,2012年起逐步開始拆分整個網站,截止2016年底,90%以上的產品已經完成產品服務化,由於前期準備充分,這個過程中整個網站性能沒有發生變化,沒有因為做了服務化導致性能上的下降,全棧可用性得到提升,不會因為新入職同事做了一個不太成功的提交,而導致全棧掛掉,發布也由每日發布變為按需隨時發布,服務化後,所有上線流程由各個業務線自行控制。

回歸今天的主題,為什麽豆瓣要做Auto Scale,做了微服務的公司內部各個系統之間會形成非常多的依賴,微服務化之後,整個系統結構很難用層次化的模型來描述,呈現出來的是一個復雜的網狀依賴關系,大量應用相互之間有交錯的依賴。

目標

這裏有個問題,單體應用時,運維人員部署應用其實非常簡單,在一臺機器上將應用部署完畢,按照機器的性能部署相應的進程,當請求過來處理能力不足時,直接加服務器。

微服務化之後,運維人員手裏有大量的微服務,每個服務的請求量和性能都不同,運維很難手工維持每個具體的應用需要多少計算資源,這就帶來一個問題:怎樣能夠讓應用既能跑得好又跑的省,如果每個應用都給予足夠多的資源,這顯然不是一個經濟的方式,迫切需要一個既能提高服務器利用率,又能提高自動化的方式。

〓 服務化之前的方式

豆瓣微服務的時間起始於2013年12月,因為過早,現在流行的一些開源技術當時還沒有用到,2014年2月,開始進行簡單的場內線上應用,3月,已經可以接管部署在平臺上的140多個應用。公司處在服務化進程中,當時只有一小部分應用部署了微服務享受到Auto Scale帶來的好處。

14年3月,Docker還沒出來,豆瓣此時是一家純Python的公司,用Python做應用打包,2014年下半年,開始發現Docker的巨大優勢,於是做了整個平臺的Docker改造,2015年Q2完成整體Docker化改造。

整個AutoScale的發展是從前面提到的140個應用開始,隨著服務化推薦,持續優化性能,提高穩定性,目前整個平臺上500個托管應用都在Auto Scale之下。

〓 DAE Scale模型

一個Git Repo映射到DAE平臺上的資源分配、調度、計費和邏輯集合,每個應用全局唯一且相互獨立,通過thrift/pidl/http RPC相互調用,對於Web和Service服務,豆瓣支持Multi-instances,比如一個應用既需要有Web頁面,也需要Thrift服務,可以用一份代碼起兩個不同服務,其中Web服務主要服務每天來自外部用戶的訪問,Thrift Service是內部調用,量級比外部訪問大很得多,Auto Scale提供一個機制,通過配置把兩個Instance分拆開,Austo Scale提供一直機制,通過配置將兩個Instance分拆開,分別做Scale。

DAE Scale是多進程模型,每個請求由一個進程來處理,整個系統可以理解為Worker的總數和應用服務處理能力直接相關,Node是物理機,有些Node會部署一個應用,有的部署若幹個應用,從平臺資源調度來看,所有無狀態節點都是均等的,差別主要在CPU和Mem方面,Node和APP之間是多對多的關系,每個APP在每個Node裏面有多少Worker(工作進程),是Auto Scale的關鍵,會放到數據庫裏。

從理論上來說,所有應用都是平等的,但有些應用相比其他應用重要度更低,需要物理層面的硬隔離,Pool就是一組節點,在被分隔開的若幹個Pool中,有的Pool是公司內部的小應用,只需做有限支持,計算資源非常受限,對外較重要的應用分成兩級,Production Pool和Stable Pool以及一些非常重要的應用,是公司的核心產品,它們會單獨用自己的資源,另外,有些部門有自己的計算資源,希望用到平臺調動的機制,這種情況部門可以將自己的計算資源貢獻出來單獨有一個Pool。

上圖是整個Auto Scale結構,最下面的節點上有Monitor,會采集借點上面各種性能指標,包括Memory、CPU、Load、當前進程的繁忙程度,采集之後發到若幹地方,主要用來給監控人員查看,在Auto Scale的應用中,其實它的性能還不夠好,所以一般會存一份數據Redis裏面,到了Redis之後,整合的數據稱作Bridge,在Bridge節點上面采集的數據進一步加工封裝出一些API,包括關於APP、Node、以及Pool的API。所有應用Scale各種策略的配置都在這個應用裏做。

真正做Auto Scale策略的應用是DAE Scale,Scale這一塊會有若幹個Cron Job,做相應的事情,比如APP的Auto Scale,Web Auto Scale、真正去Scale他們的Worker,裏面會配置一系列的策略,對於Pool,豆瓣最核心的幾個應用,計算資源也是共享的,Movie、Group和SNS是豆瓣最核心的三個業務,會獨占一個Pool,但每天需要Pool中的多少節點,是一個動態調整的過程,會有專門的Pool做彈性伸縮。

在Scale裏做完運算,下一步要麽Scale UP到某一個APP,要麽Scale Down某個APP,或把一個APP從一個節點挪到另一個節點,或者把一個APP在某個節點上放上去或拿掉,Scale產生這些行為,最後落地又回到節點上,節點上面有一些工具暴露API,讓Scale回到節點上面來,這樣將整個流程串起來。

外部應用更新完畢後,會更改Nginx的配置,不同節點同一應用的觸點不同,配置反應不同的權重,處理能力強的節點拿到的請求更多,能力弱的節點拿到的請求少一些,這就是Scale整體的結構。

〓 采集數據

關於采集數據,豆瓣是多進程模型,怎麽去判斷這個進程在工作沒有呢?是去數,每個進程在運行之前會做一個標記,完成後這個標記會刪掉,Monitor會到這個機器上數,這臺機器上有多少個Worker,多少標記,標書就是正在忙的節點,正在忙的進程,這裏有一個小技巧,標記放在內存盤上,它的系統上就看不到了。

〓 Scale應用策略

整個APP Scale有兩種策略,一是每個應用Instance現在有多少個進程在忙,需要有一個策略來計算,到底需要多少進程,豆瓣嘗試過若幹策略,比如Noop,有的應用不需要Scale,配幾個進程就夠了,不需要Scale,不需要幹涉,但busy_ratio_mark_cnt是需要幹涉的,rps_ratio可以根據應用的具體請求量和響應時間計算出來,當前應該還需多少個Worker。

還有一個Ondemand_rps進程,Auto Scale基於的假設是,所有請求都是一個逐步增長和減少過程,但有特例,比如APP做一次大規模推送,或上一個廣告,這時有預期推送後或廣告放出去後,會有大量的回放上來,此時Auto Scale的曲線型就會比較明顯,因為它沒辦法與指導RPS陡然的上漲,豆瓣處理方式是給Scale提供一個API,將主動權交回給應用開發者,讓他按照推送的規模,估計大概的規模,平均回訪率,反饋到Scale後,Scale會做一個快速拉起動作,馬上將需要的進程漲上去維持一段時間,等待請求過來,然後隨著請求過去再慢慢Down下去。

Ondemand_rps還有一點經驗,就是需要有一個大概預估的時間,Scale上去後,如果請求還沒來,那麽Auto Scale會很快介入,如果還是沒有足夠請求它會開始往下Down,比如保持半個小時,這是一個產品經驗值,如果半小時請求還沒來,可能這次就不會有那麽強的請求了。

關於哪些節點加進程,有兩個策略:一個是完全equal,比如某個應用在5個節點上需要20個進程,每個節點做4個,絕對均衡,有的應用要求每個節點處理能力是相當的,但是,更多的節點允許不同的節點上處理能力不一樣,這個前提下會稍微保證節點之間不要差的太多,某些處理能力強的節點也不會拿到太多進程,比如將80%的請求都放在一個節點,如果那個節點有問題,就會都有問題,而應該是當某個節點宕掉,當期那的冗余度能夠Cover宕掉的問題。

每個應用會做一個配置,這個應用最小需要多少節點,各個應用不一樣,有大的需求得更高,比如至少10個節點,有的應用兩個節點就可以了,這也是通過Scale確保上面做這些操作不會破壞掉最低的要求。

所以整個Scale核心訴求是,調整總Worker以及到每個節點上面去調進程,在工程上有時會將VIP和普通分開,如果某一次Scale卡住,比如早晚高峰,會有相應的報警,如果那個時候沒有把處理能力加上去,很可能會出大面積的問題。

Scale一些基本的策略,在加Worker時一定要快,請求來的時候要非常快的響應,但減的時候需要慢,如果很快減掉了,可能系統會顛簸比較厲害,另外,節點之間分配杜絕過於不均,後期簡單算一下各個節點之間的標準差距,看是不是差的太遠。

還有一個維度,從節點的角度看,需要同一個Pool裏面平衡各個節點的負載,在同一個Pool的節點之間做均衡,平衡主要看CPU、存儲、可以優先把Worker較小的應用拿掉,留下一些比較大的Worker,過一段時間Scale趨於穩定後,會發現有些訪問量很大,一些應用慢慢會獨占一些節點,這也是IT人員希望看到的情況。

對於VIP的Pool,它們會有一個彈性池子的概念,也有一個Freed Pool,我們目前閑置的資源都是Free Pool裏,當VIP Pool有資源的需求的話它會從Free Pool裏面拿,Load下去之後它會還回去,在這幾個大的VIPPool之間,其實是共享整個計算資源的,主要的考慮也是各個產品用戶訪問Pattern不太有一樣,有的產品白天訪問量比較高,晚上比較低,有的則反之,同一組機器其實通過機制調度能夠用的更充分一些。

〓 監控

Auto Scale是一個完整自動化的工具,豆瓣圍繞它做了很多監控,網站所有的資源調配都交給Auto Scale來管理,一旦Auto Scale出現任何卡頓,或其他情況,會產生非常大地問題,所以會有大量報警去看相關的事情,另外,Scale應用是5分鐘做一個,頻率更高意義並不大,會導致整個系統顛簸的太厲害,還需要提供足夠的手工工具,當Auto Scale本身出現狀況時,需要給運維人員提供充分的腳本,如果自動系統出現狀況而不能人工幹預是一件非常要命的事情。

有一些典型的情況,比如網站被DDOS,整個網站訪問量直接Down到底,所有Worker都閑下來,這時Auto Scale開始介入工作,會逐漸把Worker往下調,DDOS過去之後這些Worker是不夠的,所以當出現類似狀況時,用手工的開關把它停掉,同時也需要強勁的LOG,這樣在後續查找問題可以快速定位。

〓 推而廣之

做完App Auto Scale後推而廣之發現,豆瓣有大量離線MQ Consumer,之前是產品開發人員來調配,應該調到多少是比較難以把控的,MQ的Auto Scale做下來發現和外部請求類不太一樣,外部請求來了之後,無論響應與否,它很快就走掉了,但MQ來了之後就不會走,它會一直在那裏,MQ可能會越來越長,還有一個之前做APP沒有關註到的點——排隊,隊列在這時非常重要,需要看看隊列是不是在增長,如果增長需要快速把Consumer加上來。


Tags: 豆瓣 服務化 所有 產品 描述 主要

文章來源:


ads
ads

相關文章
ads

相關文章

ad