【Service Mesh基礎】Envoy-插件模型與插件配置

Envoy具有極爲強大的可擴展能力,通過L3/L4/L7 插件機制,可以在各個層級對Envoy實現功能擴展,本文概述了Envoy的插件模型並詳細介紹了HTTP插件配置相關的內容,但不涉及任何插件開發的細節,希望對Envoy的使用者或者更上層的工作能有所幫助。

本文由作者授權發佈,未經許可,請勿轉載。

作者:王佰平,網易杭州研究院輕舟微服務平臺研發工程師

作爲服務代理軟件中的新秀,Envoy具有極爲強大的可擴展能力,這也是網易輕舟微服務平臺採用Envoy的重要原因之一。利用Envoy的L3/L4/L7 插件機制,網易輕舟微服務團隊可以在各個層面對Envoy進行功能擴展。而且由於Envoy良好的封裝和現代C++對各種操作的簡化,其插件開發過程已經相當簡單。真正複雜的部分往往是插件本身的邏輯,而不是C++語言或者Envoy。並且在插件開發過程中,無需過多的考慮線程安全的問題,大部分情況下,都可以將插件的執行邏輯當作單線程來處理。本文將簡單介紹Envoy的插件模型。

需要額外說明的是,Envoy中的插件的重要性可能遠比“插件”這一名詞所體現出來的要多的多。在Envoy中,大量的核心功能都使用插件來實現,包括對Http流量的治理、Tracing機制、多協議支持等等。爲了方便,後續插件可能使用單詞Filter來表述,在本文中,所有“插件”與“Filter”等同。

此外,本文並不包含任何插件開發的相關內容,而是僅僅根據網易輕舟微服務團隊的Service Mesh實踐經驗,科普性地梳理Envoy中的插件機制以及插件的配置模型。希望對Envoy的使用者或者更上層的工作能有所幫助。

三種插件

Envoy包含多種不同類型的插件,如Listener、Network、Http以及Access log Filter等。其中Access log Filter僅僅用於對access log做一些個性化定製處理,所以不多做贅述。Envoy插件整體模型如下圖1所示。

https://pic3.zhimg.com/v2-6e3490be3f050690702c6a784ef29536_b.png

圖1. Envoy插件模型

Listener Filter

Listener Filter在連接建立之後,首先被執行處理,但是由於Listener Filter只能獲得極少數的信息(remote address),所以在此進行的操作極少。在絕大多數情況下,也無需擴展定製Listener Filter。

Network Filter

Network Filter是在Listener Filter處理完成之後開始執行的插件。其工作在四層,相比與Listener Filter,Network Filter可以獲取相對更加豐富的信息,但是也非常有限。Network Filter是envoy管理各種協議和流量的基礎,通過擴展Network Filter,可以實現envoy對各種不同類型流量的治理,如Dubbo、redis、MQ等等。

在所有的四層插件之中,有一個特例需要特別強調:HttpConnectionManager。該插件負責處理HTTP協議的四層流量。該插件是Envoy強大的能力的基礎,可以說是整個Envoy中最爲重要的插件。

此外,在Envoy 1.2之後,引入了一種特殊的cluster network Filter,作用於某個cluster。指向該cluster的四層流量首先需要在該cluster下的所有cluster network Filter完成處理之後纔會發送出去。而在接收到來自上游服務的響應之後,首先也會由該cluster下的所有cluster network Filter處理後再繼續傳遞給其他Filter或者下游客戶端。藉助cluster network Filter,envoy可以實現任意協議之間的流量轉換。以HTTP和Dubbo爲例:當cluster A指向一個Dubbo服務時,可以爲該cluster配置一個HTTP2Dubbo的cluster network Filter。之後,可以將HTTP請求發送給cluster A。cluster A下的HTTP2Dubbo會在四層將HTTP請求重新解析並且拼接編碼出Dubbo請求的二進制序列併發送給上游Dubbo服務。在接收到Dubbo服務響應之後,又可以利用同樣的方式將Dubbo響應轉換爲HTTP響應。如此,cluster A可以完全被當作一個HTTP服務來治理,所有的細節都被屏蔽在cluster network Filter之中。其數據處理流程如下圖2所示。

https://pic3.zhimg.com/v2-18c5563e18c466ce04afd58b451eb0ee_b.png

圖2. Cluster Network Filter

Http Filter

無需多言,互聯網是在HTTP協議之上構建的,所以在Envoy中,處處可見對於HTTP協議的強調和特化處理。實際上,Http Filter只是前文提到的HttpConnectionManager插件下的一系列子插件,但是卻在envoy中佔據了最重要的位置。HttpConnectionManager插件在完成HTTP數據解析之後,會依次調用Http Filter提供的接口,對HTTP數據做進一步處理(簡單的處理如替換header、複雜的處理如限流、錯誤注入、緩存等等)。Envoy豐富而強大的功能,很多都是依賴Http Filter插件來實現。大部分情況下,在對Envoy做擴展增強時,也是通過擴展Http Filter來做到。Http Filter實際工作流程如圖3所示。

https://pic1.zhimg.com/v2-715ddd5596d98f2a680da80e4f2a7418_b.png

圖3. Http Filters

插件配置

之所以要單獨講插件配置,是因爲大部分人都只是插件的使用者而非開發者。插件的使用者只需要知道如何下發正確配置給插件並讓插件生效即可。此處只介紹HttpConnectionManager以及Http Filter插件配置,因爲對於大部分人來說,無需瞭解四層及以下的插件內容(HttpConnectionManager是特例)。

在介紹之前,必要要再三強調:所有配置的生效與否、作用、影響都依賴於插件本身實現,沒有任何強制手段可以讓插件必須使用哪些配置。

雖然插件開發比如有一定的規範,並且大部分插件也會遵循規範,但是規範並不是強制。

插件啓用

如前所述:所有Http Filter實際上都只是HttpConnectionManager的子插件,因此,啓用哪些插件,禁用哪些插件實際上都是由HttpConnectionManager來控制。其配置形式如下(此處只做科普,所以暫時無需糾結更深的細節,只需要有大概的認識即可):

http_filters:

- name: com.netease.iprestriction

  config: {}

- name: envoy.router

  config: {}

所有在上述配置列表中的插件將會被啓用,其他插件則處於禁用狀態。必須要額外強調的是:HttpConnectionManager的配置是Listener級別配置,所以插件的啓用或者禁用也是以Listener(一個Listener就是一個監聽端口,映射到控制面Pilot中,就是一個Gateway資源)爲單位。換言之,當一個插件被啓用時,在該Listener下的所有路由、所有請求上,都會生效;當一個插件被禁用時,那麼在該Listener下的所有路由、所有請求上,都會禁用。

當然,插件啓用只是說明HttpConnectionManager會調用該插件提供的接口,用於處理解析後的header以及body。但是插件本身具體的執行邏輯依舊由插件自身決定。

目前不存在某一個插件只在某一條路由上生效。如果有,是該插件本身內部的邏輯,該插件內部做了相關判斷,如在不匹配的路由執行該插件時,直接返回等。

在Envoy中,存在兩種不同的配置用於控制插件的行爲,一種是基礎配置,一種是路由配置。兩種配置的數據模型可能相同,可能完全不同,可能部分相同,可能缺省,完全由插件設計者決定。舉例來說,transformation插件沒有基礎配置,只有路由配置;iprestriction插件有基礎配置,但是可以缺省,也有路由配置;supercache有基礎配置,且不可缺省,也有路由配置。

基礎配置

首先介紹插件基礎配置。插件基礎配置即是插件初始化配置,該配置在啓用插件(如上一段所述,在HttpConnectionManager配置中)時,在config字段中直接提供,如上一段中示例配置中的supercache插件。顯然,該配置作用範圍和插件的啓用類似,是對整個listener內所有路由生效的。假設網關只有一個listener(一般情況下都是一個listener),那麼可以認爲該配置就是在整個Envoy內全局生效的。

但是,之所有稱之爲基礎配置,而不是全局配置,是因爲該配置是無法被應用到其他作用範圍的,它是插件初始化的基礎,作用範圍不可調整(Kong的使用者往往會認爲插件全局配置就是把一份配置的作用範圍調整爲全局,全局開啓該插件;但是在需要的情況下,也可以把該配置降級爲路由級,只在某一條或者某些符合條件的路由上生效。但是在Envoy中,基礎配置作用範圍就是全局,一旦插件啓用,相關配置全局生效,不可更改)。

功能:插件初始化,一些可全局共享的插件基礎信息與配置

作用範圍:全局,不可修改

路由配置

客戶端的請求千變萬化,不同的路由往往對插件的要求也不同,需要插件在不同路由中,有不同的執行邏輯和操作。如果僅僅依賴基礎配置,那麼插件在所有路由中的行爲都是完全一致的,顯然不可能滿足需求。

所以對於每一個插件,Envoy都提供了一個額外的數據模型,用於創建路由粒度的插件配置。在插件的具體執行過程中,Envoy可以根據需要搜索路由粒度的插件配置並使用該配置決策自己的執行邏輯。

在此強調:路由配置的數據模型可能和基礎配置相同、不同或缺省,換言之,路由配置和基礎配置是完全不相關的兩種配置。

在插件執行(此時,該插件已經根據基礎配置完成了初始化)的過程中(即被HttpConnectionManager調用了相關的接口時),Envoy會主動搜索當前路由下,是否具有當前插件的路由配置。如有配置,則會根據路由配置進一步操作。每條路由下的插件路由配置完全隔離。

考慮到可能多條相似的路由需要使用相同的插件路由配置,Envoy提供了virtualhost級別的插件路由配置。配置在virtualhost級別的插件路由配置可以被該virtualhost下的所有路由所共享。

注:真正可以和Kong中插件配置相對應的實際上是路由配置,只是當前的Envoy插件路由配置不支持全局作用範圍(可以考慮上層封裝),所以略有差異。

功能:在插件執行時,動態獲取並根據配置做相關操作

作用範圍:virtualhost、route(可以由上層封裝到任意作用範圍)

ROUTER

如果說HttpConnectionManager是Network Filter中的特例的話,那麼Router插件就是Http Filter中的一個特例。Router插件是HTTP路由的基礎,所有的HTTP請求都最終由Router插件向上遊服務發送。對於其他插件而言,可能需要區分基礎配置和路由配置。它們的基礎配置作爲HttpConnectionManager配置的一部分(http_filters字段)下發,而路由配置則作爲路由的一部分下發(路由per_filter_config字段)。Router插件特殊的一點在於:它即是路由本身。一條路由包含的相關配置本質上就是對Router插件的配置。所以在更多的時候。Router不應該被視爲一個Http Filter,而應該被視爲整個HttpCononectionManager的一種功能(插件可拔插,但是爲了保證整個HTTP服務治理功能的正常工作,Router不可拔插)

Router支持常見的路由匹配(前綴匹配、精確匹配、正則匹配)、前綴重寫、重定向、直接返回、分流、header添加與移除等等。事實上,利用Router插件已經可以完成Http流量管理的很多功能。需要再三強調的是,Router插件應該看作Network Filter HttpConnectionManager的一部分,而非一個獨立的插件。換言之,如果僅僅從Http的層次來看,Router應該看作是基礎的功能,而非可擴展或者拔插的插件。

本文介紹了Envoy中常見的三種插件並對其中Http Filter及其配置進行較爲詳細的分析。希望通過本文,讀者能夠對Envoy Filter多一些瞭解。如果覺得文中有一些不解或者生澀之處,歡迎在評論區留言討論。

作者簡介:

王佰平,網易杭州研究院雲計算技術部輕舟團隊工程師,負責輕舟Envoy網關與輕舟Service Mesh數據面開發、功能增強、性能優化等工作。對於Envoy數據面開發、增強、落地具有較爲豐富的經驗。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章