网易轻舟服务网格数据面性能优化实践
本文分析了服務網格數據面的性能瓶頸,并引出基于用戶態協議棧的加速方案。詳細介紹了VPP+VCL的用戶態協議棧開源社區方案,其針對服務網格sidecar加速的優勢和不足,以及網易數帆做了哪些增強,從而實現對服務網格sidecar的無侵入加速。最后介紹VPP+VCL用戶態方案在加速網易輕舟云原生平臺服務網格產品的落地實踐,并給出實際的性能測試結果。
引子
服務網格通過引入sidecar提升了監控、流控、熔斷等服務治理能力且對業務無侵入,但同時sidecar的引入在整個網絡路徑上也相當于增加了兩個網絡處理單元,從而不可避免的會引入時延。
從業務方的角度來看,引入sidecar后的時延肯定是越短越好,特別是業務方微服務化后對時延敏感的業務,如內部各模塊之間的服務化調用。
所以,本文中的性能如果沒有特別說明,都是指時延指標。
時延分析
如果打開整個端到端的通信鏈路可以看出,sidecar引入后整個應用之間的通信鏈路其實是非常長的。應用發送的請求被iptables劫持后,經過內核協議棧發送給sidecar,sidecar經過處理后再通過內核協議棧發送出去,這里一般要先經過容器網絡,虛擬VPC網絡,再經過物理網絡,之后才被接收端的sidecar收到,sidecar處理后再通過內核協議棧發送給最終的應用,整個過程要經過6次內核協議棧,而響應報文也要反向重復這一過程。但是如果去掉sidecar呢?可以看到只需要經過兩次內核協議棧就可以了,相當于sidecar引入后多增加了4次內核協議棧的調用,另外還多引入了幾次iptables報文處理。
總體來看,整個鏈路包括物理網絡、虛擬網絡、Guest主機網絡幾個部分。其中,物理網絡鏈路(包含在圖中的⑦部分)不可控,這里不做討論。而虛擬網絡鏈路又分為虛擬VPC網絡和容器網絡。下面就來逐個分析下各個階段可能的時延優化措施。
虛擬VPC網絡
先看虛擬VPC網絡(包含在圖中的⑥部分)。一般來說,虛擬化會帶來約10%的時延開銷,那么這部分開銷可以省掉嗎?答案是肯定的,我們可以使用裸機容器的方案,略去中間的虛擬化層。
容器網絡
再看容器網絡(包含在圖中的⑤部分)。這部分依賴于具體的容器網絡方案,比如你網橋用的是Linux bridge、OVS還是VPP,虛擬端口用的是veth還是VF,性能都會不一樣。VF+用戶態OVS會是一個相對成熟以及性能較好的方案。RDMA也會是一個優化方向,不過這會牽扯到業務端改造,無法做到無侵入,同時還需要綜合考慮組網以及硬件成本等因素。
Guest主機網絡
最后重點來看Guest主機網絡(圖中①②③④⑧⑨部分),Guest可能為容器,也可能為虛擬機,這里僅考慮Guest為容器的情況。
-
①是指應用和sidecar之間的通信鏈路。通常會使用iptables做報文劫持,再通過環回口將報文轉發到sidecar,過程中會經過兩次內核協議棧。這里是有一些可加速的點可以做的,比如可以借助eBPF/sockmap bypass部分內核協議棧,或者基于eBPF改寫轉發邏輯實現對于iptables的加速,總體來說,這塊的性能有10%的提升空間。目前網易輕舟解決方案中也有相應的產品化實現;
-
⑨是應用層面的通信協議,目前有gRPC/quic協議等優化方向,不過對業務有侵入性,依賴于業務端改造;
-
⑧是sidecar自身轉發邏輯,以目前業界比較流行的Envoy為例,這塊本身轉發邏輯的優化空間不大,在10%以內;
-
②③④即為協議棧的優化。容器分為業務容器和sidecar容器,對于計算節點,一般會運行在同一個POD內。容器中的應用依賴于socket接口進行通信,目前底層都是基于內核的TCP/IP協議棧,內核和用戶態的頻繁切換會帶來性能開銷,同時內核協議棧處理本身也會占用CPU資源。下圖中以fortio測試場景看Envoy CPU占比,通過火焰圖可以看出該場景下內核協議棧占比將近50%,基本上和Envoy本身轉發邏輯對半分。
由于針對Envoy本身轉發邏輯的優化提升空間不大,所以針對協議棧優化的重要性凸顯。而且如果后續對于Envoy本身轉發邏輯可以進一步優化,那么內核協議棧的占比會進一步提升,這樣協議棧的優化的作用也會愈發明顯。那么如何優化內核協議棧這塊開銷呢?消除內核和用戶態的切換開銷,以及bypass內核復雜的TCP/IP協議棧實現,是最直接有效的方法,而這就非用戶態協議棧莫屬了。
用戶態協議棧選型
目前,社區也有不少的用戶態協議棧開源實現,比如騰訊開源的F-Stack,有google參與的LKL,華為開源的DMM等,以及思科開源的VPP+VCL。那么,該如何選型呢?
首先,要考慮單位資源占用下的性價比。用戶態協議棧一般依賴于DPDK將報文收發卸載到用戶態,使用DPDK帶來的問題是polling模式會獨占CPU。這對于perhost的應用不會有問題,可以預先規劃出幾個核來使用。但是對于sidecar這種perpod的應用則會帶來問題,一個host上幾十甚至上百個POD會導致CPU資源只夠給sidecar用了,真正的業務應用則無CPU可用。所以就要求用戶態協議棧從架構上可以支持DPDK收發和應用的分離部署。目前測試來看,F-Stack性能最好,不過F-Stack無法支持分離部署;DMM性能依賴于底層對接用戶態協議棧(如VPP/F-Stack)的性能,另外DMM雖然支持分離部署,不過DMM自己又引入了一個輪詢線程,還是會獨占CPU;LKL性能目前只能做到和內核態相當,且不支持分離部署;VPP+VCL可以實現分離部署,而且性能也較好。
其次,是侵入性。用戶態協議棧通常會有自己的一套socket接口,無法做到和現有接口兼容,這樣就會要求業務也需要修改代碼來適配這套接口。有些用戶態協議棧會在此基礎上實現一層屏蔽層,使用PRELOAD方式來完成socket接口劫持,從而實現對業務的無侵入。目前各用戶態協議棧基本上都實現了此屏蔽層。
另外,就是兼容性,或者說擴展性。內核協議棧之所以復雜,效率低,一個很重要的原因就是需要兼容不同的使用方式。舉個簡單的例子,有的應用是多進程的,如Nginx,而有的是多線程的,如Envoy。而用戶態協議棧應該都可以支持,或者說通過簡單的擴展可以支持。不過這里也有一個折中,需要在兼容性和性能方面做一個權衡。目前F-Stack對多線程還不支持,擴展起來也比較困難,所以F-Stack支持Envoy的話,首先需要將Envoy改造成多進程。
最后,就是成熟度。總體來說,開源的用戶態協議棧還沒有到很成熟的階段,目前流行的開源用戶態協議棧也或多或少會有些限制。比如,F-Stack相對成熟且性能較好,但是DPDK收發和應用綁定導致資源占用大;LKL兼容性好但是性能一般;VPP+VCL各方面則比較均衡且支持DPDK收發和應用的分離部署,性能介于F-Stack和LKL之間。
VPP+VCL用戶態協議棧
VPP
VPP全稱Vector Packet Processing,Cisco 2002年開發的商用代碼。2016年2月11號,Linux基金會創建FD.io項目。Cisco將VPP代碼的開源版本加入該項目,目前已成為該項目的核心。VPP具備成熟的二三層交換和路由功能,同時graph node+插件化提供了靈活的框架擴展性。
?
VPP平臺是通過graph node串聯起來形成一條datapath來處理報文,可以通過插件的形式引入新的graph node或者重新排列報文的graph node。將插件添加到插件目錄中,運行程序的時候就會自動加載插件。VPP平臺可以用于構建任何類型的報文處理應用,比如負載均衡、防火墻、IDS、主機棧。
通過創建插件,也可以任意擴展如下功能:
-
自定義新的graph node。
-
重新排列graph node。
-
添加底層API
VCL
VCL全稱VPP Communication Library,2017年左右正式提交加入VPP工程,目的是打造一個四層的主機棧。VCL自上到下分為三層:LDP、VLS、VCL。LDP(LD_PRELOAD)層通過LD_PRELOAD機制實現對于應用的無侵入加速;VLS(VCL locked sessions)層通過引入session鎖來支持session共享的場景,比如多進程(如Nginx)的accept競爭;VCL層主要負責和后端VPP的通信。
?
VCL和VPP支持分離部署,并通過共享內存實現高效通信。整個用戶態協議棧的實現在后端VPP實現,由于前端VCL的實現功能相對簡單,這樣可以提高Service對CPU的利用率,從而提升性能。
性能對比測試
我們使用VF口搭建一個簡單的測試環境來測試用戶態協議棧相對于內核態協議棧的性能對比情況。
這里主要測試P90的時延情況,在64并發連接及以上,用戶態協議棧相對于內核態協議棧時延可以降低30-35%。Envoy是典型的CPU密集型應用,如果消除內核態的CPU占用,讓Envoy有更多的CPU可以用來處理自身的業務邏輯,則可以獲得更低的時延。所以實測過程中,如果我們加上背景流量,讓Envoy來不及處理報文引發報文排隊,會發現用戶態協議棧相對于內核態協議棧的時延降低效果更明顯,在目前30-35%的基礎上還會有10%的時延降低。
輕舟服務網格用戶態協議棧加速落地實踐
如前所屬,目前用戶態協議棧的開源實現不夠成熟,所以在網易輕舟云原生平臺服務網格組件落地過程中,還是遇到了不小的挑戰。
多線程支持
輕舟服務網格支持Istio,sidecar使用Envoy。Envoy是典型的多線程架構,啟動時可以配置worker數從而確定啟用的工作線程數。VPP+VCL社區版本對多線程的支持僅限于dispatch+worker的線程架構,dispatch線程調用epoll_wait獲取讀寫事件,之后通知worker線程進行報文處理。而Envoy中各個工作線程地位均等,都會獨立進行epoll_wait獲取讀寫事件以及報文處理工作。這里需要解決兩大問題,一是需要各個工作線程獨立向VPP進行注冊成為app worker;另一個是要解決session在各個app worker間的遷移問題。目前我們針對多線程支持的相關patch已經合入社區。
CPU資源占用問題
VPP+VCL在epoll_wait接口中支持兩類fd的輪詢,一類是使用用戶態協議棧的fd;另一類是無法使用用戶態協議棧的fd,比如eventfd,unix socket,管道等,這些還是繼續走內核態協議棧。Envoy中目前就會同時有這兩類fd的存在。為了在一次epoll_wait里同時支持這兩類fd的輪詢,目前社區的做法是在應用指定的超時時間內,不停的以0作為超時時間去依次調用用戶態的vls_epoll_wait和內核態的epoll_wait接口,這最終會導致即使沒有報文需要處理,Envoy占用的CPU也會達到近100%,這顯然是無法接受的。
這里需要針對用戶態引入一個內核的eventfd讓VPP通知VCL產生了事件,目前這套機制社區是有的。當然,實現的時候需要考慮eventfd本身帶來的性能開銷,所以不能每次有報文就通過eventfd進行通知,需要有一定的策略。然后就可以將這個eventfd所加入的epoll fd和內核態的epoll fd使用嵌套的方式統一到一起,從而讓應用指定的超時時間真正生效,而不會出現CPU 100%占用的情況。目前我們相關的代碼修改patch已經合入社區。
雙棧支持
Envoy中對外提供HTTP接口查詢狀態信息,實際使用過程中從安全性角度考慮,我們會配置其監聽127.0.0.1地址,這樣必須管理員登錄到容器中才能查詢相關信息。另外為了支持healthcheck,Envoy會作為客戶端通過127.0.0.1地址連接到pilot-agent。可以看到,從管控面的角度是需要Envoy支持內核態協議棧的,而數據面考慮到性能繼續走用戶態協議棧。目前社區版本還不支持這種雙棧的情況。
其實,雙棧支持的思路比較簡單。應用調用socket接口的時候需要同時創建出內核態協議棧和用戶態協議棧的handle,最終在bind的時候根據綁定的IP地址是否為localhost地址來確定真正使用內核態協議棧還是用戶態協議棧,或者connect的時候根據目的IP地址是否為localhost地址來確定。我們針對雙棧支持的相關patch目前已經提交社區。
總結
針對內核態協議棧的優化,目前有兩個方向:一是使用XDP+eBPF來改寫內核,通過簡化實現來達到優化效果,但是優化之后的代碼還是跑在內核態;另一個就是用戶態協議棧,讓優化后的代碼完全跑在用戶態。針對Envoy或者Nginx、Redis這種用戶態應用的加速,用戶態協議棧可以完全消除用戶態和內核態的切換開銷,甚至讓協議棧卸載到單獨的進程上處理,性能上無疑是最優的,但是技術難度和風險也最大。當然,我們也可以選擇使用XDP+eBPF做局部優化,典型的如針對iptables的優化。
而且用戶態協議棧對于所有用戶態的應用加速其實都是適用的,而不僅僅是針對服務網格sidecar的加速。目前我們正在網易輕舟的服務網格中做相關的產品化工作,包括計算節點的sidecar,也包括API網關。后續我們也會將其擴展到通用的互聯網應用的加速,如Nginx,Redis等。
作者簡介
虎嘯,網易數帆系統開發專家,15年軟件開發經驗。先后就職于華三和華為,從事過安全、視頻監控、大數據和網絡虛擬化等產品研發,目前在網易數帆專注于高性能網絡的技術預研和產品落地工作。
百川,網易技術委員會委員,網易數帆輕舟事業部技術總監,2012 年浙江大學博士畢業后加入網易杭州研究院,負責基礎設施研發/運維至今。在虛擬化、網絡、容器、大規模基礎設施管理以及分布式系統等技術架構有多年經驗,當前主要興趣點在云原生技術方向。
云原生技術分享預告
2020年12月16-17日,來自CNCF、VMware、PingCAP、網易數帆、阿里云等17位重磅演講嘉賓,帶來2天主題分享,立體化解析云原生前沿技術與實踐?;顒釉斍槿鐖D,名額有限,歡迎點擊這里,或識別下圖二維碼報名。
總結
以上是生活随笔為你收集整理的网易轻舟服务网格数据面性能优化实践的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 5分钟教小白通过ipv6远程访问白群晖
- 下一篇: 批量修改图片格式类型