1. 程式人生 > 實用技巧 >架構師之殤:中介軟體業務在網易輕舟容器平臺的效能調優實踐

架構師之殤:中介軟體業務在網易輕舟容器平臺的效能調優實踐

隨著業務容器化的推進,經常有客戶抱怨應用 QPS 無法和在物理機或者雲主機上媲美,並且時常會出現 DNS 查詢超時、短連線 TIME_OUT、網路丟包等問題,而在容器中進行調優與診斷的效果因為安裝工具的複雜度大打折扣。本文基於網易輕舟中介軟體業務容器化實踐,總結容器場景下的效能調優心得,供讀者參考。

1效能調優的“望聞問切”

在討論容器化場景的效能調優之前,先談一下效能調優中的“望聞問切”。對於效能問題,大部分人首先想到的是 CPU 利用率高,但這只是個現象,並不是症狀。打個比方:感冒看醫生時,病人跟大夫描述的是現象,包括頭部發熱、流鼻涕等;而大夫通過探查、化驗,得到的醫學症狀是病人的白細胞較多、咽喉紅腫等,並確診為細菌性感冒,給開了 999 感冒靈。效能調優流程與此相似,也需要找到現象、症狀和解法。回到 CPU 利用率高的例子:已知現象是 CPU 利用率高,我們通過 strace 檢查,發現 futex_wait 系統呼叫佔用了 80% 的 CPU 時間——這才是症狀;根據這個症狀,我們業務邏輯程式碼降低了執行緒切換,CPU 利用率隨之降低。

大部分的效能調優都可以通過發現現象、探測症狀、解決問題這三個步驟來完成,而這在容器的效能調優中就更為重要的,因為在主機的效能調優過程中,我們有很多的經驗可以快速找到症狀,但是在容器的場景中,很多客戶只能描述問題的現象,因為他們並不瞭解使用的容器引擎的工作原理以及容器化架構的實現方式。

2容器化效能調優的難點

容器化場景中的效能調優主要面臨 7 個方面的挑戰。

中介軟體種類多,調優方法又各不相同,如何設計一種好的框架來適配

我們借鑑 redhat tuned 思想,提出一種與業務相關的核心引數配置新框架,它可以把我們對 Linux 系統現有的一些調優手段(包括電源管理工具,CPU、記憶體、磁碟、網路等核心引數)整合到一個具體的策略 (profile) 中,業務場景不同,profile 不同,以此來快速實現雲端計算對不同業務進行系統的效能調節的需求。

VM 級別的調優方式在容器中實現難度較大

在 VM 級別我們看到的即是所有,網路棧是完整暴露的,CPU、記憶體、磁碟等也是完全沒有限制的。效能調優老司機的工具箱安個遍,診斷流程走一趟基本問題就查個八九不離十了,但是在容器中,很多時候,都是預設不自帶診斷、調優工具的,很多時候連 ping 或者 telnet 等基礎命令都沒有,這導致大部分情況下我們需要以黑盒的方式看待一個容器,所有的症狀只能從物理機或者雲主機的鏈路來看。但是我們知道容器通過 namespace 的隔離,具備完整網路棧,CPU、記憶體等通過隔離,只能使用 limit 的資源,如果將容器當做黑盒會導致很多時候問題症狀難以快速發現,排查問題變難了。

容器化後應用的鏈路變長導致排查問題成本變大

容器的場景帶來很多酷炫的功能和技術,比如故障自動恢復、彈性伸縮、跨主機排程等,但是這一切的代價是需要依賴容器化的架構,比如 Kubernetes 網路中需要 FullNat 的方式完成兩層網路的轉發等,這會給排查問題帶來更復雜的障礙,當你不清楚編排引擎的架構實現原理的時候,很難將問題指向這些平時不會遇到的場景。例如上面這個例子中,FullNat 的好處是降低了網路整體方案的複雜性,但是也引入了一些 NAT 場景下的常見問題,比如短連線場景中的 SNAT 五元組重合導致包重傳的問題等等,排查問題的方位變大了。

不完整隔離帶來的調優複雜性

容器本質是一種作業系統級虛擬化技術,不可避免涉及隔離性,雖然平時並不需要考慮隔離的安全性問題,但是當遇到效能調優的時候,核心的共享使我們不得不面對一個更復雜的場景。舉個例子,由於核心的共享,系統的 proc 是以只讀的方式進行掛載的,這就意味著系統核心引數的調整會帶來的宿主機級別的變更。在效能調優領域經常有人提到 C10K 或者 C100K 等類似的問題,這些問題難免涉及到核心引數的調整,但是越特定的場景調優的引數越不同,有時會有“彼之蜜糖,我之毒藥”的效果。因此同一個節點上的不同容器會出現非常離奇的現象。

不同語言對 cgroup 的支援

這個問題在大多數場景下無需考慮,列在第四位是期望能夠引起大家重視。網易輕舟在一次排查“ES 容器(使用 java 11)將 CPU requests 都配置成 8 時,其效能低於將 request CPU 都配置成 1”的問題時,發現是 Java 的標準庫中對 cgroup 的支援不完全導致的,好在這點在大多數場景中沒有任何影響。

網路方案不同帶來的特定場景的先天缺欠

提到容器架構避不開網路、儲存和排程,網路是評判容器架構好壞的一個核心標準,不同的網路方案也會有不同的實現方式與問題。比如網易輕舟 Kubernetes 中使用了 Flannel 的 CNI 外掛實現的網路方案,標準 Flannel 支援的 Vxlan 的網路方案,Docker 的 Overlay 的 macVlan,ipvlan 的方案,或者 OpenShift SDN 網路方案,還有網易輕舟自研的雲內普通 VPC 和 SRIOV+VPC 方案等等。這些不同的網路方案無一例外都是跨宿主機的二層網路很多都會通過一些 vxlan 封包解包的方式來進行資料傳輸,這種方式難免會增加額外的 CPU 損耗,這是一種先天的缺欠,並不是調優能夠解決的問題。有的時候排查出問題也只能繞過而不是調優。

映象化的系統環境、語言版本的差異

應用容器化是一個需要特別注意的問題,很多公司並沒有嚴格的配管流程,比如系統依賴的核心版本、語言的小版本等等,很多時候都是選擇一個大概的版本,這會帶來很多語言層級的 BUG,比如 Java 應用程式執行在容器中可能會遇到更長的應用程式暫停問題、Java 7 無法感知 CPU 個數導致 GC 執行緒過多問題和 PHP7.0 中 php-fpm 的詭異行為。環境的問題本就需要嚴格管控,但是當遇到了容器,很多時候我們會分不清哪些不經意的行為會帶來嚴重的問題,警惕性因為容器映象能夠正常啟動而降低了。

3效能優化步驟和調優管理變更流程

效能優化通常可以通過如表五個步驟完成:

調優管理變更和效能優化並不直接相關,但可能是效能調優成功最重要的因素。以下總結來源於網易輕舟團隊的實踐和經驗:

  • 在調優之前,實施合理的調優管理流程變更

  • 永遠不要在生產系統上調優

  • 壓測的環境要相對獨立,不能受其他壓力的影響,這裡說的不僅是壓測的伺服器端,而且包括壓測客戶端

  • 在調優過程中,每次只修改一個變數

  • 反覆測試提升效能的引數,有時候,統計來的結果更加可靠

  • 把成功的引數調整整理成文件,和社群分享,即使你覺得它們微不足道

  • 生產環境中獲得的任何結果對 Linux 效能都有很大用處

4調優手段

1. 通用調優

對於容器業務來說,儘量讓 CPU 訪問本地記憶體,不要訪問遠端記憶體。

CPU 訪問不同型別節點記憶體的速度是不相同的,訪問本地節點的速度最快,訪問遠端節點的速度最慢,即訪問速度與節點的距離有關,距離越遠訪問速度越慢,此距離稱作 Node Distance。正是因為有這個特點,容器應用程式要儘量的減少不同 Node 模組之間的互動,也就是說,我們根據容器記憶體 Node 親和性,選擇容器使用的 CPU 固定在一個 Node 模組裡,因此其效能將會有很大的提升。有一種特殊場景除外,如果一個容器申請的 request 大於單個 Node 上預留的 CPU 後,這種親和性的繫結就會失效,此時迴歸到原始的跨 Node 範圍繫結,對於之前已經做了親和性的容器(申請的 request 小於單個 Node 上預留的 CPU)我們的策略是繼續維持不變。

2. 針對不同的場景的引數調優

針對不同的場景,可以考慮以下引數著手進行調優。

與CPU相關的配置

與記憶體相關的配置

磁碟相關的引數

與sysctl相關的配置

注:瞭解以上網路引數的具體含義,需學習 Linux 核心收發包原理,強烈推薦《Monitoring and Tuning the Linux Networking Stack》系列文章。詳見文末參考文獻 4-7。與 sysctl 相關的配置

3. 網路調優

軟中斷隔離:將容器網絡卡的軟中斷繫結到某幾個專用 CPU 上,而容器業務程序繫結到其他 CPU 上,這樣可以減少業務和網絡卡軟中斷之間的影響,避免頻繁的上下文切換,特別適用於對網路效能要求極高的服務例如 Redis。對於雲內普通 VPC 和雲內 SR-IOV VPC 都適用:

  • 雲內普通 VPC:需要把容器使用的虛擬網絡卡 veth 的軟中斷繫結到預留的某幾個專用 CPU 上

  • 雲內 SR-IOV VPC:需要把容器使用的 VF 網絡卡的軟中斷繫結到預留的某幾個專用 CPU 上

  • SR-IOV 直通網絡卡:優化後端 DPDK PMD 執行緒配比,一般由 1 個調大至 2 個或者 4 個。

5調優效果

Redis

調優後 SR-IOV 下 QPS 接近 BGP 物理網路,99.99% 時延從 BGP 物理網路的 990ms 下降到 140ms。

Flink

調優後簡單 ETL 任務 QPS 比 YARN 上高 20%,複雜 ETL 任務 QPS 比在 YARN 上高 30%。

RDS

對於 RDS MGR 叢集,K8S 容器部署相比 RDS2.0 雲主機 VM 部署,同等規格下效能提升可以達到 30%~170%;

經過優化後,與物理機部署相比,常規模式下,只寫場景、只讀場景和讀寫混合場景的效能差距保持在 5~10% 之間。

RocketMQ

非同步複製叢集:普通容器單分片相比物理機效能有 40% 差距,增加生產消費者數量,叢集整體效能有所提升,但依然與標準物理機有 25% 左右差距;增加生產消費者數量,容器調優後的效能基本持平標準物理機,差距 5% 以內。

同步複製叢集:普通容器效能略差於標準物理機,差距在 10% 左右,容器調優後的效能基本持平標準物理機,差距縮小到 5%。