WebSocket adalah protokol berbasis RFC 6455 yang memungkinkan komunikasi dua arah antara klien dan server. Proxy sidecar Istio mendukung WebSocket secara default. Topik ini menjelaskan cara mengakses layanan di Alibaba Cloud Service Mesh (ASM) melalui WebSocket, baik melalui HTTP/1.1 maupun HTTP/2.
Informasi latar belakang
Berbeda dengan HTTP, WebSocket menggunakan header HTTP Upgrade untuk membuat koneksi antara klien dan server. Istio tidak secara native mengenali protokol WebSocket. Untuk informasi lebih lanjut tentang dukungan WebSocket di Istio, lihat HTTP upgrades, HTTP connection manager, dan Protocol Selection.
Gunakan WebSocket over HTTP/1.1 atau WebSocket over HTTP/2 untuk mengakses layanan di ASM. Perbedaannya sebagai berikut:
-
WebSocket over HTTP/1.1 — Satu koneksi dibuat untuk satu sesi WebSocket, dan koneksi ditutup setelah sesi berakhir.
-
WebSocket over HTTP/2 — Beberapa permintaan dijalankan secara paralel melalui satu koneksi. Permintaan yang berjalan lama tidak memblokir permintaan lain pada koneksi yang sama.
Pertama-tama, deploy server dan klien WebSocket, lalu ikuti langkah-langkah di salah satu bagian berikut: Gunakan WebSocket over HTTP/1.1 atau Gunakan WebSocket over HTTP/2. Kedua bagian tersebut menjelaskan jalur alternatif, bukan tahapan berurutan. WebSocket over HTTP/2 juga memerlukan Istio 1.12 atau versi lebih baru, aturan tujuan (destination rule) yang melakukan upgrade protokol, serta EnvoyFilter untuk server WebSocket.
Prasyarat
-
Instans Service Mesh (ASM) telah dibuat. Kluster ACK telah ditambahkan ke instans ASM. Untuk informasi selengkapnya, lihat Buat instans ASM dan Tambahkan kluster ke instans ASM.
-
Proxy sidecar telah diinjeksikan untuk namespace tersebut. Untuk petunjuknya, lihat Konfigurasikan kebijakan injeksi sidecar. Topik ini menggunakan namespace default sebagai contoh.
-
Klien kubectl telah terhubung ke kluster. Untuk petunjuknya, lihat Hubungkan klien kubectl ke kluster.
Deploy server dan client WebSocket
-
Deploy server WebSocket.
CatatanTopik ini menggunakan server WebSocket dari pustaka Python yang disediakan oleh komunitas WebSocket sebagai contoh. Untuk mempelajari cara mengubah konfigurasi deployment server WebSocket, lihat Containerize an application.
-
Buat file bernama websockets-server.yaml dengan konten berikut:
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 -
Jalankan perintah berikut untuk mendeploy server WebSocket di namespace default:
kubectl apply -f websockets-server.yaml -n default
-
-
Deploy klien WebSocket.
-
Buat file bernama websockets-client.yaml dengan konten berikut:
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"] -
Jalankan perintah berikut untuk mendeploy klien WebSocket di namespace default:
kubectl apply -f websockets-client.yaml -n default
-
Gunakan WebSocket over HTTP/1.1
Langkah-langkah berikut memverifikasi akses WebSocket melalui HTTP/1.1 di ASM. Lakukan hanya jika Anda menggunakan WebSocket over HTTP/1.1. Jika Anda menggunakan WebSocket over HTTP/2, beralihlah ke Gunakan WebSocket over HTTP/2 sebagai gantinya.
Ketika klien WebSocket mengirim beberapa permintaan ke server, log proxy sidecar hanya berisi satu entri log akses untuk koneksi WebSocket tersebut. Envoy memperlakukan koneksi WebSocket sebagai aliran byte TCP dan hanya dapat menginterpretasikan permintaan dan respons HTTP upgrade. Oleh karena itu, Envoy menulis entri log akses hanya setelah koneksi ditutup, dan entri tersebut tidak menampilkan pesan individual yang dikirim melalui koneksi tersebut.
-
Gunakan salah satu metode berikut untuk membuka jendela shell di kontainer klien WebSocket:
-
Metode 1: Gunakan Konsol
-
Login ke Konsol ACK. Di panel navigasi kiri, klik Clusters.
-
Di halaman Clusters, klik nama kluster Anda. Di panel navigasi kiri, klik .
-
Di halaman Pods, temukan pod
websockets-client-sleep. Di kolom Actions, klik Terminal, lalu pilih kontainer websockets-client.
-
-
Metode 2: Gunakan kubectl
Jalankan perintah berikut untuk membuka jendela shell:
kubectl exec -it -n default <pod-name> -c websockets-client -- shGanti
<pod-name>dengan nama lengkap pod yang dibuat oleh deploymentwebsockets-client-sleep. Nama pod dimulai denganwebsockets-client-sleepdan diakhiri dengan sufiks yang di-generate.
-
-
Jalankan perintah berikut untuk mengakses server WebSocket:
python3 -m websockets ws://websockets-server.default.svc.cluster.local:8080Output yang diharapkan:
Connected to ws://websockets-server.default.svc.cluster.local:8080.Masukkan
hellodanworld. Server akan mengembalikan pesan tersebut.> hello < hello > world < world Connection closed: 1000 (OK). -
Periksa log proxy sidecar.
-
Periksa log proxy sidecar dari klien WebSocket.
-
Di halaman Pods, klik nama pod klien WebSocket.
-
Klik tab Logs dan atur Container ke istio-proxy.
Entri log menunjukkan bahwa koneksi menggunakan WebSocket over HTTP/1.1.
{...."upstream_host":"10.208.0.105:80","bytes_sent":23,"protocol":"HTTP/1.1",....}
-
-
Periksa log proxy sidecar dari server WebSocket.
-
Di halaman Pods, klik nama pod server WebSocket.
-
Klik tab Logs dan atur Container ke istio-proxy.
Entri log menunjukkan bahwa koneksi menggunakan WebSocket over HTTP/1.1.
{...."downstream_local_address":"10.208.0.105:80","upstream_local_address":"127.0.**.**:53983","protocol":"HTTP/1.1",....}
-
-
Kedua entri log tersebut mengonfirmasi akses WebSocket melalui HTTP/1.1. Ikuti langkah-langkah di Gunakan WebSocket over HTTP/2 hanya jika Anda ingin deployment yang sama berkomunikasi melalui HTTP/2 sebagai gantinya.
Gunakan WebSocket over HTTP/2
WebSocket over HTTP/2 di ASM memerlukan Istio 1.12 atau versi lebih baru. Ikuti langkah-langkah di bagian ini hanya jika Anda menggunakan WebSocket over HTTP/2. Jika Anda menggunakan WebSocket over HTTP/1.1, lihat Gunakan WebSocket over HTTP/1.1 sebagai gantinya. Jika mesh Anda menjalankan versi Istio sebelum 1.12, lihat Fallback ke HTTP/1.1 pada versi Istio sebelum 1.12.
Untuk menggunakan WebSocket over HTTP/2 dengan Istio 1.12 atau versi lebih baru, lakukan langkah-langkah berikut:
Perintah yang mengakses server WebSocket di bagian ini dijalankan di jendela shell dalam kontainer klien WebSocket. Untuk membuka jendela shell, gunakan salah satu metode yang dijelaskan pada langkah 1 di Gunakan WebSocket over HTTP/1.1.
-
Buat aturan tujuan.
-
Login ke Konsol ASM.
-
Di panel navigasi kiri, pilih .
-
Di halaman Mesh Management, temukan instans ASM yang ingin Anda konfigurasi. Klik nama instans ASM tersebut atau klik Manage di kolom Actions.
-
Di halaman detail instans ASM, pilih di panel navigasi kiri. Di halaman yang muncul, klik Create from YAML.
-
Atur Namespaces ke default, salin konten berikut ke kotak teks, lalu klik Create.
apiVersion: networking.istio.io/v1beta1 kind: DestinationRule metadata: labels: provider: asm name: websockets-server spec: host: websockets-server trafficPolicy: connectionPool: http: h2UpgradePolicy: UPGRADEh2UpgradePolicy: Atur parameter ini ke UPGRADE untuk mengaktifkan HTTP/2 untuk
websockets-server. Nilai ini diperlukan untuk WebSocket over HTTP/2. Jangan gunakanDO_NOT_UPGRADEdi sini, karena nilai tersebut mencegah upgrade.
-
-
Buat EnvoyFilter.
Secara default, WebSocket tidak mendukung HTTP/2. Namun, Envoy dapat melakukan tunneling WebSocket melalui aliran HTTP/2, sehingga memungkinkan Anda menggunakan jaringan HTTP/2 yang terpadu di seluruh deployment. Gunakan EnvoyFilter untuk mengatur
allow_connect: trueuntuk workload tujuan. Server WebSocket kemudian akan menerima koneksi HTTP/2.-
Login ke Konsol ASM.
-
Di panel navigasi kiri, pilih .
-
Di halaman Mesh Management, temukan instans ASM yang ingin Anda konfigurasi. Klik nama instans ASM tersebut atau klik Manage di kolom Actions.
-
Di halaman detail mesh, di panel navigasi kiri, pilih .
-
Di halaman Market Place, klik setting allow_connect true for HTTP protocol upgrade.
-
Di halaman Plugin Detail, klik tab Create Plug-in Instance. Di bagian Plugin Effective scope, pilih Workload Scope, lalu klik Add workloads to effective scope.
-
Di dialog Add workloads to effective scope, atur Namespaces ke default dan Workload Type ke Deployment. Di bagian Select workloads, pilih websockets-server, klik ikon
untuk menambahkan websockets-server ke bagian selected, lalu klik OK. -
Di kotak YAML bagian Plugin Config, masukkan
patch_context: SIDECAR_INBOUND. Lalu, aktifkan Plugin Switch dan tunggu hingga plugin diaktifkan.Setelah plugin diaktifkan, ASM secara otomatis membuat filter Envoy. Kode YAML berikut merupakan contoh filter Envoy tersebut:
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
-
-
Jalankan perintah berikut untuk mengakses server WebSocket:
python3 -m websockets ws://websockets-server.default.svc.cluster.local:8080Output yang diharapkan:
Connected to ws://websockets-server.default.svc.cluster.local:8080.Masukkan
hellodanworld. Server akan mengembalikan pesan tersebut.> hello < hello > world < world Connection closed: 1000 (OK). -
Periksa log proxy sidecar.
-
Periksa log proxy sidecar dari klien WebSocket.
-
Di halaman Pods, klik nama pod klien WebSocket.
-
Klik tab Logs dan atur Container ke istio-proxy.
Entri log menunjukkan bahwa koneksi menggunakan WebSocket over HTTP/1.1, yang mengindikasikan bahwa klien memulai permintaan melalui HTTP/1.1.
{...."authority":"websockets-server.default.svc.cluster.local:8080","upstream_service_time":null,"protocol":"HTTP/1.1",....}
-
-
Periksa log proxy sidecar dari server WebSocket.
-
Di halaman Pods, klik nama pod server WebSocket.
-
Klik tab Logs dan atur Container ke istio-proxy.
Entri log menunjukkan bahwa koneksi menggunakan WebSocket over HTTP/2, yang mengindikasikan bahwa protokol yang diterima oleh server WebSocket telah di-upgrade ke HTTP/2.
{...."method":"GET","upstream_local_address":"127.0.**.**:34477","protocol":"HTTP/2",....}
-
-
Fallback ke HTTP/1.1 pada versi Istio sebelum 1.12
Jika Anda menggunakan WebSocket over HTTP/2 dengan versi Istio sebelum 1.12, koneksi ke server WebSocket gagal dan error 503 dikembalikan.
Jika Anda telah mengonfigurasi upgrade HTTP/2 untuk versi Istio sebelum 1.12 dan error ini terjadi, atur h2UpgradePolicy ke DO_NOT_UPGRADE dalam destination rule. Versi Istio sebelum 1.12 kemudian dapat menggunakan WebSocket over HTTP/1.1 seperti yang diharapkan. Terapkan destination rule berikut hanya dalam situasi ini. Dengan Istio 1.12 atau versi lebih baru, gunakan destination rule pada langkah 1, yang mengatur h2UpgradePolicy ke UPGRADE.
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