微信業務量增加的時候,其實咱們比較關心的是效率。前期可能兩三個月就漲了1倍的量,咱們怎麼可以保證咱們的運營效率是跟得上的?後期可能主要是關心成本。咱們在2014年之後增加有點放緩,因此主要的精力會在成本這個方面。前端
分爲四塊來講:nginx
運營規範
雲化管理
容量管理後端
自動調度微信
運營規範架構
配置文件規範框架
先來看配置文件規範,咱們前期花了比較多的精力。可能整個系統設計比較複雜,最開始都會有一些配置管理工程師專門來處理,後期咱們把這塊搞得比較規範了。運維
配置文件規範分爲下面幾項:微服務
目錄結構標準
這就是一個服務部署上線的時候怎麼定義它的目錄結構,你們應該先作好這些目錄結構標準的定義。性能
跨服務的相同配置項管理
爲何提這一點?可能有些配置項你會在這個服務裏須要這幾個配置項,在另外一個服務裏也須要這幾個配置項。若是更改這個配置項的時候,你是否是把服務A發一遍,服務B也發一遍?咱們有一套機制,每臺機每一個目錄下都會有一個全局共用的配置項,咱們會經過一些自動化的灰度的方式來控制這裏的發佈,這一塊是單獨拎出來的。測試
同一服務內不一樣實例的差別配置項管理
不肯定你們運營時會不會碰到相似的問題,就算你用Docker了你鏡像管理挺好的。你部署個實例出來,可能大家的業務就須要你把實例1上作一些調整,固然你也能夠用腳原本管理。可是咱們以爲這是比較複雜的狀態,咱們會把這些差別性所有給它統一抽取出來,儘可能作到全部的環境下它的配置文件的MD5都是一致的。
開發/測試/現網的差別配置項管理
前期也會有這個問題,開發環境咱們通常無論,測試環境也是運維來負責管理,現網固然是運維管理的。基本上測試和現網的差別只有路由的差別,其餘的配置項咱們都保證它是徹底一致的。作這麼一個要求,大概實現的效果是無論你經過什麼手段擴容,咱們直接一個鏡像打過去或者直接一個包拷過去就能夠了,不會再有後續的腳原本改動它。
同一服務下同一版本的多個實例,在全部環境下配置 文件的md5都嚴格一致。
名字服務規範
名字服務這塊比較重要,分三層:
服務伸縮是運維工程,獨立於研發的變動發佈。
接入層和邏輯層,都是相似的實現,咱們內部根據咱們的業務特性作了一些業務開發。
存儲層跟QQ有點不同,QQ好像是邏輯層和存儲層都是用同一個名字服務實現,咱們在存儲層這裏尚未作這方面的配置。
咱們如今存儲層跟邏輯層隔得比較開,在涉及到數據的方面,咱們差很少能夠認爲是運維可以配置的方式,可是又不徹底是可以配置,用那些輔助腳原本配置。
服務伸縮是運維工程,咱們不但願在服務伸縮時還考慮別的因素,獨立於研發的變動發佈。咱們有個特色,咱們研發是經過運維提供的變動系統,他在上面基本上不須要作什麼操做,整條鏈就打通了,運維不用關心變動發佈,只須要管好服務伸縮就好。
接入層和邏輯層的服務伸縮,無需考慮數據遷移和cache命中率。
數據存儲方面,單獨拎一頁出來是以爲這個場景是比較多人中招的,好比接入層確定不會帶什麼數據的,邏輯層我但願它是不帶數據的,並且咱們也嚴格要求不帶數據的。
常常出現這樣的場景,他的邏輯層要自動伸縮,跑了一段時間上線了一些邏輯在上面保存了一些數據,在下面作縮容的時候是否是就中招了,會有這個問題,因此咱們會定這個規範。
邏輯層是不帶數據的,會有靜態數據,包括用戶發的消息、用戶發的朋友圈,很明顯應該放到存儲層的。
接入層不帶數據,其實歷史上咱們也有一次是帶了數據的,在每次過年搶紅包的時候,全部人都在搖的那一把,其實那個量是很是恐怖的,搖紅包那個點咱們作設計是每一個搖紅包的請求真的打倒咱們接入層,不會有客戶端搖五次纔有一次請求上來。咱們的接入層的性能保證咱們能抗住這個量,可是後面的邏輯層確定撐不了這個量,1秒鐘幾千萬,這個時候咱們會作一些很特殊的邏輯,在接入層直接帶上紅包數據,固然這是比較特殊的場景,咱們只在過年的時候這個規範是沒有執行的。
運營規範小結
這裏說了幾點,咱們的目標簡單來講就是服務可運維,可運維的意思就是你作擴容縮容的時候不須要作人工的操做,若是作人工的操做就是不可運維。
咱們爲了實現服務可運維,在變動系統裏作了一些攔截,它接下來變動可能不符合咱們運營規範或者以前有不符合咱們運營規範的地方,咱們都會攔下來,要求變動,實現咱們的運維規範。
雲化管理
接下來講一下雲,你們用雲也挺多的,近幾年也比較火,可能你們用得比較多的是Docker,微信這邊咱們沒有用Docker,後面也會說到爲何沒有用。
爲何上雲
先說爲何要上雲,在2013年、2014年時,咱們的微服務已經到差很少5000個,其實我是近幾年才知道這個叫微服務,咱們以前實現方式已是好多年都算微服務的方式。
其實最開始說微服務這個事情的時候,我記得是QQ那邊海量運營的一些課程都會提到,我以爲這個思路跟微服務是徹底一致的。
咱們運維這邊在實現了一套新服務發佈的時候,基本上不會給研發有什麼限制說你這個服務不要搞太多,因此整個系統搞下來那個量是比較誇張的,固然就會出現他的多個服務要在同一臺機上部署,由於裏有5000個微服務,必定要同物理機部署。
部署多個服務就會有資源搶佔,基於這個因素,咱們就上雲。
哪部分上雲
哪一塊上雲,剛纔也說到,接入層由於要扛住比較猛的量,微信的用戶也比較多,若是它有什麼問題,可能接入層會雪崩。因此咱們主要是獨佔物理機,容量足,變動也少,暫時沒有上雲的需求。
在邏輯層這裏,以前提到5000多個微服務,因此比較混亂,變動比較多,容量也不可控,因此這塊上了雲。
存儲層這裏,也沒有上雲,可是有單獨的容量管理和數據遷移。
基於Cgroup的雲化
咱們雲的方式是直接Cgroup,Cgroup這個名字可能有些人不知道,咱們用的是內核Cgroup這種機制。
在現網的時候,用相似簡單的虛擬機型定製,好比1個cpu+1G內存。前期咱們也有一些流量因素的考慮,後來把它給取消掉了,咱們系統架構上保證的那個流量好像是不怎麼會成爲問題的。
這裏簡單列了一下虛擬機分片的方式,怎麼隔的方式都有,咱們隔的這麼隨意也帶來另一個問題,系統運轉過程當中會有一些相似於磁盤碎片的東西存在,好像你Windows跑了好久之後也會有磁盤碎片存在同樣。這個咱們也有一些比較特殊的方法來處理。
線上未啓用Docker
這裏列了一下咱們沒有用Docker的緣由。
Docker太火了,咱們差很少在2014年、2015年的時候,線上也少許上線了一輪。
咱們這個svrkit框架是咱們微信內部自研的一套框架,100%覆蓋全網,100%什麼意思,一點開源代碼都沒有,包括前面你們可能用得最多的nginx作接入,這個咱們也是在自研的切換的,包括後面的存儲,前期用了MySQL,後期也都換成本身的組件了。
現網用咱們本身的框架100%覆蓋了,咱們的標準化和規範化都是比較好的。
能夠說Docker解決的一些問題在咱們這裏不是問題。
對Docker的需求不是很強烈
框架自己咱們用了不少IPC交互
這些東西其實在Docker裏都作了很嚴格的規範,若是咱們用Docker,咱們可能會把這些Docker裏的各類機制破壞掉。若是是這種狀況,還不如不用Docker。
對Docker這種接入方式的實現仍是有顧慮
早一兩年有人跟我討論比較多,Docker主進程起來的時候,可能你因爲要更新Docker自己,會致使你的服務重啓。
好像近期已經解決這個問題,這個在早期來看咱們認爲是一個比較嚴重的問題,我不但願說由於Docker自己的變動,對線上的服務有任何影響。
私有云調度系統
基於上面的點咱們自研了一套雲化管理的Docker系統。這是咱們私有云調度系統:
基於我前面提到的svrkit框架+自研,調度系統固然也要用咱們本身的調度系統覆蓋,目前覆蓋了80%的微服務,還差一點點100%覆蓋。
私有云調度系統架構
這是咱們的架構,熟悉的人一看就知道跟業界的事情沒有什麼區別,中間有一些虛擬化的坑,能夠認爲跟你們用得沒有太大區別,不細講了。
雲化管理小結
在雲化管理這一塊,咱們實現的一個目標就是資源隔離,Docker服務之間不要由於一個服務異常搞的第二個服務也異常。
第二是服務伸縮頁面化操做,有些服務仍是很龐大的,一個服務下幾千上萬臺均可能,這種時候不但願你上機器的,在頁面上點就能夠了。
咱們爲了落實這個目標,會把部署系統,把那些沒有上雲的攔住,他要走舊的部署方式上線,他須要走舊的流程才能走舊的商業模式。
前面這些運營規範和雲化管理,相信你們多多少少都會有本身的實現方式,也都會有本身的一些總結。後面容量這塊不肯定你們都是怎麼改這一塊的。
容量管理
如何支撐業務發展
這是一個業務量增加的曲線,這是咱們容量的曲線。
通常來講你擴了一次容就一直平衡在這裏,有一個點你發現撐不住了,要擴容,擴上去,就一直保持這個狀態,跟容量曲線是不怎麼匹配的。
第一個點是你這個容量低於現網的業務量的時候,這實際上是容量不足的,能不能很快發現這個問題。
第二個點是處理效率,容量不足的時候把曲線打上去,擴容須要多長時間,若是是幾天或者幾分鐘,這個效率是不同的。
咱們但願實現的一個最優容量的方式,它跟業務增加徹底是匹配的方式。
這個曲線並不很難實現,只要擴容夠頻繁,跟這個就是徹底吻合的最優容量的曲線。
你發現它容量不足是分鐘級的,擴容也是分鐘級的,那你徹底能夠描出這麼一套如出一轍的曲線出來。
使用硬件指標評估容量
咱們會說你怎麼知道這個服務的容量不足的?通常咱們第一個反應就是用硬件指標,包括CPU使用率是多少,磁盤空間多少,網卡容量、內存。這也能解決到問題,但它不能解決全部問題。
使用CPU評估容量
服務容量 = 當前峯值/經驗CPU上限
這是一個使用CPU來算服務容量的方式。
這是一個簡單的例子,好比你如今CPU當前峯值40%,你本身的經驗以爲這個能達到80%的CPU,簡單除下就是50%的容量。
硬件指標是否可靠
這東西靠譜嗎?我這裏畫了兩個示意圖:
有些相似左邊這張圖是靠譜的,容量基本上和CPU保持增加的。
有些相似右邊這張圖窄口瓶,CPU漲到必定點的時候,容量就上不去。
真實案例
這是現網打流量的例子,人爲把流量打上去,會發現有些服務怎麼打都是在80%;有些怎麼都是60%,上不去。
硬件指標的侷限性
硬件指標咱們認爲有一些侷限性:
確實,線上服務多了之後,作的事情不大可控。
咱們以爲應該要經過壓測,才能比較準確的獲得容量的模型。
壓測方式
壓側方式分兩種:
環境也是分兩種:
四種壓測方式
第一種模擬流量在測試環境打的時候,測試團隊內部對質量的一些驗證,這種測試方式是測試團隊負責的,咱們沒有太參與。
第二種模擬流量打現網有點相似於全鏈路壓測,好比淘寶在雙十一常常這麼幹,對微信來講,咱們只在過年這麼幹,微信過年好像跟淘寶雙十一差很少,都是一個比較瘋狂的狀態,因此咱們會在過年前用模擬的流量打一下現網,這個不是一個很常見的壓測方式。
第三種真實流量往測試環境打,通常是咱們要驗證一些存儲性能時會這麼幹,把線上的流量旁路打到測試環境裏面,看一下這些存儲性能的狀況,能夠在測試環境裏比較好的模擬出來,不會影響到現網。
第四種真實流量打現網環境,我這裏主要想說的,咱們真的在現網壓測,用真實的流量打現網環境是什麼情況。
現網壓測
現網壓測實現起來很是簡單,當你名字服務這塊實現比較標準的話,都是統一的流程,就是壓側流程,不停的調其中一個服務的權重,觀察它是什麼後果就好了。
現網壓測可能致使的異常
這樣壓有什麼問題,你們都能想到,你壓那個服務,何時停,怎麼能保證不要搞出事來。咱們認爲這裏有如下三個點:
我認爲這三個問題是比較關鍵的。
服務的自我保護
你的各個服務有沒有作好自我保護。咱們引入了一個快速拒絕的概念,這個服務正常的時候,可能你的上線每分鐘100萬個請求也是能正常服務的,上游服務給你500萬的時候,你只能處理100萬,你能不能把其餘400萬個請求拒絕掉,這是咱們框架實現的能力
上游服務的重試保護
上游服務重試保護是怎麼樣的?好比你在壓其中一個實例的時候,你一直加大它的權重,致使它快速拒絕返回失敗了,那你有沒有一個機制走到其餘的實例把整個流程跑完,這也是一個比較關鍵的點,這個咱們也是在框架裏支持了。
立體化監控
監控體系夠不夠完善,包括硬件的監控,剛纔提到快速拒絕的監控,還有前端跟後端這種耗時的監控,還有剛纔提到的前面這種,有沒有發生失敗,整條線都是咱們須要關注的。
能夠這麼說,有了服務的自我保護、上游服務的重試保護、立體化監控,咱們纔敢壓測,若是這三個點搞不定,壓測這個事情作不了。
秒級監控
能不能快的發現你的異常?爲了這個問題,咱們把分鐘級的監控升級成了秒級的監控,全部的異常差很少都是10秒鐘以內就能發現。
整個實現的方式你們應該都差很少,每臺機都有個採集的,以前是每分鐘上報一次到隊列,而後再彙總,而後再入庫。如今咱們改了這個邏輯,6秒鐘作一次採集,而後數據轉化,而後作一個秒級數據的彙總。
上面仍是分鐘級的。
放量速率動態控制
這裏還有一個速率的動態控制,這裏比較複雜,不知道怎麼解釋這種狀況。
左邊這張圖是咱們比較早期壓測的實現方式,它從一個點開始,可能用一個比較快速的調整它權重的方式,直到調用失敗出來了,而後再回退,再繼續往上壓,不停往上不往下,用這種方式來接近你的容量上限。這個點你們很明顯看到一個問題,運維在壓測的時候實際上是給本身找事,每次壓測都打上來,又掉下去,打上來。失敗曲線就像狗啃的同樣,一直有抖來抖去的曲線。這種壓測方式,運維本身都受不了。
後面咱們調了一下,其實這個也跟咱們服務框架提供的能力相關,咱們整個服務框架會有一個入隊/出隊的機制,每一個微服務自己都會有這樣的機制。這裏的隊列的積壓狀況是比較關鍵的指標,咱們會監控入隊延遲,它出隊,發現它一有積壓,性能已經跟不上了,咱們經過這種指標來調整壓測的速率,大概實現的效果是右邊這張圖。前期是比較快的權重,當觀察到隊列已經有積壓有延遲,就開始放緩,一直達到一個點,可能最後那個點是有一點點壓測失敗,實現這麼一個效果,整個過程當中可能只有幾秒鐘,就獲得性能模型,獲得壓測真實的值。
現網壓測效果
這是咱們真實的線上壓縮的結果。
這張圖打出來的斜率是先漲得比較快,後期再慢慢增加,而後把這個壓測點停掉了。
爲了打出這張圖的效果,咱們還搞了蠻久的,可能大概一年多才達到這種現狀,基本上不會給現網服務帶來失敗的。
容量管理小結
這個事情咱們作完了,以爲有幾方面的收益:
服務的資源需求可準確量化
剛纔提到幾百微服務,每一個是怎麼算出來的。
怎麼知道你這個微服務適合於哪一種機型?有些服務根據咱們壓測會發現它有些場景跟別人不同,咱們只要把自動化壓測的方式實現了,每一個模型試一下,壓出來你知道它最優的機型是怎麼樣的。
自動調度
業務增加的自動擴容
解決業務增加的自動擴容,由於你的業務量在漲,其實你的用戶的請求包括各類請求量都是跟着指標在漲的,你知道業務量怎麼增加,知道微服務怎麼增加曲線,前面的壓測又知道每一個實例的性能怎麼樣,你就可以準確知道我如今容量大概比例是在哪條線上。
咱們通常讓它跑在50%、60%這個區間內,66%是一個容災的預留,咱們先部署三個IDC裏面,你要想掛掉兩個,另一個也不會有什麼異常的話,可能就是這兩個限。
咱們會留出一些時間給採購機器給咱們,會把一些服務的流量控制在50%這個點。
異常狀況的自動擴容
還有一些異常的狀況:
這種某些產品搞活動沒有通知咱們,咱們會用一些粗暴的方式來解決,包括說CPU,咱們會給它定一個點,當你的CPU衝過這個點的時候,咱們會自動發起擴容。
你業務沒有太大有變化,但你程序變了,這其實也會致使容量不ok。這個點咱們是可以監測到這種狀況的,就看咱們壓測的頻率有多頻繁,若是你天天都壓測,你把壓測的曲線描出來。
程序性能降低的合理性評估
咱們差很少有些服務是2015年天天都在壓,每一天他的性能是怎麼樣的,咱們描出一條曲線出來。可能會發現有一些時間點性能降低比較遠,好比這裏的例子是他發了個大版本,特性裏面增長了一些處理邏輯,因此性能降低比較明顯。這個事情可能過了一兩個月之後,有些同事出來解決fix它,這種性能監控我認爲在前面的容量管理和智能交互這一塊的副產品,這個副產品咱們用得還比較多的,能夠準確知道整個微服務性能變化怎麼樣。
性能管理閉環
能不能不要讓它出現這種新的降低的點,咱們天天都在壓,能不能再快一點,直接在它上線的時候直接攔住。好比說開發同窗灰度上了一個臺機,咱們立刻壓測它灰度上線的這臺的這個機器,看它的性能怎麼樣,若是發現它的性能降低,就把他拉住。
幾種業務形態
這是咱們現網的一些業務形態,可能比較多的就是最上面這種圖,它在晚上9點到10點迎來它的最高峯。
中間這種圖通常跟工做相關的如微信,工做時間段用得比較多的。
還有一種是最底下這種,比較典型的例子是微信活動,微信活動好像是晚上22點的時候會來一步。還有一些比較古老的業務,漂流瓶,用得腦殘粉還挺多的,他們會守着0點的時候。
削峯填谷
咱們對這些業務曲線但願作什麼?
第一,峯那麼高,咱們全部的設備都是爲了應付最高的那個峯,這個峯能不能作點特殊處理,不給它們危險設備。
第二,晚上零點之後,這麼低的業務量,設備挺浪費的。
咱們但願有一個削峯填谷的做用,原理仍是很簡單,就是把你的有些服務跟另一些服務的峯值錯開。有些服務高峯期過了,把它的資源放棄出來,至於誰去用它無論。
在線業務削峯
離線計算填谷
cpu.shares + memory.limit_in_bytes + blkio
離線計算,凌晨那段時間確實都很閒。這個時候比較適合離線計算來調度,微信羣以前離線計算的東西比較少,主要是語音輸入等一些人工智能方面的東西。最近可能有一些看一看、搜一搜新功能,他們用的離線計算的調度還挺多的。
資源佔用方面,這幾個場所的配置基本上是Cgroup控制得比較嚴格一些。
而後把離線任務的優先級調一下,用離線任務來把咱們低峯的谷填平了。
自動調度小結
這在自動調度這塊是咱們實現的一個目標: