Wasm C++ 篩選器

此沙箱示範了一個基本的 C++ 編寫的 Envoy Wasm 篩選器,該篩選器將內容注入到 HTTP 回應的主體中,並新增和更新一些標頭。

它還將引導您完成建置自己的 C++ Wasm 篩選器,並使用 Envoy 執行它的步驟。

步驟 1:啟動所有容器

首先,讓我們啟動容器 - 一個使用 Wasm 篩選器的 Envoy 代理,以及一個回顯我們請求的後端。Envoy 組態公開了兩個監聽器,第一個監聽器在 8000 埠中,其中包含監聽器篩選器鏈中的 wasm 篩選器。第二個監聽器在 8001 埠中,路由到包含叢集篩選器鏈中 wasm 篩選器的叢集。

變更到 Envoy 儲存庫中的 examples/wasm-cc 資料夾,然後啟動組合

$ pwd
envoy/examples/wasm-cc
$ docker compose pull
$ docker compose up --build -d
$ docker compose ps

    Name                     Command                State             Ports
-----------------------------------------------------------------------------------------------
wasm_proxy_1         /docker-entrypoint.sh /usr ... Up      10000/tcp, 0.0.0.0:8000->8000/tcp, 0.0.0.0:8001->8001/tcp
wasm_web_service_1   node ./index.js                Up

步驟 2:檢查 Web 回應

當您向代理發出請求時,Wasm 篩選器應將「Hello, world」插入回應主體的末尾。

$ curl -s https://127.0.0.1:8000 | grep "Hello, world"
}Hello, world

篩選器也會將 content-type 標頭設定為 text/plain,並新增自訂 x-wasm-custom 標頭。

$ curl -v https://127.0.0.1:8000 | grep "content-type: "
content-type: text/plain; charset=utf-8

$ curl -v https://127.0.0.1:8000 | grep "x-wasm-custom: "
x-wasm-custom: FOO

在第二個監聽器中,也可以獲得類似的輸出,該監聽器會路由到具有上游 wasm 篩選器的叢集。

$ curl -s https://127.0.0.1:8001 | grep "Hello, world"
}Hello, world

$ curl -v https://127.0.0.1:8001 | grep "content-type: "
content-type: text/plain; charset=utf-8

$ curl -v https://127.0.0.1:8001 | grep "x-wasm-custom: "
x-wasm-custom: FOO

步驟 3:編譯更新後的篩選器

為 Wasm 篩選器提供了兩個原始碼檔案。

envoy_filter_http_wasm_example.cc 提供內含預先建置二進位檔案的原始碼。

envoy_filter_http_wasm_updated_example.cc 對原始檔案進行了一些變更。

以下差異顯示了已進行的變更

--- /tmp/tmpiw2hzbvp/generated/rst/start/sandboxes/_include/wasm-cc/envoy_filter_http_wasm_example.cc
+++ /tmp/tmpiw2hzbvp/generated/rst/start/sandboxes/_include/wasm-cc/envoy_filter_http_wasm_updated_example.cc
@@ -65,8 +65,8 @@
   for (auto& p : pairs) {
     LOG_INFO(std::string(p.first) + std::string(" -> ") + std::string(p.second));
   }
-  addResponseHeader("X-Wasm-custom", "FOO");
-  replaceResponseHeader("content-type", "text/plain; charset=utf-8");
+  addResponseHeader("X-Wasm-custom", "BAR");
+  replaceResponseHeader("content-type", "text/html; charset=utf-8");
   removeResponseHeader("content-length");
   return FilterHeadersStatus::Continue;
 }
@@ -78,9 +78,9 @@
   return FilterDataStatus::Continue;
 }
 
-FilterDataStatus ExampleContext::onResponseBody(size_t body_buffer_length,
+FilterDataStatus ExampleContext::onResponseBody(size_t /* body_buffer_length */,
                                                 bool /* end_of_stream */) {
-  setBuffer(WasmBufferType::HttpResponseBody, 0, body_buffer_length, "Hello, world\n");
+  setBuffer(WasmBufferType::HttpResponseBody, 0, 17, "Hello, Wasm world");
   return FilterDataStatus::Continue;
 }
 

警告

這些編譯更新後 Wasm 二進位檔案的說明使用 envoyproxy/envoy-build-ubuntu 映像檔。您將需要 4-5 GB 的磁碟空間來容納此映像檔。

從您的主機系統匯出 UID。這將確保在建置容器內建立的二進位檔案與您的主機使用者具有相同的權限

$ export UID

注意

建置組合的設計方式與 Envoy 儲存庫中的 ./ci/run_envoy_docker.sh 命令類似。

Bazel 暫時性成品是在 /tmp/envoy-docker-build 中使用從 UID 環境變數取得的 uid 建立的。

停止代理伺服器,然後使用更新後的程式碼編譯 Wasm 二進位檔案

$ docker compose stop proxy
$ docker compose -f docker-compose-wasm.yaml up --remove-orphans wasm_compile_update

編譯後的二進位檔案現在應該在 lib 資料夾中。

$ ls -l lib
total 120
-r-xr-xr-x 1 root root 59641 Oct 20 00:00 envoy_filter_http_wasm_example.wasm
-r-xr-xr-x 1 root root 59653 Oct 20 10:16 envoy_filter_http_wasm_updated_example.wasm

步驟 4:編輯 Dockerfile 並重新啟動代理

編輯範例中提供的 Dockerfile-proxy 配方,以使用您在步驟 3 中建立的更新後二進位檔案。

找到將 Wasm 二進位檔案新增到映像檔的 COPY

1FROM envoyproxy/envoy:dev
2COPY ./envoy.yaml /etc/envoy.yaml
3COPY ./lib/envoy_filter_http_wasm_example.wasm /lib/envoy_filter_http_wasm_example.wasm
4RUN chmod go+r /etc/envoy.yaml /lib/envoy_filter_http_wasm_example.wasm
5CMD ["/usr/local/bin/envoy", "-c", "/etc/envoy.yaml", "--service-cluster", "proxy"]

將此行替換為以下內容

COPY ./lib/envoy_filter_http_wasm_updated_example.wasm /lib/envoy_filter_http_wasm_example.wasm

現在,重建並啟動代理容器。

$ docker compose up --build -d proxy

步驟 5:檢查代理是否已更新

Wasm 篩選器應改為將「Hello, Wasm world」插入回應主體的末尾。

$ curl -s https://127.0.0.1:8000 | grep "Hello, Wasm world"
}Hello, Wasm world

content-typex-wasm-custom 標頭也應已變更

$ curl -v https://127.0.0.1:8000 | grep "content-type: "
content-type: text/html; charset=utf-8

$ curl -v https://127.0.0.1:8000 | grep "x-wasm-custom: "
x-wasm-custom: BAR

另請參閱

Envoy Wasm 篩選器

關於 Envoy Wasm 篩選器的更多資訊。

Envoy Wasm API (V3)

Envoy Wasm API - 第 3 版。

Proxy Wasm C++ SDK

代理的 WebAssembly (C++ SDK)