做者:劉俊海mysql
微服務架構解決了業務的諸多問題的同時也帶來了不少挑戰,須要經過完善的微服務治理體系逐一進行解決。微服務治理主要有遠程Proxy方式、智能客戶端方式以及本地Proxy 3種主要承載方式,下面分別討論這幾種方式的優缺點。web
微服務下的服務框架基本解決了微服務開發和測試的效率問題,業務同窗能夠把精力聚焦投入到業務需求上面。多語言服務化背景下,服務治理的基礎設施的每一次改動和升級,須要多語言框架的同時升級,這裏多語言服務框架的開發、測試和維護的開銷有很大的工做量。
因爲服務框架以lib的形式存在,和業務代碼存在於一個服務裏面,會致使作業務需求的業務同窗和負責服務治理的基礎同窗之間仍然會有不少溝通和交互,隨着組織和團隊的擴大,受康威定律的影響,這個溝通成本會變得不可控。
如何減小多語言接入場景下服務治理基礎設施的維護開銷,同時減小服務治理基礎設施升級對業務的影響,儘可能將服務治理和業務解耦,是微服務架構面前的一道課題。
客戶端和服務端通訊,客戶端和服務端都須要有很多服務治理相關的考慮,好比客戶端訪問服務端時須要考慮服務發現、流量路由、負載均衡、調用熔斷、請求降級、mock支持、請求跟蹤等諸多特性,服務端也須要考慮限流、降級、安全、統計等;隨着業務迭代發展,客戶端和服務端須要支持的服務治理特性愈來愈多,影響業務迭代效率。架構設計上有個不成文的說法,任何軟件工程遇到的問題均可以經過增長一箇中間層來解決。按照這個說法,能夠很天然的想到,微服務架構下,是否能夠在客戶端和服務端中間增長一箇中間層,避免二者直接通訊,同時把服務治理相關功能從客戶端和服務端代碼解耦,移到中間層來,這樣服務治理特性的變化收斂在中間代理層,對客戶端和服務端透明。
API網關就是用來解決上述微服務治理的效率問題,API網關封裝了服務訪問和服務治理相關的具體邏輯,客戶端只須要使用簡單的訪問方式,統一訪問API網關,由API網關來代理對後端服務的訪問,同時因爲服務治理特性統一放到API網關上面,服務治理特性的變動能夠作到對客戶端透明,必定程度上實現了服務治理等基礎特性和業務服務的解耦,服務治理特性的升級也比較容易實現。
爲了簡化客戶端的訪問方式,對調用方屏蔽集羣訪問的複雜度,API網關通常會提供一個VIP,調用方直接使用VIP進行訪問,由負載均衡設備負責VIP到API網關地址的映射。
API網關和直接使用服務框架相比,優勢是業務使用起來很簡單,沒有什麼入門成本,很是容易上手,對業務來講,簡單和效率每每是第一位的;同時API網關也能夠屏蔽多語言調用方使用方式的差別,避免了微服務框架語言級別的限制,多語言調用方都可以使用簡單一致的調用方式訪問後端服務,基本解決了多語言的服務治理問題。
固然API網關在提供便捷的服務訪問和服務治理能力的同時,相應的也會有一些問題。
首先,引入API網關,通訊層面會增長一跳;若是是採用簡單易用的VIP訪問方式,還須要加上用於VIP解析的負載均衡服務這一跳,通訊層面會比直接訪問後端服務增長二跳,性能上確定會有必定的損耗。
其次,通訊鏈路上多一跳就會多一個故障點,會對系統的總體穩定性和可用性有必定的影響。
最後,API網關簡單易用的同時,靈活性和定製化支持不太好,很難支持複雜的服務治理定製化需求,好比服務若是想支持動態路由切換,API網關支持起來就有點力不從心。
所以,在業務相對簡單,或業務線上部署結構不太複雜時,使用API網關是一個很好的選擇,能夠簡化微服務的開發和運維,提升業務迭代的效率。但業務若是發展到比較複雜時,好比生產環境有多個機房,或者同一個機房內部有全流量環境、小流量環境等多套環境,就會有比較多的路由策略需求和動態路由切換需求,這種狀況下就須要探索服務層面是否能夠有一種對效率和擴展性更好的平衡方式。sql
和遠程Proxy不一樣,基於智能客戶端的服務框架採用和服務端直連的方式,客戶端和服務端直接通訊,中間不通過任何節點,不只性能提高,同時加強了穩定性。
服務框架須要支持完善的流量調度和容錯設計,同時須要支持常見的服務治理策略,對技術的要求相對較高,對於中小公司來講,開發或維護一款完善的服務框架的開銷都是不小的。
除了開發維護成本高以外,服務框架做爲Lib和客戶端服務綁定在一塊兒,所以是語言相關的,每一個語言均須要相應的服務框架,這會帶來很大的多語言服務治理成本。
另外,因爲和客戶端服務綁定在一塊兒部署,服務框架的迭代升級相對麻煩,當服務框架進行升級時,須要使用框架的服務均進行升級,對於普遍使用的服務框架來講,這是筆不小的開銷,框架和微服務的綁定和耦合,會影響框架自身的迭代和創新。編程
API網關把服務治理相關特性從服務框架中解耦出來,能夠提升效率,但靈活性和擴展性稍差;服務框架能夠支持自如的支持各類服務治理需求,但多語言服務治理支持方面會有很大的開銷,同時服務治理特性的升級和維護比較困難,所以,可否有一種機制或方式,兼顧API網關和服務框架各自的優勢,在提升業務開發效率的同時,也能很好的支持微服務治理的擴展性和定製化需求,本地網關應運而生。
本地網關,又稱爲Sidecar, 經過在每一個服務實例對應的本地機器上部署實現服務治理功能的代理,來實現服務治理能力的快速落地。最有表明性的是Netfilx的微服務中間件Prana, 初衷是將Netfilx OSS微服務治理套件的能力,經過HTTP API接口的方式,賦能給非Java語言使用,以很小的開銷得到Netfilx OSS體系強大的服務治理能力。受到Netflix Prana的啓發,Spring Cloud也推出了Spring Cloud Netflix Sidecar。
和API網關相比,本地網關的訪問方式更爲簡單,事先給本地網關綁定固定的端口號,業務服務經過localhost:本地端口號的方式便可訪問,和直接訪問服務端相比,雖然也多了一跳,因爲是本地訪問,比API網關的性能損耗要小;同時因爲本地網關每一個機器上都會有部署,所以API網關單個節點故障對系統穩定性的影響相對較小;最後本地網關和服務部署在一塊兒,具備感知本地部署環境的能力,方便一些業務或者環境相關的服務治理特性的落地,好比機房級別的動態路由調整等。
從效率和擴展性上看,本地網關和API網關相比,都有着很多優點。那麼是否意味着本地網關就是一個沒有問題的完美方案呢,其實本地網關最大的問題是運維上的複雜度比較高,本地網關節點不少,而且業務服務對本地網關也是強依賴,所以須要對本地網關的部署、監控、升級、高可用保障等,都須要有一套完善的機制來保障。因爲本地網關對運維的要求比較高,須要有一套完善的運維工具體系支撐。
這個時期的本地網關通常是爲了解決業務當前面臨的特定問題,好比業務多語言接入,業務基礎庫升級困難等,通常會和公司特定基礎設施進行綁定,不太通用,這些公司通常也沒有太多的動力對它進行擴展性和通用性改造和升級,同時本地網關模式運維上的複雜度比較高,本地網關節點不少,而且業務服務對本地網關也是強依賴,所以須要對本地網關的部署、監控、升級、高可用保障等,都須要有一套完善的機制來保障。須要有一套完善的運維工具體系支撐,不多有公司具有這樣的技術實力,所以這種模式在一些中大型互聯網公司中獲得採用,如Netfilx、Airbnb等,很難賦能給更多的企業和業務使用,並無大規模應用起來。
當前微服務容器化、雲化的趨勢愈來愈明顯,爲了最大程度的利用雲技術基礎設施,應用自身的架構也須要升級,持續輕量化,將業務需求和非業務需求解耦,業務只須要關注業務相關的功能,這樣業務迭代效率能夠大大提升。爲了支撐雲原生時代下的微服務架構,提升微服務迭代效率,對微服務治理提出了以下要求:
(1)標準化
標準化的微服務基礎設施,保證了微服務架構的通用性、可維護性和可移植性,同時基於標準化的微服務基礎設施,能夠更方便的實現微服務自身的標準化。
(2)配置化
配置化是保障微服務治理和微服務穩定性敏捷性的關鍵,理想的微服務基礎設施,須要能夠經過統一的治理平臺,對服務治理的效果進行可視化度量,同時能夠經過可視化界面方便的調整服務治理的策略,即時生效。經過配置化,能夠創建服務治理策略調整和反饋的閉環機制,支撐服務治理特性的快速迭代。
(3)服務化
若是能夠將微服務基礎設施服務化,微服務像訪問其餘微服務同樣,經過標準化接口獲取服務訪問和服務治理能力,能夠真正作到服務治理對業務的解耦和透明,實現服務治理和微服務的並行開發和升級。
(4)平臺化、產品化
平臺化、產品化的微服務基礎設施,能夠將服務治理能力經過開放平臺,賦能給更多的微服務用戶,經過微服務基礎設施的產品化,能夠加快微服務基礎設施的創新。
Service Mesh解決了哪些問題
Service Mesh就是爲了解決上述微服務治理當前問題而生,做爲Service Mesh技術探索和實踐的先行者,全球第一個真正的Service Mesh項目Linkerd負責人、Buoyant公司創始人兼CEO William Morgan第一次完整的闡述了Service Mesh,按照William Morgan的定義,Service Mesh 是一個致力於解決服務間通訊的基礎設施層,他負責在現代雲原生應用的複雜服務拓撲下實現請求的可靠傳遞,在實踐中,服務網格一般被實現爲一組輕量級網絡代理,這些代理與應用程序部署在一塊兒,而且對應用程序透明。
從上述Service Mesh的定義看,基礎設施層是Service Mesh的定位,致力於解決本書第1章提出的微服務基礎設施標準化、配置化、服務化和產品化問題;服務間通訊,這個是Service Mesh技術面對的問題域,對微服務屏蔽通訊的複雜度,解決微服務的通訊治理問題;請求的可靠傳遞是Service Mesh的目標;輕量級網絡代理是Service Mesh的部署方式;對應用程序透明是Service Mesh的亮點和特點,Service Mesh接入對業務無侵入,能夠很是方便的獲取Service Mesh帶來的便捷性,算是Service Mesh的一大優點。
綜合來看,Service Mesh主要解決用戶以下3個維度的痛點需求。後端
Service Mesh經過將微服務通訊下沉到基礎設施層,屏蔽了微服務處理各類通訊問題的複雜度,能夠當作是微服務之間的抽象協議層,抽象層面能夠當作是TCP/IP協議棧的一部分。對於微服務的開發者來講,好比當前使用HTTP或者Thrift進行RPC通訊時,你不須要關注TCP/IP這一層的具體實現;有了Service Mesh以後,微服務也再也不須要關注RPC通訊(包含服務發現、負載均衡、流量調度、限流降級、監控統計等)的一切細節,真正像本地調用同樣使用微服務,通訊相關的一切工做直接交給Service Mesh。
所以,對於一些須要經過微服務改造提高業務敏捷性,但沒有相應技術能力的中小團隊來講,能夠藉助Service Mesh提供的完善的微服務基礎設施,加速微服務的落地。緩存
功能上,Service Mesh並無提供任何新的特性和能力,Service Mesh提供的全部通訊和服務治理能力在Service Mesh以前的技術中均能找到,好比Spring Cloud就實現完善了微服務RPC通訊和服務治理支持,Service Mesh改變的是通訊和服務治理能力提供的方式,經過將這些能力實現從各語言業務實現中解耦,下沉到基礎設施層面,以一種更加通用和標準化的方式提供,屏蔽不一樣語言、不一樣平臺的差別性,這樣不只有利於通訊和服務治理能力的迭代和創新,業務使用的時候也會更加方便。
Service Mesh避免了多語言服務治理上的重複建設,經過Service Mesh語言無關的通訊和服務治理能力,助力多語言技術棧的效率提高。安全
微服務治理層面,Service Mesh是標準化、體系化、無侵入的分佈式服務治理平臺,標準化方面,Sidecar成爲全部微服務流量通訊的約束標準,同時Service Mesh的數據平面和控制平面也經過標準協議進行交互;體系化方面,從全局考慮,提供多維度立體的微服務Observability能力(metric、trace、logging),而且提供體系化的服務治理能力,好比限流、熔斷、安全、灰度等;最爲重要的是,Service Mesh經過透明無侵入的方式提供全面的服務治理能力,對微服務自己不會帶來直接影響。
經過標準化,帶來一致的服務治理體驗,減小多業務之間因爲服務治理標準不一帶來的溝通和轉換成本,提高全局服務治理的效率。
根據Service Mesh的發展歷程和使用方式,咱們能夠把Service Mesh劃分爲兩個模式。服務器
在Service Mesh的發展早期,Service Mesh以Sidecar的形態存在。Sidecar,中文上通常被譯爲「挎鬥」或「邊車」,相似於三輪摩托車上的挎鬥,Sidecar模式下,網絡代理服務附近在微服務旁邊,爲微服務提供通訊和鏈路治理功能。所以,數據平面代理服務也常常被簡稱爲Sidecar。
此時,只有數據平面的網絡代理服務,沒有控制平面,和外部基礎設施服務的交互直接在網絡代理服務中進行。
Sidecar模式能夠看做是第一代ServiceMesh,表明有早期的Linkerd和Envoy。
第一代Service Mesh採用Sidecar模式,只有數據平面代理,沒有控制平面,數據平面代理直接負責和其餘外部系統進行交互,經過Sidecar模式,經過將通訊和通訊鏈路治理功能從微服務中剝離出來,實現了通訊基礎設施的下沉和服務化,這裏也體現了架構解耦的思想,經過解耦減小了微服務的負擔。網絡
Sidecar模式的ServiceMesh有一個突出的問題,將通訊和通訊鏈路治理的全部功能都放到這個代理服務中,致使數據平面代理很重,而且因爲承載了太多的特性和功能,會使得數據平面代理的更新和修改會特別頻繁,頻繁的更新和升級會致使代理服務出問題的機率增大,影響代理服務的穩定性。同時,Service Mesh模式下,數據平面代理承載了微服務通訊的所有流量,對穩定性要求極高,這個服務的任何故障都會對整個系統的穩定性產生很大的影響。爲了解決上述頻繁升級和穩定性之間的矛盾,將策略和配置決策邏輯從代理服務中脫離出來,造成了獨立的控制平面,這就是第二代Service Mesh。
第二代Service Mesh最重要的標誌就是控制平面和數據平面分離,數據平面和控制平面並非一個新的概念,路由器/交換機等數據通訊產品架構上,就有運行於專門處理器上的控制平面和多個獨立運行、用於路由或交換功能的數據平面。SDN(Software Defined Network,軟件定義網絡)正是經過數據平面和控制平面分離,控制平面的可編程性,使得網絡更加智能、靈活和易擴展,激發了網絡技術的又一次革命。
第二代Service Mesh借鑑了SDN的思路,基於控制平面和數據平面分離,有了完善的控制平面,全部的代理服務都由控制平面掌控,經過控制平面能夠控制整個系統,提供了強大的控制能力和策略能力;同時將具體的控制邏輯從數據平面移除,簡化了數據平面的設計,同時數據平面不須要和外部系統進行交互,數據平面徹底聚焦在變動頻率很低的流量路由和轉發邏輯上,提高了數據平面的穩定性。第二代Service Mesh架構上分爲數據平面和控制平面兩個部分。多線程
經典Service Mesh的基本架構
數據平面負責代理微服務之間的通訊,具體包含RPC通訊、服務發現、負載均衡、降級熔斷、限流容錯等,數據平面能夠認爲是將SpringCloud、Dubbo等語言相關的微服務框架的通訊和服務治理能力獨立而成的一個單獨的語言無關的進程,而且更注重通用性和擴展性,在ServiceMesh中,再也不將數據平面代理視爲一個個孤立的組件,而是將這些代理鏈接在一塊兒造成一個全局的分佈式網絡。
控制平面負責對數據平面進行管理,定義服務發現、路由、流量控制、遙測統計等策略,這些策略能夠是全局的,也能夠經過配置某個數據平面節點單獨指定,控制平面經過必定的機制將策略下發到各個數據平面節點,數據平面節點在通訊時會使用這些策略。
Service Mesh發展和現狀
2016年1月,Twitter前基礎設施工程師William Morgan和Oliver Gould組建了一個名爲Buoyant的公司,同時在GitHub上提交了第一個Linkerd版本Linkerd 0.0.7。這是業界第一個Service Mesh項目,標誌着Service Mesh的誕生;2016年9月,開發Linkerd的Buoyant公司第一次提出了Service Mesh的概念;2017年5月,Istio0.1版本發佈,Istio一發布,就對Service Mesh屆產生巨大影響,直接致使Service Mesh今後以後的發展路徑發生一系列的變化。
下面就以ServiceMesh領域當前最有表明性的產品Istio爲例,簡要介紹Service Mesh的架構和現狀。
Envoy是一個用 C++ 編寫的雲原生高性能邊緣代理、中間代理和服務代理,做爲專門爲微服務架構設計的通訊總線,定位是做爲Service Mesh的數據平面,接管微服務通訊的所有流量,對應用程序屏蔽網絡和通訊的複雜性。
Envoy做爲一個獨立進程,設計爲和每一個應用程序一塊運行,全部的 Envoy 造成一個透明的通訊網格,每一個應用程序發送消息到本地Envoy代理或從本地Envoy代理接收消息,但不須要知道具體的網絡拓撲。
Envoy的核心設計理念是網絡應該對應用服務透明,職責劃分上比較明確,當網絡和應用程序出現故障時,能夠很容易定位出問題的具體根源。
架構上Envoy內部能夠分爲數據平面、控制平面和管理平面3個部分,其中控制平面用於對流量路由和轉發相關的策略和配置進行管理,Envoy和控制平面經過標準API獲取最新的流量配置信息,數據平面的流量轉發就是基於控制平面下發的配置規則進行。
爲了方便對Envoy運行狀態進行監控和管理,Envoy內置一個HTTP Server,做爲Envoy的管理平面,HTTP Server會註冊一系列的Handler,對外暴露管理平面的API,用於外界查詢當前Envoy各個維度的狀態,好比外界能夠經過管理平面API查詢Envoy當前的集羣和路由配置、當前的統計信息等。
Envoy的數據流和控制流
Envoy接收到Downstream客戶端發過來的請求時,通常先通過相似Iptables的透明攔截機制,而後將流量交給Envoy,Envoy獲取請求對應的原目的地址,根據目的地址信息獲取對應的網絡過濾鏈信息,根據網絡過濾鏈配置創建新的鏈接,並經過網絡過濾鏈對應的協議對請求進行解碼和路由,選擇合適的Upstream節點,將請求發送出去,同時創建Downstream鏈接和Upstream鏈接的對應關係,將Upstream返回的響應消息發送給Downstream客戶端。
Envoy之因此在如此短的時間內,在Service Mesh數據平面中脫穎而出,是和它優雅的架構設計密切相關,主要體如今以下方面。
Envoy擴展性經過插件機制實現,Envoy內部當前已經支持衆多擴展點,經過網絡協議插件和HTTP處理擴展插件,分別從通訊協議和鏈路治理兩個層面進行擴展,Envoy插件機制是Service Mesh數據轉發和數據處理的基石,基於插件擴展性機制進行擴展和定製開發很是方便,能夠創建起強大的Service Mesh生態。
配置動態化是Envoy架構層面最優雅的設計,基於配置動態化設計,Envoy集羣管理和流量轉發相關的全部配置都可以經過xDS協議動態下發和生效,不只減小了運維複雜度,同時藉助動態配置化能力,方便經過必定機制發現Envoy運行時的風險並快速調整,提升了Envoy的總體穩定性。
Envoy支持如此衆多特性的同時,仍然能夠提供優秀的性能指標,得益於良好的架構設計,Envoy架構設計方面對性能的考慮隨處可見,好比數據轉發層面,Envoy採用異步事件驅動的方式,而且保證一個請求只會在一個線程內處理,減小了請求在線程間切換的開銷;此外經過數據平面和控制平面分離,配置變動時,經過無鎖機制,保證數據轉發的性能不受任何影響。
此外Envoy對Service Mesh的一大貢獻是第一個提出了通用數據平面API的概念,經過通用數據平面API,創建了數據平面和控制平面之間交互的標準,實現了數據平面和控制平面通訊的標準化。只要基於數據平面API實現,能夠根據須要方便的對數據平面或控制平面進行替換,有利於Service Mesh生態體系的建設。
Nginx是Envoy出現以前網絡通訊中間件領域很是有表明性的開源系統,功能強大,同時性能表現也很是出色,同時擴展性很強,已經造成了強大的生態,已經成爲HTTP流量管理領域事實上的標杆。Envoy做爲後起之秀,雖然定位和目標上和Nginx有很多差別,但架構設計層面,Envoy和Nginx都有不少的可取之處,下面會從功能定位、總體網絡模型、鏈接處理、請求解析、插件機制、配置管理、部署和運維、管理方式等諸多維度,對Envoy和Nginx進行詳細剖析和比較,經過和Nginx功能和架構層面的全方位對比,你們也能夠對Envoy的架構設計有着更立體的認識。
Nginx最核心的功能是web服務器和反向代理服務器,web服務器完成對 http請求協議的解析和以http協議格式響應請求、緩存、日誌處理這些基本web服務器功能;反向代理服務器完成對請求的轉發、負載均衡、鑑權、限流、緩存、日誌處理等代理經常使用功能。
除了對Nginx協議的支持外,Nginx還支持普通的tcp、udp反向代理功能,同時以stream方式支持通用的基於4層協議的反向代理,好比mysql代理、memcached代理等。
Envoy的目標比較遠大,定位是透明接管微服務之間的通訊流量,將通訊和服務治理功能從微服務中解耦,經過Envoy,能夠方便的增長對自定義協議的支持。
歸納起來,Nginx的關鍵詞是web服務器和反向代理,Envoy是透明接管流量,更加體現對流量的控制和掌控力。
另外,從使用方式上看,微服務對於Nginx是顯式調用,經過Nginx完成負載均衡等相關功能,Envoy是隱式調用,業務微服務不須要感知到Envoy的存在,和使用Envoy使用相同的方式進行通訊,只不過再也不須要關注通訊和鏈路治理的細節。
網絡模型上,Nginx採用的是經典的多進程架構,由master進程和worker進程組成,其中,master進程負責對worker進程進行管理,具體包含監控worker進程的運行狀態、根據外部輸入的一些管理命令向worker進程發送處理信號以及worker進程退出時啓動新的worker進程。worker進程負責處理各類網絡事件,各個worker進程之間相互獨立,一塊競爭來自客戶端的新的鏈接和請求,爲了保證請求處理的高效,一個請求處理的所有過程在同一個worker進程中。
網絡模型上,Nginx採用的是多進程架構,由master進程和worker進程組成,其中,master進程負責對worker進程進行管理,具體包含監控worker進程的運行狀態、根據外部輸入的一些管理命令向worker進程發送處理信號以及worker進程退出時啓動新的worker進程。worker進程負責處理各類網絡事件,各個worker進程之間相互獨立,一塊競爭來自客戶端的新的鏈接和請求,爲了保證請求處理的高效,一個請求處理的所有過程在同一個worker進程中。worker進程的個數推薦配置爲和當前環境的CPU核數相同。
自從Nginx誕生以來,一直使用上述經典的多進程架構,這種架構下,請求處理過程當中若是遇到特別耗時的操做,好比磁盤訪問,第三方服務同步訪問等,會致使處理該請求的進程被夯住,不只CPU資源沒有獲得充分利用,夯住時間比較長時不只會影響當前請求,嚴重時會致使本進程的待處理請求大量超時。爲了解決這種問題,Nginx從1.7.11版本開始引入了線程池的概念,若是遇到耗時特別長的邏輯,能夠增長線程池配置,放到線程池中進行處理。線程池機制的引入對Nginx架構上是個很好的補充,經過針對性的解決耗時特別長的一些阻塞場景,使得Nginx的性能達到一個新的高度。
和Nginx不一樣,Envoy採用了多線程的網絡架構,Envoy通常會根據當前CPU核數建立相同個數的worker線程,全部worker線程同時對Envoy配置的監聽器進行監聽,接受新的鏈接,爲每一個新鏈接實例化相應的過濾器處理鏈,處理該鏈接上的全部請求。和Nginx相似,Envoy的每一個請求的處理全流程都在同一個線程下進行。
從上面的分析看,Envoy和Nginx的網絡處理方式大致相似,這兩種方式都是全異步的編程模式,全部的操做都是異步進行,每一個執行上下文使用一個單獨的事件調度器,對該執行上下文的異步事件進行調度和觸發,只是承載網絡的執行上下文有差別,Nginx經過多進程的方式進行承載,Envoy使用的是多線程方式。
Nginx經過線程池的方式,從設計上解決異步編程中的阻塞問題,但仍然沒有從根本上解決這個問題,若是遇到設計或者代碼層面沒有注意到這個問題的場景,仍然會出現由於當前請求阻塞致使後續等待的請求由於得不處處理而超時的現象。因爲都是全異步的編程模式,Envoy也會遇到一樣的問題,同時Envoy開始嘗試着對這種現象進行解決,具體的解決方式是,爲每一個worker線程分別設置一個看門狗,並經過定時器按期更新本線程看門狗的最新更新時間,主線程會監控各個worker線程看門狗一段時間內是否有更新,若是超過一段時間沒有更新,能夠認爲該線程的看門狗定時更新操做得不到執行的機會,能夠推斷出這個線程當前已經夯住,沒法處理請求消息。Envoy經過這種機制能夠檢測出worker線程是否被長時間阻塞住,在此機制的基礎上,後續能夠增長相應的處理(好比將待處理請求移到其餘線程,而後把該線程殺掉),能夠從機制上解決工做線程被阻塞的問題。
Nginx經過worker_connections參數來控制每一個worker可以創建的最大鏈接數,從Nginx網絡模型能夠看出,客戶端鏈接到來時,全部空閒的進程都會去競爭這個新鏈接,這種競爭若是致使某個進程獲得的新鏈接比較多,同時該進程的空閒鏈接也會很快用完,若是不進行控制,後續該進程獲取新鏈接時會遇到沒有空閒鏈接而丟棄,同時有的進程有空閒鏈接而獲取不到新鏈接的不公平現象。那麼直接按照均等的方式將鏈接分配給各個進程是否可行呢,這種方式其實也是有問題的,不一樣鏈接上可能承載的請求QPS差別很大,可能會出現兩個進程處理相同鏈接數,但一個特別忙另一個特別閒的現象,所以爲了保證各個工做進程都可以最大限度的提供本身的計算能力,須要對對鏈接進行精細化管理,Nginx採起的方式是各工做進程根據自身的忙閒程度,動態調整獲取新鏈接的時機,具體實現是,當本進程當前鏈接數達到最大worker_connections的7/8時,本worker進程不會去試圖拿accept鎖,也不會去處理新鏈接,這樣其餘worker進程就更有機會去處理監聽句柄,創建新鏈接。並且,因爲超時時間的設定,使得沒有拿到鎖的worker進程,去拿鎖的頻繁更高,經過這種方式,Nginx解決了worker進程之間的負載均衡問題。
Envoy也會遇到和Nginx相似的負載不均問題,Envoy當前發展很快,同時須要解決的問題不少,Envoy社區的同窗以爲這個問題當前的優先級還不夠高,後續會根據具體狀況對這個問題進行討論和解決。
Nginx擁有強大的插件擴展能力,基於Nginx的插件擴展機制,業務能夠很是方便的完成差別化和個性化定製,Nginx 插件經過模塊的方式提供,具體來講,Nginx主要提供以下幾種形式的插件擴展:
對於最成熟的HTTP協議來講,Nginx把整個請求處理過程劃分爲多個階段,當前一共有包含讀取請求內容、請求地址改寫等一共11個處理階段,業務須要在某個階段進行擴展和定製處理時,只須要掛載該階段對應的回調函數,Nginx核心處理HTTP請求到這個階段時,會回調以前註冊的回調函數進行處理。
Nginx對模塊的支持整體來講不算靈活,Nginx模塊必須和Nginx自身源碼一塊編譯,而且只能在編譯期間選擇當前支持的模塊,不支持運行時進行模塊動態選取和加載,你們一直以來吐槽比較多,爲了解決這個問題,Nginx在1.9.11版本引入了模塊動態加載支持,今後再也不須要替換Nginx文件便可增長第三方模塊擴展。
Nginx也支持Lua擴展,利用Lua語言的簡單易用和強大的協程機制,能夠很是方便地實現不少擴展機制,而且性能也可以基本知足需求。
Envoy也提供了強大的插件擴展機制,當前使用最多的地方是監聽過濾插件和網絡處理過濾插件,和Nginx相比,Envoy網絡插件定位在協議層面,以HTTP協議爲例,Envoy並無那麼細粒度的插件擴展機制,若是想對Envoy的HTTP協議處理進行擴展,當前並無提供特別多的擴展點。
Envoy的插件當前採用的是靜態註冊的方式,插件代碼和Envoy代碼一塊進行編譯,和Nginx不一樣,Envoy從最開始就支持插件的動態加載,Envoy經過獨特的xDS API設計,能夠隨時對Envoy的xDS插件進行定製修改,Istio將修改後的xDS配置經過Grpc的方式推送給Envoy動態加載和生效。
此外,當前Envoy社區和Cilium社區一塊探索利用,利用eBPF提供的用戶態網絡定製能力,對Envoy的流量進行精細化的管理和擴展定製。Cilium從1.3版本開始,引入了Envoy的Go擴展,經過Go擴展實現Filter插件向Envoy註冊,主要實現的仍是OnData()函數,當Envoy接受到流量時,就會調用插件的OnData函數進行處理。
Envoy在Lua擴展支持方面也作進行一些探索性的工做,當前已經試驗性的支持使用Lua腳步對HTTP請求進行過濾和調整,Lua腳步HTTP過濾器當前仍處於實驗階段,不建議直接在生產環境下使用,後續待驗證成熟後才能生產就緒。這種機制成熟後能夠在更多的場景下經過Lua腳步機制,加強Envoy的擴展性。
Nginx的配置格式使用自定義的方式,配置結構和配置解析過程都很是複雜。
配置組織上,Nginx採用層層嵌套的方式,最外層是核心模塊的配置,主要包括events事件模塊、http模塊和stream模塊,對於最複雜的http模塊來講,下面會嵌套着server子模塊,負責監聽和管理http請求,server子模塊下還會嵌套着一到多個location,用於描述具體的路由規則。
Nginx的配置解析代碼能夠說是Nginx整個源碼體系中最晦澀難懂的,配置解析的核心代碼在
ngx_conf_file.c中,經過層層嵌套解析,造成了一顆樹狀的配置信息結構。
和Nginx相比,Envoy的配置管理部分設計的就比較優雅,配置格式直接使用了Protobuf3,複用了Protobuf3的數據描述能力和自動代碼生成機制,徹底省去了配置解析的過程,而且也很是方便對配置格式的有效性進行驗證。
Nginx的配置都是靜態配置,不支持任何形式的動態配置能力。
動態配置能力是Envoy相比Nginx最核心的競爭力,經過動態配置,能夠在線修改流量路由和鏈路治理策略,實現策略配置修改的即時生效。
Nginx內存管理經過Nginx內存池實現,經過內存池的良好設計,使用內存池進行內存管理時,不須要關注內存何時釋放,鏈接銷燬時,會回收鏈接對應的內存資源;同時經過內存池能夠減小內存碎片,經過內存對齊、內存分頁等機制,能夠有效減小Cache Miss,提升內存訪問的效率。
Envoy在內存管理方面的支持還很粗糙,直接基於原生的內存管理lib,內存釋放時機管理上,經過智能指針管理內存的生命週期。
和Nginx相比,Envoy在內存管理方面提供的支持很少,徹底依賴智能指針機制,對使用者的要求比較高,同時沒法知足對性能的極致要求。
運維上,Nginx採用多進程的通訊架構,主進程負責維護工做進程的狀態,一方面監控工做進程的狀態,狀態異常時會對工做進程進行重啓,同時主進程也能夠接收外界的管理信號,通知工做進程完成相應的操做,好比經過kill信號通知Nginx優雅重啓,主進程在接收到重啓信號後,會先從新加載配置,而後啓動新進程開始接收新的請求,並向全部工做線程發送信號,通知它們再也不接收新的請求,並在處理完全部pending請求後自動退出。
Envoy是經過控制平面組件PilotAgent和Sidecar-injection進行管理,Pilot Agent負責管理Envoy的運行狀態,當Envoy狀態有問題時,Pilot Agent會將Envoy重啓,若是重啓仍然不能解決問題,會嘗試將Envoy調度到其餘環境下;Sidecar-injection負責Envoy的自動注入。
所以,從架構上看Nginx是自運維的,Envoy是藉助控制平面來完成Envoy運行狀態的管理, 運維上比Nginx方便。
服務的可觀測以及診斷上,Envoy投入了大量的精力,當前已經全面支持Log、Metric、Trace等可觀測機制,而且每種觀測方式均提供相應的擴展機制,Nginx在這方面相對遜色不少,可觀測以及診斷支持上相對弱一些,當前多是爲了和商業版進行區分,Nginx商業版有完善的運維和問題診斷支持。
Istio是Google、IBM和Lyft聯合推出的開源微服務ServiceMesh框架,旨在解決大量微服務的發現、鏈接、管理、監控以及安全等問題,Istio綜合了Google、IBM和Lyft在微服務領域的強大積累和經驗,以Envoy爲基礎,將Envoy做爲默認的數據平面,同時提供強大的控制平面能力。一經推出在Service Mesh領域就引發強大的反響,當前已成爲Service Mesh事實上的平臺和標準。
Envoy已經能夠很出色的完成流量路由和轉發工做,Istio在Envoy的基礎上,提供以下幾方面的核心能力:
Istio經過提供通用的配置管理能力,保證不一樣平臺、不一樣環境下的配置均可以經過一致的方式對Envoy進行配置和下方,對Envoy屏蔽了配置管理的複雜性。這個工做具體由Istio的Pilot組件負責完成。
通訊安全對於微服務來講是一個很是重要的基礎能力,Istio經過託管身份驗證、受權和服務之間通訊的雙向TLS加密, 保障通訊的安全性,這個工做具體由Istio的security組件負責完成。
對於一些核心資源,須要經過必定的策略,在不一樣消費服務以及服務的不一樣實例中進行分配,保證資源可以按照預期進行管理,這個工做具體由Istio的mixer組件負責完成。
Envoy自身也能進行一些遙測統計相關的工做,但若是須要支持不一樣的遙測統計後端基礎設施,能夠將這部分工做移到控制平面上,保證Envoy自身架構的簡潔性和穩定性,經過收集遙測統計相關的數據和指標,能夠對服務進行全方位的監控。
Service Mesh以其優雅的設計理念,良好的架構設計和生態佈局,被業界普遍看好,但 ServiceMesh技術畢竟從誕生到如今纔不到4年的時間,在穩定性和成熟度上還有不少須要增強和改進的地方,當前主要有以下幾個突出問題:
Service Mesh架構上的最大亮點就是數據平面和控制平面分離,不只簡化了數據平面的設計,提升數據平面代理的穩定性,同時控制平面基於數據平面全局網格強大的可觀測能力,提供強大的全局治理視角和能力,架構上幾乎完美,但Service Mesh透明攔截帶來的通訊消耗,控制平面Mixer交互帶來的性能損耗,Service Mesh當前過度偏重架構,而致使性能問題一直沒有獲得很好的解決,這也很大程度上制約了Service Mesh的落地。
Service Mesh和Kubernetes是一對完美的組合,Service Mesh在Kubernetes平臺下充分利用Kubernetes基礎設施的優點,能夠最大程度上釋放Service Mesh的能量。當前很多Service Mesh主要針對Kubernetes進行設計,主要着眼於雲原生應用的前景和將來,對非Kubernetes平臺的支持不太友好,現實狀況下大量業務仍然部署在非Kubernetes平臺上,會致使Service Mesh落地起來很是艱難,業界至今未能看到Service Mesh在生產環境下的大規模落地。
當前市場了已經涌現了很多Service Mesh,這些Service Mesh各自爲政,相互不兼容,不一樣Service Mesh之間遷移的成本很是高,嚴重影響Service Mesh生態的繁榮和發展。
爲了實現Service Mesh生態的健康持續發展,須要創建一套標準,你們遵守相同的標準互聯互通,擴展實現。
Service Mesh帶來的下一代微服務革命浪潮已經到來,雖然當前仍然有很多現實性問題,但只有緊跟技術的方向,才能充分利用技術帶來的核心價值,最後一句話展望,Service Mesh前途是光明的,道路是曲折的。
原文:學而思網校技術團隊-一文讀懂Service Mesh技術