大規(guī)模微服務場景下的性能問題定位與優(yōu)化

分享下劉超老師的一篇文章,好好學習。

今天我的主題是在微服務場景下的一個性能問題的定位優(yōu)化,那么今天會講一個我們其實出現(xiàn)的一個真實的一個場景,然后其實還是花了蠻長時間,然后把這個東西才定位到一個具體的問題。

image

現(xiàn)在云原生微服務架構(gòu)特別的火,有非常多的優(yōu)勢,比如說這里面寫的快速迭代,高并發(fā),可維護,可擴展,灰度發(fā)布,高可用,這些詞大家都耳熟能詳,這些就不用細說了。

image

但是微服務不是沒有成本的,如果說單體應用的復雜度大概是10的話,上了微服務可能是變成100,可能是十倍的復雜度提高,需要投入大量的人去做這個事兒,并且需要一定的支撐系統(tǒng)和工具鏈,才能將這些復雜性降下來。

我這邊總結(jié)了一下微服務實施之后,會大概率出現(xiàn)以下的痛點:

第一:服務依賴的管理,就是一個服務到底調(diào)用了哪些,被哪些服務調(diào)用,如果依賴管理比較混亂,就會比較痛苦,比如說你要發(fā)布一個應用,你可能不知道這個應用被誰依賴了,有沒有有一個特別關(guān)鍵的應用在依賴于我這個應用,會不會我升級了以后是否會引發(fā)關(guān)鍵業(yè)務的不穩(wěn)定,是應該白天發(fā)布,還是凌晨發(fā)布,這個時候我們就特別需要希望有一個系統(tǒng)能夠看到任何一個服務都被哪些服務依賴以及依賴于哪些服務。

第二:調(diào)用統(tǒng)計問題,對于調(diào)用記錄有一個統(tǒng)計和告警,例如有沒有接口突然調(diào)用失敗率增高,有沒有接口突然時延增長,都應該及早發(fā)現(xiàn),而不能因為因為一次發(fā)布引入一個bug,導致時延變長但無人知曉,等到流量一來,直接就可能壓掛了。再就是有沒有接口再也沒有人調(diào)用,這個接口是否可以下線,這在接口升級的時候,常常采取先添加接口,再下線接口的方式,就需要這樣一個統(tǒng)計系統(tǒng)。

第三:接口規(guī)范問題,各個團隊開發(fā)出來的各個服務的接口是否符合統(tǒng)一的接口規(guī)范,有沒有統(tǒng)一的地方去看接暴露出來的接口?如果說有的接口不遵守規(guī)范,那么是不是時候會在同一個地方能看到,然后去盡早的去發(fā)現(xiàn)這個問題。

第四:安全管理,很多企業(yè)往往通過白名單通過配置中心配到各個服務里面去的,比如說支付這個服務不是所有服務都能調(diào)用的,只有部分服務可以調(diào)用他。這些配置原來都是散落在這個服務里面去的,各自為站,有可能一不小心就配置錯了或者漏了,應該能訪問的訪問不了,不該訪問的能夠訪問了,但是沒有人察覺。

第五,熔斷限流降級這些服務治理能力。雖然有很多開源組件可以做這些事情,但是需要寫大量重復代碼去做,同樣是散落在各個地方。

第六,接口測試問題,我們?nèi)绾伪WC在不斷的拆合的過程中不會引入新的bug,這其實是比較頭疼的一個事情,所以需要一個比較大的一個測試集合,就需要一個測試平臺來保證。

第七,灰度發(fā)布問題,很多公司做灰度發(fā)布,都是通過代碼里面寫if-else做的,當什么條件滿足的時候,走這個邏輯,當時什么條件滿足的時候,走那個邏輯,這個時候也是相對比較痛苦的。

第八,壓力測試問題,這一般是實施微服務的后期,當需要面對大規(guī)模流量的時候,才會引入進來的。一開始線上大促的時候,基本處于這種一臉蒙,靠運氣的這種狀態(tài),心里壓根都沒有譜,必須要通過壓力測試去做這個事兒。

第九,調(diào)用鏈分析問題,一旦出現(xiàn)慢的時候,相對比較難以發(fā)現(xiàn)慢的點,尤其是當服務數(shù)目多,調(diào)用鏈長了之后。

第十,測試環(huán)境治理。服務數(shù)目增多了,大家都用了容器,帶來的好處就是部署的特別方便,一個編排就能啟動一套系統(tǒng),但是同時也帶來一個痛苦,其實我們從云的時候就有這個痛苦,一旦放給大家的權(quán)限讓大家可以隨時部署,對于資源的使用就控制不住了,大家誰都想啟動一個新的環(huán)境,自己的測試環(huán)境和別人都不在一塊。如果說只有幾個容器,那么每次都重新部署一個新環(huán)境,這沒有問題,但是如果服務特別多的時候,例如一百個容器的時候,這時候全量部署比較困難。

image

為了解決這些問題,需要配備比較復雜的工具集合:容器平臺負責聲明式部署,持續(xù)集成和測試平臺負責灰度發(fā)布和測試集合的維護,API網(wǎng)關(guān)負責入口流量的接入,微服務框架負責微服務之間的相互調(diào)用,管理和治理,分布式事物負責拆分后的事務問題,APM性能管理負責調(diào)用鏈分析。我們后面也能看到這些組件在定位問題的過程中都起到了什么樣子的作用。

微服務的拆分過程并不是一蹴而就的,我們發(fā)現(xiàn)很多公司開始計劃實施微服務的時候,往往第一個問題是微服務應該怎么拆,應該拆分到什么粒度?覺得是這是一個最重要的一個維度。后來我們發(fā)現(xiàn)其實并不是這個樣子的,微服務的拆分只是其中很小的一個方面,需要匹配一套工具鏈,并且經(jīng)歷十二個過程,逐步完成。

image
image
image

接下來,我們來解析一個微服務場景下的問題定位過程。

image

為什么說在微服務場景下,我們發(fā)現(xiàn)定位問題的時候,我們會覺得它特別的復雜,往往需要架構(gòu)師牽頭協(xié)調(diào)各個部門一塊去定位某個問題。

首先第一個復雜度就是,從頂層到底層這個層次是實在是太多了,我們能想到就是任何一個比如說我們發(fā)現(xiàn)請求比較慢的時候,我們首先會想到整個層次中,最上面的應用是不是出了問題,應用這一層本身就比較復雜,圖中密密麻麻的線是double服務之間的一個調(diào)用關(guān)系,它的復雜度已經(jīng)十分高了,然后中間一旦出現(xiàn)了慢請求,這時候其實很難定位到一哪一個點,哪個服務集群調(diào)用哪個服務集群。

應用層下面這就是容器層,容器下面其實是openstack的云網(wǎng)絡,我們采取方式是kubernetes和openstack整合的一個方式。因為kubernetes對于容器的發(fā)布,運行十分友好,對于網(wǎng)絡尤其是多機房高可用橫向擴展的vpc網(wǎng)絡特性相對弱一些,那么正好云在VPC這方面相對比較強一些,例如浮動ip,跨機房高科用,專線等。容器層或者云網(wǎng)絡層,都可能產(chǎn)生問題,例如容器網(wǎng)卡吞吐量受限制,或者ovs吞吐量受限制,都會造成性能問題。

再往下是物理網(wǎng)絡,因為牽扯到多機房了,那么可能每機房還有多高可用區(qū),那么整個機房的拓撲結(jié)構(gòu)邏輯也會很復雜。

這時候就可以想象說當一個服務的多個副本構(gòu)成一個業(yè)務集群,當從一個業(yè)務集群到另一個業(yè)務集群時延高,每個層次都其實都有可能出現(xiàn)問題是吧?然后我們就需要層層的去排查這個事情。

image

另外一個相對比較頭疼的一個事,是從前端到后端的層級也是挺多的。問題往往是在壓測的時候會發(fā)現(xiàn),那么壓測的時候,我們是在我們公有云上去壓真實線上的業(yè)務,所以其實是走公有網(wǎng)絡的。

我們可以想象,從前端到后端經(jīng)歷的環(huán)節(jié)實在是太多了,你比較難判斷他會慢在什么地方。

一開始進入機房,有邊界路由器,然后有核心匯聚交換機,這是網(wǎng)管部去管的。

接下來就進入了虛擬的云網(wǎng)絡網(wǎng)關(guān),由云計算部門維護。

云網(wǎng)關(guān)進來后,會有一層負載均衡,這個負載均衡是可以適配多機房的負載均衡,可以做跨機房浮動IP漂移。

再往里面會有個API網(wǎng)關(guān)作為接入層,然后再往后就是服務層了。服務層分業(yè)務服務層和基礎(chǔ)服務層,之間會引入注冊發(fā)現(xiàn)機制,比如說用dubbo管理他們之間的相互調(diào)用。由于微服務規(guī)模比較大,就像剛才圖中展示的一樣,復雜度很高。

業(yè)務之間調(diào)用完畢之后,最終肯定是要落庫的,這時候會涉及到緩存的訪問,緩存后面是數(shù)據(jù)庫。

有時候還涉及到調(diào)用云外的系統(tǒng),因而需要經(jīng)過云網(wǎng)絡的網(wǎng)關(guān)。比如說外部的一些支付系統(tǒng),安全檢測系統(tǒng),包括大數(shù)據(jù)等,都是云外的。這兩次網(wǎng)關(guān)其實是不一樣的,前面網(wǎng)關(guān)是DNAT網(wǎng)關(guān),后面網(wǎng)關(guān)是SNAT網(wǎng)關(guān)。

可以想象一旦出現(xiàn)性能問題的時候,經(jīng)過這么多環(huán)節(jié)就比較頭疼,經(jīng)常會困惑,這個問題到底出現(xiàn)在哪個環(huán)節(jié)呢?

image

一般來說,性能問題往往通過線上性能壓測發(fā)現(xiàn)的。一般大促之前,提前一段時間,就要開始進行壓測。壓的時候就會涉及到從前往后,從底到上的所有的系統(tǒng)和部門,都要派代表去參加,哪一塊出現(xiàn)了問題,哪一個環(huán)節(jié)出現(xiàn)了性能瓶頸,哪一塊就要改。

線上壓力測試需要有一個性能測試的平臺,做多種形式的壓力測試。例如容量測試,通過梯度的加壓,看到什么時候?qū)嵲诓恍小C邷y試,測試在最大的限度之上還能承受多大的量,有一定的余量會保險一些,心里相對比較有底。再就是穩(wěn)定性測試,測試峰值的穩(wěn)定性,看這個峰值能夠撐一分鐘,兩分鐘還是30分鐘。還有秒殺場景測試,限流降級演練測試等。

有的時候壓測會遇到讓人崩潰的事情,例如可能前幾天壓測的時候,看著吞吐量在向好的方向發(fā)展,突然有一天一下子就降下來了,這個時候離大促時間越來越近,心態(tài)就會比較崩潰,需要大家一塊去看到底是什么問題。

image

對于測試環(huán)境的管理,也是非常關(guān)鍵的。線上壓測的時候,為了讓數(shù)據(jù)和正式的線上數(shù)據(jù)實現(xiàn)隔離,常用的方法是對于消息隊列,緩存,數(shù)據(jù)庫,都是使用影子的方式。就需要流量染色的技術(shù),帶一個tag進去,說明這個請求是測試數(shù)據(jù),還是真實數(shù)據(jù)。

流量染色的功能,除了壓測里面使用,還可以用于測試環(huán)境治理。在大規(guī)模微服務場景下,不可能每個部門部署一套完整的環(huán)境,因為耗費的資源量實在是太大了。

這時候就需要合理規(guī)劃測試環(huán)境。測試環(huán)境是應該和持續(xù)集成的流程緊密協(xié)作的。我們使用分支開發(fā)的方式,每個功能的開發(fā)在分支上,上線的時候,合并到主分支上來,主分支對應線上環(huán)境。

對于測試環(huán)境的規(guī)劃,也是采取類似的思路。我們會有一個基準測試環(huán)境,對應master分支,里面部署全量的應用。每一個分支,比如說你修改了五個工程,測試的時候,不需要部署全量的應用,只需要把這五個工程去創(chuàng)建一個Delta測試環(huán)境就可以了。當客戶端進行測試的時候,帶上一個此分支的tag,從API網(wǎng)關(guān)開始,微服務框架嵌入的jar會將這個tag一直帶下去。當這五個服務之內(nèi)相互調(diào)用的時候,微服務框架就會選擇這五個服務的實例進行調(diào)研,如果需要調(diào)用五個服務之外的其他服務的時候,微服務框架會到master環(huán)境里面,選擇服務實例進行調(diào)用。

有了流量染色的環(huán)境治理機制,測試環(huán)境數(shù)量就會小小特別多。

image

壓測中一旦出現(xiàn)了慢請求,最先從哪里能夠看出來呢。在微服務的接入層有API網(wǎng)關(guān)這一層。

在API網(wǎng)關(guān)中,有一個調(diào)用統(tǒng)計功能,可以篩選出慢請求。在壓測的時候,每一輪都有一個壓測結(jié)果,是一個列表,按請求時間排序。通過這個列表,可以篩選出這次壓測的時候,最慢的接口都是哪一些,異常的接口(也即請求響應速度有巨大反差)有哪一些? 我們就可以針對于這些接口進行特別的排查。

在服務治理平臺中,服務之間的調(diào)用也有一個統(tǒng)計,也有個一個排名,同樣會列出來哪幾個應用需要改進,重構(gòu),或者排查。

image

和壓測匹配的一個重要的系統(tǒng)是全方位的性能監(jiān)控。一般的監(jiān)控平臺僅僅會監(jiān)控第一項就是服務器的性能,比如cpu,內(nèi)存,網(wǎng)卡等。其實監(jiān)控應該是全方位的,對于應用方面的,應該監(jiān)控堆的內(nèi)存,GC,線程,cpu利用率等。業(yè)務指標應該監(jiān)控下單數(shù),支付數(shù),購物車請求數(shù)等。調(diào)用鏈路監(jiān)控應該包括RT值,TPS等。應用組件應該監(jiān)控連接的狀態(tài),消息積壓,zookeeper節(jié)點數(shù)等。還應該有一些異常監(jiān)控,例如異常的流量,Exception,報警等。這些都是在統(tǒng)一的一個平臺上去做的。

定位問題需要深度的依賴于這個平臺,一般先在這個平臺上去找到大概的問題點,如果不能找到真正原因的話,就可以更加細粒度的登到機器上去看。沒有統(tǒng)一的監(jiān)控,會在大規(guī)模微服務場景下,有了問題,比較茫然,根本找不到地方。

image

有了統(tǒng)一監(jiān)控平臺,我們也在壓測的時候,在API網(wǎng)關(guān)上發(fā)現(xiàn)了慢請求,接下來就需要逐層定位了。

高延遲的現(xiàn)象往往會先出現(xiàn)在應用層,外部的現(xiàn)象就是外部請求的時延高,如果順著調(diào)用鏈定位下來,往往會反應到內(nèi)部從一個服務集群到另一個服務集群的RT值高或者出現(xiàn)大量超時異常。

我們可以查看對于服務之間相互調(diào)用的監(jiān)控,dubbo和hystrix我們做了集成,右下角的這個圖是熔斷的基本原理。通過監(jiān)控我們可以發(fā)現(xiàn)有熔斷的情況出現(xiàn),我們就知道這可能是出現(xiàn)了問題。

image

一旦出現(xiàn)了問題,架構(gòu)部一步一步來分析分析這個問題。我們的排查思路是從上層往下層,從業(yè)務層往底層層層排查,因為如果讓物理網(wǎng)絡或者虛擬網(wǎng)絡直接去定位,會比較迷茫。

第一步:先應用層初步定位。

第一件事情,查看近期是否有新變更的發(fā)布上線,例如昨天壓測的時候還正常,這次突然出現(xiàn)超時,很可能是新的發(fā)布導致的。

我們可以重點查看新發(fā)布的應用,甚至可以進行代碼review。

如果新發(fā)布的應用沒有發(fā)現(xiàn)問題,就需要在整條調(diào)用鏈路上定位問題了。這個時候應用性能監(jiān)控APM可以幫上忙,他可以在整條調(diào)用鏈路里面,找到最耗時的那個環(huán)節(jié),這是我們應該重點定位問題的地方。

image

在最耗時的環(huán)節(jié)上,如果我們發(fā)現(xiàn)TPS比較低,相應時間長,但是CPU使用率不高。

我們可以通過服務治理平臺,查看這兩個服務之間的調(diào)用是否開啟了足夠的線程池,當前的線程池是否已經(jīng)被打滿,如果滿了,是否可以提高線程池的數(shù)目,這和集群所在的虛擬機和物理的核的分配是有關(guān)系的,因為核數(shù)用完了,再多的線程徒增調(diào)度成本,沒有收益。如果可以提供線程池的數(shù)目,可以通過配置中心進行統(tǒng)一的配置這個服務集群的線程池數(shù)目。

很多情況下,性能的降低的原因在于數(shù)據(jù)庫層,這一點在APM上也能看的出來。這個時候應該DBA去查看問題,可以梳理一下SQL語句,通過慢SQL分析,查看慢的原因,例如索引問題,死鎖問題等,這些都可以通過Mysql或者DDB的日志找出來。

image

另外一個經(jīng)常出現(xiàn)的問題就是TPS比較低,但是CPU使用率非常高。

這時候我們需要通過監(jiān)控系統(tǒng)查看線程的狀態(tài),查看耗時的方法列表以及調(diào)用棧,看哪個線程耗時比較多,是否因為業(yè)務邏輯的Bug,是否在一直計算某個東西,或者出現(xiàn)業(yè)務層的死鎖。

另外就是看是否頻繁的FullGC,一旦出現(xiàn)了FullGC就會出現(xiàn)一段時間的業(yè)務邏輯暫停,在大促本來壓力就很大,而且峰值時間比較短的情況下,一個線程hang就會使得調(diào)用鏈擁塞一片。我們要通過監(jiān)控系統(tǒng)查看堆的信息,找出耗內(nèi)存的對象,看是否內(nèi)存一直往上漲,是否存在泄露。

另外對于緩存的一個監(jiān)控,應用層的緩存設(shè)計一般有多層。我們本來一開始設(shè)計的是有三層緩存的,localcache有兩層,然后分布式緩存有一層,localcache分主動刷新和被動刷新的兩層,被動刷新就是遇到請求了再刷新,主動刷新是主動的去過一段時間去刷新。后來我們又把三層緩存簡化成了兩層緩存,被動刷新的localcache的命中率已經(jīng)足夠用了,再多一層反而會降低性能。

我們之所以監(jiān)控緩存,是因為我們發(fā)現(xiàn)有時候應用層Key使用的不對,或者是配置的不對,會導致緩存層失效,請求就會直接打到數(shù)據(jù)庫,導致請求相對比較的慢。對于緩存的監(jiān)控,我們在緩存的客戶端的jar,會和配置中心進行聯(lián)動,監(jiān)控某些我們認為相對比較重要的Key,當Key出現(xiàn)緩存丟失,寫頻繁,或者寫丟失等類似這種事件的時候,它就會上報到我們的監(jiān)控系統(tǒng)。這個時候,就會發(fā)現(xiàn)導致緩存失效的程序Bug。

image

第二步:如果應用層沒有問題,則檢查異常流量

如果我們確認應用層的確沒有問題,就需要開始往下層去進行懷疑了。

首先第一個比較懷疑的是,是不是出現(xiàn)異常流量。比如說有外部的異常流量,可以問問網(wǎng)管和安全部是否網(wǎng)站被DDoS,另外入口網(wǎng)關(guān)是否接受到了大量的請求,例如有臨時的促銷或者臨時的事件。

如果入口沒有問題,則查看集群的監(jiān)控,要對照著兩個指標看,一個是服務端的請求數(shù)目的一個統(tǒng)計,看是否有集中的熱點,比如說一個集群有多個副本,其中某個副本收到的請求量特別的大,而其他副本收到的請求數(shù)相對比較低。二是在云主機里面的網(wǎng)卡虛擬網(wǎng)卡,也是能夠看到相應的監(jiān)控的,看是不是網(wǎng)絡流量就集中到某幾臺機器上。這兩個會有一個對照,如果兩方面指標能夠?qū)φ掌饋?,集中熱點比較容易定位,也即請求數(shù)上去了,同時云網(wǎng)絡的網(wǎng)卡流量也上去了。當出現(xiàn)了熱點的時候,就需要通過服務治理中心或者配置中心,將請求打散。

如果兩個指標不匹配,這時候就有問題了,也即服務端請求的數(shù)目其實并沒有多,但是云網(wǎng)絡發(fā)現(xiàn)出現(xiàn)了問題,這時候就就可能是底層基礎(chǔ)設(shè)施的問題,我們這個例子遇到這個點就是相對比較詭異,還需要接著解析。

image

如果不是異常流量,就需要從前往后再來梳理這個事,比如說從核心交換機到VPC的網(wǎng)關(guān)區(qū)域這些是不是出了問題,這時候就要聯(lián)系機房的網(wǎng)管部門去定位,然后是VPC網(wǎng)關(guān)到云的負載均衡,然后是從負載均衡到應用的API網(wǎng)關(guān),然后API網(wǎng)關(guān)到應用的Controller層,然后是中間的dubbo調(diào)用,然后緩存層到數(shù)據(jù)庫層。接下來要按照整個鏈路依次的去排查。

image

這里畫了一張經(jīng)比較經(jīng)典的機房的一個圖,其實任何一家公司機房的樣子要比這個圖可能要復雜得多,這就需要架構(gòu)部門對機房的架構(gòu)相對比較清楚。

我們會分機房,分可用區(qū),還會分二級可用區(qū),他們會走不同的匯聚交換機,在監(jiān)控系統(tǒng)里面也要標明某個服務器群和另一個服務集群之間的訪問到底是哪個物理機集群到哪個物理機集群之間的訪問,這時候你心里可能需要清楚他們是否在同一個機架里面,或者是在同一個二級可用區(qū),還是在同一個一級可用區(qū),是跨機房了,或者是甚至到異地了,這時候你要心里有個數(shù),因為他們之間的時延都是不一樣的。

image

第二個就是對于VPC網(wǎng)絡的架構(gòu)是要比較清楚。我們是通過OpenStack Neutron的vxlan去做的這個事情的。橫向流量是通過vxlan,基于OVS去做的,縱向的流量,出去的時候會有網(wǎng)關(guān),我們不是用的物理網(wǎng)關(guān),而是虛擬網(wǎng)關(guān),在數(shù)據(jù)中心里面有一個虛擬網(wǎng)關(guān)的網(wǎng)關(guān)層,網(wǎng)關(guān)層有的時候是掛在匯聚交換機下面的,有的機房要求吞吐量比較大,網(wǎng)關(guān)層可以直接掛在核心交換機下面的,很可能網(wǎng)絡瓶頸點會發(fā)生在這些網(wǎng)關(guān)上。

image

我們的VPC網(wǎng)絡是有一定的改進的,因為我們要求一個VPC里面能承載的虛擬機的數(shù)量要比開源的OpenStack要多得多,能達到5萬臺的規(guī)模。

限制網(wǎng)絡規(guī)模的一是廣播問題,我們可以事先把整個網(wǎng)絡拓撲下發(fā)到一個拓撲庫上去,每一個節(jié)點上的Agent會訂閱拓撲庫的更新事件,從而更新本地的OVS策略。每個Agent都會看到整個網(wǎng)絡的拓樸結(jié)構(gòu),則ARP的時候,本地就可以攔截來進行返回。

另外的一個改進就是虛擬網(wǎng)絡,默認的虛擬網(wǎng)關(guān)只能做主備,橫向擴展能力沒有這么好,不能夠承載大的并發(fā)量,這其實需要有一排的虛擬網(wǎng)關(guān),全部掛載到匯聚或者核心交換機上。接下來的問題是縱向的流量怎么從這一排網(wǎng)關(guān)里面去選擇,這里使用了一致性哈希的算法。

image

另外一個改進是Kubernetes和OpenStack的整合。左面的圖是Kubernetes默認創(chuàng)建一個Pod的流程,好在他是基于事件驅(qū)動的,使得我們可以定制化右面創(chuàng)建Pod的流程。我們開發(fā)了自己的Resource Controller和Scheduler,當發(fā)現(xiàn)容器的節(jié)點資源不足的情況下,Controller會調(diào)用IaaS的接口創(chuàng)建云主機,然后加到Kubernetes集群中。這種模式下,在應用層的角度,只能看到容器,不需要運維Kubernetes,更加看不到OpenStack的接口,使得應用層有統(tǒng)一的編排接口。

image

另外對于容器和Kubernetes層的整合,網(wǎng)絡層也需要整合,容器也要融合VPC網(wǎng)絡,只有適配了VPC網(wǎng)絡才能實現(xiàn)多機房的高可用性,跨機房的負載均衡,以及跨機房的浮動IP漂移和切換。比如說一個機房掛了,則掛在A機房的浮動IP地址要能夠切換到B機房的網(wǎng)關(guān)上去,并且和核心交換機有聯(lián)動,路由也要切過來,這些都只有VPC可以完成這個事情。

我們開發(fā)了一個自己的CNI插件去做這個事兒,容器沒有使用單獨容器網(wǎng)絡方案,而是直接用了OVS的網(wǎng)絡,也即OpenStack的OVS是可以直接看到容器的IP地址的,容器的IP地址和虛擬機的IP是平的,是屬于同一個局域網(wǎng)。

這樣其實還有另外一個好處,因為我們還有很多沒有容器化的應用,如果部分做容器化,是可以和容器內(nèi)的應用無縫的打通的。一些有狀態(tài)的PaaS也是部署在虛擬機里面的,也可以實現(xiàn)在同一個局域網(wǎng)內(nèi)的互通。

image

另外一個針對Kubernetes的優(yōu)化就是規(guī)模問題,這是其中的一個優(yōu)化的例子。

重啟一個API server的時候會導致一些問題,尤其是在Pod的數(shù)目比較多的時候。通過監(jiān)控圖可以看出,中間會重啟時間長達七分鐘,中間出現(xiàn)429錯誤并且飆升,是因為流控。為什么會流控?因為它重啟的時候,會有大量的請求重新再連上來,由于并發(fā)太多,有可能就把它再沖掛了。

image

那么應該如何改進呢?方法一就是多級流控,根據(jù)UserAgent, Resource, Verb幾個參數(shù),對于不同的客戶端有不同的流控策略,比如說對于master上面的進程優(yōu)先級相對高一點,對于kubelet結(jié)點上的進程,優(yōu)先級就低一些。不會所有的kubelet節(jié)點一股腦上來進行注冊。方法二是擁塞控制,Retry-After參數(shù)也即多長時間再重試一次,這個原來是一個默認值,我們改成一個動態(tài)的值,根據(jù)系統(tǒng)的繁忙程度是調(diào)節(jié)到1秒到8秒之間,這樣不同的客戶端重試的時間會錯開。使得把整個恢復時間大幅度的降低了,這是我們做的規(guī)?;囊粋€例子。

image

來我們從接入層開始分析。我們在VPC的網(wǎng)關(guān)以及負載均衡層也是做了優(yōu)化的。

優(yōu)化之一是基于BGP ECMP的等價路由,也即對于LB集群和前面的核心交換機之間配置等價路由,實現(xiàn)橫向擴展和負載均衡。如果使用LVS做這個網(wǎng)關(guān)的話,可以使用DPDK技術(shù),也即基于DPVS的負載均衡。

電商請求基本上都是基于HTTPS協(xié)議的,SSL往往通過offload的方式通過硬件進行加速,在壓力大的時候,優(yōu)化明顯。

image

對于負載均衡這一層的問題,出問題的點往往在于虛擬網(wǎng)關(guān)和負載均衡,

我們要中斷看這一層的網(wǎng)卡是不是丟包?

另外就是DPDK的PMD進程的CPU占用率是不是特別的高,因為默認的網(wǎng)卡接收網(wǎng)絡包是通過中斷通知內(nèi)核來接收包,但是DPDK進行了優(yōu)化,它通過主動polling的模式減少中斷,它在用戶態(tài)有一個PMD的進程,他會不斷地從網(wǎng)卡里面去polling,會占用大量CPU,如果他CPU特別高就說明接收包的速度本身就很高了。這時候要注意觀察流量是否存在熱點,流量是否突破單臺瓶頸。

對于虛擬網(wǎng)關(guān)來說,使用的是一致性哈希的方法選擇網(wǎng)關(guān),隨著持續(xù)的浮動IP的創(chuàng)建和刪除,分布不一定均衡,就算IP分布均衡,這些IP對應的業(yè)務其實沒有那么均衡,例如多個熱點請求落到一個網(wǎng)關(guān)上。

如果說是存在熱點,導致DPDK的PMD進程CPU過高,可以采取的策略是高流量的IP地址可以進一步地打散,重新調(diào)整哈希的策略。

另外會觀察是否超過單臺的瓶頸,我們會測試每臺機器的IO的瓶頸,也會進行QoS限流,如果是超過了瓶頸,說明這一臺的確壓力過大,如果其他的節(jié)點網(wǎng)絡IO還相對比較低,基本上也是熱點問題。如果都高,則說明需要擴容。

另外網(wǎng)關(guān)要注意區(qū)分走哪種類型的網(wǎng)關(guān),通過測試,我們發(fā)現(xiàn)DNAT網(wǎng)關(guān)由于是一對一的,性能比較好。SNAT因為共享IP并且要計算哈希,還要做conntrack,吞吐量不太容易優(yōu)化上去。對于功能需求走SNAT網(wǎng)關(guān)比較方便的應用,可以建議用戶換成DNAT網(wǎng)關(guān),從而獲得高的吞吐量。

image

如果入口流量沒有問題,這時候就要看服務器之間的調(diào)用是不是有問題,因為我們的容器是套在虛擬機里面的,主要起編排和發(fā)布的作用,這時候就要看云主機的steal是不是特別的高,對于物理機上的cpu,多個虛擬機會競爭排隊,排隊不上就會等待,等待的時候就會出現(xiàn)CPU steal,網(wǎng)絡吞吐量肯定就上不去,甚至會出現(xiàn)丟包,因為收到的網(wǎng)絡包來不及處理。

另外就是磁盤的IO utils是不是有異常,雖然容器中多部署無狀態(tài)服務,對于磁盤的依賴相對比較小,日志也是以異步的方式輸出的,但是有時候也會存在IO hang的情況,這時候就要看IO的監(jiān)控。

如果需要細致的分析,可以登錄到宿主機上看KVM,分析KVM的性能的瓶頸在哪里,在虛擬機里面進行網(wǎng)絡監(jiān)控之外,在宿主機上可以對虛擬網(wǎng)絡的組件進行分析,測試兩個集群之間的虛擬網(wǎng)絡組件是否出現(xiàn)了問題。

image

分析完了網(wǎng)絡和存儲虛擬化,接下來看計算虛擬化KVM。可以做一些定制化的一些調(diào)優(yōu),比如說CPU的BIOS中會把C-States和P-States這種節(jié)能開關(guān)關(guān)掉,如果是核心業(yè)務集群,不需要打開這些開關(guān)。

另外就是物理CPU和vCPU的綁定,這是為了解決steal的問題,如果把核綁到虛擬機上,基本上就不會存在VCPU在物理CPU之間切換的問題,就會把steal解決掉。

另外是NUMA親和性的問題,在同一個NUMA Node中,CPU對內(nèi)存的訪問就會快一些,跨NUMA node就會慢一點,分配的時候盡量是同樣CPU和同樣的內(nèi)存放在同一個NUMA 節(jié)點。

虛擬機網(wǎng)卡可以通過SR-IOV的方式來進行優(yōu)化,云主機綁定核也是在grub中設(shè)定好,一臺機器上面能起多少個服務,給宿主肌留多少核,給監(jiān)控留多少核,然后最后給應用留多少核,都是提前規(guī)劃好的,例如前幾個核是給宿主機自己去用的,然后幾個核是留給DPDK去用的,最后幾個核是留給監(jiān)控去用的,中間的核留給服務。

image

對于限流策略問題,基礎(chǔ)設(shè)施層和業(yè)務層有一個配合的問題,底層的網(wǎng)絡有QoS流控的,業(yè)務其實也有限流的,這兩個值要匹配起來,否則會有問題,比如當業(yè)務層把線程數(shù)調(diào)大的時候,結(jié)果基礎(chǔ)設(shè)施層被限流了會出現(xiàn)丟包。
image

當我們從監(jiān)控里面看到有丟包事件的時候,業(yè)務層會懷疑是虛擬網(wǎng)絡的問題,丟包了以后TCP會重傳,重傳會使得響應比較的慢。

在沒有定位到到底哪個環(huán)節(jié)丟包的時候,可以先做如下的處理。為了使TCP的丟包重傳和流控策略不要用默認的策略,也即一旦出現(xiàn)了丟包,內(nèi)核協(xié)議棧就認為網(wǎng)絡擁塞,從而減少擁塞窗口,這時候本來就想加速重傳,結(jié)果窗口下來了,想加速也加不上去。如果切換成BBR,出現(xiàn)丟包的時候就會好很多。

但是我們還是就要看底層的網(wǎng)絡,網(wǎng)絡包會丟在什么地方。

image

最后實在沒有辦法,就需要登到物理機上去debug整條鏈路。從集群A到集群B中間抽出兩臺機器進行測試。測試完畢后通過tcpdump進行分析虛擬機和虛擬機之間的情況,通過ovs-tcpdump可以分析兩臺物理機上的OVS之間的情況,物理機之間的鏈路可需要進行分析。如果包的數(shù)目比較多,需要寫程序比對時間戳序列號。

抓包分析之后,我們發(fā)現(xiàn)兩個集群之間并不是任何兩兩個服務之間都會丟包,而是發(fā)生在兩個集群全部在某一批匯聚交換機出現(xiàn)。

原來從來沒有懷疑過是物理硬件的問題,物理交換機的監(jiān)控網(wǎng)粒度往往不會非常細,而且有堆疊這種高可用策略,在監(jiān)控調(diào)整到分鐘級別的時候,看流量根本就沒有達到上限。

但是一旦我們發(fā)現(xiàn)出問題的兩個集群總是要過某一臺匯聚交換機的時候,我們就建議網(wǎng)管,你能不能把那臺的監(jiān)控配置到秒級,然后就發(fā)現(xiàn)問題了,就是分鐘級監(jiān)控沒有超過它的瓶頸,但是秒級的監(jiān)控就會發(fā)現(xiàn)它瞬時流量是超過了瓶頸的,因而會丟包。原因是部署緩存集群的時候,實例過于集中了,兩個集群之間的交互基本上都集中在同一個匯聚交換機上,導致出了問題,接下來的方式就是把網(wǎng)絡優(yōu)化型的實例打散了以后,只要流量瞬時不會超過物理交換機峰值,基本上就沒有問題了。

這個例子最后有一點狗血,其實這是一個分析思路,從應用層逐漸的去分析,架構(gòu)部就要協(xié)調(diào)各個層次,最后才把這個事情定位到好,我今天的分享就到這里。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,533評論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,055評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 175,365評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,561評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,346評論 6 404
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 54,889評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,978評論 3 439
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,118評論 0 286
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,637評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 40,558評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,739評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,246評論 5 355
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 43,980評論 3 346
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,362評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,619評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,347評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,702評論 2 370

推薦閱讀更多精彩內(nèi)容