Resilience patterns - bu microservice tizimda bir service ishdan chiqsa yoki sekinlashsa, butun system qulab tushmasligi uchun ishlatiladigan patternlar. Bu mavzu Spring Cloud ecosystem’dan keyingi muhim blok sifatida keladi: Resilience4j, fallback strategies, timeout propagation, idempotency keys, graceful degradation.
1. Muammo: microservice’da xato zanjir bo‘lib tarqaladi
Oddiy flow:
Client
↓
Gateway
↓
Order Service
↓
Payment Service
↓
Bank APIAgar Bank API sekinlashsa:
Bank API sekin
↓
Payment Service kutadi
↓
Order Service kutadi
↓
Gateway kutadi
↓
Client timeout oladiYomon tomoni: bitta tashqi service muammosi butun tizimni sekinlashtiradi.
Resilience patternlar shuni oldini oladi.
2. Resilience4j nima?
Resilience4j - Java/Spring Boot’da fault-tolerance uchun ishlatiladigan kutubxona.
U quyidagi patternlarni beradi:
Pattern | Vazifasi |
|---|---|
CircuitBreaker | Buzilgan service’ga request yuborishni vaqtincha to‘xtatadi |
Retry | Xato bo‘lsa qayta urinadi |
RateLimiter | Juda ko‘p request kelishini cheklaydi |
Bulkhead | Resurslarni izolyatsiya qiladi |
TimeLimiter | Juda uzoq ishlayotgan call’ni timeout qiladi |
Fallback | Asosiy call ishlamasa alternativ javob qaytaradi |
Dependency:
<dependency>
<groupId>io.github.resilience4j</groupId>
<artifactId>resilience4j-spring-boot3</artifactId>
</dependency>3. CircuitBreaker
Nima qiladi?
CircuitBreaker - elektr avtomatga o‘xshaydi.
Agar service ko‘p xato qaytarsa, CircuitBreaker uni vaqtincha "o‘chiradi".
Normal holat:
Order Service → Payment Service
Payment Service xato bera boshlaydi:
Order Service → CircuitBreaker → requestni bloklaydi
Birozdan keyin:
CircuitBreaker test request yuboradiCircuitBreaker holatlari
CLOSED → normal ishlaydi
OPEN → request yubormaydi
HALF_OPEN → test uchun ozgina request yuboradi1. CLOSED
Hammasi normal.
Order Service → Payment Service2. OPEN
Xato ko‘paydi. CircuitBreaker request yubormaydi.
Order Service → fallback response3. HALF_OPEN
Biroz vaqt o‘tgach, service tuzaldimi deb tekshiradi.
Order Service → Payment Service test callAgar muvaffaqiyatli bo‘lsa:
HALF_OPEN → CLOSEDAgar yana xato bo‘lsa:
HALF_OPEN → OPENSpring Boot misol
@Service
@RequiredArgsConstructor
public class PaymentService {
private final BankClient bankClient;
@CircuitBreaker(name = "bankService", fallbackMethod = "paymentFallback")
public PaymentResponse pay(PaymentRequest request) {
return bankClient.charge(request);
}
public PaymentResponse paymentFallback(PaymentRequest request, Throwable ex) {
return new PaymentResponse(
"PENDING",
"Bank service vaqtincha ishlamayapti. To‘lov keyinroq qayta tekshiriladi."
);
}
}Bu yerda:
@CircuitBreaker(name = "bankService", fallbackMethod = "paymentFallback")shuni bildiradi:
Agar
bankClient.charge()ko‘p xato bersa, fallback ishlaydi.
Config misol
resilience4j:
circuitbreaker:
instances:
bankService:
slidingWindowSize: 10
failureRateThreshold: 50
waitDurationInOpenState: 10s
permittedNumberOfCallsInHalfOpenState: 3Tushuntirish:
Config | Ma’nosi |
|---|---|
| Oxirgi 10 ta call hisoblanadi |
| 50% xato bo‘lsa breaker ochiladi |
| 10 sekund OPEN holatda turadi |
| HALF_OPEN’da 3 ta test call yuboradi |
4. Retry
Nima qiladi?
Retry - vaqtinchalik xatoda qayta urinadi.
Masalan:
1-call → timeout
2-call → timeout
3-call → successBu foydali bo‘lishi mumkin, lekin noto‘g‘ri ishlatilsa tizimni yanada bosib yuboradi.
Qachon Retry qilish mumkin?
Retry qilish mumkin:
Holat | Retry mumkinmi? |
|---|---|
Network timeout | Ha |
Temporary 503 | Ha |
Rate limit 429 | Ehtiyotkorlik bilan |
Validation error 400 | Yo‘q |
Unauthorized 401 | Yo‘q |
Payment already processed | Yo‘q, idempotency bo‘lmasa xavfli |
Retry misol
@Service
@RequiredArgsConstructor
public class NotificationService {
private final SmsClient smsClient;
@Retry(name = "smsService", fallbackMethod = "smsFallback")
public SmsResponse sendSms(SmsRequest request) {
return smsClient.send(request);
}
public SmsResponse smsFallback(SmsRequest request, Throwable ex) {
return new SmsResponse("FAILED", "SMS hozir yuborilmadi");
}
}Config:
resilience4j:
retry:
instances:
smsService:
maxAttempts: 3
waitDuration: 500msBu nima qiladi?
1-urinish
500ms kutadi
2-urinish
500ms kutadi
3-urinish
xato bo‘lsa fallbackRetry xavfi
Eng katta xato:
1000 ta request
har biri 3 marta retry qiladi
=
3000 ta requestBu sekinlashgan service’ni yanada yiqitadi.
Shuning uchun retry doim quyidagilar bilan birga o‘ylanadi:
Retry + Timeout + CircuitBreaker + Idempotency5. RateLimiter
Nima qiladi?
RateLimiter - ma’lum vaqt ichida nechta request o‘tishini cheklaydi.
Masalan:
1 sekundda faqat 100 ta requestAgar undan ko‘p bo‘lsa:
Too many requestsQayerda ishlatiladi?
Joy | Misol |
|---|---|
API Gateway | Client request’larini cheklash |
External API client | Bank API’ga ko‘p request yubormaslik |
Expensive operation | PDF generate, report export |
Login endpoint | Brute force’dan himoya |
Misol
@Service
@RequiredArgsConstructor
public class ReportService {
private final ReportClient reportClient;
@RateLimiter(name = "reportLimiter", fallbackMethod = "rateLimitFallback")
public ReportResponse generateReport(Long userId) {
return reportClient.generate(userId);
}
public ReportResponse rateLimitFallback(Long userId, Throwable ex) {
return new ReportResponse("TOO_MANY_REQUESTS", "Birozdan keyin urinib ko‘ring");
}
}Config:
resilience4j:
ratelimiter:
instances:
reportLimiter:
limitForPeriod: 10
limitRefreshPeriod: 1s
timeoutDuration: 0Bu nimani bildiradi?
1 sekundda 10 ta request o‘tadi.
11-request darhol reject bo‘ladi.6. Bulkhead
Nima qiladi?
Bulkhead - tizim resurslarini bo‘lib qo‘yadi.
Kema misoli:
Kemaning bitta qismi suvga to‘lsa ham, butun kema cho‘kmaydi.Microservice’da ham shunday:
Payment API sekinlashsa,
Notification API uchun threadlar band bo‘lib qolmasligi kerak.Bulkhead bo‘lmasa
Thread pool: 100 thread
Payment call sekinlashdi
↓
100 thread ham Payment’da kutib qoldi
↓
Order, User, Notification ham ishlamay qoldiBulkhead bilan
Payment uchun: 20 thread
Notification uchun: 20 thread
User uchun: 20 thread
Payment sekinlashsa ham,
boshqa qismlar ishlashda davom etadi.Misol
@Service
@RequiredArgsConstructor
public class PaymentClientService {
private final PaymentClient paymentClient;
@Bulkhead(name = "paymentBulkhead", fallbackMethod = "bulkheadFallback")
public PaymentResponse pay(PaymentRequest request) {
return paymentClient.pay(request);
}
public PaymentResponse bulkheadFallback(PaymentRequest request, Throwable ex) {
return new PaymentResponse("BUSY", "Payment service hozir band");
}
}Config:
resilience4j:
bulkhead:
instances:
paymentBulkhead:
maxConcurrentCalls: 20
maxWaitDuration: 100msBu nimani bildiradi?
Config | Ma’nosi |
|---|---|
| Bir vaqtda faqat 20 ta call |
| Joy bo‘shashini 100ms kutadi |
7. TimeLimiter / Timeout
Nima qiladi?
Timeout - call juda uzoq cho‘zilib ketsa, uni to‘xtatadi.
Yomon holat:
Order Service → Payment Service
kutadi...
kutadi...
kutadi...Yaxshi holat:
Order Service → Payment Service
2 sekund kutadi
timeout
fallbackTimeout nega muhim?
Timeout bo‘lmasa:
Threadlar band bo‘lib qoladi.
Connection pool to‘lib qoladi.
Gateway timeout beradi.
Client tajribasi yomonlashadi.
System domino kabi yiqiladi.
Timeout propagation
Senior darajada eng muhim joy shu.
Agar client umumiy 5 sekund kutsa, ichki service’lar ham shunga mos timeout olishi kerak.
Yomon:
Client timeout: 5s
Gateway timeout: 10s
Order timeout: 15s
Payment timeout: 30sBu xato. Chunki client allaqachon ketib bo‘lgan bo‘ladi, lekin backend hali ham ishlaydi.
Yaxshi:
Client timeout: 5s
Gateway timeout: 4.5s
Order timeout: 3s
Payment timeout: 1.5s
Bank API timeout: 1sYa’ni timeout ichkariga kirgan sari kichrayadi.
8. Fallback strategies
Fallback nima?
Fallback - asosiy service ishlamasa, alternativ javob qaytarish.
Masalan:
Recommendation Service ishlamadi
↓
Popular products qaytarYoki:
Payment Service timeout
↓
Order status = PENDING_PAYMENTFallback turlari
Fallback turi | Misol |
|---|---|
Static fallback | "Service vaqtincha ishlamayapti" |
Cached fallback | Oldingi cache’dagi ma’lumotni qaytarish |
Default fallback | Default qiymat berish |
Queue fallback | Request’ni queue’ga yozib, keyin process qilish |
Degraded response | Kamroq ma’lumot bilan javob qaytarish |
Real misollar
1. Product rating fallback
Rating Service ishlamasa:
rating = nullResponse:
{
"id": 10,
"name": "iPhone 15",
"rating": null
}Bu yaxshi. Product sahifasi butunlay yiqilmaydi.
2. Payment fallback
Payment’da ehtiyot bo‘lish kerak.
Yomon:
Payment timeout bo‘ldi
↓
Order SUCCESS qilib qo‘yishBu xavfli.
Yaxshi:
Payment timeout bo‘ldi
↓
Order PENDING_PAYMENT
↓
Payment status keyin tekshiriladi3. Notification fallback
SMS yuborilmadi
↓
Email yuborYoki:
SMS yuborilmadi
↓
notification_outbox table’ga yoz
↓
background job keyin yuboradi9. Idempotency keys
Muammo
User payment tugmasini ikki marta bosdi:
POST /payments
POST /paymentsYoki retry sababli request ikki marta ketdi:
1-request timeout
2-request retryAgar idempotency bo‘lmasa:
Userdan 2 marta pul yechilishi mumkin.Idempotency nima?
Idempotency - bir xil request bir necha marta yuborilsa ham natija bir marta bajariladi.
Client header yuboradi:
Idempotency-Key: 8f7b4c1a-123-paymentBackend bu key’ni saqlaydi.
Idempotency-Key bor
↓
oldin ishlanganmi?
↓
ha → eski response qaytar
yo‘q → operation bajar va key’ni saqlaPayment misol
@PostMapping("/payments")
public PaymentResponse pay(
@RequestHeader("Idempotency-Key") String idempotencyKey,
@RequestBody PaymentRequest request
) {
return paymentService.pay(idempotencyKey, request);
}Service:
@Transactional
public PaymentResponse pay(String key, PaymentRequest request) {
Optional<PaymentLog> existing = paymentLogRepository.findByIdempotencyKey(key);
if (existing.isPresent()) {
return existing.get().toResponse();
}
PaymentResponse response = bankClient.charge(request);
paymentLogRepository.save(
new PaymentLog(key, request.amount(), response.status())
);
return response;
}Database’da unique constraint kerak:
ALTER TABLE payment_log
ADD CONSTRAINT uk_payment_idempotency_key UNIQUE (idempotency_key);Bu juda muhim. Faqat Java check yetmaydi. Parallel request kelganda DB unique constraint himoya qiladi.
10. Graceful degradation
Nima?
Graceful degradation - tizim to‘liq yiqilmasdan, kamroq imkoniyat bilan ishlashda davom etishi.
Masalan:
Search service ishlamayapti
↓
Category bo‘yicha oddiy list qaytarYoki:
Recommendation ishlamayapti
↓
Popular products ko‘rsatYoki:
Analytics ishlamayapti
↓
User flow davom etadi, analytics keyin yuboriladiMuhim qoida
Har bir service bir xil critical emas.
Service | Critical daraja | Degradation |
|---|---|---|
Payment | Juda critical | PENDING status |
Login | Juda critical | Fallback deyarli yo‘q |
Recommendation | Pastroq | Popular list |
Notification | O‘rta | Queue’ga yozish |
Analytics | Past | Drop yoki async retry |
Rating | Past | Null/default rating |
11. Patternlarni noto‘g‘ri ishlatish
Xato 1: Har joyga Retry qo‘yish
Yomon:
Gateway retry
Order retry
Payment retry
Bank client retryNatija:
1 request → 3 × 3 × 3 × 3 = 81 requestBu retry storm deyiladi.
Xato 2: Fallback’da yolg‘on success qaytarish
Yomon:
public PaymentResponse fallback(...) {
return new PaymentResponse("SUCCESS");
}Bu production’da moliyaviy muammo keltiradi.
To‘g‘ri:
public PaymentResponse fallback(...) {
return new PaymentResponse("PENDING");
}Xato 3: Timeout yo‘q
Timeoutsiz HTTP call - production’da xavfli.
Har bir external call’da timeout bo‘lishi kerak:
connect timeout
read timeout
overall timeoutXato 4: CircuitBreaker threshold juda agressiv
Masalan:
failureRateThreshold: 10
slidingWindowSize: 55 ta requestdan bittasi xato bo‘lsa, breaker ochilishi mumkin. Bu false alarm beradi.
12. Real architecture example
Order yaratish flow:
Client
↓
Gateway
↓
Order Service
├── Inventory Service
├── Payment Service
└── Notification ServiceResilience bilan:
Order Service
├── Inventory Service
│ ├── Timeout: 1s
│ ├── Retry: 2 attempts
│ └── CircuitBreaker
│
├── Payment Service
│ ├── Timeout: 2s
│ ├── Idempotency-Key
│ ├── CircuitBreaker
│ └── Fallback: PENDING_PAYMENT
│
└── Notification Service
├── Async
├── Retry
└── Fallback: Outbox table13. Senior darajadagi qarorlar
Senior developer faqat annotation qo‘ymaydi. U quyidagi qarorlarni beradi:
1. Qaysi xatoda retry qilamiz?
Timeout → retry mumkin
500 → retry mumkin
400 → retry yo‘q
401 → retry yo‘q
Payment duplicate risk → retry faqat idempotency bilan2. Timeout qancha bo‘ladi?
Har bir service uchun alohida:
Payment: 2s
Inventory: 1s
Notification: async
Recommendation: 500ms3. Fallback business jihatdan to‘g‘rimi?
Technical fallback yetarli emas. Business holat to‘g‘ri bo‘lishi kerak.
Payment failed → order success emas
Payment unknown → pending
Notification failed → order failed emas4. Observability bormi?
Resilience pattern ishlayotganini ko‘rish kerak:
circuitbreaker.open.count
retry.calls
fallback.count
timeout.count
rate_limited.count14. Minimal production config namunasi
resilience4j:
circuitbreaker:
instances:
paymentService:
slidingWindowType: COUNT_BASED
slidingWindowSize: 20
minimumNumberOfCalls: 10
failureRateThreshold: 50
waitDurationInOpenState: 15s
permittedNumberOfCallsInHalfOpenState: 5
retry:
instances:
paymentService:
maxAttempts: 2
waitDuration: 300ms
bulkhead:
instances:
paymentService:
maxConcurrentCalls: 30
maxWaitDuration: 100ms
ratelimiter:
instances:
paymentService:
limitForPeriod: 100
limitRefreshPeriod: 1s
timeoutDuration: 015. Qisqa interview javob
Agar suhbatda so‘rasa:
Resilience patterns nima?
Javob:
Resilience patterns microservice tizimda xatolar tarqalib ketmasligi uchun ishlatiladi.
Masalan, CircuitBreaker buzilgan service’ga request yuborishni vaqtincha to‘xtatadi,
Retry vaqtinchalik xatoda qayta urinadi, RateLimiter ortiqcha requestni cheklaydi,
Bulkhead resurslarni izolyatsiya qiladi, Timeout sekin call’larni to‘xtatadi,
Fallback esa service ishlamasa alternativ javob qaytaradi.
Senior darajada bularni biznes holat bilan moslashtirish muhim:
payment’da fallback SUCCESS bo‘lmasligi kerak, PENDING bo‘lishi kerak.
Retry esa faqat idempotency bilan xavfsiz bo‘ladi.16. Eng muhim xulosa
Resilience patternlarning asosiy maqsadi:
Bitta service yiqilsa, butun system yiqilmasin.Eng kerakli kombinatsiya:
Timeout
+ CircuitBreaker
+ Retry
+ Fallback
+ Bulkhead
+ Idempotency
+ ObservabilitySenior developer uchun eng muhim narsa - annotation yodlash emas, qaysi biznes holatda qaysi pattern xavfsiz yoki xavfli ekanini bilish.