前面我們和大家學(xué)習(xí)了 Envoy 的基礎(chǔ)知識,使用靜態(tài)配置來認(rèn)識了 Envoy,但實際上 Envoy 的閃光點在于其動態(tài)配置,動態(tài)配置主要有基于文件和 API 兩種方式。
Envoy 除了支持靜態(tài)配置之外,還支持動態(tài)配置,而且動態(tài)配置也是 Envoy 重點關(guān)注的功能,本節(jié)我們將學(xué)習(xí)如何將 Envoy 靜態(tài)配置轉(zhuǎn)換為動態(tài)配置,從而允許 Envoy 自動更新。
前面的章節(jié)中,我們都是直接使用的靜態(tài)配置,但是當(dāng)我們需要更改配置的時候就比較麻煩了,需要重啟 Envoy 代理才會生效。要解決這個問題,我們可以將靜態(tài)配置更改成動態(tài)配置,當(dāng)我們使用動態(tài)配置的時候,更改了配置,Envoy 將會自動去重新加載配置。
Envoy 支持不同的模塊進行動態(tài)配置,可配置的有如下幾個 API(統(tǒng)稱為 xDS):
動態(tài)資源,是指由 Envoy 通過 xDS 協(xié)議發(fā)現(xiàn)所需要的各項配置的機制,相關(guān)的配置信息保存于稱之為管理服務(wù)器(Management Server )的主機上,經(jīng)由 xDS API 向外暴露;下面是一個純動態(tài)資源的基礎(chǔ)配置框架。
{ "lds_config": "{...}", "cds_config": "{...}", "ads_config": "{...}"}
xDS API 為 Envoy 提供了資源的動態(tài)配置機制,它也被稱為 Data Plane API。
xDS API
Envoy 支持三種類型的配置信息的動態(tài)發(fā)現(xiàn)機制,相關(guān)的發(fā)現(xiàn)服務(wù)及其相應(yīng)的 API 聯(lián)合起來 稱為 xDS API。
gRPC 服務(wù):啟動 gRPC 流。
v3 版本的 xDS 支持如下幾種資源類型:
Envoy 對 xDS API 的管理由后端服務(wù)器實現(xiàn),包括 LDS、CDS、RDS、SRDS(Scoped Route)、VHDS (Virtual Host)、EDS、SDS、RTDS(Runtime )等。
接下來我們先更改配置來使用 EDS,讓 Envoy 根據(jù)配置文件的數(shù)據(jù)來動態(tài)添加節(jié)點。
首先我們這里定義了一個基本的 Envoy 配置文件,如下所示:
# envoy.yamladmin: access_log_path: /tmp/admin_access.log address: socket_address: address: 0.0.0.0 port_value: 9901static_resources: listeners: - name: listener_0 # 監(jiān)聽器的名稱 address: socket_address: address: 0.0.0.0 # 監(jiān)聽器的地址 port_value: 10000 # 監(jiān)聽器的端口 filter_chains: - filters: - name: envoy.filterswork.http_connection_manager typed_config: "@type": type.googleapis.com/envoy.extensions.filterswork.http_connection_manager.v3.HttpConnectionManager stat_prefix: ingress_http access_log: - name: envoy.access_loggers.stdout typed_config: "@type": type.googleapis.com/envoy.extensions.access_loggers.stream.v3.StdoutAccessLog http_filters: # 定義http過濾器鏈 - name: envoy.filters.http.router # 調(diào)用7層的路由過濾器 typed_config: "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router route_config: name: local_route virtual_hosts: - name: backend domains: ["*"] routes: - match: prefix: "/" route: cluster: targetCluster
現(xiàn)在我們還沒有配置 clusters 集群部分,這是因為我們要通過使用 EDS 來進行自動發(fā)現(xiàn)。
首先我們需要添加一個 node 節(jié)點讓 Envoy 來識別并應(yīng)用這一個唯一的配置,動態(tài)配置中 Envoy 實例需要有唯一的 id 標(biāo)識。將下面的配置放置在配置文件的頂部區(qū)域:
node: id: envoy_eds_id cluster: youdianzhishi_cluster
除了 id 和 cluster 之外,我們還可以配置基于區(qū)域的一些位置信息來進行聲明,比如 region、zone、sub_zone 等。
端點發(fā)現(xiàn)服務(wù) EDS 是基于 gRPC 或 REST-JSON API 服務(wù)器的 xDS 管理服務(wù)器,Envoy 使用它來獲取集群成員。集群成員在 Envoy 術(shù)語中稱為“端點”。對于每個集群,Envoy 從發(fā)現(xiàn)服務(wù)獲取端點,EDS 是首選的服務(wù)發(fā)現(xiàn)機制:
接下來我們就可以來定義 EDS 配置了,可以來動態(tài)控制上游集群數(shù)據(jù)。在前面這部分的靜態(tài)配置是這樣的:
clusters: - name: targetCluster connect_timeout: 0.25s type: STRICT_DNS dns_lookup_family: V4_ONLY lb_policy: ROUND_ROBIN load_assignment: cluster_name: targetCluster endpoints: - lb_endpoints: - endpoint: address: socket_address: address: 192.168.215.3 port_value: 80 - endpoint: address: socket_address: address: 192.168.215.4 port_value: 80
現(xiàn)在我們將上面的靜態(tài)配置轉(zhuǎn)換成動態(tài)配置,首先需要轉(zhuǎn)換為基于 EDS 的 eds_cluster_config 屬性,并將類型更改為 EDS,將下面的集群配置添加到 Envoy 配置的末尾:
clusters: - name: targetCluster connect_timeout: 0.25s lb_policy: ROUND_ROBIN type: EDS eds_cluster_config: service_name: localservices # 可選,代替集群的名稱,提供給 EDS 服務(wù) eds_config: # 集群的 EDS 更新源配置 path_config_source: # 本地文件配置源 path: "/etc/envoy/eds.yaml" # watched_directory: # 可選,監(jiān)視目錄中的文件更改 # path: "/etc/envoy"
在上面的集群配置中我們設(shè)置了 type: EDS,表示這是一個基于 EDS 的集群配置,然后使用 eds_cluster_config 屬性來定義 EDS 的配置信息,其中 service_name 屬性是可選的,如果沒有設(shè)置則使用集群的名稱,這個屬性是提供給 EDS 服務(wù)的,eds_config 屬性定義了 EDS 更新源的配置,這里我們使用的是本地文件配置源,所以使用 path_config_source 屬性來指定本地配置文件的路徑,這里我們使用的是 /etc/envoy/eds.yaml 這個文件,這個文件將會被 Envoy 代理監(jiān)視,當(dāng)文件內(nèi)容發(fā)生變化的時候,Envoy 將會自動更新配置。
此外還可以配置一個 watched_directory 屬性來監(jiān)視目錄中的文件更改,當(dāng)該目錄中的文件被移動到時,該路徑將被重新加載。這在某些部署場景中是必需的。比如如果我們使用 Kubernetes ConfigMap 來加載 xDS 資源,則可能會使用以下配置:
上述配置將確保 Envoy 監(jiān)視所屬目錄的移動,這是由于 Kubernetes 在原子更新期間管理 ConfigMap 符號鏈接的方式而必需的。
上游的服務(wù)器 192.168.215.3 和 192.168.215.3 就將來自于 /etc/envoy/eds.yaml 這個文件,我們創(chuàng)建一個如下所示的 eds.yaml 文件,內(nèi)容如下所示:
resources: - "@type": type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment cluster_name: localservices # 集群的名稱,如果在集群 eds_cluster_config 中指定,這將是 service_name 值。 endpoints: - lb_endpoints: - endpoint: address: socket_address: address: 192.168.215.3 port_value: 80
上面我們暫時只定義了 192.168.215.3 這一個端點。該配置文件是以 DiscoveryResponse 的格式提供響應(yīng)實例的。
現(xiàn)在配置完成后,我們可以啟動 Envoy 代理來進行測試。執(zhí)行下面的命令啟動 Envoy 容器:
$ docker run --name=proxy-eds -d / -p 9901:9901 / -p 80:10000 / -v $(pwd)/manifests/3.Envoy:/etc/envoy / envoyproxy/envoy:v1.28.0
然后同樣和前面一樣運行兩個 HTTP 服務(wù)來作為上游服務(wù)器:
$ docker run -d cnych/docker-http-server; docker run -d cnych/docker-http-server;$ docker psCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES4ee790db09db cnych/docker-http-server "/app" 3 seconds ago Up 3 seconds 80/tcp fervent_khoranaf9456b56f1ff cnych/docker-http-server "/app" 4 seconds ago Up 3 seconds 80/tcp wonderful_carsonf9ce95dcc434 envoyproxy/envoy:v1.28.0 "/docker-entrypoint.…" About a minute ago Up 44 seconds 0.0.0.0:9901->9901/tcp, :::9901->9901/tcp, 0.0.0.0:80->10000/tcp, :::80->10000/tcp proxy-eds
根據(jù)上面的 EDS 配置,Envoy 將把所有的流量都發(fā)送到 192.168.215.3 這一個節(jié)點上去,我們可以使用 curl localhost 來測試下:
$ curl localhost<h1>This request was processed by host: f9456b56f1ff</h1>$ curl localhost<h1>This request was processed by host: f9456b56f1ff</h1>
可以看到可以正常得到響應(yīng),而且都是由 f9456b56f1ff 這個容器來處理的請求。現(xiàn)在我們來嘗試更新上面的 EDS 配置添加上另外的一個節(jié)點,觀察 Envoy 代理是否會自動生效。
由于我們這里使用的是 EDS 動態(tài)配置,所以當(dāng)我們要擴展上游服務(wù)的時候,只需要將新的端點添加到上面我們指定的 eds.yaml 配置文件中即可,然后 Envoy 就會自動將新添加的端點包含進來。用上面同樣的方式添加 192.168.215.4 這個端點,eds.yaml 內(nèi)容如下所示:
resources: - "@type": type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment cluster_name: localservices # 集群的名稱,如果在集群 eds_cluster_config 中指定,這將是 service_name 值。 endpoints: - lb_endpoints: - endpoint: address: socket_address: address: 192.168.215.3 port_value: 80 - endpoint: address: socket_address: address: 192.168.215.4 port_value: 80
更新后,正常情況下 Envoy 就會自動重新加載配置并將新的端點添加到負載均衡中去,這個時候我們再來訪問代理:
$ curl localhost<h1>This request was processed by host: 2135ba4e10c9</h1>$ curl localhost<h1>This request was processed by host: f9456b56f1ff</h1>
可以看到已經(jīng)可以自動訪問到另外的端點去了。
我在測試階段發(fā)現(xiàn)在 Mac 系統(tǒng)下面并沒有自動熱加載,在 Linux 系統(tǒng)下面是可以正常重新加載的。
現(xiàn)在已經(jīng)配置好了 EDS,接下來我們就可以去擴大上游集群的規(guī)模了,如果我們想要能夠動態(tài)添加新的域名和集群,就需要實現(xiàn)集群發(fā)現(xiàn)服務(wù)(CDS)API,在下面的示例中,我們將配置集群發(fā)現(xiàn)服務(wù)(CDS)和監(jiān)聽器發(fā)現(xiàn)服務(wù)(LDS)來進行動態(tài)配置。
創(chuàng)建一個名為 cds.yaml 的文件來配置集群服務(wù)發(fā)現(xiàn)的數(shù)據(jù),文件內(nèi)容如下所示:
resources: - "@type": type.googleapis.com/envoy.config.cluster.v3.Cluster name: targetCluster connect_timeout: 0.25s lb_policy: ROUND_ROBIN type: EDS eds_cluster_config: service_name: localservices eds_config: path: /etc/envoy/eds.yaml
此外,還需要創(chuàng)建一個名為 lds.yaml 的文件來放置監(jiān)聽器的配置,文件內(nèi)容如下所示:
resources: - "@type": type.googleapis.com/envoy.config.listener.v3.Listener name: listener_0 # 監(jiān)聽器的名稱 address: socket_address: address: 0.0.0.0 # 監(jiān)聽器的地址 port_value: 10000 # 監(jiān)聽器的端口 filter_chains: - filters: - name: envoy.filterswork.http_connection_manager typed_config: "@type": type.googleapis.com/envoy.extensions.filterswork.http_connection_manager.v3.HttpConnectionManager stat_prefix: ingress_http access_log: - name: envoy.access_loggers.stdout typed_config: "@type": type.googleapis.com/envoy.extensions.access_loggers.stream.v3.StdoutAccessLog http_filters: # 定義http過濾器鏈 - name: envoy.filters.http.router # 調(diào)用7層的路由過濾器 typed_config: "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router route_config: name: local_route virtual_hosts: - name: backend domains: ["*"] routes: - match: prefix: "/" route: cluster: targetCluster
仔細觀察可以發(fā)現(xiàn) cds.yaml 和 lds.yaml 配置文件的內(nèi)容基本上和之前的靜態(tài)配置文件一致的。我們這里只是將集群和監(jiān)聽器拆分到外部文件中去,這個時候我們需要修改 Envoy 的配置來引用這些文件,我們可以通過將 static_resources 更改為 dynamic_resources 來進行配置。
重新新建一個 Envoy 配置文件,命名為 envoy-dynamic.yaml,內(nèi)容如下所示:
# envoy-dynamic.yamlnode: id: envoy_eds_id cluster: youdianzhishi_clusteradmin: access_log_path: "/dev/null" address: socket_address: address: 0.0.0.0 port_value: 9901dynamic_resources: # 動態(tài)配置 lds_config: path: "/etc/envoy/lds.yaml" cds_config: path: "/etc/envoy/cds.yaml"
然后使用上面的配置文件重新啟動一個新的 Envoy 代理,命令如下所示:
$ docker run --name=proxy-xds -d / -p 9901:9901 / -p 80:10000 / -v $(pwd)/manifests/3.Envoy:/etc/envoy / -v $(pwd)/manifests/3.Envoy/envoy-dynamic.yaml:/etc/envoy/envoy.yaml / envoyproxy/envoy:v1.28.0
啟動完成后,同樣可以訪問 Envoy 代理來測試是否生效了:
$ curl localhostcurl localhost<h1>This request was processed by host: 4ee790db09db</h1>$ curl localhost<h1>This request was processed by host: f9456b56f1ff</h1>
現(xiàn)在我們再基于上面配置的 CDS、LDS、EDS 的配置來動態(tài)添加一個新的集群。比如添加一個名為 newTargetCluster 的集群,內(nèi)容如下所示:
# cds.yamlresources: - "@type": type.googleapis.com/envoy.config.cluster.v3.Cluster name: targetCluster connect_timeout: 0.25s lb_policy: ROUND_ROBIN type: EDS eds_cluster_config: service_name: localservices eds_config: path: /etc/envoy/eds.yaml - "@type": type.googleapis.com/envoy.config.cluster.v3.Cluster name: newTargetCluster connect_timeout: 0.25s lb_policy: ROUND_ROBIN type: EDS eds_cluster_config: service_name: localservices eds_config: path: /etc/envoy/eds-1.yaml
上面我們新增了一個新的集群,對應(yīng)的 eds_config 配置文件是 eds-1.yaml,所以我們同樣需要去創(chuàng)建該文件去配置新的端點服務(wù)數(shù)據(jù),內(nèi)容如下所示:
resources: - "@type": type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment cluster_name: localservices # 集群的名稱,如果在集群 eds_cluster_config 中指定,這將是 service_name 值。 endpoints: - lb_endpoints: - endpoint: address: socket_address: address: 192.168.215.5 port_value: 80 - endpoint: address: socket_address: address: 192.168.215.6 port_value: 80
這個時候新的集群添加上了,但是還沒有任何路由來使用這個新集群,我們可以在 lds.yaml 中去配置,將之前配置的 targetCluster 替換成 newTargetCluster。
當(dāng)然同樣我們這里還需要運行兩個簡單的 HTTP 服務(wù)來作為上游服務(wù)提供服務(wù),執(zhí)行如下所示的命令:
$ docker run -d cnych/docker-http-server; docker run -d cnych/docker-http-server;
這個時候 Envoy 應(yīng)該就會自動重新加載并添加新的集群,我們同樣可以執(zhí)行 curl localhost 命令來驗證:
$ curl localhost<h1>This request was processed by host: 5f43efcb9432</h1>$ curl localhost<h1>This request was processed by host: 4986b39d716f</h1>
可以看到已經(jīng)變成了新的兩個端點數(shù)據(jù)了,證明我們這里基于文件的 xDS 動態(tài)配置已經(jīng)生效了。
當(dāng)在 Envoy 配置中定義了上游集群后,Envoy 需要知道如何解析集群成員,這就是服務(wù)發(fā)現(xiàn)。端點發(fā)現(xiàn)服務(wù)(EDS)是 Envoy 基于 gRPC 或者用來獲取集群成員的 REST-JSON API 服務(wù)的 xDS 管理服務(wù)。在本節(jié)我們將學(xué)習(xí)如何使用 REST-JSON API 來配置端點的自動發(fā)現(xiàn)。
在前面的章節(jié)中,我們使用文件來定義了靜態(tài)和動態(tài)配置,在這里我們將介紹另外一種方式來進行動態(tài)配置:API 動態(tài)配置。
Envoy 項目在 Java 和 Golang 中都提供了 EDS 和其他服務(wù)發(fā)現(xiàn)的 gRPC 實現(xiàn)參考。
接下來我們將更改配置來使用 EDS,從而允許基于來自 REST-JSON API 服務(wù)的數(shù)據(jù)進行動態(tài)添加節(jié)點。
下面是提供的一個 Envoy 配置的初始配置 envoy.yaml,文件內(nèi)容如下所示:
# envoy.yamladmin: access_log_path: /tmp/admin_access.log address: socket_address: address: 0.0.0.0 port_value: 9901static_resources: listeners: - name: listener_0 # 監(jiān)聽器的名稱 address: socket_address: address: 0.0.0.0 # 監(jiān)聽器的地址 port_value: 10000 # 監(jiān)聽器的端口 filter_chains: - filters: - name: envoy.filterswork.http_connection_manager typed_config: "@type": type.googleapis.com/envoy.extensions.filterswork.http_connection_manager.v3.HttpConnectionManager stat_prefix: ingress_http access_log: - name: envoy.access_loggers.stdout typed_config: "@type": type.googleapis.com/envoy.extensions.access_loggers.stream.v3.StdoutAccessLog http_filters: # 定義http過濾器鏈 - name: envoy.filters.http.router # 調(diào)用7層的路由過濾器 typed_config: "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router route_config: name: local_route virtual_hosts: - name: backend domains: ["*"] routes: - match: prefix: "/" route: cluster: targetCluster
接下來需要添加一個 EDS 類型的集群配置,并在 eds_config 中配置使用 REST API:
clusters: - name: targetCluster type: EDS connect_timeout: 0.25s eds_cluster_config: service_name: myservice eds_config: resource_api_version: V3 # xDS資源的API版本,支持 AUTO、V2、V3,如果未指定,默認(rèn)為 v2。 api_config_source: # api_config_source的數(shù)據(jù)來自于 xDS API Server,即 Management Server。 api_type: REST cluster_names: [xds_cluster] # 該字段只用于REST,cluster_names 的集群必須是靜態(tài)定義的,其類型不能是EDS。 transport_api_version: V3 refresh_delay: 5s
上面配置中我們使用 api_config_source 來使用 REST API 的配置,其中 api_type 屬性指定了使用 REST API,cluster_names 屬性指定了使用 xds_cluster 這個集群來獲取數(shù)據(jù),refresh_delay 屬性指定了刷新間隔時間,這里我們設(shè)置為 5 秒。
然后需要定義 xds_cluster 的解析方式,這里我們可以使用靜態(tài)配置:
- name: xds_cluster type: STATIC connect_timeout: 0.25s load_assignment: cluster_name: xds_cluster endpoints: - lb_endpoints: - endpoint: address: socket_address: address: 192.168.0.112 port_value: 8080
然后同樣啟動一個 Envoy 代理實例來進行測試:
$ docker run --name=api-eds -d / -p 9901:9901 / -p 80:10000 / -v $(pwd)/manifests/4.Envoy:/etc/envoy / envoyproxy/envoy:v1.28.0
然后啟動一個如下所示的上游端點服務(wù):
$ docker run -p 8081:8081 -d -e EDS_SERVER_PORT='8081' cnych/docker-http-server:v4
啟動完成后我們可以使用如下命令來測試上游的端點服務(wù):
$ curl http://localhost:8081 -iHTTP/1.0 200 OKContent-Type: text/html; charset=utf-8Content-Length: 36Server: Werkzeug/0.15.4 Python/2.7.16Date: Fri, 27 Oct 2023 06:58:29 GMT4caf19d5-6765-470b-a95c-a3615aea9796
現(xiàn)在我們啟動了 Envoy 代理和上游的服務(wù)集群,但是由于我們這里啟動的服務(wù)并不是 xds_cluster 中配置的服務(wù),所以還沒有連接它們。這個時候我們?nèi)ゲ榭?Envoy 代理得日志,可以看到如下所示的一些錯誤:
$ docker logs -f api-eds[2023-10-27 08:43:48.964][1][warning][config] [source/extensions/config_subscription/rest/http_subscription_impl.cc:120] REST update for /v3/discovery:endpoints failed......
為了讓 Envoy 獲取端點服務(wù),我們需要啟動 xds_cluster,我們這里將使用 python 實現(xiàn)的一個 REST-JSON 的管理服務(wù),代碼如下所示:
# server.pyfrom flask import Flask, request, jsonifyimport uuidapp = Flask(__name__)# 存儲 endpoints 的數(shù)據(jù)庫endpoints_db = {}@app.route('/endpoints', methods=['POST'])def add_endpoint(): data = request.get_json() endpoint_id = str(uuid.uuid4()) endpoints_db[endpoint_id] = data return jsonify({"id": endpoint_id}), 201@app.route('/v3/discovery:endpoints', methods=['POST'])def discovery_endpoints(): xds_response = { # 構(gòu)造 xDS v3 EDS 響應(yīng)格式 "version_info": "0", "resources": [ {"@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", "cluster_name": "myservice", "endpoints": [{"lb_endpoints": [{"endpoint": {"address": {"socket_address": endpoint}}} for endpoint in endpoints_db.values()]}] } ], "type_url": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", "nonce": "0" } return jsonify(xds_response)if __name__ == '__main__': app.run(host="0.0.0.0", port=8080, debug=True)
上面的代碼中我們使用 Flask 實現(xiàn)了一個 /v3/discovery:endpoints 的 POST 接口,這個是 Envoy 用來請求發(fā)現(xiàn) Endpoints 端點的接口,需要注意的是該接口必須返回 DiscoveryResponse 協(xié)議格式的數(shù)據(jù),我們這里就是組裝一個 ClusterLoadAssignment。
我們這里直接在本地啟動(當(dāng)然也可以打包成 Docker 鏡像在容器中啟動):
$ python server.py * Serving Flask app 'server' * Debug mode: onWARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead. * Running on all addresses (0.0.0.0) * Running on http://127.0.0.1:8080 * Running on http://192.168.0.112:8080Press CTRL+C to quit * Restarting with stat * Debugger is active! * Debugger PIN: 131-555-179
要注意前面配置的 xds_cluster 的地址和端口要和上面的服務(wù)一致,并要能夠訪問到。
然后我們就可以將上游的服務(wù)配置添加到 EDS 服務(wù)中去了,這樣可以讓 Envoy 來自動發(fā)現(xiàn)上游服務(wù)。上面的管理服務(wù)中我們定義了一個 /endpoints 的添加端點的接口,我們只需要將要添加的端點提交給這個接口即可,然后在發(fā)現(xiàn)接口里面會自動獲取添加的端點,然后 Envoy 就可以動態(tài)感知到了。
$ curl --location --request POST 'http://localhost:8080/endpoints' /--header 'Content-Type: application/json' /--data-raw '{ "address": "192.168.215.7", "port_value": 8081}'
由于我們已經(jīng)啟動了上面注冊的上游服務(wù),所以現(xiàn)在我們可以通過 Envoy 代理訪問到它了:
$ curl -i http://localhostHTTP/1.1 200 OKcontent-type: text/html; charset=utf-8content-length: 36server: envoydate: Fri, 27 Oct 2023 09:02:07 GMTx-envoy-upstream-service-time: 84caf19d5-6765-470b-a95c-a3615aea9796
接下來我們在上游集群中運行更多的節(jié)點,并調(diào)用 API 來進行動態(tài)注冊,使用如下所示的命令來向上游集群再添加 4 個節(jié)點:
for i in 8082 8083 8084 8085 do docker run -d -e EDS_SERVER_PORT=$i cnych/docker-http-server:v4; sleep .5done
然后將上面的 4 個節(jié)點注冊到 EDS 服務(wù)上面去,同樣使用如下所示的 API 接口調(diào)用:
$ curl --location --request POST 'http://localhost:8080/endpoints' /--header 'Content-Type: application/json' /--data-raw '{ "address": "192.168.215.8", "port_value": 8082}'$ curl --location --request POST 'http://localhost:8080/endpoints' /--header 'Content-Type: application/json' /--data-raw '{ "address": "192.168.215.9", "port_value": 8083}'$ curl --location --request POST 'http://localhost:8080/endpoints' /--header 'Content-Type: application/json' /--data-raw '{ "address": "192.168.215.10", "port_value": 8084}'$ curl --location --request POST 'http://localhost:8080/endpoints' /--header 'Content-Type: application/json' /--data-raw '{ "address": "192.168.215.11", "port_value": 8085}'
注冊成功后,我們可以通過如下所示的命令來驗證網(wǎng)絡(luò)請求是否與注冊的節(jié)點之間是均衡的:
$ while true; do curl http://localhost; sleep .5; printf '/n'; done2a73139d-5929-4224-a227-a1aa560162df4caf19d5-6765-470b-a95c-a3615aea97964395d85c-a216-46e4-bed7-04cc122c19039a22d774-62aa-47cc-bc35-c592015e55804caf19d5-6765-470b-a95c-a3615aea97962a73139d-5929-4224-a227-a1aa560162df......
根據(jù)上面的輸出結(jié)果可以看到每次請求的服務(wù)是不同的響應(yīng),我們一共注冊了 5 個端點服務(wù)。
到這里我們就實現(xiàn)了基于 REST-JSON 方式的 EDS 動態(tài)配置了,當(dāng)然在實際使用的時候,更多的時候會使用 gRPC 的方式來實現(xiàn)管理服務(wù),這樣可以實現(xiàn)流式的數(shù)據(jù)傳輸,更加高效,可以查看官方提供的 go-control-plane 示例了解如何實現(xiàn)(https://github.com/envoyproxy/go-control-plane/blob/main/internal/example/server.go)。
gRPC xDS 服務(wù)相比 REST-JSON xDS 服務(wù),通常更為復(fù)雜一些,因為 gRPC 是基于 HTTP/2 的,并且使用 Protocol Buffers 作為序列化協(xié)議。
首先我們需要定義一個 gRPC 服務(wù)來實現(xiàn) xDS API。可以從 Envoy 的 data-plane-api(https://github.com/envoyproxy/data-plane-api/blob/main/envoy/service/endpoint/v3/eds.proto) 獲取 .proto 文件,然后可以使用 protoc 編譯器生成 Python 代碼,然后就可以去實現(xiàn)具體的業(yè)務(wù)邏輯了,比如 istio 就類似這種方式。
本文鏈接:http://www.tebozhan.com/showinfo-26-15747-0.htmlEnvoy 基于文件和 API 的動態(tài)配置方式
聲明:本網(wǎng)頁內(nèi)容旨在傳播知識,若有侵權(quán)等問題請及時與本網(wǎng)聯(lián)系,我們將在第一時間刪除處理。郵件:2376512515@qq.com
下一篇: Spring事務(wù)的傳播機制