GoDasturchi
Circuit Breaker Pattern

Circuit Breaker Pattern

Circuit Breaker (elektr uzgichi) naqshi

Uyingizdagi elektr shchitidagi "avtomat uzgich"ni bilasizmi? Agar biror asbob juda ko'p tok tortsa (qisqa tutashuv bo'lsa), uzgich avtomatik ravishda o'chadi — butun uyni yong'indan himoya qilish uchun. U darhol qayta yoqilmaydi, chunki muammo hali ham davom etayotgan bo'lishi mumkin.

Dasturda ham xuddi shunday muammo bor: agar sizning xizmatingiz boshqa (masalan tashqi) xizmatga so'rov yuborsa-yu, u xizmat ishlamay qolgan bo'lsa, har bir so'rovni baribir yuborishda davom etish — vaqtni behuda sarflaydi (har biri xato bilan tugaguncha kutish kerak) va hatto vaziyatni yomonlashtirishi mumkin (allaqachon qiynalayotgan xizmatga yana ko'proq so'rov yuborish). Circuit Breaker — bunday holatda "uzgichni o'chirib", bir muddat so'rov yubormaslikni tanlaydi.

example.go
package main

import (
	"errors"
	"fmt"
)

type CircuitBreaker struct {
	failureCount int
	threshold    int
	open         bool
}

func NewCircuitBreaker(threshold int) *CircuitBreaker {
	return &CircuitBreaker{threshold: threshold}
}

func (cb *CircuitBreaker) Call(fn func() error) error {
	if cb.open {
		return errors.New("circuit ochiq: so'rov rad etildi")
	}
	err := fn()
	if err != nil {
		cb.failureCount++
		if cb.failureCount >= cb.threshold {
			cb.open = true
		}
		return err
	}
	cb.failureCount = 0
	return nil
}

func main() {
	cb := NewCircuitBreaker(3)
	failing := func() error { return errors.New("xato") }

	for i := 0; i < 3; i++ {
		fmt.Println(cb.Call(failing))
	}
	fmt.Println(cb.Call(func() error { return nil }))
}

CircuitBreaker ichki holatni kuzatib boradi: har bir muvaffaqiyatsiz chaqiruvdan keyin failureCount oshadi. Agar u threshold (chegara)ga yetsa, opentrue bo'ladi, ya'ni "uzgich ochildi". Shundan keyin Call chaqirilganda, u haqiqiy funksiyani (fn) umuman chaqirmaydi — darhol xato qaytaradi, xuddi "hozir urinmang, xizmat baribir ishlamayapti" deganday.

E'tibor bering: bu soddalashtirilgan misolda open bo'lgach hech qachon avtomatik yopilmaydi. Haqiqiy Circuit Breaker'larda (masalan mashhur "half-open" holati bilan) ma'lum vaqtdan keyin "ehtiyotkorlik bilan" bitta sinov so'rovi yuboriladi — agar u muvaffaqiyatli bo'lsa, uzgich yana yopiladi ("normal ishlash" tiklanadi). Bu — ishlab chiqarish darajasidagi tarmoq mijozlarining (masalan gRPC yoki HTTP klientlar kutubxonasining) muhim qismi.

>_ Exercise

Circuit Breaker'ga holatni qo'lda tiklash (Reset) imkonini qo'shing.

  • Reset() metodini yozing: failureCount'ni 0 ga, open'ni false ga qaytaring
  • 3 marta xato chaqiruvidan keyin Reset() qiling
  • so'ng muvaffaqiyatli chaqiruv (nil qaytaradigan) qilib, natijani chop eting

Stuck? Reveal a hint to help you.

Hints (0/3)

Key Takeaway

Key Takeaway:

Circuit Breaker — muvaffaqiyatsiz chaqiruvlar chegaraga yetganda, keyingi so'rovlarni vaqtincha butunlay rad etib, ishlamayotgan xizmatga ortiqcha yuk tushishining oldini oladi.

NEXT UP

Graceful Shutdown Basics

OUTPUT

$ go run main.go
Kodingizni ishga tushiring

Circuit Breaker Pattern

Circuit Breaker (elektr uzgichi) naqshi

Uyingizdagi elektr shchitidagi "avtomat uzgich"ni bilasizmi? Agar biror asbob juda ko'p tok tortsa (qisqa tutashuv bo'lsa), uzgich avtomatik ravishda o'chadi — butun uyni yong'indan himoya qilish uchun. U darhol qayta yoqilmaydi, chunki muammo hali ham davom etayotgan bo'lishi mumkin.

Dasturda ham xuddi shunday muammo bor: agar sizning xizmatingiz boshqa (masalan tashqi) xizmatga so'rov yuborsa-yu, u xizmat ishlamay qolgan bo'lsa, har bir so'rovni baribir yuborishda davom etish — vaqtni behuda sarflaydi (har biri xato bilan tugaguncha kutish kerak) va hatto vaziyatni yomonlashtirishi mumkin (allaqachon qiynalayotgan xizmatga yana ko'proq so'rov yuborish). Circuit Breaker — bunday holatda "uzgichni o'chirib", bir muddat so'rov yubormaslikni tanlaydi.

example.go
package main

import (
	"errors"
	"fmt"
)

type CircuitBreaker struct {
	failureCount int
	threshold    int
	open         bool
}

func NewCircuitBreaker(threshold int) *CircuitBreaker {
	return &CircuitBreaker{threshold: threshold}
}

func (cb *CircuitBreaker) Call(fn func() error) error {
	if cb.open {
		return errors.New("circuit ochiq: so'rov rad etildi")
	}
	err := fn()
	if err != nil {
		cb.failureCount++
		if cb.failureCount >= cb.threshold {
			cb.open = true
		}
		return err
	}
	cb.failureCount = 0
	return nil
}

func main() {
	cb := NewCircuitBreaker(3)
	failing := func() error { return errors.New("xato") }

	for i := 0; i < 3; i++ {
		fmt.Println(cb.Call(failing))
	}
	fmt.Println(cb.Call(func() error { return nil }))
}

CircuitBreaker ichki holatni kuzatib boradi: har bir muvaffaqiyatsiz chaqiruvdan keyin failureCount oshadi. Agar u threshold (chegara)ga yetsa, opentrue bo'ladi, ya'ni "uzgich ochildi". Shundan keyin Call chaqirilganda, u haqiqiy funksiyani (fn) umuman chaqirmaydi — darhol xato qaytaradi, xuddi "hozir urinmang, xizmat baribir ishlamayapti" deganday.

E'tibor bering: bu soddalashtirilgan misolda open bo'lgach hech qachon avtomatik yopilmaydi. Haqiqiy Circuit Breaker'larda (masalan mashhur "half-open" holati bilan) ma'lum vaqtdan keyin "ehtiyotkorlik bilan" bitta sinov so'rovi yuboriladi — agar u muvaffaqiyatli bo'lsa, uzgich yana yopiladi ("normal ishlash" tiklanadi). Bu — ishlab chiqarish darajasidagi tarmoq mijozlarining (masalan gRPC yoki HTTP klientlar kutubxonasining) muhim qismi.

>_ Exercise

Circuit Breaker'ga holatni qo'lda tiklash (Reset) imkonini qo'shing.

  • Reset() metodini yozing: failureCount'ni 0 ga, open'ni false ga qaytaring
  • 3 marta xato chaqiruvidan keyin Reset() qiling
  • so'ng muvaffaqiyatli chaqiruv (nil qaytaradigan) qilib, natijani chop eting

Stuck? Reveal a hint to help you.

Hints (0/3)

Key Takeaway

Key Takeaway:

Circuit Breaker — muvaffaqiyatsiz chaqiruvlar chegaraga yetganda, keyingi so'rovlarni vaqtincha butunlay rad etib, ishlamayotgan xizmatga ortiqcha yuk tushishining oldini oladi.

NEXT UP

Graceful Shutdown Basics