Saat layanan mikro mengalami kelebihan beban atau kegagalan parsial, lalu lintas yang tidak terkendali dapat menyebar ke seluruh sistem dan menjatuhkan layanan yang sehat. Circuit breaking di tingkat jaringan—melalui proxy sidecar Service Mesh (ASM)—menolak lalu lintas berlebih sebelum mencapai backend, tanpa memerlukan perubahan kode pada setiap layanan. Pendekatan tradisional seperti Resilience4j memerlukan penyematan logika circuit breaking langsung ke dalam kode aplikasi.
Konfigurasikan field connectionPool dalam DestinationRule untuk membatasi jumlah koneksi bersamaan dan permintaan tertunda ke layanan tujuan. Bagian-bagian berikut mencakup parameter tersebut, mendemonstrasikan perilakunya pada empat topologi penskalaan Pod, serta menjelaskan cara memantau circuit breaking di lingkungan produksi.
Prasyarat
Sebelum memulai, pastikan Anda telah:
Menambahkan kluster Container Service for Kubernetes (ACK) ke instans Service Mesh (ASM) Anda (lihat Tambahkan kluster ke instans ASM)
Cara kerja circuit breaking berbasis connection pool
Buat DestinationRule dengan pengaturan connectionPool untuk mengaktifkan circuit breaking pada layanan target. Untuk referensi lengkap field, lihat Destination Rule.
Tiga parameter mengontrol perilaku connection pool:
| Parameter | Tipe | Wajib | Bawaan | Deskripsi |
|---|---|---|---|---|
tcp.maxConnections | int32 | Tidak | 2^32-1 | Maksimum koneksi HTTP/1.1 atau TCP ke host tujuan. Diterapkan pada proxy sidecar di sisi client maupun server. Satu Pod client tidak dapat membuka lebih dari jumlah koneksi ini, dan satu Pod server tidak dapat menerima lebih. Kapasitas efektif di sisi server: min(jumlah Pod client, jumlah Pod server) x maxConnections. |
http.http1MaxPendingRequests | int32 | Tidak | 1024 | Maksimum permintaan yang diantrikan saat menunggu koneksi tersedia. Mengatur nilai ini ke 0 akan menggunakan nilai bawaan (1024), sehingga gunakan nilai minimal 1. |
http.http2MaxRequests | int32 | Tidak | 1024 | Maksimum permintaan aktif ke backend. |
FieldconnectionPoolmembatasi koneksi dan permintaan yang diantrikan tetapi tidak mengeluarkan host yang tidak sehat dari pool load balancing. Untuk pengeluaran host berdasarkan tingkat error, kombinasikanconnectionPooldenganoutlierDetectiondalam DestinationRule yang sama. Lihat Destination Rule untuk fieldoutlierDetection.
Dengan satu Pod client dan satu Pod server, parameter-parameter ini berperilaku secara prediktif. Di lingkungan produksi, layanan biasanya menjalankan beberapa Pod. Skenario berikut menunjukkan bagaimana circuit breaking berperilaku pada empat topologi umum:
Satu Pod client, satu Pod layanan tujuan
Satu Pod client, beberapa Pod layanan tujuan
Beberapa Pod client, satu Pod layanan tujuan
Beberapa Pod client, beberapa Pod layanan tujuan
Terapkan aplikasi contoh
Pengaturan contoh terdiri dari dua komponen:
Server: Aplikasi Flask yang mendengarkan pada port 9080 di titik akhir
/hello. Setiap permintaan membutuhkan waktu 5 detik untuk diproses (mensimulasikan backend yang lambat).Client: Skrip Python yang mengirim 10 permintaan paralel per batch. Batch dikirim pada detik ke-0, ke-20, dan ke-40 setiap menit agar beberapa Pod client mengirim permintaan secara bersamaan.
Simpan YAML berikut dan jalankan
kubectl apply -f <file-name>.yamluntuk menerapkan aplikasi contoh.Verifikasi bahwa Pod sedang berjalan. Output yang diharapkan:
kubectl get po | grep circuitcircuit-breaker-sample-client-d4f64d66d-fwrh4 2/2 Running 0 1m22s circuit-breaker-sample-server-6d6ddb4b-gcthv 2/2 Running 0 1m22s
Tanpa DestinationRule, server menangani semua 10 permintaan bersamaan dan setiap respons mengembalikan status 200:
----------Info----------
Status: 200, Start: 02:39:20, End: 02:39:25, Elapsed Time: 5.016539812088013
Status: 200, Start: 02:39:20, End: 02:39:25, Elapsed Time: 5.012614488601685
Status: 200, Start: 02:39:20, End: 02:39:25, Elapsed Time: 5.015984535217285
Status: 200, Start: 02:39:20, End: 02:39:25, Elapsed Time: 5.015599012374878
Status: 200, Start: 02:39:20, End: 02:39:25, Elapsed Time: 5.012874364852905
Status: 200, Start: 02:39:20, End: 02:39:25, Elapsed Time: 5.018714904785156
Status: 200, Start: 02:39:20, End: 02:39:25, Elapsed Time: 5.010422468185425
Status: 200, Start: 02:39:20, End: 02:39:25, Elapsed Time: 5.012431621551514
Status: 200, Start: 02:39:20, End: 02:39:25, Elapsed Time: 5.011001348495483
Status: 200, Start: 02:39:20, End: 02:39:25, Elapsed Time: 5.01432466506958Buat DestinationRule untuk circuit breaking
Definisikan DestinationRule untuk layanan tujuan guna mengaktifkan circuit breaking. Untuk informasi lebih lanjut, lihat Kelola destination rules.
Aturan berikut membatasi koneksi TCP hingga 5:
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: circuit-breaker-sample-server
spec:
host: circuit-breaker-sample-server
trafficPolicy:
connectionPool:
tcp:
maxConnections: 5Skenario 1: Satu Pod client, satu Pod layanan tujuan
Mulai ulang Pod client dan periksa log-nya. Semua 10 permintaan berhasil, tetapi hanya 5 yang selesai dalam waktu sekitar 5 detik. Sisanya menunggu lebih dari 10 detik karena diantrikan hingga koneksi tersedia. Dengan hanya mengatur
tcp.maxConnections, permintaan berlebih diantrikan alih-alih gagal—kedalaman antrian bawaan adalah 2^32 - 1.----------Info---------- Status: 200, Start: 02:49:40, End: 02:49:45, Elapsed Time: 5.0167787075042725 Status: 200, Start: 02:49:40, End: 02:49:45, Elapsed Time: 5.011920690536499 Status: 200, Start: 02:49:40, End: 02:49:45, Elapsed Time: 5.017078161239624 Status: 200, Start: 02:49:40, End: 02:49:45, Elapsed Time: 5.018405437469482 Status: 200, Start: 02:49:40, End: 02:49:45, Elapsed Time: 5.018689393997192 Status: 200, Start: 02:49:40, End: 02:49:50, Elapsed Time: 10.018936395645142 Status: 200, Start: 02:49:40, End: 02:49:50, Elapsed Time: 10.016417503356934 Status: 200, Start: 02:49:40, End: 02:49:50, Elapsed Time: 10.019930601119995 Status: 200, Start: 02:49:40, End: 02:49:50, Elapsed Time: 10.022735834121704 Status: 200, Start: 02:49:40, End: 02:49:55, Elapsed Time: 15.02303147315979Untuk circuit breaking fail-fast, batasi juga
http.http1MaxPendingRequests. Perbarui DestinationRule. Untuk informasi lebih lanjut, lihat Kelola destination rules.apiVersion: networking.istio.io/v1alpha3 kind: DestinationRule metadata: name: circuit-breaker-sample-server spec: host: circuit-breaker-sample-server trafficPolicy: connectionPool: tcp: maxConnections: 5 http: http1MaxPendingRequests: 1Mulai ulang Pod client dan periksa log-nya. Empat permintaan langsung ditolak (503), lima mencapai tujuan, dan satu diantrikan (selesai dalam waktu sekitar 10 detik setelah menunggu koneksi tersedia).
----------Info---------- Status: 503, Start: 02:56:40, End: 02:56:40, Elapsed Time: 0.005339622497558594 Status: 503, Start: 02:56:40, End: 02:56:40, Elapsed Time: 0.007254838943481445 Status: 503, Start: 02:56:40, End: 02:56:40, Elapsed Time: 0.0044133663177490234 Status: 503, Start: 02:56:40, End: 02:56:40, Elapsed Time: 0.008964776992797852 Status: 200, Start: 02:56:40, End: 02:56:45, Elapsed Time: 5.018309116363525 Status: 200, Start: 02:56:40, End: 02:56:45, Elapsed Time: 5.017424821853638 Status: 200, Start: 02:56:40, End: 02:56:45, Elapsed Time: 5.019804954528809 Status: 200, Start: 02:56:40, End: 02:56:45, Elapsed Time: 5.01643180847168 Status: 200, Start: 02:56:40, End: 02:56:45, Elapsed Time: 5.025975227355957 Status: 200, Start: 02:56:40, End: 02:56:50, Elapsed Time: 10.01716136932373Verifikasi jumlah koneksi aktif dari proxy sidecar client. Output yang diharapkan: Lima koneksi aktif dari proxy client ke Pod tujuan, sesuai dengan batas
maxConnections.kubectl exec $(kubectl get pod --selector app=circuit-breaker-sample-client --output jsonpath='{.items[0].metadata.name}') -c istio-proxy -- curl -X POST http://localhost:15000/clusters | grep circuit-breaker-sample-server | grep cx_activeoutbound|9080||circuit-breaker-sample-server.default.svc.cluster.local::172.20.192.124:9080::cx_active::5
Skenario 2: Satu Pod client, beberapa Pod layanan tujuan
Skenario ini menguji apakah batas koneksi berlaku per Pod atau per layanan. Dengan satu client dan tiga Pod tujuan:
Batas per Pod: Setiap Pod mengizinkan 5 koneksi, total 15. Semua 10 permintaan seharusnya berhasil dalam waktu sekitar 5 detik.
Batas per layanan: Hanya 5 koneksi total, terlepas dari jumlah Pod. Perilaku throttling sama seperti Skenario 1.
Skalakan layanan tujuan menjadi tiga replika.
kubectl scale deployment/circuit-breaker-sample-server --replicas=3Mulai ulang Pod client dan periksa log-nya. Pola throttling identik dengan Skenario 1. Menambahkan lebih banyak Pod tujuan tidak meningkatkan batas koneksi client. Batas koneksi berlaku per layanan, bukan per Pod.
----------Info---------- Status: 503, Start: 03:06:20, End: 03:06:20, Elapsed Time: 0.011791706085205078 Status: 503, Start: 03:06:20, End: 03:06:20, Elapsed Time: 0.0032286643981933594 Status: 503, Start: 03:06:20, End: 03:06:20, Elapsed Time: 0.012153387069702148 Status: 503, Start: 03:06:20, End: 03:06:20, Elapsed Time: 0.011871814727783203 Status: 200, Start: 03:06:20, End: 03:06:25, Elapsed Time: 5.012892484664917 Status: 200, Start: 03:06:20, End: 03:06:25, Elapsed Time: 5.013102769851685 Status: 200, Start: 03:06:20, End: 03:06:25, Elapsed Time: 5.016939163208008 Status: 200, Start: 03:06:20, End: 03:06:25, Elapsed Time: 5.014261484146118 Status: 200, Start: 03:06:20, End: 03:06:25, Elapsed Time: 5.01246190071106 Status: 200, Start: 03:06:20, End: 03:06:30, Elapsed Time: 10.021712064743042Verifikasi distribusi koneksi aktif. Output yang diharapkan: Proxy mendistribusikan koneksi ke seluruh Pod—dua per Pod, total enam bukan lima. Seperti disebutkan dalam dokumentasi Envoy dan Istio, proxy memberikan toleransi tertentu terhadap jumlah koneksi.
kubectl exec $(kubectl get pod --selector app=circuit-breaker-sample-client --output jsonpath='{.items[0].metadata.name}') -c istio-proxy -- curl -X POST http://localhost:15000/clusters | grep circuit-breaker-sample-server | grep cx_activeoutbound|9080||circuit-breaker-sample-server.default.svc.cluster.local::172.20.192.124:9080::cx_active::2 outbound|9080||circuit-breaker-sample-server.default.svc.cluster.local::172.20.192.158:9080::cx_active::2 outbound|9080||circuit-breaker-sample-server.default.svc.cluster.local::172.20.192.26:9080::cx_active::2
Skenario 3: Beberapa Pod client, satu Pod layanan tujuan
Sesuaikan replika: skalakan server menjadi 1 dan client menjadi 3.
kubectl scale deployment/circuit-breaker-sample-server --replicas=1 kubectl scale deployment/circuit-breaker-sample-client --replicas=3Mulai ulang Pod client dan periksa log-nya.
Tingkat error 503 meningkat pada setiap client. Setiap proxy client menerapkan batas 5 koneksi secara independen, tetapi proxy layanan tujuan tunggal juga menerapkan batas 5 koneksi. Hanya 5 permintaan dari seluruh client yang dapat berhasil secara bersamaan.
Periksa log proxy client untuk flag respons.
Permintaan yang dibatasi mengembalikan status 503 dengan salah satu dari dua flag respons:
Flag Makna Tempat terjadinya UOUpstream overflow (circuit breaking) Proxy client membatasi permintaan secara lokal URXUpstream retry/connection limit exceeded Proxy layanan tujuan menolak permintaan Bedakan keduanya dengan memeriksa
DURATION,UPSTREAM_HOST, danUPSTREAM_CLUSTERdalam log akses. Permintaan dengan flagUOtidak memiliki host upstream (dibatasi sebelum dikirim), sedangkan permintaanURXmencapai proxy tujuan dan ditolak di sana.Konfirmasi dengan memeriksa log proxy layanan tujuan.
Proxy layanan tujuan juga mengembalikan status 503 dengan flag
UO. Hal ini mengonfirmasi bahwa entriURXdalam log proxy client berasal dari penolakan koneksi berlebih oleh proxy layanan tujuan.
Ringkasan alur permintaan:
Setiap proxy client menerapkan batas 5 koneksi secara independen. Dengan 3 client, hingga 15 permintaan dapat dikirim secara paralel dari proxy client. Namun, proxy layanan tujuan tunggal juga menerapkan batas 5 koneksi, sehingga hanya menerima 5 dan menolak sisanya. Permintaan yang ditolak muncul sebagai URX dalam log proxy client.
Skenario 4: Beberapa Pod client, beberapa Pod layanan tujuan
Menambah jumlah Pod layanan tujuan meningkatkan tingkat keberhasilan keseluruhan karena proxy setiap Pod tujuan secara independen mengizinkan 5 koneksi.
Atur server menjadi 2 replika dan client menjadi 3. Dengan 2 Pod tujuan (masing-masing menerima 5), 10 dari total 30 permintaan (dari 3 client) berhasil per batch.
kubectl scale deployment/circuit-breaker-sample-server --replicas=2 kubectl scale deployment/circuit-breaker-sample-client --replicas=3Skalakan server menjadi 3 replika. 15 permintaan berhasil per batch.
kubectl scale deployment/circuit-breaker-sample-server --replicas=3Skalakan server menjadi 4 replika. Tetap hanya 15 permintaan yang berhasil. Batas proxy client membatasi maksimal 5 per client terlepas dari jumlah Pod tujuan yang tersedia. Dengan 3 client, maksimum adalah 3 x 5 = 15 permintaan bersamaan yang berhasil.
kubectl scale deployment/circuit-breaker-sample-server --replicas=4
Ringkasan batasan client dan server
| Peran | Cara penerapan batas |
|---|---|
| Client | Setiap proxy client menerapkan batas secara independen. Jika maxConnections bernilai 100 dan terdapat N Pod client, hingga N x 100 permintaan dapat dalam proses di seluruh client. Batas ini berlaku untuk seluruh layanan tujuan, bukan untuk masing-masing Pod tujuan. Bahkan dengan 200 Pod tujuan, satu proxy client tetap dibatasi hingga 100 koneksi. |
| Layanan tujuan | Proxy setiap Pod tujuan menerapkan batas secara independen. Dengan 50 Pod aktif dan maxConnections diatur ke 100, setiap Pod menerima hingga 100 koneksi dari proxy client sebelum mengembalikan status 503. |
Pantau metrik circuit breaking
Saat circuit breaking diaktifkan, Envoy menghasilkan metrik untuk mendeteksi dan mendiagnosis throttling.
| Metrik | Tipe | Deskripsi |
|---|---|---|
envoy_cluster_circuit_breakers_default_cx_open | Gauge | 1 jika circuit breaker connection pool terbuka (aktif); 0 jika tidak. |
envoy_cluster_circuit_breakers_default_rq_pending_open | Gauge | 1 jika antrian permintaan tertunda melebihi batasnya; 0 jika tidak. |
Aktifkan metrik circuit breaking
Konfigurasikan
proxyStatsMatcheruntuk proxy sidecar. Pilih Regular Expression Match dan atur nilainya ke.*circuit_breaker.*. Untuk informasi lebih lanjut, lihat proxyStatsMatcher.Terapkan ulang Deployment
circuit-breaker-sample-serverdancircuit-breaker-sample-client. Untuk informasi lebih lanjut, lihat Terapkan ulang beban kerja.Jalankan kembali pengujian circuit breaking dari skenario-skenario sebelumnya.
Kueri metrik dari proxy client. Output yang diharapkan:
kubectl exec -it deploy/circuit-breaker-sample-client -c istio-proxy -- curl localhost:15090/stats/prometheus | grep circuit_breaker | grep circuit-breaker-sample-serverenvoy_cluster_circuit_breakers_default_cx_open{cluster_name="outbound|9080||circuit-breaker-sample-server.default.svc.cluster.local"} 1 envoy_cluster_circuit_breakers_default_cx_pool_open{cluster_name="outbound|9080||circuit-breaker-sample-server.default.svc.cluster.local"} 0 envoy_cluster_circuit_breakers_default_remaining_cx{cluster_name="outbound|9080||circuit-breaker-sample-server.default.svc.cluster.local"} 0 envoy_cluster_circuit_breakers_default_remaining_cx_pools{cluster_name="outbound|9080||circuit-breaker-sample-server.default.svc.cluster.local"} 18446744073709551613 envoy_cluster_circuit_breakers_default_remaining_pending{cluster_name="outbound|9080||circuit-breaker-sample-server.default.svc.cluster.local"} 1 envoy_cluster_circuit_breakers_default_remaining_retries{cluster_name="outbound|9080||circuit-breaker-sample-server.default.svc.cluster.local"} 4294967295 envoy_cluster_circuit_breakers_default_remaining_rq{cluster_name="outbound|9080||circuit-breaker-sample-server.default.svc.cluster.local"} 4294967295 envoy_cluster_circuit_breakers_default_rq_open{cluster_name="outbound|9080||circuit-breaker-sample-server.default.svc.cluster.local"} 0 envoy_cluster_circuit_breakers_default_rq_pending_open{cluster_name="outbound|9080||circuit-breaker-sample-server.default.svc.cluster.local"} 0 envoy_cluster_circuit_breakers_default_rq_retry_open{cluster_name="outbound|9080||circuit-breaker-sample-server.default.svc.cluster.local"} 0 envoy_cluster_circuit_breakers_high_cx_open{cluster_name="outbound|9080||circuit-breaker-sample-server.default.svc.cluster.local"} 0 envoy_cluster_circuit_breakers_high_cx_pool_open{cluster_name="outbound|9080||circuit-breaker-sample-server.default.svc.cluster.local"} 0 envoy_cluster_circuit_breakers_high_rq_open{cluster_name="outbound|9080||circuit-breaker-sample-server.default.svc.cluster.local"} 0 envoy_cluster_circuit_breakers_high_rq_pending_open{cluster_name="outbound|9080||circuit-breaker-sample-server.default.svc.cluster.local"} 0 envoy_cluster_circuit_breakers_high_rq_retry_open{cluster_name="outbound|9080||circuit-breaker-sample-server.default.svc.cluster.local"} 0
Siapkan peringatan untuk circuit breaking
Gunakan Managed Service for Prometheus untuk mengumpulkan metrik circuit breaking dan menyiapkan aturan peringatan. Untuk detail integrasi komponen, lihat Kelola komponen.
Jika Anda sudah menggunakan instans Prometheus yang dikelola sendiri untuk mengumpulkan metrik ASM (lihat Pantau instans ASM menggunakan instans Prometheus yang dikelola sendiri), lewati langkah 1.
Di Managed Service for Prometheus, hubungkan kluster bidang data ke komponen Alibaba Cloud ASM atau tingkatkan ke versi terbaru.
Buat aturan peringatan dengan pernyataan PromQL kustom. Untuk informasi lebih lanjut, lihat Gunakan pernyataan PromQL kustom untuk membuat aturan peringatan. Gunakan parameter berikut sebagai referensi:
Parameter Contoh Deskripsi Pernyataan PromQL kustom (sum by(cluster_name, pod_name, namespace) (envoy_cluster_circuit_breakers_default_cx_open)) != 0Memeriksa apakah circuit breaking aktif di connection pool mana pun. Dikelompokkan berdasarkan nama layanan upstream, Pod, dan namespace sehingga Anda dapat mengidentifikasi lokasi terjadinya throttling. Pesan peringatan Circuit breaking aktif. Batas koneksi TCP telah tercapai. Namespace: {{$labels.namespace}}, Pod: {{$labels.pod_name}}, Layanan upstream: {{$labels.cluster_name}} Mengidentifikasi Pod yang terpengaruh, namespace-nya, dan layanan upstream.