Náš hlavní produkt — informační systém pro pojišťovnu — narostl do rozměrů, které znemožňovaly rychlé nasazování změn. Jeden deployment trval hodiny, jedna chyba v modulu fakturace shodila celý systém. Rozhodli jsme se monolit rozdělit na mikroslužby. Tady jsou naše zkušenosti z prvních měsíců.
Co je monolit a proč přestává stačit¶
Monolitická aplikace je jediný deployovatelný artefakt — v našem případě WAR soubor o velikosti přes 400 MB. Obsahoval vše: správu smluv, fakturaci, reporting, notifikace, importy z externích systémů. Každá změna vyžadovala sestavení celého artefaktu, regresní testy trvaly přes noc a deployment znamenal odstávku.
Vývojový tým rostl — z pěti na dvacet lidí. Merge konflikty byly denní rutinou. Každý sprint končil „integration hell” — tři dny, kdy se všichni snažili dostat své změny do hlavní větve bez toho, aby rozbili kolegy.
Mikroslužby: princip jedné odpovědnosti¶
Myšlenka mikroslužeb je jednoduchá: každá služba dělá jednu věc a dělá ji dobře. Má vlastní databázi, vlastní API, vlastní deployment cyklus. Komunikuje s ostatními přes jasně definované rozhraní — typicky REST API nebo messaging.
Martin Fowler a James Lewis v březnu 2014 publikovali definitivní článek o mikroslužbách, který shrnul to, co Netflix, Amazon a Spotify praktikovaly roky. My jsme začali experimentovat na menším projektu — systému notifikací.
První kroky: extrakce notifikační služby¶
Notifikační modul byl ideální kandidát na extrakci. Měl jasné rozhraní (přijmi událost → odešli email/SMS), minimální závislosti na zbytku systému a vlastní datový model. Vytvořili jsme samostatnou Spring Boot aplikaci s REST endpointem:
@RestController
@RequestMapping("/api/v1/notifications")
public class NotificationController {
@Autowired
private NotificationService service;
@PostMapping
public ResponseEntity<Void> send(
@RequestBody NotificationRequest request) {
service.dispatch(request);
return ResponseEntity.accepted().build();
}
}
Monolit nyní místo přímého volání třídy posílal HTTP POST na notifikační službu. Přidali jsme circuit breaker pattern (knihovna Hystrix od Netflixu) — pokud notifikační služba neodpověděla do 2 sekund, systém pokračoval bez notifikace a zařadil ji do retry fronty.
Výzvy, na které jsme narazili¶
Distribuované transakce¶
V monolitu stačila jedna databázová transakce. Napříč službami to nefunguje. Přešli jsme na model eventual consistency — systém není konzistentní okamžitě, ale do krátké doby se sjednotí. Pro business procesy, které vyžadovaly atomicitu, jsme implementovali Saga pattern — řetězec kompenzačních akcí.
Service discovery¶
Kde běží notifikační služba? Na jakém portu? Hardcoded URL v konfiguraci se rychle ukázaly jako noční můra. Nasadili jsme Netflix Eureka jako service registry — každá služba se při startu zaregistruje a ostatní se ptají Eureky, kam mají posílat požadavky.
Monitoring a logování¶
V monolitu stačil jeden log soubor. S mikroslužbami máme desítky logů na různých serverech. Zavedli jsme centralizované logování přes ELK stack (Elasticsearch, Logstash, Kibana) a correlation ID — unikátní identifikátor požadavku, který putuje všemi službami.
Testování¶
Unit testy zůstaly jednoduché. Integrační testy se ale zkomplikovaly — potřebujete mít běžící závislé služby. Zavedli jsme Consumer-Driven Contract Testing pomocí knihovny Pact: každá služba definuje kontrakt svého API a konzumenti ho validují ve svých testech.
Technologický stack¶
- Spring Boot — rychlý start nové služby, embedded Tomcat, auto-konfigurace
- Netflix OSS — Eureka (discovery), Hystrix (circuit breaker), Ribbon (load balancing)
- RabbitMQ — asynchronní messaging mezi službami
- PostgreSQL — každá služba má vlastní schéma nebo celou databázi
- ELK Stack — centralizované logování a monitoring
- Jenkins — CI/CD pipeline pro každou službu zvlášť
Výsledky po šesti měsících¶
Z monolitu jsme extrahovali pět služeb: notifikace, reporting, import dat, autentizace a správa dokumentů. Deployment jedné služby trvá minuty místo hodin. Tým je rozdělen do squad — každý squad vlastní 1–2 služby end-to-end.
Frekvence nasazení vzrostla z jednoho deploymentu měsíčně na několik týdně pro každou službu. Chyba v reportingu neznamená výpadek celého systému — ostatní služby běží dál.
Kdy mikroslužby nedávají smysl¶
Mikroslužby nejsou stříbrná kulka. Pro malý tým (2–3 vývojáři) je režie obrovská — provozujete distribuovaný systém se vším, co to obnáší. Pokud nemáte jasné hranice mezi doménami, skončíte s „distribuovaným monolitem” — to nejhorší z obou světů.
Naše doporučení: začněte s monolitem, ale s čistou modulární strukturou. Až budete cítit bolest — pomalé deploymenty, organizační tření, potřeba škálovat jen část systému — pak extrahujte.
Mikroslužby jsou organizační i technická změna¶
Přechod na mikroslužby není jen o technologii — je to změna způsobu, jakým tým pracuje. Conway’s Law platí: architektura systému odráží strukturu organizace. Pokud chcete nezávislé služby, potřebujete nezávislé týmy.
Pro nás to byl správný krok. Ale udělali bychom ho znovu jen za předpokladu, že máme dostatečně velký tým a jasné doménové hranice.