微服務(wù):微服務(wù)“新秀”之Service Mesh

女主宣言

本文出自于ADDOPS團(tuán)隊(duì),該文章的譯者霍明明參與了360 HULK云平臺(tái)容器化及虛擬化平臺(tái)相關(guān)服務(wù)建設(shè),對(duì)微服務(wù)有著獨(dú)到的見解。今天的主角Istio是Google/IBM/Lyft聯(lián)合開發(fā)的開源項(xiàng)目,估計(jì)很多同學(xué)在此之前可能完全沒有聽過這個(gè)名字,請(qǐng)不必介意,因?yàn)镮stio出世也才五個(gè)月而已。讓我們跟著作者一起揭開Service Mesh的神秘面紗。PS:豐富的一線技術(shù)、多元化的表現(xiàn)形式,盡在“HULK一線技術(shù)雜談”,點(diǎn)關(guān)注哦!

前言

有人將 Service Mesh 看成是一次 "Network Application Revolution",我還是非常認(rèn)同的,所以也就有了進(jìn)一步了解和學(xué)習(xí)Service Mesh的動(dòng)力。

在看本文章前,強(qiáng)烈建議先看一下這兩篇文章《深度剖析Service Mesh服務(wù)網(wǎng)格新生代Istio》,《從分布式到微服務(wù),深挖Service Mesh》,了解一下Service Mesh的歷史。

1、Envoy 簡(jiǎn)介

在 Service Mesh 模式中,每個(gè)服務(wù)都配備了一個(gè)代理“sidecar”,用于服務(wù)之間的通信。這些代理通常與應(yīng)用程序代碼一起部署,并且它不會(huì)被應(yīng)用程序所感知。Service Mesh 將這些代理組織起來形成了一個(gè)輕量級(jí)網(wǎng)絡(luò)代理矩陣,也就是服務(wù)網(wǎng)格。這些代理不再是孤立的組件,它們本身是一個(gè)有價(jià)值的網(wǎng)絡(luò)。其部署模式如圖所示:


綠色部分代表應(yīng)用程序

藍(lán)色部分則是sidecar

服務(wù)網(wǎng)格是用于處理服務(wù)到服務(wù)通信的“專用基礎(chǔ)設(shè)施層”。它通過這些代理來管理復(fù)雜的服務(wù)拓?fù)洌煽康貍鬟f服務(wù)之間的請(qǐng)求。 從某種程度上說,這些代理接管了應(yīng)用程序的網(wǎng)絡(luò)通信層。

Envoy是 Service Mesh 中一個(gè)非常優(yōu)秀的 sidecar 的開源實(shí)現(xiàn)。我們就來看看 Envoy 都是做些什么工作。

2、Envoy 用到的幾個(gè)術(shù)語

Host: 通常我們將 Host 看做是一個(gè)具備網(wǎng)絡(luò)通信功能的實(shí)體(可以是一臺(tái)物理機(jī),也可以是一臺(tái)移動(dòng)設(shè)備等等) 。在 Envoy 中,host 是一個(gè)邏輯網(wǎng)絡(luò)中的應(yīng)用. 可能運(yùn)行在由有多個(gè)主機(jī)組成的底層硬件,只要它們各自獨(dú)立尋址。

Downstream: 請(qǐng)求發(fā)起者(服務(wù)請(qǐng)求方)。

Upstream: 請(qǐng)求接收者(服務(wù)提供方)。

Listener: 服務(wù)(程序)監(jiān)聽者。就是真正干活的。 envoy 會(huì)暴露一個(gè)或者多個(gè)listener監(jiān)聽downstream的請(qǐng)求。

Cluster: upstream 集群。Envoy 通過服務(wù)發(fā)現(xiàn)定位集群成員并獲取服務(wù)。具體請(qǐng)求到哪個(gè)集群成員是由負(fù)載均衡策略決定。通過健康檢查服務(wù)來對(duì)集群成員服務(wù)狀態(tài)進(jìn)行檢查。

Mesh: 在本文中 "Envoy mesh" 指的是由一組 Envoy 代理組成的,為不同服務(wù)之間可靠傳遞請(qǐng)求的服務(wù)網(wǎng)格。

Runtime configuration: Envoy 配置是熱更新的,無需重啟。

Filter: 過濾器。在 Envoy 中指的是一些“可插拔”和可組合的邏輯處理層。是 Envoy 核心邏輯處理單元。

3、Envoy 基礎(chǔ)概念

線程模型

Envoy 使用單進(jìn)程多線程模式。一個(gè)主線程,多個(gè)工作線程。主線程協(xié)調(diào)和管理這多個(gè)線程來工作。每個(gè)線程都獨(dú)立監(jiān)聽服務(wù),并對(duì)請(qǐng)求進(jìn)行過濾和數(shù)據(jù)的轉(zhuǎn)發(fā)等。

一個(gè)連接建立后,這個(gè)線程將會(huì)管理該連接的整個(gè)生命周期。通常 Envoy 是非阻塞的,對(duì)于大多數(shù)情況建議每個(gè) Envoy 配置的工作線程數(shù)等于機(jī)器的 CPU 線程數(shù)。

Listeners

Envoy 中真正干活的(通常是一個(gè)監(jiān)聽服務(wù)端口的工作線程)。

Envoy 會(huì)啟動(dòng)一個(gè)或者多個(gè)listener,監(jiān)聽來自 downstream 的請(qǐng)求。當(dāng) listener 接收到新的請(qǐng)求時(shí),會(huì)根據(jù)關(guān)聯(lián)的filters模板初始化配置這些 filters,并根據(jù)這些 filters 鏈對(duì)這些請(qǐng)求做出處理(例如:限速、TLS 認(rèn)證、HTTP 連接管理、MongoDB 嗅探、TCP 代理等等)。

Envoy 是多線程模型,支持單個(gè)進(jìn)程配置任意數(shù)量的 listeners。通常建議一個(gè)機(jī)器上運(yùn)行一個(gè) Envoy 進(jìn)程,而不關(guān)心配置了多少個(gè)listerners(如上:大多數(shù)情況listener數(shù)量等于機(jī)器的CPU線程數(shù))。

目前 Envoy 只支持 TCP 類型的 listeners。每個(gè) listener 都可以獨(dú)立配置一些L3/L4層的 filters。

Listener 還可以通過 listener 發(fā)現(xiàn)服務(wù)來動(dòng)態(tài)獲取。

Network (L3/L4) filters

network (L3/L4) filters 構(gòu)成了Envoy連接處理的核心。 在 listener 部分我們介紹過, 每個(gè) listener 可以組合使用多個(gè) filters 來處理連接數(shù)據(jù)。

目前有三種類型的 network (L3/L4) filters:

Read: 當(dāng) Envoy 接收來自下游服務(wù)請(qǐng)求數(shù)據(jù)時(shí)被調(diào)用。

Write: 當(dāng) Envoy 向上游服務(wù)發(fā)送數(shù)據(jù)時(shí)被調(diào)用。

Read/Write: 上面兩種fileter都是單向控制,Read/Write filters 在接收來自下游服務(wù)請(qǐng)求數(shù)據(jù)和向上游服務(wù)發(fā)送數(shù)據(jù)時(shí)被調(diào)用,是雙向控制。

這些 filter 通過分析原始字節(jié)流和少量連接事件(例如,TLS握手完成,本地或遠(yuǎn)程連接斷開等)對(duì)連接進(jìn)行處理。

Network Filter(L7)/HTTP Filter

HTTP 協(xié)議是當(dāng)前許多服務(wù)構(gòu)建的基礎(chǔ)協(xié)議,作為核心組件,Envoy 內(nèi)置了 HTTP 連接管理 filter。 該 filter 將原始數(shù)據(jù)字節(jié)轉(zhuǎn)換成 HTTP 協(xié)議類型數(shù)據(jù)(比如: headers、body、trailers等)。它還會(huì)處理一些通用的問題(比如:request日志、request ID生成和request追蹤、請(qǐng)求/響應(yīng)頭控制、路由表管理和狀態(tài)數(shù)據(jù)統(tǒng)計(jì)等)。

HTTP 連接管理提供了三種類型的filter:

HTTP 協(xié)議是當(dāng)前許多服務(wù)構(gòu)建的基礎(chǔ)協(xié)議,作為核心組件,Envoy 內(nèi)置了 HTTP 連接管理 filter。 該 filter 將原始數(shù)據(jù)字節(jié)轉(zhuǎn)換成 HTTP 協(xié)議類型數(shù)據(jù)(比如: headers、body、trailers等)。它還會(huì)處理一些通用的問題(比如:request日志、request ID生成和request追蹤、請(qǐng)求/響應(yīng)頭控制、路由表管理和狀態(tài)數(shù)據(jù)統(tǒng)計(jì)等)。

HTTP 連接管理提供了三種類型的filter:

Decoder: 解析請(qǐng)求數(shù)據(jù)流時(shí)(headers,body,trailers等)調(diào)用,屬于入口單方向控制。

Encoder: 編碼響應(yīng)數(shù)據(jù)流時(shí)(headers, body, and trailers)調(diào)用,屬于出口單方向控制.

Decoder/Encoder: Decoder/Encoder 用于入/出口雙向控制.

HTTP Filters

(https://envoyproxy.github.io/envoy/configuration/http_filters/http_filters.html#config-http-filters)

HTTP protocols

Envoy HTTP 連接管理原生支持HTTP/1.1, WebSockets 和 HTTP/2,暫不支持 SPDY。

Envoy 對(duì) HTTP 的支持在設(shè)計(jì)之初就是一個(gè)HTTP/2的多路復(fù)用代理。對(duì)于 HTTP/1.1 類型連接,編解碼器將 HTTP/1.1 的數(shù)據(jù)轉(zhuǎn)換為類似于 HTTP/2 或者更高層的抽象處理。這意味著大多數(shù)代碼不用關(guān)心底層連接使用的是 HTTP/1.1 還是 HTTP/2。

access log

HTTP 連接管理支持 access log,可以記錄訪問日志,且可以靈活的配置。

HTTP 路由

Envoy 包含了一個(gè) HTTP router filter,該 filter 可以用來實(shí)現(xiàn)更高級(jí)的路由功能。它可以用來處理邊緣流量/請(qǐng)求(類似傳統(tǒng)的反向代理),同時(shí)也可以構(gòu)建一個(gè)服務(wù)與服務(wù)之間的 Envoy 網(wǎng)格(典型的是通過對(duì)HTTP header等的處理實(shí)現(xiàn)到特定服務(wù)集群的轉(zhuǎn)發(fā))。

每個(gè)HTTP連接管理 filter 都會(huì)關(guān)聯(lián)一個(gè)路由表。每個(gè)路由表會(huì)包含對(duì) HTTP 頭、虛擬主機(jī)等的配置信息。

{

? "cluster": "...",

? "route_config_name": "route_config_example",

? "refresh_delay_ms": "3000"

}

route_config_example:

{

? "validate_clusters": "example",

? "virtual_hosts": [

? ? ? ? {

? ? ? ? ? "name": "vh01",

? ? ? ? ? "domains": ["test.foo.cn"],

? ? ? ? ? "routes": [],

? ? ? ? ? "require_ssl": "...",?

? ? ? ? ? "virtual_clusters": [],?

? ? ? ? ? "rate_limits":?

? ? ? ? ? "request_headers_to_add": [

? ? ? ? ? ? ? ? ? {"key": "header1", "value": "value1"},

? ? ? ? ? ? ? ? ? {"key": "header2", "value": "value2"}

? ? ? ? ? ]

? ? ? ? },

? ],

? "internal_only_headers": [],

? "response_headers_to_add": [],

? "response_headers_to_remove": [],

? "request_headers_to_add": [

? ]

}

路由表有兩種配置方式:

靜態(tài)配置文件。

通過RDS(Route discovery service) API動(dòng)態(tài)配置。

RDS 是一組API用來動(dòng)態(tài)獲取變更后的路由配置。

router filter 支持如下功能:

支持 Virtual hosts。映射 domains/authorities 到一系列的路由規(guī)則上。[和nginx等一樣]。

基于前綴和精確path的規(guī)則匹配(有的對(duì)大小寫既敏感,有的不敏感)。 由于 Regex/slug 會(huì)使得用程序來判定路由規(guī)則是否與其它規(guī)則沖突很困難, 所以,目前暫不支持。由于這個(gè)原因,我們不建議在反向代理層面使用基于regex/slug的路由, 當(dāng)然了,未來我們會(huì)根據(jù)需求添加對(duì)它的支持。

Virual host 層面的 TLS 重定向。 分兩類:

all: 所有請(qǐng)求都必須使用TLS。如果請(qǐng)求沒有使用TLS,返回302。

external_only: 只要求外網(wǎng)請(qǐng)求使用TLS。如果來自外網(wǎng)的請(qǐng)求沒有使用TLS。 如果,改參數(shù)沒有配置,該virtual host將不會(huì)對(duì)TLS有要求。

路由層面對(duì) Path/host 重定向。

host重寫。 支持兩種重寫方式:

1. 固定值。host_rewrite參數(shù)配置。

2. 動(dòng)態(tài)配置。根據(jù)upstream 主機(jī)的 DNS 類型動(dòng)態(tài)配置。 具體的值是由cluster manager從upstream中選出來的,其主機(jī)名作為重寫的值。 這種方式只用在route的目的集群是 strict_dns or logical_dns 類型的場(chǎng)景。其它集群類型不起作用。 將 auto_host_rewrite 設(shè)置true即可。這兩個(gè)參數(shù)不能同時(shí)使用。

前綴重寫(prefix)。

路由層面對(duì) Websocket upgrades. 配置該規(guī)則后,來自 HTTP/1.1 客戶端到該路由規(guī)則的連接都會(huì)被轉(zhuǎn)換成 WebSocket 的連接。 如果配置為 true, Envoy 對(duì)于該路由的第一個(gè)請(qǐng)求需帶 WebSocket upgrade headers。如果沒有添加該header,請(qǐng)求江北拒絕。如果設(shè)置了, Envoy 將會(huì)在client和upstream server之間設(shè)置TCP代理 。upstream 負(fù)責(zé)斷開該連接,否則 Envoy 任然會(huì)轉(zhuǎn)發(fā)數(shù)據(jù)到該upstream server。

請(qǐng)求重試和超時(shí)設(shè)置 Envoy 有兩種方式來設(shè)置請(qǐng)求重試。

1. 通過route設(shè)置。

2. 通過request header設(shè)置。 支持的配置項(xiàng)有: 2.1 最大重試次數(shù): 每次重試之間會(huì)使用指數(shù)退避算法.另外,所有重試都包含在整體請(qǐng)求超時(shí)之內(nèi)。這避免了由于大量重試而需要較長的請(qǐng)求時(shí)間。 2.2 重試條件: 可以根據(jù)應(yīng)用的需求配置觸發(fā)重試的條件。例如: 網(wǎng)絡(luò)錯(cuò)誤, 5xx 返回碼, 冪等的4xx返回碼, 等等。

運(yùn)行時(shí)對(duì)來自上下游數(shù)據(jù)的嗅探。

使用基于 weight/percentage-based 的路由,對(duì)來自多個(gè)上游的數(shù)據(jù)進(jìn)行拆分。

任意 HTTP 頭匹配路由規(guī)則。

支持虛擬集群。

基于路由的優(yōu)先級(jí)。

基于路由的 hash 負(fù)載均衡。需要在 header 中設(shè)置 hash 使用的策略。

對(duì)于非 TLS 的轉(zhuǎn)發(fā)支持絕對(duì) urls。

其中:重定向、超時(shí)、重試對(duì)于 websocket upgrades 是不支持的。

Connection pooling

對(duì)于 HTTP 類型,Envoy 提供了對(duì)連接池的抽象,連接池屏蔽底層協(xié)議類型(HTTP/1.1、HTTP/2),向上層提供統(tǒng)一的接口。用戶不用關(guān)心底層是基于HTTP/1.1的多線程還是基于HTTP/2的多路復(fù)用方式實(shí)現(xiàn)細(xì)節(jié)。

TCP proxy

TCP 代理,L3/L4層連接的轉(zhuǎn)發(fā)。這應(yīng)該是 Envoy 最基礎(chǔ)的功能。一般是作為 downstream 客戶端與 upstream 服務(wù)集群之間的連接代理。TCP 代理既可以單獨(dú)使用,也可以與其它 filter 組合使用,例如( MongoDB filter 或者 限速filter)。

在 TCP 代理層還可以配置 route 策略,比如: 允許哪些IP段和哪些端口進(jìn)來的請(qǐng)求訪問,允許訪問哪些IP段和哪些端口的服務(wù)。

TCP 代理配置如下:

{

? "name": "tcp_proxy",

? "config": {

? ? "stat_prefix": "...",

? ? "route_config": "{...}"

? }

}

stat_prefix: 統(tǒng)計(jì)數(shù)據(jù)前綴,主要是用于區(qū)分統(tǒng)計(jì)數(shù)據(jù)。

route_config: filter 的路由表。

例如:

{

? "name": "tcp_proxy",

? "config": {

? ? "stat_prefix": "...",

? ? "route_config": "{

? ? ? "routes": [

? ? ? ? {

? ? ? ? ? ? "cluster": "...",

? ? ? ? ? ? "destination_ip_list": [

? ? ? ? ? ? ? ? ? "192.168.3.0/24",

? ? ? ? ? ? ? ? ? "50.1.2.3/32",

? ? ? ? ? ? ? ? ? "10.15.0.0/16",

? ? ? ? ? ? ? ? ? "2001:abcd::/64"

? ? ? ? ? ? ],

? ? ? ? ? ? "destination_ports": "1-1024,2048-4096,12345",

? ? ? ? ? ? "source_ip_list": [

? ? ? ? ? ? ? ? ? "192.168.3.0/24",

? ? ? ? ? ? ? ? ? "50.1.2.3/32",

? ? ? ? ? ? ? ? ? "10.15.0.0/16",

? ? ? ? ? ? ? ? ? "2001:abcd::/64"

? ? ? ? ? ? ],

? ? ? ? ? ? "source_ports": "1-1024,2048-4096,12345"

? ? ? ? },

? ? ? ]

? ? }"

? }

}

簡(jiǎn)單說,就是上下游服務(wù)的訪問控制。

TPC 代理支持的一些統(tǒng)計(jì)數(shù)據(jù):

downstream_cx_total 處理的連接總數(shù).

downstream_cx_no_route 不匹配route的總數(shù).

downstream_cx_tx_bytes_total 發(fā)送給下游的總字節(jié)數(shù)

downstream_cx_tx_bytes_buffered Gauge 當(dāng)前為下游服務(wù)緩存的字節(jié)數(shù)

downstream_flow_control_paused_reading_total 被流控暫停從下游服務(wù)讀取數(shù)據(jù)的次數(shù)

downstream_flow_control_resumed_reading_total 被流控控制重新從下游服務(wù)讀取數(shù)據(jù)的次數(shù)

gRPC 的支持

Envoy 在傳輸層和應(yīng)用層兩個(gè)層給予gRPC的高度支持。

Envoy 是當(dāng)前極少數(shù)能同時(shí)正確支持HTTP/2 trailers和傳輸gRPC請(qǐng)求和響應(yīng)的的HTTP代理。

gRPC 運(yùn)行時(shí)對(duì)于一些語言而言還是不太成熟。為此,Envoy 支持一個(gè)叫 gRPC bridge 的 filter,它允許gRPC請(qǐng)求能夠通過HTTP/1.1發(fā)送給Envoy。 Envoy 會(huì)將該請(qǐng)求轉(zhuǎn)換成HTTP/2傳輸?shù)侥康膕erver。響應(yīng)會(huì)被轉(zhuǎn)換成 HTTP/1.1 返回。

當(dāng)裝了bridge filter后, bridge filter 除了收集全局HTTP統(tǒng)計(jì)之外,橋接過濾器還收集每個(gè)RPC統(tǒng)計(jì)信息。

gRPC-Web is supported by a filter that allows a gRPC-Web client to send requests to Envoy over HTTP/1.1 and get proxied to a gRPC server. It’s under active development and is expected to be the successor to the gRPC bridge filter.

支持 gRPC-web。通過 filter 能夠?qū)⑹褂?HTTP/1.1 發(fā)送到Envoy 的 gRPC-Web 客戶端請(qǐng)求代理到 gRPC server。該 feature 正在開發(fā)階段。

JSON 轉(zhuǎn)換器支持基于 JSON 的 RESTFUL 客戶端通過 HTTP 發(fā)送請(qǐng)求給 Envoy 并代理給 gRPC 服務(wù).

WebSocket 的支持

Envoy 支持HTTP/1.1連接到WebSocket連接的切換(默認(rèn)是支持的)。

條件:

client 需要顯示添加 upgrade headers 。

HTTP 路由規(guī)則中顯示的設(shè)置了對(duì) websocket的支持(use_websocket)。

因?yàn)?Envoy 將 WebSocket connections 作為 TCP connection 來處理,因此,一些HTTP的特性它不支持,例如: 重定向、超時(shí)、重試、限速、 shadowing . 但是, prefix 重寫, host 重寫, traffic shifting and splitting 都是支持的.

Envoy對(duì)WebSocket的代理是TCP層,它理解不了WebSocket層的語義,所以對(duì)于連接斷開應(yīng)該由upstream的client來主動(dòng)關(guān)閉。

Envoy對(duì)WebSocket的支持與nginx對(duì)WebSocket的支持是相同的。

關(guān)于 Envoy 對(duì) WebSocket 的支持可以參考 nginx 對(duì) WebSocket 的支持。

(http://www.itfanwan.com/xinwen/6385)

4、高級(jí)概念

集群管理器(Cluster manager)

Envoy 集群管理器管理所有 upstream 集群節(jié)點(diǎn)。

upstream 集群節(jié)點(diǎn)都由一些列 L3/L4/L7 層 filter 鏈組成,它們可用于任意數(shù)量的不同代理服務(wù)。

集群管理器向 filter 鏈暴露一組API,這組API允許 filters 獲取發(fā)往 upstream 集群的L3/L4層的連接或抽象的 HTTP 連接池的數(shù)據(jù)。在 filter 處理階段通過對(duì)原始字節(jié)流的分析確定是一個(gè)連接是 L3/L4 層的連接還是一個(gè)新的 HTTP 流。

除了基本的連接類型分析外,集群管理器還要處理一些列的復(fù)雜工作,例如:知道哪些主機(jī)可用和健康,負(fù)載均衡,網(wǎng)絡(luò)連接數(shù)據(jù)的本地存儲(chǔ),連接類型(TCP/IP, UDS),協(xié)議類型(HTTP/1.1,HTTP/2)等。

集群管理器支持兩種方式獲取它管理的集群節(jié)點(diǎn):

通過靜態(tài)的配置文件

通過動(dòng)態(tài)的集群發(fā)現(xiàn)API(CDS)。

CDS:Cluster discovery service,是一個(gè)可選的API,Envoy用它來動(dòng)態(tài)的獲取cluster manager的成員。

集群管理器配置項(xiàng)如下:

{

? "clusters": [],?

? "sds": "{...}",

? "local_cluster_name": "...",

? "outlier_detection": "{...}",

? "cds": "{...}"

}

Service discovery(SDS)

服務(wù)發(fā)現(xiàn)有幾種方式:

靜態(tài)配置。通過配置文件配置(IP/PORT、unix domain socket等)。

基于DNS的服務(wù)發(fā)現(xiàn)。

Original destination

Service discovery service (SDS)

On eventually consistent service discovery

更多服務(wù)發(fā)現(xiàn)內(nèi)容

(https://envoyproxy.github.io/envoy/intro/arch_overview/service_discovery.html)

主動(dòng)健康檢查

根據(jù)配置的不同, Envoy 支持3種健康檢查方式。

基于 HTTP

Envoy 向 upstream 節(jié)點(diǎn)發(fā)送一個(gè) HTTP 請(qǐng)求,返回 200 代表健康, 返回 503 代表該host不再接收請(qǐng)求/流量。

基于 HTTP 的健康檢查支持3種策略:

1.1 No pass through

這種模式 Envoy 不會(huì)將健康檢查的請(qǐng)求轉(zhuǎn)發(fā)給本地的服務(wù),而是根據(jù)當(dāng)前節(jié)點(diǎn)是否被 draining 返回 200 或者 503.

1.2 Pass through

與第一種模式不同,這種模式 Envoy 會(huì)將健康檢查的請(qǐng)求轉(zhuǎn)發(fā)給本地服務(wù),調(diào)用本地服務(wù)的健康檢查接口,返回 200 或 503.

1.3 Pass through with caching

這種模式是前兩種模式的高級(jí)版,第一種方案數(shù)據(jù)不一定準(zhǔn),第二種請(qǐng)求太頻繁會(huì)對(duì)性能有影響。

該模式加了個(gè)緩存的支持,在緩存周期內(nèi)結(jié)果直接從緩存中取,緩存失效后再請(qǐng)求一次本地服務(wù)加載到緩存中。

這是推薦的一種模式。 健康檢查時(shí) Envoy 與 Envoy之間是長連接,他們不會(huì)消耗太大性能;對(duì)于 upstream 節(jié)點(diǎn)而言,則是新請(qǐng)求新連接。

基于 HTTP 的健康檢查支持身份認(rèn)證。

如果你在云平臺(tái)中用了最終一致性的服務(wù)發(fā)現(xiàn)服務(wù)或者容器環(huán)境中,趕上服務(wù)水平擴(kuò)展,這個(gè)時(shí)候其中一個(gè)節(jié)點(diǎn)掛掉后又"回到平臺(tái)"且使用的是同一個(gè) IP 是有可能的,但是確是不同的服務(wù)(在容器服務(wù)中尤為明顯)。一種解決方案是,對(duì)不同的服務(wù)使用不同的健康檢查URL,但是這種配置復(fù)雜度非常高。Envoy 采用的方案是在 header 中添加一個(gè) service_name 選項(xiàng)來支持。如果設(shè)置了該選項(xiàng),在健康檢查時(shí)會(huì)對(duì)比 header 中的 x-envoy-upstream-healthchecked-cluster 是否和該選項(xiàng)值匹配,如果不匹配則會(huì)忽略該請(qǐng)求。

L3/L4

基于L3/L4層的健康檢查, Envoy 向 upstream 節(jié)點(diǎn)發(fā)送定義好的一個(gè)字符串. 如果 upstream 節(jié)點(diǎn)返回該值,則代表健康, 否則不健康。

Redis

Envoy 向 Redis 發(fā)送一個(gè) PING 命令, 返回 PONG 代表健康, 其它的代表不健康。

Passive health checking(鈍態(tài)檢查)

Envoy 通過 Outlier detection 進(jìn)行鈍態(tài)(實(shí)在是找不出太合適的詞)檢查

Outlier detection,用來檢查某些集群成員在給定范圍內(nèi)是否“正常”,不正常則將其從負(fù)載均衡列表中移除。

有時(shí)候一個(gè)節(jié)點(diǎn)雖然在進(jìn)行主動(dòng)健康檢查是是正常的,但是會(huì)存在某些不正常的狀態(tài)被遺漏的情況,而 Outlier detection 則是彌補(bǔ)這個(gè)“漏洞”的 。它通過跟高級(jí)的一些算法來判定該節(jié)點(diǎn)是否是正常的。

Outlier detection 有兩種檢查類型:

基于連續(xù)的 5xx 錯(cuò)誤碼

upstream 成員連續(xù)N次返回5xx錯(cuò)誤碼, N默認(rèn)為5(可配置)。

基于成功率

基于成功率的檢查在兩種情況下是不處理的:

針對(duì)集群中單個(gè)節(jié)點(diǎn)

單個(gè)節(jié)點(diǎn)的請(qǐng)求數(shù)量在聚合區(qū)間內(nèi)少于outlier_detection.success_rate_request_volume值時(shí)(默認(rèn)100)。

集群級(jí)別

集群中 outlier_detection.success_rate_minimum_hosts 個(gè)節(jié)點(diǎn)在檢查周期內(nèi)請(qǐng)求量都小于 outlier_detection.success_rate_request_volume 時(shí)。

配置項(xiàng):

? {

? "consecutive_5xx": "...",

? "interval_ms": "...",

? "base_ejection_time_ms": "...",

? "max_ejection_percent": "...",

? "enforcing_consecutive_5xx" : "...",

? "enforcing_success_rate" : "...",

? "success_rate_minimum_hosts" : "...",

? "success_rate_request_volume" : "...",

? "success_rate_stdev_factor" : "..."

}

主動(dòng)健康檢查和鈍態(tài)檢查可以配合使用,也可以單獨(dú)使用。

Circuit breaking(斷路器)

斷路器是一種分布式的限速機(jī)制,它針對(duì)每個(gè)upstream的host設(shè)置,有時(shí)候也需要針對(duì)整個(gè)cluster進(jìn)行限制, 這個(gè)時(shí)候全局的限速就非常有必要了。Envoy支持全局限速(L3/L4、HTTP 都支持),它有一個(gè)集中的限速服務(wù), 對(duì)于到達(dá)該集群的每個(gè)連接,都會(huì)從限速服務(wù)那里查詢?nèi)窒匏龠M(jìn)行判斷。 Envoy 是通過一個(gè)全局的gRPC限速服務(wù)來實(shí)現(xiàn)全局限速。通過redis來做后端存儲(chǔ)。

Envoy 的斷路器可以控制 envoy 與 downstream 節(jié)點(diǎn)的最大連接數(shù)、集群最大支持的 pending 請(qǐng)求數(shù)、集群最大支持的請(qǐng)求數(shù)(適用HTTP/2)、集群存活最大探測(cè)次數(shù)。

斷路器配置:

{

? "max_connections": "...",?

? "max_pending_requests": "...", # 默認(rèn) 1024

? "max_requests": "...", # 默認(rèn)? 1024

? "max_retries": "...", 默認(rèn) 3

}

max_connections:Envoy 與 upstream 集群所有節(jié)點(diǎn)能夠建立的最大連接數(shù)量。該參數(shù)適用于HTTP/1.1,因?yàn)镠TTP/2是使用單個(gè)連接與每個(gè)host建連,連接復(fù)用(默認(rèn)1024)。

max_pending_requests: 等待線程池有可用連接時(shí)的最大排隊(duì)請(qǐng)求數(shù)量。該參數(shù)適用于HTTP/1.1,HTTP/2采用多路復(fù)用方式,無需排隊(duì)請(qǐng)求(默認(rèn) 1024)。

max_requests: 給定時(shí)間內(nèi)最大請(qǐng)求數(shù),該參數(shù)適用于HTTP/2,HTTP/1.1 通過max_connections來限制。(默認(rèn) 1024)。

max_retries: 給定時(shí)間內(nèi)Envoy與請(qǐng)求upstream集群時(shí)的最大重試次數(shù),該值不宜設(shè)置過大,重試過多可能會(huì)帶來更多其它的級(jí)聯(lián)故障,甚至導(dǎo)致雪崩。(默認(rèn) 3)。

熱更新

簡(jiǎn)化操作是Envoy一個(gè)非常重要的設(shè)計(jì)目標(biāo)。除了強(qiáng)大的統(tǒng)計(jì)和本地管理接口, Envoy還具備自身熱重啟的功能。 這意味著 Envoy 能夠全自動(dòng)的更新自己(包括代碼和配置的變更),而不會(huì)丟失任何連接。

看下熱更新的過程:

統(tǒng)計(jì)數(shù)據(jù)和一些lock都放到了共享內(nèi)存中。進(jìn)程在重啟時(shí)這些數(shù)據(jù)是持久的,不會(huì)丟失。

新舊進(jìn)程通過RPC協(xié)議進(jìn)行通信。

新的進(jìn)程在接管舊進(jìn)程的unix domain socket前,先完成一系列的初始化(比如:加載配置, 初始化服務(wù)發(fā)現(xiàn)和健康檢查, 其它)。然后,新的進(jìn)程開始監(jiān)聽服務(wù),并告訴老的Envoy進(jìn)程進(jìn)入驅(qū)逐階段。

在舊進(jìn)程驅(qū)逐階段, 舊的進(jìn)程嘗試平滑的關(guān)閉已存在的連接。具體如何做要依賴于配置的filters。 --drain-time-s 配置項(xiàng)用來配置等待平滑退出的時(shí)間。如果平滑退出花費(fèi)的時(shí)間超過了這個(gè)值,進(jìn)程會(huì)強(qiáng)制關(guān)閉和回收。

驅(qū)逐過程結(jié)束后, 新的Envoy進(jìn)程告訴舊的Envoy進(jìn)程關(guān)閉自己。參數(shù) --parent-shutdown-time-s 用來配置關(guān)閉自己的超時(shí)時(shí)間。

Envoy 的熱重啟的設(shè)計(jì)支持新老進(jìn)程同時(shí)存在時(shí)也能正常工作。新舊進(jìn)程之間的通信只能是通過unix domain socket。

5、Envoy 部署方式

這一塊是大家關(guān)注的重點(diǎn),也就是應(yīng)用程序如何與 Envoy 結(jié)合來使用的、請(qǐng)求是如何轉(zhuǎn)到 Envoy 的等等。

根據(jù)不同的使用場(chǎng)景,Envoy有不同的部署方式。

Service to service only

這是最簡(jiǎn)單的部署和使用方式,在這種方式中 Envoy 作為內(nèi)部與外部服務(wù)通信的總線。Envoy 啟動(dòng)多個(gè) listeners 用于本地流量轉(zhuǎn)發(fā)和服務(wù)與服務(wù)之間的流量轉(zhuǎn)發(fā)。

上圖展示了最簡(jiǎn)單的 Envoy 部署方式。在這種部署方式中 Envoy 承擔(dān)的是SOA服務(wù)內(nèi)部流量的消息總線角色。在這種場(chǎng)景中, Envoy 會(huì)暴露一些 listeners 用于本地流量或者本地服務(wù)與遠(yuǎn)端服務(wù)之間流量的轉(zhuǎn)發(fā)。

listener 類型:

Service to service egress listener

本地服務(wù)到遠(yuǎn)端服務(wù)的出口 listener。該類型 listener 會(huì)監(jiān)聽在某個(gè)指定的端口上,所有內(nèi)部應(yīng)用出去的請(qǐng)求都重定向到該端口上,由該 listener 處理并轉(zhuǎn)發(fā)到目的服務(wù)集群節(jié)點(diǎn)。

例如:http://localhost:9001?或 tcp://localhost:9001。 HTTP 和 gRPC 類型請(qǐng)求使用 host header,HTTP/2使用 authority header 來指定訪問的遠(yuǎn)端服務(wù)集群。 在數(shù)據(jù)流經(jīng) Envoy 過程中會(huì)進(jìn)行服務(wù)發(fā)現(xiàn)、負(fù)載均衡、限速等處理。

本地 Services 只需要知道本地的Envoy,無需關(guān)心它們自己所處的網(wǎng)絡(luò)拓?fù)浼碍h(huán)境。

Service to service ingress listener

本地服務(wù)到遠(yuǎn)端服務(wù)的入口 listener。該 listener 提供遠(yuǎn)端 Envoy 調(diào)用本地 Envoy 的端口。

例如:http://localhost:9211。?進(jìn)入本地 Envoy 的請(qǐng)求都被路由/重定向到本地 service 的監(jiān)聽端口。根據(jù)需要,本地的Envoy 會(huì)進(jìn)行一些緩存、斷路檢查等處理。

Optional external service egress listeners

有時(shí),需要訪問外部的服務(wù),此時(shí)需要提供一個(gè)端口提供訪問。因?yàn)椋行┩獠糠?wù)SDK不支持host header的重寫來支持標(biāo)準(zhǔn)的HTTP反向代理行為。

例如:http://localhost:9250?might be allocated for connections destined for DynamoDB.我們建議為所有外部服務(wù)使用本地端口路由,而不是使用主機(jī)路由和專用本地端口路由

Discovery service integration

集成外部服務(wù)發(fā)現(xiàn)組件來提供服務(wù)到服務(wù)的發(fā)現(xiàn)功能。

service to service 模式配置模板

(https://github.com/envoyproxy/envoy/blob/master/configs/envoy_service_to_service.template.json)

Service to service plus front proxy

上圖展示了在 service to service 模式前增加 Envoy 集群作為7層反向代理的部署模式。

該部署模式有以下特點(diǎn):

TLS 卸載

同時(shí)支持 HTTP/1.1 和 HTTP/2

完整的 HTTP 7層路由支持

前端的 Envoy 代理集群使用標(biāo)準(zhǔn)的 ingress 端口與后端的 service to service 集群通信。對(duì)于后端服務(wù)集群節(jié)點(diǎn)使用服務(wù)發(fā)現(xiàn)方式獲取。前端的 Envoy 集群節(jié)點(diǎn)是完全對(duì)等的提供服務(wù),沒有任何差異。

這種方式和 service to service 方式相比多出了 前端七層代理的部分。可以適配更多的使用場(chǎng)景。

Service to service plus front proxy 配置模板

(https://github.com/envoyproxy/envoy/blob/master/configs/envoy_front_proxy.template.json)

Service to service, front proxy, and double proxy

雙代理模式

雙代理模式的設(shè)計(jì)理念是: 更加高效的卸載TLS、更快速的與client端建立連接(更短的TLS握手時(shí)間,更快的TCP擁塞窗口調(diào)整,更少的丟包等等)。 這些在雙代理上卸載TLS后的連接最終都會(huì)復(fù)用 已經(jīng)與數(shù)據(jù)中心完成連接建立的 HTTP/2 連接。

Service to service, front proxy, and double proxy 配置模板

(https://github.com/envoyproxy/envoy/blob/master/configs/envoy_double_proxy.template.json)

總結(jié)

以上就是ServiceMesh 數(shù)據(jù)面板 Envoy

的基本介紹。如果大家對(duì) Istio 感興趣,可以之后自行瀏覽 Istio 的官方網(wǎng)站,我也預(yù)期會(huì)在之后閱讀其源碼,更深入的了解 Envoy 工作原理,并會(huì)陸續(xù)給出Istio相關(guān)的文章和分享。

---------------------

原文:https://blog.csdn.net/ZVAyIVqt0UFji/article/details/78351355

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。