Pokazywanie postów oznaczonych etykietą microservices. Pokaż wszystkie posty
Pokazywanie postów oznaczonych etykietą microservices. Pokaż wszystkie posty

poniedziałek, 21 lipca 2025

EA 12 factor app - fundament dla nowoczesnych aplikacji chmurowych czy przestarzały hype?

 W poprzednim wpisie „EA: 12 Factor Agents — Nowe podejście, które może zmienić Twoje myślenie o AI” zaproponowałem przeniesienie idei 12 Factor App na grunt architektury agentowej. Czas wrócić do źródeł i przyjrzeć się oryginalnemu manifestowi 12factor.net, który — mimo że powstał ponad dekadę temu — wciąż stanowi solidny fundament dla budowania nowoczesnych aplikacji chmurowych, mikrousług i systemów agentowych.



Dlaczego warto znać 12 Factor App?

Zasady 12 Factor App to nie przepis na framework czy technologię, ale zestaw praktyk projektowych, które pomagają budować aplikacje:

  • przenośne (cloud-native),

  • skalowalne poziomo,

  • łatwe do wdrażania, monitorowania i rozwijania.

W świecie, w którym infrastruktura staje się zautomatyzowana, a aplikacje coraz bardziej rozproszone, te zasady okazują się nie tyle dobrowolnymi rekomendacjami, co warunkiem „przeżycia” w produkcji.

12 czynników — w skrócie i z komentarzem architekta

Przyjrzyjmy się krótko każdemu z 12 czynników, z perspektywy osoby projektującej systemy rozproszone, często hybrydowe, integrujące się z agentami, API, systemami kolejkowymi i narzędziami DevOps.

1. Codebase — jedna baza kodu na aplikację

Każdy serwis powinien mieć jedno źródło prawdy (repozytorium Git). W przypadku systemów agentowych może to oznaczać, że agent to również jednostka wdrożeniowa (np. kontener), a nie biblioteka współdzielona przez inne serwisy.

2. Dependencies — jawne zarządzanie zależnościami

Brak polegania na globalnym środowisku (jak systemowe paczki). W świecie micro-agents oznacza to np. unikanie ukrytych zależności między agentami a platformą hostującą.

3. Config — konfiguracja przez zmienne środowiskowe

Oddzielenie kodu od konfiguracji to baza dla portowalności i automatyzacji — zarówno w CI/CD, jak i w orkiestracji (Kubernetes, Nomad).

4. Backing services — traktuj zewnętrzne zasoby jak attachable

Usługi takie jak bazy danych, kolejki, pamięci cache są zależnościami, nie integralną częścią aplikacji. Ułatwia to testowanie, replikację, skalowanie.

5. Build, release, run — rozdzielenie etapów cyklu życia aplikacji

Oddzielenie builda (np. Docker image), release'u (konfiguracja + build) i uruchomienia (run-time). Kluczowe przy wersjonowaniu agentów i rollbackach.

6. Processes — bezstanowe procesy

Statelessness to kręgosłup skalowalności i niezawodności. Dane sesyjne powinny trafić do Redis, a nie do pamięci agenta.

7. Port binding — self-contained aplikacje nasłuchujące na porcie

Każda aplikacja (lub agent) powinna być samodzielna i gotowa do uruchomienia w dowolnym środowisku przez proste docker run.

8. Concurrency — skalowanie przez procesy

Nie chodzi tylko o wielowątkowość, ale o świadome projektowanie poziomów równoległości (np. web, worker, cron). W systemach agentowych: osobne procesy dla agentów odpowiedzialnych za inne zadania.

9. Disposability — szybki start i czyste wyłączanie

Aplikacja (agent) powinna uruchamiać się i zamykać szybko i bezpiecznie. Przydatne w autoskalowaniu i orchestracji (K8s, ECS).

10. Dev/prod parity — minimalizacja różnic środowiskowych

Im mniejsza różnica między lokalnym docker-compose up a produkcją w chmurze, tym mniej „niespodzianek”. Infrastructure as Code to tu podstawa.

11. Logs — traktuj logi jako strumień zdarzeń

Nie zapisuj logów do pliku — logi mają iść na stdout/stderr, by mogły być przechwycone przez ELK, Loki, czy inny system monitorujący.

12. Admin processes — pomocnicze zadania jako jednorazowe procesy

Migracje bazy, inspekcja danych czy czyszczenie cache — wszystko jako osobne, uruchamialne procesy. Idealne do CRON-jobów lub zadań DevOps.

12 Factor App vs. 12 Factor Agents

W podejściu agentowym mówimy o architekturze zorientowanej na samodzielne, autonomiczne komponenty komunikujące się ze sobą. W tym świetle:

  • Agent może być procesem zgodnym z 12FA.

  • Platforma dla agentów powinna wspierać lifecycle wg 12FA (deployment, logi, konfiguracja).

  • Rozproszenie i niezależność agentów staje się naturalnym rozszerzeniem idei „self-contained apps”.

W praktyce — 12 Factor App to doskonały fundament, na którym możemy budować 12 Factor Agents.

Kiedy 12 Factor App się nie sprawdzi?

Oczywiście, jak każde podejście, 12FA ma swoje ograniczenia:

  • Trudno je zastosować do monolitów z dużym stanem wewnętrznym (ERP, legacy).

  • Nie nadaje się do aplikacji wymagających silnego stateful compute (np. stream processing bez zewnętrznego stanu).

  • Wymaga kultury DevOps i automatyzacji — bez tego wiele założeń się nie obroni.

Podsumowanie

Zasady 12 Factor App pozostają aktualne, zwłaszcza jako podstawa dla nowoczesnych, autonomicznych komponentów — w tym agentów. W połączeniu z architekturą agentową stanowią przepis na systemy:

  • elastyczne i odporne na zmiany,

  • łatwe do wdrażania i skalowania,

  • zgodne z filozofią „as a Service”.

Jeśli jeszcze nie stosujesz 12FA — warto zacząć chociażby od rozdzielenia konfiguracji, logów i budowania obrazów aplikacyjnych. Małe kroki, wielki zysk.


Czy Twój system jest zgodny z 12 Factor App? A może agenci w Twojej organizacji mogliby na tym podejściu skorzystać? Daj znać w komentarzach lub na LinkedInie — chętnie podyskutuję.


poniedziałek, 2 czerwca 2025

dev{tools}: Para – lekka platforma backendowa do tworzenia aplikacji i API

Jeśli potrzebujesz prostego sposobu na szybkie uruchomienie backendu dla swojej aplikacji — bez budowania wszystkiego od zera — Para może być dokładnie tym, czego szukasz.

To lekki framework backendowy typu open source, który pozwala w kilka minut zbudować REST API, zarządzać danymi i obsługiwać uwierzytelnianie — bez konieczności pisania setek linii kodu infrastrukturalnego.



Czym jest Para?

Para to backend oparty o Java i Spring Boot, który działa w duchu „backend-as-a-service”.
Umożliwia łatwe tworzenie i zarządzanie obiektami danych, integrację z aplikacjami frontendowymi oraz uruchamianie go lokalnie lub w chmurze.

Ciekawostka: choć niektóre źródła rozwijają nazwę jako Pluggable and Reusable Architecture, autor projektu wskazuje, że pochodzi ona od bułgarskiego słowa „pára” (para wodna) – symbolicznie „zasilająca” backend Twojej aplikacji.
➡️ Źródło – GitHub README

Najważniejsze cechy Para:

  • przechowuje i zarządza obiektami (modelami) w stylu NoSQL,

  • zapewnia gotowe mechanizmy uwierzytelniania i RBAC,

  • wspiera relacje między obiektami,

  • udostępnia RESTful API natychmiast po wdrożeniu,

  • obsługuje tagowanie, wyszukiwanie i wersjonowanie danych.

📘 Oficjalna dokumentacja: https://paraio.org/docs/

Z czego się składa?

KomponentOpis
para-coreSilnik backendu (Java) zarządzający danymi, API i logiką.
para-serverSamodzielna aplikacja REST oparta na Spring Boot.
para-clientKlient Java do komunikacji z API Para.
para-jsKlient JS/TS do integracji z aplikacjami frontendowymi (np. React).
para-admin-uiGraficzny panel administracyjny oparty na Angular.

Architektura i komponenty

System Para składa się z kilku współpracujących warstw:

  • Para Server – główny punkt wejścia (Spring Boot), udostępniający REST API.

  • Para Core – logika obiektów, typów, zabezpieczeń i relacji.

  • Storage Layer – przechowywanie danych (np. ElasticSearch, DynamoDB, H2).

  • Client SDKs – integracja z frontendem lub backendem (JS/Java).

  • Admin UI – panel do zarządzania modelami i konfiguracją.

Dzięki modułowości możesz wymienić lub rozszerzyć każdy z komponentów — np. podmienić bazę danych, system logowania, dodać middleware.

Do czego mogę użyć Para?

  • budowa CMS-ów, katalogów, blogów, e-commerce i prostych aplikacji,

  • szybkie tworzenie REST API dla aplikacji mobilnych i SPA,

  • backend do MVP, proof-of-concept, hackathonów,

  • mikroserwis z autoryzacją i relacjami obiektów,

  • backend dla aplikacji JAMstack (React/Vue + Para + CDN).

Jak zacząć? (Quickstart)

1. Uruchomienie Para lokalnie (Docker)


docker run -p 8080:8080 --name para \ -e PARA_ENV=dev \ -e PARA_APP_NAME=app \ -e PARA_SECRET_KEY=mysecret \ erudika/para

Po uruchomieniu REST API będzie dostępne pod adresem:
📍 http://localhost:8080


2. Tworzenie obiektów

📌 Upewnij się, że posiadasz poprawny token JWT (np. po logowaniu).


curl -X POST http://localhost:8080/v1/app/object \ -H "Content-Type: application/json" \ -H "Authorization: Bearer YOUR-JWT-TOKEN" \ -d '{ "type": "person", "name": "Jan Kowalski", "email": "jan@example.com" }'

Otrzymasz obiekt z id, timestamp, metadanymi i możliwością dalszej edycji przez API.


3. Użycie z JavaScript (np. w React)


import { ParaClient } from '@erudika/para-client'; const para = new ParaClient('accessKey', 'secretKey'); para.getAll('person').then(results => { console.log(results); });

📌 Domyślnie dane są paginowane — jeśli chcesz uzyskać więcej wyników, pamiętaj o ustawieniu limitu.

Wbudowane funkcje bezpieczeństwa

  • uwierzytelnianie (OAuth2, Google, GitHub, Facebook),

  • RBAC – role i uprawnienia,

  • szyfrowanie haseł, tokeny JWT,

  • full-text search (ElasticSearch / Lucene),

  • tagowanie i relacje między obiektami,

  • wsparcie dla middleware i hooków (Spring Boot).

Integracja z architekturą

Para działa jako mikroserwis REST – możesz zintegrować go z:

  • frontendem (React, Vue, Angular),

  • systemami auth (np. Keycloak, Auth0),

  • CI/CD (np. GitHub Actions),

  • backendami Node.js, Spring Boot lub .NET.

Wersja self-hosted działa na Dockerze, VPS lub w K8s — masz pełną kontrolę nad danymi i środowiskiem.

Podsumowanie

Para to backend idealny do szybkich wdrożeń, prototypów i lekkich aplikacji.
Daje Ci REST API, uwierzytelnianie, przechowywanie danych i relacje — bez konieczności budowania tego wszystkiego od zera.

✅ REST API w kilka minut
✅ Możliwość pełnej kontroli (self-hosting)
✅ Integracja z frontendem i CI/CD
✅ Bezpieczna architektura oparta o Java/Spring
✅ Gotowe do użycia jako komponent w mikroserwisach

poniedziałek, 28 kwietnia 2025

Wzorce MSA - Testy kontraktowe i Consumer-Driven Contract

 W architekturze mikroserwisów komunikacja między usługami to chleb powszedni. Serwis A woła B, B woła C, a C czasem pyta jeszcze o coś D... I wszystko działa — do pierwszej zmiany w jednym z tych komponentów.



Zamiast "to się chyba uda", lepiej postawić na testy kontraktowe, a konkretnie na podejście Consumer-Driven Contract (CDC). To technika, która pozwala upewnić się, że komunikujące się systemy rozumieją się bez niedomówień.

Czym jest test kontraktowy?

To umowa między usługą kliencką (consumer) a usługą dostarczającą dane (provider).
Kontrakt opisuje co dokładnie oczekuje klient, a testy sprawdzają, czy dostawca spełnia te wymagania.

Nie chodzi tu o pełne testy integracyjne – tylko o weryfikację zachowania w określonych scenariuszach komunikacyjnych.

Consumer-Driven Contract (CDC) – o co chodzi?

W podejściu CDC:

  1. Klient definiuje kontrakt – np. jaką strukturę odpowiedzi HTTP oczekuje po zapytaniu GET /orders/{id}.

  2. Kontrakt jest zapisywany jako artefakt (np. plik .json, .yml, .pact).

  3. Dostawca (provider) implementuje API, które musi spełniać oczekiwania konsumentów.

  4. W CI/CD kontrakt jest weryfikowany po stronie providera, by uniknąć regresji.

Przykład (Pact)

Załóżmy, że aplikacja frontendowa (consumer) oczekuje takiej odpowiedzi z serwisu zamówień:


{ "id": "abc123", "status": "DELIVERED", "total": 99.99 }

Konsument definiuje kontrakt:


const provider = new Pact({ consumer: 'Frontend', provider: 'OrderService', }); provider .given('Order exists') .uponReceiving('a request for order details') .withRequest({ method: 'GET', path: '/orders/abc123', }) .willRespondWith({ status: 200, body: { id: like('abc123'), status: like('DELIVERED'), total: like(99.99), }, });

📤 Kontrakt jest publikowany do brokera (np. Pactflow), a provider w swoim CI odpala testy, które go weryfikują.

Dlaczego warto?

  • ✅ Zwiększasz pewność, że nie złamiesz kompatybilności

  • ✅ Wcześnie wykrywasz konflikty między zespołami

  • ✅ Odchudzasz testy E2E (bo nie musisz testować wszystkiego z wszystkimi)

  • ✅ Automatyzujesz weryfikację zgodności API

  • ✅ Ułatwiasz niezależne wdrażanie mikroserwisów

Typowe problemy bez CDC

  • 🔴 Zmiana API w jednym mikroserwisie powoduje błędy w innym (niespójność)

  • 🔴 Brak testów integracyjnych → produkcja testuje za nas

  • 🔴 "Ale przecież dokumentacja mówiła inaczej..."

  • 🔴 Trudność w wersjonowaniu i utrzymaniu API

Popularne narzędzia CDC

NarzędzieJęzyk / EkosystemUwagi
PactJava, JS, Python, .NETNajpopularniejsze narzędzie CDC
Spring Cloud ContractJavaIntegracja z Spring Boot
HoverflyHTTP proxy, języki dowolneSimulacja usług w testach
ContractTestJS, RESTLekkie testy kontraktowe

Jak wdrożyć CDC w praktyce

  1. Zdefiniuj kontrakt po stronie klienta (frontend, inny mikroserwis)

  2. Publikuj kontrakt do repozytorium (broker)

  3. W CI providera uruchamiaj testy weryfikujące kontrakt

  4. Nie wdrażaj providerów, którzy łamią oczekiwania klientów

  5. Automatyzuj ten proces w CI/CD

Podsumowanie

Testy kontraktowe i podejście CDC to must-have w ekosystemie mikroserwisów:

🔹 Gwarantują kompatybilność usług
🔹 Ułatwiają komunikację między zespołami
🔹 Wzmacniają kulturę DevOps i ciągłą integrację
🔹 Ograniczają chaos wersjonowania API

poniedziałek, 7 kwietnia 2025

Wzorce MSA - Distributed Tracing B3 propagation

 W architekturze mikroserwisów każdy system to zbiór wielu mniejszych komponentów, które komunikują się między sobą najczęściej za pomocą żądań HTTP, wiadomości z kolejek lub gRPC. To świetnie wspiera skalowalność i elastyczność… dopóki coś nie przestanie działać.


Wtedy pojawia się pytanie:
  • Gdzie utknęło żądanie?
  • Który mikroserwis zawiódł?
  • Jak długo trwało przetwarzanie w każdym kroku?

Distributed Tracing to wzorzec, który pozwala śledzić żądania przez cały łańcuch mikroserwisów, a standard B3 umożliwia łatwą i jednolitą identyfikację każdego kroku tej podróży.

Na czym polega Distributed Tracing?

Distributed Tracing (śledzenie rozproszone) to mechanizm, który rejestruje ścieżkę żądania przez wiele usług. Każde żądanie otrzymuje unikalny identyfikator, który jest przekazywany między usługami — dzięki temu możemy odtworzyć całą trasę żądania i zmierzyć czas trwania każdego kroku.

Wprowadzenie do standardu B3

B3  to lekki, prosty do wdrożenia standard propagowania trace-id w systemach rozproszonych. Wystarczy dodać kilka nagłówków HTTP, by rozpocząć śledzenie żądań.

Kluczowe nagłówki B3:

NagłówekOpis
X-B3-TraceIdUnikalny identyfikator całego śledzenia (trace)
X-B3-SpanIdIdentyfikator konkretnego kroku (span) w ramach trace
X-B3-ParentSpanId(opcjonalnie) identyfikator nadrzędnego span
X-B3-SampledCzy trace ma być zarejestrowany (1 = tak)
X-B3-FlagsDodatkowa flaga debugowania

Przykład nagłówków B3 w żądaniu HTTP:


X-B3-TraceId: 4bf92f3577b34da6a3ce929d0e0e4736 X-B3-SpanId: 00f067aa0ba902b7 X-B3-ParentSpanId: b73a56a1d2ee0eb2 X-B3-Sampled: 1

Jak to działa w praktyce?

Schemat przepływu

Wyobraźmy sobie system z trzema mikroserwisami:


Klient → Gateway → Serwis A → Serwis B → Serwis C

Dzięki nagłówkom B3:

  1. Klient wysyła żądanie do Gateway z X-B3-TraceId.

  2. Gateway tworzy X-B3-SpanId i wysyła je do Serwisu A.

  3. Serwis A generuje swój SpanId, zachowuje ParentSpanId z Gatewaya i przekazuje trace dalej.

  4. Na końcu, Serwis C kończy trace — a wszystkie kroki są zarejestrowane.

Wizualizacja śladu (trace)

Po zebraniu wszystkich danych (np. za pomocą Jaeger, Zipkin lub Grafana Tempo), możemy zobaczyć wizualnie:


TraceId: 4bf92f3577b34da6a3ce929d0e0e4736 ├── Gateway [15 ms] │ └── Serwis A [30 ms] │ └── Serwis B [40 ms] │ └── Serwis C [25 ms]

Implementacja Distributed Tracing z użyciem Spring Boot i Sleuth


<!-- pom.xml --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-sleuth</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-zipkin</artifactId> </dependency>

# application.yml spring: zipkin: base-url: http://zipkin:9411 sleuth: sampler: probability: 1.0

Dzięki Sleuth i Zipkin aplikacja automatycznie:

  • generuje trace-id i span-id,

  • przekazuje nagłówki HTTP,

  • wysyła dane do Zipkina.

Korzyści z wdrożenia Distributed Tracing

✅ Szybsze diagnozowanie problemów
✅ Pomiar czasu odpowiedzi poszczególnych usług
✅ Widoczność zależności między mikroserwisami
✅ Identyfikacja wąskich gardeł
✅ Lepsze wsparcie operacyjne i DevOps


Wnioski i dobre praktyki

  • Zawsze przekazuj trace-id i span-id w żądaniach HTTP, gRPC i eventach.
  • Testuj czy wszystkie mikroserwisy poprawnie obsługują nagłówki B3.
  • Używaj narzędzi jak Zipkin, Jaeger lub Grafana Tempo do analizy trace’ów.
  • W systemach rozproszonych bez observability jesteś ślepy.


Podsumowanie

Wzorzec Distributed Tracing to fundament nowoczesnych, obserwowalnych systemów mikroserwisowych. W połączeniu ze standardem B3 umożliwia łatwą propagację identyfikatorów śledzenia między usługami. Dobrze wdrożony trace pozwala nie tylko znaleźć błędy, ale też optymalizować wydajność i rozumieć złożoność architektury.


poniedziałek, 31 marca 2025

Wzorce MSA — Historia Darka i pewnego mikroserwisu

Darek był doświadczonym programistą backendowym. Pracował nad dużą aplikacją monolityczną obsługującą klientów w branży e-commerce. Kod miał swoje lata, swoje kruczki, ale ogólnie był w porządku — przynajmniej dopóki się nie psuł. A psuł się coraz częściej.



Pewnego dnia Darek postanowił, że nadszedł czas na zmiany. “Ten moduł płatności... aż się prosi, żeby go wydzielić do osobnego mikroserwisu!” — pomyślał.

Refaktoryzacja. Decoupling. Swoboda wdrożeń. Skalowalność. Brzmi pięknie. Co mogłoby pójść nie tak?

Przejście z komunikacji lokalnej do sieciowej

W monolicie wszystko było proste. Jedna metoda wywoływała drugą. Dane wędrowały po stosie w tym samym procesie JVM. Teraz — po wydzieleniu płatności do osobnego serwisu — zaczęło się dziać coś nowego. Darek wystawił endpoint REST i zaczął go wołać z głównego systemu.

Na lokalnym hoście działało to świetnie. Jednak po wdrożeniu na środowisko testowe okazało się, że...

DNS nie rozwiązuje się tak, jak Darek myślał.

Raz działał adres payment-service, raz payment.internal.local, innym razem... nie działał wcale. “Dlaczego curl działa, a HttpClient wyrzuca timeout?” — pytał ze złością. Zrozumiał, że sieć rządzi się swoimi prawami. I że trzeba się zaprzyjaźnić z service discovery.

Opóźnienia i retry

Wcześniej wszystko było instant. Teraz? Zdarzało się, że płatność odpowiadała po sekundzie, a czasem wcale. Timeout. I znowu.

“No to dorzucę retry” — pomyślał. I tak zrobił. Tyle że teraz system zaczął... powielać żądania. Dwukrotne opłaty, chaos w logach, sfrustrowani testerzy.

Nauczył się, że retry musi być idempotentne, a najlepiej opatrzone unikalnym ID żądania.

Circuit Breaker i fallback

Retry to nie wszystko. Mikroserwis płatności zaczął się czasem zawieszać przy dużym obciążeniu. A główny system... zawieszał się razem z nim.

Wtedy Darek odkrył Circuit Breaker. Dodał warstwę zabezpieczającą, która w razie błędu "odcinała" płatności i wrzucała je do kolejki z komunikatem: “usługa chwilowo niedostępna, spróbuj później”. Uratowało to resztę aplikacji.

Samodzielne wdrożenie... i nowe wyzwania

Wydzielenie mikroserwisu oznaczało możliwość niezależnego wdrażania kodu. Super. Do czasu.

Po wdrożeniu nowej wersji płatności logi z głównego systemu zaczęły krzyczeć: “500 Internal Server Error”. Co się okazało?

Nowa wersja zmieniła kontrakt API. Brak zgodności. Brak komunikacji między zespołami. Brak testów integracyjnych.

Darek nauczył się, że niezależność mikroserwisów nie oznacza dowolności. Kontrakty API muszą być święte — albo przynajmniej wersjonowane.

Brak kontraktu... czyli gorzkie lekcje integracji

W pewnym momencie frontend został zmodyfikowany tak, aby korzystał z nowej wersji mikroserwisu płatności. Ale… mikroserwis miał już też innych klientów. Nagle okazało się, że jedna z aplikacji mobilnych nie działa — nowy endpoint miał inny format odpowiedzi.

Darek odkrył wtedy Consumer-Driven Contract (CDC) — podejście, w którym to konsumenci mikroserwisu definiują oczekiwania wobec API, a producent (czyli mikroserwis) weryfikuje zgodność przy każdej zmianie. Narzędzia takie jak Pact pozwalają testować te kontrakty automatycznie w CI/CD.

💡 „Gdybyśmy mieli kontrakty konsumenckie wcześniej — uniknęlibyśmy błędów na produkcji i nieporozumień z zespołem mobilnym” – przyznał później Darek.

Monitoring, tracing i chaos w logach

Z czasem pojawiło się więcej mikroserwisów. I więcej pytań:

  • Gdzie utknęło żądanie?

  • Dlaczego płatność trwała 4 sekundy?

  • Kto wysłał ten dziwny request?

Logi z jednego serwisu przestały wystarczać. Darek wdrożył centralny monitoring (ELK Stack), a potem distributed tracing (np. Jaeger). I zrozumiał, że bez identyfikatora correlation-id w nagłówkach niczego nie da się poskładać.

DevOps

W miarę jak pojawiało się więcej mikroserwisów, więcej pipeline’ów CI/CD, więcej testów, Darek zrozumiał, że same zmiany w kodzie to za mało.

🔹 Musiał przygotować procesy wdrożeniowe z podziałem na środowiska.
🔹 Zautomatyzować testy integracyjne i rollback w przypadku błędów.
🔹 Wdrożyć monitoring stanu zdrowia usług (healthcheck, readiness, liveness).
🔹 I wreszcie — spiąć to wszystko z GitLab CI i ArgoCD.

„Mikroserwisy bez kultury DevOps to jak wyścigówka bez kierowcy – teoretycznie szybka, ale łatwo o kraksę.”

Skalowalność i autoscaling

Ruch wzrósł. Płatności musiały działać szybko, więc dorzucono autoscaling w Kubernetesie. Ale... przy skoku ruchu nowe instancje nie miały cache’a i ładowały dane z opóźnieniem.

Nauczył się, że skalowalność pozioma nie rozwiązuje wszystkiego, jeśli nie pomyślisz o stanie aplikacji, cache’ach i bazach danych.

Podsumowanie: Mikroserwisy? To nie tylko podział na pliki

Darek zaczął od pomysłu: "podzielmy system, będzie lepiej".

Ale każdy krok — DNS, retry, service discovery, tracing, versioning, deployment, skalowanie — wymagał świadomości, planowania i odpowiedzialności.

💡 Mikroserwisy to nie tylko “dzielenie systemu na kawałki”. To świadome projektowanie rozproszonego ekosystemu z wszystkimi jego pułapkami i możliwościami.


„Dziś, gdy ktoś mówi mi, że ‘chce sobie coś wydzielić’, pytam: ‘czy jesteś gotów na konsekwencje?’” – śmieje się Darek, patrząc na swój dashboard Prometheusa.


 


Część praktyk i wzorców zdążyłeś już poznać w moich poprzednich wpisach. Kolejne będą się pojawiać w następnych. Więc zapraszam do czytania i śledzenia mojego bloga!

wtorek, 18 marca 2025

Wzorce MSA: Ambasador (Ambassador Pattern)

W architekturze mikroserwisów (MSA) bardzo często mikroserwisy muszą komunikować się z zewnętrznymi usługami lub innymi mikroserwisami. W takich przypadkach kluczowe jest zapewnienie stabilności, bezpieczeństwa i odpowiedniej kontroli nad ruchem wychodzącym.
Jednym z rozwiązań ułatwiających te zadania jest Ambassador Pattern (wzorzec ambasador), który pozwala na odciążenie głównej logiki mikroserwisu i lepsze zarządzanie połączeniami z innymi systemami.



W tym artykule omówię:

  • Jak działa wzorzec ambasador?
  • Kiedy warto go stosować?
  • Przykłady implementacji w Kubernetes i Spring Cloud

Jak działa wzorzec Ambassador?

Ambassador Pattern zakłada, że zamiast bezpośredniego łączenia się z zewnętrznymi usługami, mikroserwis deleguje połączenia do specjalnej warstwy proxy (ambasadora). Proxy obsługuje komunikację, dodając dodatkowe funkcjonalności, takie jak:
✅ Monitoring i logowanie ruchu
✅ Buforowanie żądań
✅ Circuit Breaker dla zwiększenia odporności
✅ Autoryzacja i kontrola dostępu
✅ Obsługa retrysów i time-outów

Z perspektywy mikroserwisu, ambasador działa jak lokalny serwis, a w rzeczywistości przekazuje żądania do rzeczywistego odbiorcy.

Kiedy warto stosować wzorzec Ambasador?

🔹 Gdy mikroserwis komunikuje się z zewnętrznymi API lub usługami
🔹 Gdy chcemy dodać mechanizmy odporności, np. Circuit Breaker lub Retry Logic
🔹 Gdy chcemy przechwycić ruch i logować zdarzenia na poziomie proxy
🔹 Gdy chcemy uprościć kod mikroserwisu i uniknąć bezpośredniej integracji z komponentami sieciowymi

Dzięki oddzieleniu odpowiedzialności za komunikację, możemy utrzymać czysty kod mikroserwisu, a konfiguracja ambasadora może być łatwo zmieniana bez konieczności ingerencji w główny serwis.

Przykład implementacji w Kubernetes – Ambassador Sidecar

W środowisku Kubernetes, wzorzec ambasador jest najczęściej realizowany za pomocą kontenera sidecar, który działa obok mikroserwisu w tym samym podzie.

Przykładowy manifest dla ambasadora w Kubernetes (Envoy Proxy)


apiVersion: v1 kind: Pod metadata: name: my-microservice labels: app: my-microservice spec: containers: - name: my-microservice image: my-microservice:latest ports: - containerPort: 8080 - name: ambassador image: envoyproxy/envoy:latest ports: - containerPort: 9901 volumeMounts: - name: envoy-config mountPath: /etc/envoy volumes: - name: envoy-config configMap: name: envoy-config

🔹 Pierwszy kontener (my-microservice) to aplikacja biznesowa.
🔹 Drugi kontener (ambasador – Envoy Proxy) przejmuje ruch wychodzący i zarządza komunikacją.

Dzięki temu mikroserwis nie musi zajmować się takimi aspektami jak retry logic, circuit breaker czy monitoring – wszystkim zarządza ambasador.

Przykład w Spring Cloud – Ambassador Pattern z Resilience4j

W Spring Cloud możemy zaimplementować wzorzec Ambasador za pomocą Resilience4j, który zapewnia obsługę Circuit Breaker, Retry i Rate Limiting.


@CircuitBreaker(name = "externalService", fallbackMethod = "fallbackResponse") @Retry(name = "externalService", maxAttempts = 3) public String callExternalService() { return restTemplate.getForObject("https://api.external.com/data", String.class); } public String fallbackResponse(Exception e) { return "Fallback: Serwis niedostępny"; }

✅ Circuit Breaker – zapobiega przeciążeniu systemu, blokując wywołania do usługi, gdy wykryje jej awarię.
✅ Retry Logic – podejmuje kilka prób ponownego wykonania żądania w przypadku błędu.

Dzięki temu mikroserwis nie musi samodzielnie obsługiwać problemów z siecią, a cała logika odpornościowa jest zarządzana przez warstwę ambasadora.

Korzyści z zastosowania wzorca Ambasador

✅ Lepsza separacja odpowiedzialności – mikroserwis skupia się na logice biznesowej, a ambasador zarządza komunikacją.
✅ Odporność na błędy sieciowe – retry logic, circuit breaker i load balancing poprawiają stabilność systemu.
✅ Bezpieczeństwo – ambasador może obsługiwać autoryzację i szyfrowanie ruchu.
✅ Łatwiejsza skalowalność – warstwa proxy może być dynamicznie konfigurowana i skalowana niezależnie od mikroserwisów.

Ambassador a API Gateway

Być może zwróciłeś uwagą na podobieństwo wzorca Ambasador do omawianego przeze mnie innego wzorca MSA - API Gateway. Jednak wzorce te, mają różne zastosowania i uzupełniają się w architekturze mikroserwisów.

Podsumowanie

🔹 Ambassador Pattern to skuteczny sposób na zarządzanie komunikacją mikroserwisów z zewnętrznymi usługami.
🔹 W Kubernetes ambasador jest często realizowany jako sidecar proxy, np. Envoy Proxy.
🔹 W Spring Cloud można wykorzystać Resilience4j do obsługi circuit breaker i retry logic.
🔹 Wzorzec ambasador pozwala na odporność, monitoring i bezpieczeństwo połączeń wychodzących, co znacząco zwiększa stabilność systemów opartych na MSA.

poniedziałek, 3 marca 2025

EA - shorts #001



Świat Javy

Aktualizacje JDK:


  • OpenJDK 21.0.6, 17.0.14, 11.0.26 oraz 8u441 zostały wydane z poprawkami bezpieczeństwa i ulepszeniami wydajności.
  • Wersje wczesne JDK 24 i JDK 25 wprowadzają eksperymentalne funkcje, takie jak lepsze zarządzanie pamięcią i optymalizacje dla architektury ARM.

Źródło: OpenJDK Updates

Frameworki i narzędzia:


Spring Boot 3.2.2 wprowadza ulepszenia dla GraalVM Native Image oraz lepszą integrację z narzędziami DevOps.

Hibernate ORM dodaje wsparcie dla Jakarta EE 11, co jest kluczowe dla migracji starszych aplikacji Java EE.


Konferencje i wydarzenia:

  • Devoxx UK 2025 (maj) i JavaLand 2025 (marzec) zapowiadają sesje dotyczące przyszłości JVM oraz nowych technologii w ekosystemie Javy.

Źródło: Devoxx UK | JavaLand

Architektura korporacyjna

Trendy i nowości:


  • Data Mesh staje się popularnym podejściem do zarządzania danymi w dużych organizacjach, umożliwiając zespołom większą autonomię w zarządzaniu danymi.
  • API Management rozwija się jako kluczowy element integracji systemów wewnętrznych z partnerami zewnętrznymi.


Frameworki i narzędzia:


  • ArchiMate 5.0 wspiera modelowanie architektury korporacyjnej zgodnie z TOGAF, ułatwiając wizualizację procesów biznesowych.
  • Sparx Enterprise Architect zdobywa popularność dzięki nowym funkcjom wspierającym modelowanie w chmurze.


Wydarzenia branżowe:

  • Konferencja online o transformacji cyfrowej odbędzie się 5 marca, obejmując tematy takie jak chmury hybrydowe i automatyzacja procesów biznesowych.


Architektura systemów

Nowości technologiczne:


  • Zero Trust Architecture (ZTA) zyskuje na znaczeniu, szczególnie w sektorze finansowym, gdzie bezpieczeństwo danych jest kluczowe.
  • Kubernetes 1.29 wprowadza nowe funkcje ułatwiające zarządzanie systemami rozproszonymi.


Chmura i mikroserwisy:


  • AWS Lambda dodał funkcje precyzyjnego skalowania, co pozwala na bardziej efektywne zarządzanie kosztami w aplikacjach serverless.
  • Microsoft Azure rozszerzył swoją infrastrukturę w Europie, co ułatwia wdrażanie systemów zgodnych z RODO.
Źródło: AWS Lambda Updates | Microsoft Azure News

Wydarzenia branżowe:

  • Konferencja poświęcona mikroserwisom odbędzie się 4 marca – omówione zostaną najlepsze praktyki projektowania systemów o wysokiej dostępności.

środa, 12 lutego 2025

EA: Błędne założenia w projektowaniu systemów rozproszonych

 Systemy rozproszone są podstawą nowoczesnych aplikacji, od usług w chmurze po globalne sieci dostarczania treści (CDN). Jednak projektowanie takich systemów wymaga zrozumienia specyficznych wyzwań i ograniczeń. Zbyt często zakładamy, że technologia działa idealnie, co prowadzi do problemów z wydajnością, stabilnością i skalowalnością. Te założenia zostały zebrane w formie ośmiu błędów systemów rozproszonych, po raz pierwszy opisanych przez Petera Deutscha i Jamesa Goslinga w Sun Microsystems.



Osiem błędnych założeń w systemach rozproszonych

  1. Sieć jest niezawodna
    W rzeczywistości sieci są podatne na awarie, opóźnienia i pakiety gubione w transmisji. Aplikacje muszą być przygotowane na błędy sieciowe i mieć mechanizmy ponawiania prób.

  2. Opóźnienie jest zerowe
    W systemach rozproszonych, zwłaszcza w skali globalnej, opóźnienia w transmisji danych są nieuniknione. Projektanci muszą optymalizować komunikację między komponentami, np. przez minimalizację liczby zapytań.

  3. Przepustowość jest nieskończona
    Przepustowość sieci jest ograniczona i zależy od fizycznej infrastruktury, obciążenia oraz lokalizacji geograficznej. Wysokie obciążenie może prowadzić do spadków wydajności.

  4. Sieć jest bezpieczna
    Każdy punkt komunikacji w sieci rozproszonej jest potencjalnym wektorem ataku. Bezpieczeństwo danych wymaga szyfrowania, uwierzytelniania i regularnego monitorowania.

  5. Topologia sieci jest statyczna
    W praktyce topologia sieci zmienia się dynamicznie – np. serwery mogą być dodawane lub usuwane, a trasy przesyłu danych modyfikowane. Systemy muszą adaptować się do tych zmian.

  6. Nie ma więcej niż jednego administratora
    W systemach rozproszonych, szczególnie w chmurze lub między organizacjami, różne części systemu mogą być zarządzane przez różne zespoły lub podmioty. To prowadzi do komplikacji w koordynacji i wdrażaniu zmian.

  7. Koszt transportu danych jest zerowy
    Transfer danych między regionami lub dostawcami chmurowymi jest kosztowny. Optymalizacja przesyłu danych jest kluczowa, aby uniknąć wysokich kosztów operacyjnych.

  8. Sieć jest jednorodna
    Sieci różnią się pod względem infrastruktury, protokołów, opóźnień i polityk bezpieczeństwa. Projektowanie uniwersalnych rozwiązań wymaga uwzględnienia tej różnorodności.

Przykłady błędnych założeń w praktyce

1. Rozproszone bazy danych

Przy założeniu, że opóźnienia sieci są zerowe, projektanci mogą nieświadomie wprowadzić problemy z wydajnością podczas replikacji danych między regionami. Przykład: opóźnienia w synchronizacji danych w bazach takich jak MongoDB czy Cassandra.

2. Load Balancing w chmurze

Założenie, że topologia sieci jest stała, może prowadzić do problemów w konfiguracji load balancera. W dynamicznym środowisku chmurowym, instancje serwerów są uruchamiane i wyłączane w zależności od obciążenia.

3. Komunikacja mikroserwisów

Przyjęcie, że sieć jest niezawodna, prowadzi do błędów w komunikacji między mikroserwisami. Rozwiązaniem są wzorce takie jak circuit breaker lub retry logic, które zwiększają odporność systemu.

Jak unikać błędnych założeń?

  1. Monitorowanie i obserwowalność
    Narzędzia takie jak Prometheus, Grafana czy Jaeger umożliwiają monitorowanie opóźnień, błędów i stanu sieci w czasie rzeczywistym.

  2. Projektowanie odporności

    • Wprowadź mechanizmy ponawiania prób i timeouty.
    • Stosuj wzorce takie jak circuit breaker i bulkhead pattern, które minimalizują wpływ awarii jednego komponentu na całość systemu.
  3. Testowanie w warunkach rzeczywistych
    Narzędzia takie jak Chaos Monkey pozwalają symulować awarie sieci i ocenić, jak system reaguje na problemy.

  4. Optymalizacja kosztów transferu danych
    Korzystaj z usług takich jak AWS S3 Transfer Acceleration lub CDN, aby zmniejszyć koszty i poprawić wydajność.

Podsumowanie

Systemy rozproszone są nieodzowną częścią współczesnych aplikacji, ale ich projektowanie wymaga uwzględnienia licznych ograniczeń i wyzwań. Zrozumienie i unikanie ośmiu błędnych założeń to klucz do budowy wydajnych, skalowalnych i odpornych systemów. Należy pamiętać, że choć technologia ciągle się rozwija, podstawowe ograniczenia sieci pozostają niezmienne. Właściwe projektowanie i testowanie systemów rozproszonych pozwala uniknąć kosztownych błędów i zapewnić stabilność w nawet najbardziej wymagających środowiskach.

poniedziałek, 10 lutego 2025

Wzorce MSA: Circuit Breaker

W systemach mikroserwisowych komunikacja między usługami jest kluczowa, ale również narażona na wiele problemów. Jednym z najbardziej efektywnych wzorców projektowych, które pomagają zapewnić stabilność i odporność systemu, jest Circuit Breaker. W tym artykule omówię, czym jest ten wzorzec, jak działa oraz dlaczego warto go stosować w architekturze mikroserwisowej.



Czym jest Circuit Breaker?

Circuit Breaker (z ang. wyłącznik obwodu) to wzorzec, który chroni system przed przeciążeniami i umożliwia szybsze reagowanie na problemy w komunikacji między usługami. Jego działanie można porównać do elektrycznego wyłącznika, który odłącza obwód w przypadku wykrycia problemu, aby uniknąć dalszych uszkodzeń.

W kontekście systemów rozproszonych, Circuit Breaker monitoruje połączenia między usługami i blokuje dalsze próby komunikacji z usługą, która aktualnie nie działa poprawnie. Dzięki temu system nie traci zasobów na wykonywanie bezsensownych żądań.

Jak działa Circuit Breaker?

Circuit Breaker przechodzi przez trzy podstawowe stany:

  1. Closed (zamknięty)

    • Domyślny stan, w którym wszystkie żądania są przepuszczane do usługi docelowej.
    • Jeśli żądania są realizowane poprawnie, Circuit Breaker pozostaje zamknięty.
  2. Open (otwarty)

    • Gdy liczba błędów przekroczy określony próg, Circuit Breaker przechodzi w stan otwarty.
    • W tym stanie żadne nowe żądania nie są wysyłane do usługi docelowej.
  3. Half-Open (półotwarty)

    • Po pewnym czasie Circuit Breaker przechodzi w stan półotwarty, aby sprawdzić, czy usługa docelowa zaczęła działać poprawnie.
    • Jeśli testowe żądania zakończą się sukcesem, Circuit Breaker wraca do stanu zamkniętego. W przeciwnym razie pozostaje w stanie otwartym.

Dlaczego warto stosować Circuit Breaker?

  1. Ochrona przed przeciążeniami
    Chroni usługi przed przeciążeniem, ograniczając liczbę żądań wysyłanych do usługi, która nie działa poprawnie.

  2. Szybsze reagowanie na błędy
    Unika oczekiwania na timeouty, ponieważ od razu blokuje żądania do niesprawnej usługi.

  3. Poprawa odporności systemu
    Minimalizuje ryzyko kaskadowych awarii w systemie mikroserwisowym.

  4. Efektywne zarządzanie zasobami
    Zasoby systemowe nie są marnowane na obsługę żądań, które z góry są skazane na porażkę.

Przykład implementacji Circuit Breaker w Javie z użyciem Resilience4j

Resilience4j to popularna biblioteka w ekosystemie Javy, która oferuje łatwą implementację wzorca Circuit Breaker.

Przykład konfiguracji


import io.github.resilience4j.circuitbreaker.CircuitBreaker; import io.github.resilience4j.circuitbreaker.CircuitBreakerConfig; import io.github.resilience4j.circuitbreaker.CircuitBreakerRegistry; import java.time.Duration; public class CircuitBreakerExample { public static void main(String[] args) { CircuitBreakerConfig config = CircuitBreakerConfig.custom() .failureRateThreshold(50) // Próg błędów (50%) .waitDurationInOpenState(Duration.ofSeconds(5)) // Czas oczekiwania w stanie otwartym .slidingWindowSize(10) // Rozmiar okna (liczba żądań do analizy) .build(); CircuitBreakerRegistry registry = CircuitBreakerRegistry.of(config); CircuitBreaker circuitBreaker = registry.circuitBreaker("example"); // Przykład wywołania usługi z Circuit Breaker try { String result = circuitBreaker.executeSupplier(() -> callExternalService()); System.out.println(result); } catch (Exception e) { System.out.println("Service is unavailable: " + e.getMessage()); } } private static String callExternalService() { // Logika wywołania usługi zewnętrznej throw new RuntimeException("Service failed"); } }

Diagram działania Circuit Breaker

Oto prosty diagram obrazujący przepływ żądań z wykorzystaniem Circuit Breaker:


@startuml participant "Klient" as Client participant "Circuit Breaker" as CB participant "Usługa docelowa" as Target Client -> CB: Wysyła żądanie CB -> Target: Przekazuje żądanie (stan Closed) Target --> CB: Odpowiedź (sukces lub błąd) CB -> Client: Odpowiedź alt Stan Open Client -> CB: Wysyła żądanie CB --> Client: Blokuje żądanie end @enduml



Narzędzia wspierające implementację Circuit Breaker

  • Resilience4j: Biblioteka dla Javy, wspierająca także inne wzorce odpornościowe.
  • Hystrix: Popularna biblioteka od Netflixa (obecnie nie jest już rozwijana).
  • Istio: Service mesh, który wspiera zarządzanie Circuit Breaker na poziomie sieciowym.

Podsumowanie

Circuit Breaker to kluczowy wzorzec w systemach mikroserwisowych, który zwiększa odporność i stabilność systemu. Chroni przed przeciążeniami, minimalizuje czas oczekiwania na odpowiedzi i redukuje ryzyko kaskadowych awarii. W połączeniu z innymi wzorcami i narzędziami, takimi jak Resilience4j czy Istio, stanowi fundament nowoczesnych systemów rozproszonych. Jeśli Twój system wymaga wysokiej dostępności, Circuit Breaker powinien znaleźć się w Twoim zestawie narzędzi projektowych.

środa, 5 lutego 2025

Wzorce MSA: Retry Logic

 W systemach mikroserwisowych problemy z komunikacją między usługami są nieuniknione. Jednym z prostych, ale skutecznych wzorców pozwalających radzić sobie z tymi problemami jest Retry Logic. W tym artykule przedstawię, czym jest Retry Logic, jak działa, dlaczego jest istotny oraz jak poprawnie go zaimplementować, aby uniknąć nieoczekiwanych skutków ubocznych.



Czym jest Retry Logic?

Retry Logic to mechanizm automatycznego ponawiania żądań w przypadku, gdy wystąpią tymczasowe błędy w komunikacji, takie jak:

  • Czasowe przerwy w sieci,
  • Chwilowa niedostępność usługi,
  • Przekroczenie limitów zapytań.

Retry Logic zwiększa szanse na pomyślne wykonanie żądania, zakładając, że problem jest krótkotrwały i może zostać rozwiązany przy kolejnej próbie.

Jak działa Retry Logic?

Retry Logic składa się z kilku kluczowych elementów:

  1. Liczba prób (retry attempts)
    Określa, ile razy żądanie powinno zostać ponowione w przypadku błędu.

  2. Odstęp między próbami (retry interval)
    Czas oczekiwania między kolejnymi próbami. Może być stały lub rosnący (np. wykładniczo).

  3. Maksymalny czas oczekiwania (max retry timeout)
    Całkowity czas, po którym żądanie jest uznawane za nieudane, jeśli wszystkie próby zakończyły się błędem.

  4. Obsługiwane błędy
    Retry Logic powinien być stosowany tylko do błędów, które mają charakter tymczasowy (np. status HTTP 500, 503 lub błędy sieciowe).

Dlaczego Retry Logic jest ważny?

Retry Logic jest kluczowy w systemach rozproszonych, ponieważ:

  1. Zwiększa odporność systemu
    Usuwa problem chwilowych zakłóceń w komunikacji między mikroserwisami.

  2. Poprawia doświadczenie użytkownika
    Minimalizuje liczbę widocznych błędów, co przekłada się na lepszą jakość usług.

  3. Zwiększa niezawodność
    Redukuje ryzyko, że tymczasowe problemy sieciowe wpłyną na działanie całego systemu.

Jak zaimplementować Retry Logic w Javie z Resilience4j

Biblioteka Resilience4j oferuje gotowe rozwiązania do implementacji Retry Logic. Poniżej znajduje się przykład implementacji.

Przykład implementacji


import io.github.resilience4j.retry.Retry; import io.github.resilience4j.retry.RetryConfig; import io.github.resilience4j.retry.RetryRegistry; import java.time.Duration; public class RetryExample { public static void main(String[] args) { // Konfiguracja Retry Logic RetryConfig retryConfig = RetryConfig.custom() .maxAttempts(3) // Liczba prób .waitDuration(Duration.ofSeconds(2)) // Odstęp między próbami .retryExceptions(RuntimeException.class) // Typy obsługiwanych wyjątków .build(); RetryRegistry retryRegistry = RetryRegistry.of(retryConfig); Retry retry = retryRegistry.retry("example"); // Wywołanie z Retry Logic Retry.decorateRunnable(retry, () -> { System.out.println("Próba wykonania żądania..."); callExternalService(); }).run(); } private static void callExternalService() { // Symulacja błędu throw new RuntimeException("Service is temporarily unavailable"); } }

Diagram działania Retry Logic

Oto diagram przedstawiający, jak działa Retry Logic w systemie mikroserwisowym:


@startuml actor Client participant "Retry Logic" as Retry participant "External Service" as Service Client -> Retry: Wysyła żądanie Retry -> Service: Przekazuje żądanie Service --> Retry: Błąd alt Kolejne próby Retry -> Service: Ponowienie żądania Service --> Retry: Błąd end Retry --> Client: Błąd po maksymalnej liczbie prób @enduml




Najlepsze praktyki stosowania Retry Logic

  1. Używaj wykładniczego odstępu między próbami (exponential backoff)
    Pozwala zmniejszyć obciążenie systemu w przypadku licznych żądań ponawianych w krótkim czasie.

  2. Zaimplementuj Circuit Breaker
    Połączenie Retry Logic z Circuit Breaker chroni system przed przeciążeniem, gdy usługa docelowa jest długotrwale niedostępna.

  3. Określ odpowiednie wyjątki
    Retry Logic powinien obsługiwać tylko błędy tymczasowe, takie jak HTTP 500 (Internal Server Error) lub 503 (Service Unavailable).

  4. Ogranicz liczbę prób
    Zbyt duża liczba prób może dodatkowo obciążyć system. Zawsze testuj konfigurację w praktyce.

  5. Monitoruj efektywność Retry Logic
    Używaj narzędzi monitorujących, takich jak Prometheus lub Grafana, aby śledzić liczbę ponawianych żądań i ich skuteczność.

Podsumowanie

Retry Logic to prosty, ale potężny wzorzec, który zwiększa niezawodność systemów rozproszonych. Dzięki mechanizmowi ponawiania prób możesz lepiej radzić sobie z chwilowymi problemami w komunikacji między usługami. Pamiętaj jednak, że Retry Logic musi być stosowany ostrożnie i w połączeniu z innymi wzorcami, takimi jak Circuit Breaker, aby uniknąć przeciążenia systemu. Implementując Retry Logic, twój system stanie się bardziej odporny na błędy i niezawodny dla użytkowników końcowych.