前端代理

為了讓您體驗 Envoy 作為前端代理的功能,我們發布了一個 docker compose 沙盒,它會部署一個前端 Envoy 和幾個服務(簡單的 aiohttp 應用程式),這些服務與正在執行的服務 Envoy 放置在一起。

這三個容器將部署在一個名為 envoymesh 的虛擬網路中。

您可以在下面看到一個圖形,顯示 docker compose 部署

../../_images/docker_compose_front_proxy.svg

所有傳入的請求都會透過前端 Envoy 進行路由,該 Envoy 充當位於 envoymesh 網路邊緣的反向代理。Docker compose 公開了連接埠 808084438001 (請參閱 docker-compose.yaml),分別處理對服務的 HTTPHTTPS 呼叫以及對 /admin 的請求。

此外,請注意,前端 Envoy 路由到服務容器的所有流量實際上都會路由到服務 Envoy(在 envoy.yaml 中設定的路由)。

反過來,服務 Envoy 會透過迴路位址將請求路由到 aiohttp 應用程式(在 service-envoy.yaml 中設定的路由)。此設定說明了與服務並置執行服務 Envoy 的優點:所有請求都由服務 Envoy 處理,並有效率地路由到您的服務。

步驟 1: 啟動所有容器

切換到 examples/front-proxy 目錄。

$ pwd
envoy/examples/front-proxy
$ docker compose pull
$ docker compose up --build -d
$ docker compose ps

          Name                         Command               State                                           Ports
---------------------------------------------------------------------------------------------------------------------------------------------------------
front-proxy_front-envoy_1   /docker-entrypoint.sh /bin ... Up           10000/tcp, 0.0.0.0:8080->8080/tcp, 0.0.0.0:8001->8001/tcp, 0.0.0.0:8443->8443/tcp
front-proxy_service1_1      python3 /code/service.py   ... Up (healthy)
front-proxy_service2_1      python3 /code/service.py   ... Up (healthy)

步驟 2: 測試 Envoy 的路由能力

您現在可以透過 front-envoy 將請求傳送到這兩個服務。

對於 service1

$ curl -v localhost:8080/service/1
*   Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 8080 (#0)
> GET /service/1 HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.64.1
> Accept: */*
>
< HTTP/1.1 200 OK
< content-type: text/html; charset=utf-8
< content-length: 92
< server: envoy
< date: Mon, 06 Jul 2020 06:20:00 GMT
< x-envoy-upstream-service-time: 2
<
Hello from behind Envoy (service 1)! hostname: 36418bc3c824 resolvedhostname: 192.168.160.4

對於 service2

$ curl -v localhost:8080/service/2
*   Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 8080 (#0)
> GET /service/2 HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.64.1
> Accept: */*
>
< HTTP/1.1 200 OK
< content-type: text/html; charset=utf-8
< content-length: 92
< server: envoy
< date: Mon, 06 Jul 2020 06:23:13 GMT
< x-envoy-upstream-service-time: 2
<
Hello from behind Envoy (service 2)! hostname: ea6165ee4fee resolvedhostname: 192.168.160.2

請注意,雖然每個請求都傳送到前端 Envoy,但都正確地路由到各自的應用程式。

我們也可以使用 HTTPS 來呼叫前端 Envoy 後面的服務。例如,呼叫 service1

$ curl https://127.0.0.1:8443/service/1 -k -v
*   Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 8443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
*   CAfile: /etc/ssl/cert.pem
  CApath: none
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-CHACHA20-POLY1305
* ALPN, server did not agree to a protocol
* Server certificate:
*  subject: CN=front-envoy
*  start date: Jul  5 15:18:44 2020 GMT
*  expire date: Jul  5 15:18:44 2021 GMT
*  issuer: CN=front-envoy
*  SSL certificate verify result: self signed certificate (18), continuing anyway.
> GET /service/1 HTTP/1.1
> Host: localhost:8443
> User-Agent: curl/7.64.1
> Accept: */*
>
< HTTP/1.1 200 OK
< content-type: text/html; charset=utf-8
< content-length: 92
< server: envoy
< date: Mon, 06 Jul 2020 06:17:14 GMT
< x-envoy-upstream-service-time: 3
<
Hello from behind Envoy (service 1)! hostname: 36418bc3c824 resolvedhostname: 192.168.160.4

步驟 3: 測試 Envoy 的負載平衡能力

現在,讓我們擴充 service1 節點,以展示 Envoy 的負載平衡能力

$ docker compose scale service1=3
Creating and starting example_service1_2 ... done
Creating and starting example_service1_3 ... done

現在,如果我們多次將請求傳送到 service1,前端 Envoy 將會透過循環方式對三個 service1 機器進行請求的負載平衡

$ curl -v localhost:8080/service/1
*   Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 8080 (#0)
> GET /service/1 HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.64.1
> Accept: */*
>
< HTTP/1.1 200 OK
< content-type: text/html; charset=utf-8
< content-length: 92
< server: envoy
< date: Mon, 06 Jul 2020 06:21:47 GMT
< x-envoy-upstream-service-time: 6
<
Hello from behind Envoy (service 1)! hostname: 3dc787578c23 resolvedhostname: 192.168.160.6

$ curl -v localhost:8080/service/1
*   Trying 192.168.99.100...
* Connected to 192.168.99.100 (192.168.99.100) port 8080 (#0)
> GET /service/1 HTTP/1.1
> Host: 192.168.99.100:8080
> User-Agent: curl/7.54.0
> Accept: */*
>
< HTTP/1.1 200 OK
< content-type: text/html; charset=utf-8
< content-length: 89
< x-envoy-upstream-service-time: 1
< server: envoy
< date: Fri, 26 Aug 2018 19:40:22 GMT
<
Hello from behind Envoy (service 1)! hostname: 3a93ece62129 resolvedhostname: 192.168.160.5

$ curl -v localhost:8080/service/1
*   Trying 192.168.99.100...
* Connected to 192.168.99.100 (192.168.99.100) port 8080 (#0)
> GET /service/1 HTTP/1.1
> Host: 192.168.99.100:8080
> User-Agent: curl/7.43.0
> Accept: */*
>
< HTTP/1.1 200 OK
< content-type: text/html; charset=utf-8
< content-length: 89
< x-envoy-upstream-service-time: 1
< server: envoy
< date: Fri, 26 Aug 2018 19:40:24 GMT
< x-envoy-protocol-version: HTTP/1.1
<
Hello from behind Envoy (service 1)! hostname: 36418bc3c824 resolvedhostname: 192.168.160.4

步驟 4: 進入容器並使用 curl 請求服務

除了從您的主機使用 curl 之外,您還可以進入容器本身並從內部 curl。若要進入容器,您可以使用 docker compose exec <container_name> /bin/bash。例如,我們可以進入 front-envoy 容器,並在本機 curl 請求服務

$ docker compose exec front-envoy /bin/bash
root@81288499f9d7:/# curl localhost:8080/service/1
Hello from behind Envoy (service 1)! hostname: 85ac151715c6 resolvedhostname: 172.19.0.3
root@81288499f9d7:/# curl localhost:8080/service/1
Hello from behind Envoy (service 1)! hostname: 20da22cfc955 resolvedhostname: 172.19.0.5
root@81288499f9d7:/# curl localhost:8080/service/1
Hello from behind Envoy (service 1)! hostname: f26027f1ce28 resolvedhostname: 172.19.0.6
root@81288499f9d7:/# curl localhost:8080/service/2
Hello from behind Envoy (service 2)! hostname: 92f4a3737bbc resolvedhostname: 172.19.0.2

步驟 5: 進入容器並使用 curl 請求管理介面

當 Envoy 執行時,它還會將一個 admin 連接到您所需的連接埠。

在範例組態中,管理介面會繫結至連接埠 8001

我們可以 curl 它來取得有用的資訊

  • /server_info 提供有關您正在執行之 Envoy 版本資訊。

  • /stats 提供有關 Envoy 伺服器的統計資訊。

在範例中,我們可以進入 front-envoy 容器來查詢管理介面

$ docker compose exec front-envoy /bin/bash
root@e654c2c83277:/# curl localhost:8001/server_info
{
  "version": "093e2ffe046313242144d0431f1bb5cf18d82544/1.15.0-dev/Clean/RELEASE/BoringSSL",
  "state": "LIVE",
  "hot_restart_version": "11.104",
  "command_line_options": {
    "base_id": "0",
    "use_dynamic_base_id": false,
    "base_id_path": "",
    "concurrency": 8,
    "config_path": "/etc/envoy.yaml",
    "config_yaml": "",
    "allow_unknown_static_fields": false,
    "reject_unknown_dynamic_fields": false,
    "ignore_unknown_dynamic_fields": false,
    "admin_address_path": "",
    "local_address_ip_version": "v4",
    "log_level": "info",
    "component_log_level": "",
    "log_format": "[%Y-%m-%d %T.%e][%t][%l][%n] [%g:%#] %v",
    "log_format_escaped": false,
    "log_path": "",
    "service_cluster": "front-proxy",
    "service_node": "",
    "service_zone": "",
    "drain_strategy": "Gradual",
    "mode": "Serve",
    "disable_hot_restart": false,
    "enable_mutex_tracing": false,
    "restart_epoch": 0,
    "cpuset_threads": false,
    "disabled_extensions": [],
    "bootstrap_version": 0,
    "hidden_envoy_deprecated_max_stats": "0",
    "hidden_envoy_deprecated_max_obj_name_len": "0",
    "file_flush_interval": "10s",
    "drain_time": "600s",
    "parent_shutdown_time": "900s"
  },
  "uptime_current_epoch": "188s",
  "uptime_all_epochs": "188s"
}
root@e654c2c83277:/# curl localhost:8001/stats
cluster.service1.external.upstream_rq_200: 7
...
cluster.service1.membership_change: 2
cluster.service1.membership_total: 3
...
cluster.service1.upstream_cx_http2_total: 3
...
cluster.service1.upstream_rq_total: 7
...
cluster.service2.external.upstream_rq_200: 2
...
cluster.service2.membership_change: 1
cluster.service2.membership_total: 1
...
cluster.service2.upstream_cx_http2_total: 1
...
cluster.service2.upstream_rq_total: 2
...

請注意,我們可以取得上游叢集成員數、他們所滿足的請求數、有關 http 輸入的資訊,以及其他大量的有用統計資訊。

另請參閱

Envoy 管理介面快速入門指南

Envoy 管理介面的快速入門指南。