WebSocket是基於RFC 6455標準,用於用戶端和伺服器端之間進行雙向通訊的協議。Istio Sidecar Proxy提供了開箱即用方式使用WebSocket協議,便於您使用WebSocket協議實現服務訪問。本文介紹如何在ASM中使用WebSocket over HTTP/1.1和HTTP/2協議訪問服務。
背景資訊
WebSocket與HTTP協議不同,WebSocket協議使用HTTP Upgrade標題來建立各方之間的串連。Istio無法識別WebSocket協議,但Istio Sidecar Proxy提供了開箱即用方式支援WebSocket協議。關於Istio支援WebSocket協議詳細介紹,請參見HTTP upgrades、HTTP connection manager和Protocol Selection。
您可以在ASM中使用WebSocket over HTTP/1.1和HTTP/2協議訪問服務,區別如下:
WebSocket over HTTP/1.1協議:一次請求和響應,建立一個串連,用完關閉串連。
WebSocket over HTTP/2協議:多個請求可同時在一個串連上並存執行,某個請求任務耗時嚴重,不會影響到其它串連的正常執行。
前提條件
已建立一個ASM執行個體,並已將ACK叢集添加到ASM執行個體中。具體操作,請參見建立ASM執行個體和添加叢集到ASM執行個體。
已為命名空間注入Sidecar ,具體操作,請參見配置Sidecar注入策略。本文以default命名空間為例。
已通過kubectl工具串連叢集。具體操作,請參見通過kubectl工具串連叢集。
部署WebSocket用戶端和服務端
部署WebSocket服務端。
說明本文使用WebSocket社區提供的Python庫中WebSocket服務端為例。如果您想修改WebSocket服務端的部署配置,請參見容器化應用程式。
使用以下內容,建立websockets-server.yaml。
apiVersion: v1 kind: Service metadata: name: websockets-server labels: app: websockets-server spec: type: ClusterIP ports: - port: 8080 targetPort: 80 name: http-websocket selector: app: websockets-server --- apiVersion: apps/v1 kind: Deployment metadata: name: websockets-server labels: app: websockets-server spec: selector: matchLabels: app: websockets-server template: metadata: labels: app: websockets-server spec: containers: - name: websockets-test image: registry.cn-beijing.aliyuncs.com/aliacs-app-catalog/istio-websockets-test:1.0 ports: - containerPort: 80
執行以下命令,在default命名空間下部署WebSocket服務端。
kubectl apply -f websockets-server.yaml -n default
部署WebSocket用戶端。
使用以下內容,建立websockets-client.yaml。
apiVersion: v1 kind: Service metadata: name: websockets-client labels: app: websockets-client spec: type: ClusterIP ports: - port: 8080 targetPort: 80 name: http-websockets-client selector: app: websockets-client --- apiVersion: apps/v1 kind: Deployment metadata: name: websockets-client-sleep labels: app: websockets-client spec: selector: matchLabels: app: websockets-client template: metadata: labels: app: websockets-client spec: containers: - name: websockets-client image: registry.cn-beijing.aliyuncs.com/aliacs-app-catalog/istio-websockets-client-test:1.0 command: ["sleep", "14d"]
在default命名空間下部署WebSocket用戶端。
kubectl apply -f websockets-client.yaml -n default
使用WebSocket over HTTP/1.1協議
使用WebSocket用戶端向服務端發送了多個請求,Sidecar Proxy日誌只會包含一個WebSocket串連的訪問日誌條目。 Envoy將WebSocket串連視為TCP位元組流,並且代理只能理解HTTP升級請求或響應,因此Envoy只會在串連關閉後建立該訪問日誌條目,並且也不會看到每個TCP請求的任何訊息。
任選以下方式,開啟Shell命令列視窗。
方式一:
登入Container Service管理主控台,在左側導覽列單擊叢集。
在叢集列表頁面,單擊目的地組群名稱,然後在左側導覽列,選擇
。在容器組頁面單擊websockets-client右側操作列下終端,單擊websockets-client。
方式二:
執行以下命令,開啟Shell命令列視窗。
kubectl exec -it -n <namespace> websockets-client-sleep... -c websockets-client -- sh
執行以下命令,訪問WebSocket服務端。
python3 -m websockets ws://websockets-server.default.svc.cluster.local:8080
預期輸出:
Connected to ws://websockets-server.default.svc.cluster.local:8080.
輸入hello和word,可以看到返回hello和word。
> hello < hello > world < world Connection closed: 1000 (OK).
查看Sidecar Proxy日誌。
查看WebSocket用戶端的Sidecar Proxy日誌。
在容器組頁面單擊WebSocket用戶端容器名稱。
單擊日誌頁簽,設定容器為istio-proxy。
可以看到日誌中包含使用WebSocket over HTTP/1.1協議記錄。
{...."upstream_host":"10.208.0.105:80","bytes_sent":23,"protocol":"HTTP/1.1",....}
查看WebSocket服務端的Sidecar Proxy日誌。
在容器組頁面單擊WebSocket服務端容器名稱。
單擊日誌頁簽,設定容器為istio-proxy。
可以看到日誌中包含使用WebSocket over HTTP/1.1協議記錄。
{...."downstream_local_address":"10.208.0.105:80","upstream_local_address":"127.0.**.**:53983","protocol":"HTTP/1.1",....}
使用WebSocket over HTTP/2協議
低於1.12版本的Istio使用WebSocket over HTTP/2協議,將不能正常串連到WebSocket伺服器端, 並返回503錯誤。
如果您已經為低於1.12版本的Istio設定HTTP/2升級,並發生報錯,您可以通過在目標規則中定義h2UpgradePolicy為DO_NOT_UPGRADE的方式,使低於1.12版本的Istio可以正常使用WebSocket over HTTP/1.1協議。
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
labels:
provider: asm
name: websockets-server
spec:
host: websockets-server
trafficPolicy:
connectionPool:
http:
h2UpgradePolicy: DO_NOT_UPGRADE
Istio 1.12或以上版本使用WebSocket over HTTP/2協議的操作如下:
建立目標規則。
登入ASM控制台。
在左側導覽列,選擇 。
在網格管理頁面,找到待配置的執行個體,單擊執行個體的名稱或在操作列中單擊管理。
在網格詳情頁面左側導覽列,選擇 ,然後在右側頁面,單擊使用YAML建立。
設定命名空間為default,複製以下內容到文字框中,然後單擊建立。
apiVersion: networking.istio.io/v1beta1 kind: DestinationRule metadata: labels: provider: asm name: websockets-server spec: host: websockets-server trafficPolicy: connectionPool: http: h2UpgradePolicy: UPGRADE
h2UpgradePolicy:設定為UPGRADE,表示為websockets-server啟用HTTP/2協議。
建立EnvoyFilter。
預設情況下,WebSocket不支援HTTP/2協議,但Envoy卻支援WebSocket在HTTP/2流上進行隧道傳輸,以便在整個部署過程中可以使用統一的HTTP/2網路。您可以通過EnvoyFilter針對目標工作負載設定
allow_connect: true
,從而使WebSocket服務端允許HTTP/2協議串連。登入ASM控制台。
在左側導覽列,選擇 。
在網格管理頁面,找到待配置的執行個體,單擊執行個體的名稱或在操作列中單擊管理。
在網格詳情頁面左側導覽列選擇 。
在外掛程式市場頁面,單擊設定allow_connect為true允許升級的協議串連。
在外掛程式詳情頁面,單擊建立外掛程式執行個體頁簽,在外掛程式生效範圍地區,選中工作負載生效,然後單擊添加工作負載到生效範圍。
在添加工作負載到生效範圍對話方塊中,設定命名空間為default,工作負載類型為Deployment,在選擇負載地區選中websockets-server,單擊表徵圖,將websockets-server添加到已選擇地區中,然後單擊確定。
在外掛程式配置地區的YAML框中輸入
patch_context: SIDECAR_INBOUND
,然後開啟生效開關,等待外掛程式啟用。在外掛程式啟用後,ASM會自動建立Envoy過濾器,Envoy過濾器的YAML樣本如下:
apiVersion: networking.istio.io/v1alpha3 kind: EnvoyFilter metadata: name: h2-upgrade-wss labels: asm-system: 'true' provider: asm spec: workloadSelector: labels: app: websockets-server configPatches: - applyTo: NETWORK_FILTER match: context: SIDECAR_INBOUND proxy: proxyVersion: '^1\.*.*' listener: filterChain: filter: name: "envoy.filters.network.http_connection_manager" patch: operation: MERGE value: typed_config: '@type': type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager http2_protocol_options: allow_connect: true
執行以下命令,訪問WebSocket服務端。
python3 -m websockets ws://websockets-server.<namespace>.svc.cluster.local:8080
預期輸出:
Connected to ws://websockets-server.default.svc.cluster.local:8080.
輸入hello和word,可以看到返回hello和word。
> hello < hello > world < world Connection closed: 1000 (OK).
查看Sidecar Proxy日誌。
查看WebSocket用戶端的Sidecar Proxy日誌。
在容器組頁面單擊WebSocket用戶端容器名稱。
單擊日誌頁簽,設定容器為istio-proxy。
可以看到日誌中包含使用WebSocket over HTTP/1.1協議記錄,說明用戶端發起請求使用的是HTTP/1.1協議。
{...."authority":"websockets-server.default.svc.cluster.local:8080","upstream_service_time":null,"protocol":"HTTP/1.1",....}
查看WebSocket服務端的Sidecar Proxy日誌。
在容器組頁面單擊WebSocket服務端容器名稱。
單擊日誌頁簽,設定容器為istio-proxy。
可以看到日誌中包含使用WebSocket over HTTP/2協議記錄,說明WebSocket服務端的接收到的協議已經升級為HTTP/2。
{...."method":"GET","upstream_local_address":"127.0.**.**:34477","protocol":"HTTP/2",....}