Pemutus Litar dalam Go: Hentikan Kegagalan Lata
Pemutus Litar
Pemutus litar mengesan kegagalan dan merangkum logik pengendalian kegagalan tersebut dengan cara yang menghalang kegagalan daripada terus berulang. Contohnya, ia berguna apabila berurusan dengan panggilan rangkaian ke perkhidmatan luaran, pangkalan data, atau benar-benar, mana-mana bahagian sistem anda yang mungkin gagal buat sementara waktu. Dengan menggunakan pemutus litar, anda boleh mengelakkan kegagalan melata, mengurus ralat sementara dan mengekalkan sistem yang stabil dan responsif di tengah-tengah kerosakan sistem.
Kegagalan Lata
Kegagalan berlatarkan berlaku apabila kegagalan dalam satu bahagian sistem mencetuskan kegagalan di bahagian lain, yang membawa kepada gangguan yang meluas. Contohnya ialah apabila perkhidmatan mikro dalam sistem teragih menjadi tidak bertindak balas, menyebabkan perkhidmatan bergantung tamat masa dan akhirnya gagal. Bergantung pada skala aplikasi, impak kegagalan ini boleh menjadi malapetaka yang akan merendahkan prestasi dan mungkin juga memberi kesan kepada pengalaman pengguna.
Corak Pemutus Litar
Pemutus litar itu sendiri ialah teknik/corak dan terdapat tiga keadaan berbeza ia beroperasi yang akan kita bincangkan:
- Keadaan Tertutup: Dalam keadaan tertutup, pemutus litar membenarkan semua permintaan melalui perkhidmatan sasaran seperti biasa. Jika permintaan berjaya, litar tetap ditutup. Walau bagaimanapun, jika ambang kegagalan tertentu dicapai, litar beralih ke keadaan terbuka. Anggap ia seperti perkhidmatan yang beroperasi sepenuhnya di mana pengguna boleh log masuk dan mengakses data tanpa masalah. Semuanya berjalan lancar.
2. Keadaan Terbuka : Dalam keadaan terbuka, pemutus litar serta-merta gagal semua permintaan masuk tanpa cuba menghubungi perkhidmatan sasaran. Negeri itu dimasukkan untuk mengelakkan lebihan beban perkhidmatan yang gagal dan memberi masa untuk pulih. Selepas tamat masa yang telah ditetapkan, pemutus litar bergerak ke keadaan separuh terbuka. Contoh yang boleh dikaitkan ialah ini; Bayangkan kedai dalam talian mengalami isu mendadak di mana setiap percubaan pembelian gagal. Untuk mengelak daripada membebankan sistem, kedai berhenti menerima sebarang permintaan pembelian baharu buat sementara waktu.
3. Keadaan Separuh Terbuka : Dalam keadaan separuh terbuka, pemutus litar membenarkan bilangan permintaan ujian terhad (boleh dikonfigurasikan) untuk melalui perkhidmatan sasaran. Dan jika permintaan ini berjaya, litar beralih kembali ke keadaan tertutup. Jika gagal, litar kembali ke keadaan terbuka. Dalam contoh kedai dalam talian yang saya berikan dalam keadaan terbuka di atas, di sinilah kedai dalam talian mula membenarkan beberapa percubaan pembelian untuk melihat sama ada isu itu telah dibetulkan. Jika beberapa percubaan ini berjaya, kedai akan membuka semula perkhidmatannya sepenuhnya untuk menerima permintaan pembelian baharu.
Rajah ini menunjukkan apabila pemutus litar cuba untuk melihat sama ada permintaan untuk Perkhidmatan B berjaya dan kemudian ia gagal/putus:
Rajah susulan kemudian menunjukkan apabila ujian meminta Perkhidmatan B berjaya, litar ditutup dan semua panggilan selanjutnya dihalakan ke Perkhidmatan B sekali lagi:
Nota : Konfigurasi utama untuk pemutus litar termasuk ambang kegagalan (bilangan kegagalan yang diperlukan untuk membuka litar), tamat masa untuk keadaan terbuka dan bilangan permintaan ujian dalam separuh terbuka negeri.
Melaksanakan Pemutus Litar dalam Go
Adalah penting untuk menyatakan bahawa pengetahuan awal tentang Go diperlukan untuk diikuti dalam artikel ini.
Seperti mana-mana corak kejuruteraan perisian, pemutus litar boleh dilaksanakan dalam pelbagai bahasa. Walau bagaimanapun, artikel ini akan menumpukan pada pelaksanaan di Golang. Walaupun terdapat beberapa perpustakaan yang tersedia untuk tujuan ini, seperti goresilience, go-resiliency dan gobreaker, kami secara khusus akan menumpukan pada menggunakan perpustakaan gobreaker.
Petua Pro : Anda boleh melihat pelaksanaan dalaman pakej gobreaker, semak di sini.
Mari kita pertimbangkan aplikasi Golang mudah di mana pemutus litar dilaksanakan untuk mengendalikan panggilan ke API luaran. Contoh asas ini menunjukkan cara membungkus panggilan API luaran dengan teknik pemutus litar:
Mari kita sentuh beberapa perkara penting:
- Fungsi gobreaker.NewCircuitBreaker memulakan pemutus litar dengan tetapan tersuai kami
- Kaedah cb.Execute membungkus permintaan HTTP, mengurus keadaan litar secara automatik.
- Permintaan Maksimum ialah bilangan maksimum permintaan yang dibenarkan untuk dilalui apabila keadaan separuh terbuka
- Selang ialah tempoh kitaran keadaan tertutup untuk pemutus litar mengosongkan kiraan dalaman
- Tamat masa ialah tempoh sebelum beralih daripada keadaan terbuka kepada separuh terbuka.
- ReadyToTrip dipanggil dengan salinan kiraan apabila permintaan gagal dalam keadaan tertutup. Jika ReadyToTrip kembali benar, pemutus litar akan diletakkan dalam keadaan terbuka. Dalam kes kami di sini, ia kembali benar jika permintaan telah gagal lebih daripada tiga kali berturut-turut.
- OnStateChange dipanggil apabila keadaan pemutus litar berubah. Anda biasanya ingin mengumpulkan metrik perubahan keadaan di sini dan melaporkan kepada mana-mana pengumpul metrik pilihan anda.
Mari kita tulis beberapa ujian unit untuk mengesahkan pelaksanaan pemutus litar kami. Saya hanya akan menerangkan ujian unit yang paling kritikal untuk difahami. Anda boleh menyemak di sini untuk kod penuh.
- Kami akan menulis ujian yang mensimulasikan permintaan gagal berturut-turut dan menyemak sama ada pemutus litar bergerak ke keadaan terbuka. Pada asasnya, selepas 3 kegagalan, apabila kegagalan keempat berlaku, kami menjangkakan pemutus litar akan tersandung (terbuka) kerana keadaan kami berkata penting.Kegagalan Berturut-turut > 3 . Begini rupa ujian itu:
t.Run("FailedRequests", func(t *testing.T) { // Override callExternalAPI to simulate failure callExternalAPI = func() (int, error) { return 0, errors.New("simulated failure") } for i := 0; i < 4; i++ { _, err := cb.Execute(func() (interface{}, error) { return callExternalAPI() }) if err == nil { t.Fatalf("expected error, got none") } } if cb.State() != gobreaker.StateOpen { t.Fatalf("expected circuit breaker to be open, got %v", cb.State()) } })
- Kami akan menguji terbuka > separuh - terbuka > ditutup menyatakan. Tetapi kita akan mula-mula mensimulasikan litar terbuka dan memanggil tamat masa. Selepas tamat masa, kita perlu membuat sekurang-kurangnya satu permintaan kejayaan untuk litar beralih kepada separuh terbuka. Selepas keadaan separuh terbuka, kita perlu membuat satu lagi permintaan kejayaan untuk litar ditutup sepenuhnya semula. Jika atas sebarang sebab, tiada rekod permintaan kejayaan dalam kes itu, ia akan kembali dibuka. Begini rupa ujian itu:
//Simulates the circuit breaker being open, //wait for the defined timeout, //then check if it closes again after a successful request. t.Run("RetryAfterTimeout", func(t *testing.T) { // Simulate circuit breaker opening callExternalAPI = func() (int, error) { return 0, errors.New("simulated failure") } for i := 0; i < 4; i++ { _, err := cb.Execute(func() (interface{}, error) { return callExternalAPI() }) if err == nil { t.Fatalf("expected error, got none") } } if cb.State() != gobreaker.StateOpen { t.Fatalf("expected circuit breaker to be open, got %v", cb.State()) } // Wait for timeout duration time.Sleep(settings.Timeout + 1*time.Second) //We expect that after the timeout period, //the circuit breaker should transition to the half-open state. // Restore original callExternalAPI to simulate success callExternalAPI = func() (int, error) { resp, err := http.Get(server.URL) if err != nil { return 0, err } defer resp.Body.Close() return resp.StatusCode, nil } _, err := cb.Execute(func() (interface{}, error) { return callExternalAPI() }) if err != nil { t.Fatalf("expected no error, got %v", err) } if cb.State() != gobreaker.StateHalfOpen { t.Fatalf("expected circuit breaker to be half-open, got %v", cb.State()) } //After verifying the half-open state, another successful request is simulated to ensure the circuit breaker transitions back to the closed state. for i := 0; i < int(settings.MaxRequests); i++ { _, err = cb.Execute(func() (interface{}, error) { return callExternalAPI() }) if err != nil { t.Fatalf("expected no error, got %v", err) } } if cb.State() != gobreaker.StateClosed { t.Fatalf("expected circuit breaker to be closed, got %v", cb.State()) } })
Salin selepas log masuk- Mari kita uji keadaan ReadyToTrip yang tercetus selepas 2 permintaan kegagalan berturut-turut. Kami akan mempunyai pembolehubah yang menjejaki kegagalan berturut-turut. Panggilan balik ReadyToTrip dikemas kini untuk memeriksa sama ada pemutus litar terputus selepas 2 kegagalan ( dikira.ConsecutiveFailures > 2). Kami akan menulis ujian yang mensimulasikan kegagalan dan mengesahkan kiraan dan peralihan pemutus litar ke keadaan terbuka selepas bilangan kegagalan yang ditentukan.
t.Run("ReadyToTrip", func(t *testing.T) { failures := 0 settings.ReadyToTrip = func(counts gobreaker.Counts) bool { failures = int(counts.ConsecutiveFailures) return counts.ConsecutiveFailures > 2 // Trip after 2 failures } cb = gobreaker.NewCircuitBreaker(settings) // Simulate failures callExternalAPI = func() (int, error) { return 0, errors.New("simulated failure") } for i := 0; i < 3; i++ { _, err := cb.Execute(func() (interface{}, error) { return callExternalAPI() }) if err == nil { t.Fatalf("expected error, got none") } } if failures != 3 { t.Fatalf("expected 3 consecutive failures, got %d", failures) } if cb.State() != gobreaker.StateOpen { t.Fatalf("expected circuit breaker to be open, got %v", cb.State()) } })
Salin selepas log masukStrategi Lanjutan
Kami boleh melangkah lebih jauh dengan menambahkan strategi mundur eksponen pada pelaksanaan pemutus litar kami. Kami akan memastikan artikel ini ringkas dan ringkas dengan menunjukkan contoh strategi mundur eksponen. Walau bagaimanapun, terdapat strategi lanjutan lain untuk pemutus litar yang patut disebut, seperti penumpahan beban, sekat, mekanisme sandaran, konteks dan pembatalan. Strategi ini pada asasnya meningkatkan keteguhan dan kefungsian pemutus litar. Berikut ialah contoh menggunakan strategi mundur eksponen:
Penyingkiran Eksponen
Pemutus litar dengan mundur eksponen
Mari kita jelaskan beberapa perkara:
Fungsi Backoff Tersuai: Fungsi ExponentialBackoff melaksanakan strategi backoff eksponen dengan jitter. Ia pada asasnya mengira masa mundur berdasarkan bilangan percubaan, memastikan bahawa kelewatan meningkat secara eksponen dengan setiap percubaan mencuba semula.
Mengendalikan Percubaan Semula: Seperti yang anda lihat dalam pengendali /api, logik kini termasuk gelung yang cuba memanggil API luaran sehingga bilangan percubaan yang ditentukan ( percubaan := 5). Selepas setiap percubaan yang gagal, kami menunggu tempoh yang ditentukan oleh fungsi ExponentialBackoff sebelum mencuba semula.
Perlaksanaan Pemutus Litar: Pemutus litar digunakan dalam gelung. Jika panggilan API luaran berjaya ( err == nil), gelung pecah, dan hasil yang berjaya dikembalikan. Jika semua percubaan gagal, ralat HTTP 503 (Perkhidmatan Tidak Tersedia) dikembalikan.
Mengintegrasikan strategi mundur tersuai dalam pelaksanaan pemutus litar sememangnya bertujuan untuk mengendalikan ralat sementara dengan lebih anggun. Kelewatan yang semakin meningkat antara percubaan semula membantu mengurangkan beban pada perkhidmatan yang gagal, memberikan masa untuk pulih. Seperti yang terbukti dalam kod kami di atas, fungsi ExponentialBackoff kami telah diperkenalkan untuk menambah kelewatan antara percubaan semula apabila memanggil API luaran.
Selain itu, kami boleh menyepadukan metrik dan pengelogan untuk memantau perubahan keadaan pemutus litar menggunakan alat seperti Prometheus untuk pemantauan dan amaran masa nyata. Berikut ialah contoh mudah:
Melaksanakan corak pemutus litar dengan strategi lanjutan semasa
Seperti yang anda akan lihat, kini kami telah melakukan perkara berikut:
- Dalam L16–21, kami mentakrifkan vektor pembilang prometheus untuk menjejaki bilangan permintaan dan keadaannya (berjaya, kegagalan, perubahan keadaan pemutus litar).
- Dalam L25–26, metrik yang ditakrifkan didaftarkan dengan Prometheus dalam fungsi init.
Petua Pro : Fungsi init dalam Go digunakan untuk memulakan keadaan pakej sebelum fungsi utama atau mana-mana kod lain dalam pakej dilaksanakan. Dalam kes ini, fungsi init mendaftarkan metrik requestCount dengan Prometheus. Dan ini pada asasnya memastikan bahawa Prometheus mengetahui metrik ini dan boleh mula mengumpul data sebaik sahaja aplikasi mula berjalan.
Kami mencipta pemutus litar dengan tetapan tersuai, termasuk fungsi ReadyToTrip yang meningkatkan pembilang kegagalan dan menentukan masa untuk mengelirukan litar.
OnStateChange untuk mencatat perubahan keadaan dan menambah metrik prometheus yang sepadan
Kami mendedahkan metrik Prometheus pada titik akhir /metrics
Membungkus
Untuk mengakhiri artikel ini, saya harap anda melihat bagaimana pemutus litar memainkan peranan yang besar dalam membina sistem yang berdaya tahan dan boleh dipercayai. Dengan secara proaktif mencegah kegagalan melata, mereka mengukuhkan kebolehpercayaan perkhidmatan mikro dan sistem yang diedarkan, memastikan pengalaman pengguna yang lancar walaupun dalam menghadapi kesukaran.
Perlu diingat, mana-mana sistem yang direka untuk skalabiliti mesti menggabungkan strategi untuk menangani kegagalan dengan anggun dan pulih dengan pantas — Oluwafemi , 2024
Asalnya diterbitkan di https://oluwafemiakinde.dev pada 7 Jun 2024.
Atas ialah kandungan terperinci Pemutus Litar dalam Go: Hentikan Kegagalan Lata. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!
- Mari kita uji keadaan ReadyToTrip yang tercetus selepas 2 permintaan kegagalan berturut-turut. Kami akan mempunyai pembolehubah yang menjejaki kegagalan berturut-turut. Panggilan balik ReadyToTrip dikemas kini untuk memeriksa sama ada pemutus litar terputus selepas 2 kegagalan ( dikira.ConsecutiveFailures > 2). Kami akan menulis ujian yang mensimulasikan kegagalan dan mengesahkan kiraan dan peralihan pemutus litar ke keadaan terbuka selepas bilangan kegagalan yang ditentukan.

Alat AI Hot

Undresser.AI Undress
Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover
Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool
Gambar buka pakaian secara percuma

Clothoff.io
Penyingkiran pakaian AI

Video Face Swap
Tukar muka dalam mana-mana video dengan mudah menggunakan alat tukar muka AI percuma kami!

Artikel Panas

Alat panas

Notepad++7.3.1
Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina
Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1
Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6
Alat pembangunan web visual

SublimeText3 versi Mac
Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Topik panas











Golang lebih baik daripada Python dari segi prestasi dan skalabiliti. 1) Ciri-ciri jenis kompilasi Golang dan model konkurensi yang cekap menjadikannya berfungsi dengan baik dalam senario konvensional yang tinggi. 2) Python, sebagai bahasa yang ditafsirkan, melaksanakan perlahan -lahan, tetapi dapat mengoptimumkan prestasi melalui alat seperti Cython.

Golang lebih baik daripada C dalam kesesuaian, manakala C lebih baik daripada Golang dalam kelajuan mentah. 1) Golang mencapai kesesuaian yang cekap melalui goroutine dan saluran, yang sesuai untuk mengendalikan sejumlah besar tugas serentak. 2) C Melalui pengoptimuman pengkompil dan perpustakaan standard, ia menyediakan prestasi tinggi yang dekat dengan perkakasan, sesuai untuk aplikasi yang memerlukan pengoptimuman yang melampau.

GoisidealforbeginnersandSuekableforcloudandnetworkservicesduetoitssimplicity, kecekapan, danconcurrencyfeatures.1) installgofromtheofficialwebsiteandverifywith'goversion'.2)

Golang sesuai untuk pembangunan pesat dan senario serentak, dan C sesuai untuk senario di mana prestasi ekstrem dan kawalan peringkat rendah diperlukan. 1) Golang meningkatkan prestasi melalui pengumpulan sampah dan mekanisme konvensional, dan sesuai untuk pembangunan perkhidmatan web yang tinggi. 2) C mencapai prestasi muktamad melalui pengurusan memori manual dan pengoptimuman pengkompil, dan sesuai untuk pembangunan sistem tertanam.

Goimpactsdevelopmentpositivielythroughspeed, efficiency, andsimplicity.1) Speed: goCompilesquicklyandrunsefficiently, idealforlargeproject.2) Kecekapan: ITSComprehensivestandardlibraryraryrarexternaldependencies, enhingdevelyficiency.

Golang dan Python masing -masing mempunyai kelebihan mereka sendiri: Golang sesuai untuk prestasi tinggi dan pengaturcaraan serentak, sementara Python sesuai untuk sains data dan pembangunan web. Golang terkenal dengan model keserasiannya dan prestasi yang cekap, sementara Python terkenal dengan sintaks ringkas dan ekosistem perpustakaan yang kaya.

Perbezaan prestasi antara Golang dan C terutamanya ditunjukkan dalam pengurusan ingatan, pengoptimuman kompilasi dan kecekapan runtime. 1) Mekanisme pengumpulan sampah Golang adalah mudah tetapi boleh menjejaskan prestasi, 2) Pengurusan memori manual C dan pengoptimuman pengkompil lebih cekap dalam pengkomputeran rekursif.

Golang dan C masing-masing mempunyai kelebihan sendiri dalam pertandingan prestasi: 1) Golang sesuai untuk kesesuaian tinggi dan perkembangan pesat, dan 2) C menyediakan prestasi yang lebih tinggi dan kawalan halus. Pemilihan harus berdasarkan keperluan projek dan tumpukan teknologi pasukan.
