Home SOFTWAREArhitektura modernih web aplikacija – Deo 5: Mikroservisna arhitektura – dizajn i izazovi

Arhitektura modernih web aplikacija – Deo 5: Mikroservisna arhitektura – dizajn i izazovi

od itn
Mikroservisna arhitektura

Dobrodošli u peti deo serijala na ITNetwork.rs! Do sada smo prošli kroz monolit i mikroservise, frontend (SPA/SSR/SSG), API-je (REST/GraphQL/gRPC) i baze podataka (polyglot, CQRS, Event Sourcing). Sada ulazimo u srž mikroservisne arhitekture – kako pravilno podeliti sistem na servise, kako oni komuniciraju, i kako upravljati haosom distribuiranog sistema.

Šta su mikroservisi – podsetnik

„Mikroservis je nezavisna, samostalno deploy-ovana jedinica koja rešava jedan poslovni problem i komunicira preko jasno definisanih interfejsa.“Sam Newman, „Building Microservices“

Karakteristika Objašnjenje
Jedan domen „Korisnici“, „Porudžbine“, „Plaćanje“
Vlasništvo tima „You build it, you run it“
Nezavisni deploy Bez koordinacije sa drugim timovima
Sopstvena baza Nema deljene tabele
1. Granice servisa – kako ne podeliti na 1000 servisa?

Loš pristup: Podela po tehnologiji

Frontend servis → React
Backend servis → Node.js
Baza servis → PostgreSQL
→ Ovo je distribuirani monolit.

Pravi pristup: Domain-Driven Design (DDD)

Bounded Context

„Jasno definisana granica unutar koje model ima smisao.“

Bounded Context Servis
Korisničko upravljanje user-service
Katalog proizvoda catalog-service
Proces naručivanja order-service
Plaćanje payment-service
Primer: E-commerce

E-commerce2. Komunikacija između servisa

Tip Protokol Kada koristiti
Sinhrona HTTP/REST, gRPC Brzi odgovor, zahteva rezultat
Asinhrona Message Queue (RabbitMQ, Kafka) Eventual consistency, skalabilnost

Sinhrona komunikacija (Request/Response)

Sinhrona komunikacija

Problem: Ako PaymentService padne → OrderService čeka → kaskadni pad

Asinhrona komunikacija (Event-Driven)

Asinhrona komunikacija

Prednost: Servisi su otporni na pad drugih

3. Ključni obrasci u komunikaciji

Obrazac Alat Primer
Service Discovery Consul, Eureka, Kubernetes DNS payment-service.svc.cluster.local
Circuit Breaker Resilience4j, Polly, Istio „Ne zovi servis ako je 5x pao“
Retry & Timeout Axios-retry, gRPC retry Pokušaj 3x, čekaj 100ms
Bulkhead Semaphore „Samo 10 paralelnih poziva ka servisu“
Primer: Circuit Breaker u Node.js
import CircuitBreaker from 'opossum';

const breaker = new CircuitBreaker(async (userId: number) => {
  const res = await fetch(`http://payment-service/charge/${userId}`);
  if (!res.ok) throw new Error('Payment failed');
  return res.json();
}, {
  timeout: 3000,
  errorThresholdPercentage: 50,
  resetTimeout: 30000
});

breaker.fallback(() => ({ status: 'degraded', message: 'Try later' }));

// Korišćenje
const result = await breaker.fire(userId);
4. Lokalni razvoj mikroservisa – Docker Compose

docker-compose.yml

version: '3.8'
services:
  user-service:
    build: ./services/user
    ports: ["3001:3000"]
    environment:
      - DB_URL=postgresql://postgres:pass@db:5432/users
    depends_on: [db, rabbitmq]

  order-service:
    build: ./services/order
    ports: ["3002:3000"]
    depends_on: [rabbitmq, db]

  payment-service:
    build: ./services/payment
    ports: ["3003:3000"]
    depends_on: [rabbitmq]

  rabbitmq:
    image: rabbitmq:3-management
    ports: ["5672:5672", "15672:15672"]

  db:
    image: postgres:15
    environment:
      POSTGRES_PASSWORD: pass
      POSTGRES_MULTIPLE_DATABASES: users,orders
    volumes:
      - postgres_data:/var/lib/postgresql/data

volumes:
  postgres_data:

Pokretanje: docker-compose up –build

5. Praktičan primer: Dva mikroservisa sa RabbitMQ

1. user-service → emituje UserCreated

// user-service/src/events.ts
import amqplib from 'amqplib';

const conn = await amqplib.connect('amqp://rabbitmq');
const channel = await conn.createChannel();

await channel.assertExchange('user.events', 'fanout');

export const publishUserCreated = (user: any) => {
  channel.publish('user.events', '', Buffer.from(JSON.stringify({
    type: 'UserCreated',
    user
  })));
};

2. notification-service → prima i šalje email

// notification-service/src/consumer.ts
channel.consume('user_queue', async (msg) => {
  if (msg) {
    const event = JSON.parse(msg.content.toString());
    if (event.type === 'UserCreated') {
      await sendWelcomeEmail(event.user.email);
    }
    channel.ack(msg);
  }
});
6. Izazovi mikroservisa (i kako ih rešiti)
Izazov Rešenje
Distribuirane transakcije Saga Pattern, Eventual Consistency
Praćenje grešaka Distributed Tracing (Jaeger, OpenTelemetry)
Verzionisanje API-ja Consumer-Driven Contracts (Pact)
Testiranje Contract Testing, E2E sa Testcontainers
Deployment haos GitOps, ArgoCD, Progressive Delivery
Dijagram: Kompletna mikroservisna arhitektura

Kompletna mikroserverska arhitekturaPoređenje: Monolit vs Mikroservisi

Aspekt Monolit Mikroservisi
Brzina razvoja (početak) ★★★★★ ★★
Skalabilnost ★★ ★★★★★
Nezavisni deploy
Tehnološka sloboda
Operativni trošak ★★★★★ ★★
Tim veličina Mali Srednji+
Kada preći na mikroservise?
Situacija Preporuka
1–3 developera, MVP Monolit
5+ timova, 10+ funkcionalnosti Mikroservisi
Potreba za Go/Rust/Python po servisu Mikroservisi
Česta downtime zbog jedne izmene Mikroservisi

Zlatno pravilo: „Prvo napravi monolit koji radi. Zatim ga razbij – ako i samo ako osetiš bol.“

Šta dalje?

U šestom delu ulazimo u serverless i edge computing:

  • AWS Lambda, Vercel, Cloudflare Workers
  • Hladni start, troškovi
  • Edge funkcije

Tvoj izazov

  1. Napravi dva servisa sa docker-compose:
    • order-service → kreira porudžbinu
    • email-service → prima OrderCreated preko RabbitMQ
  2. Deploy-uj na Render, Fly.io ili Railway
  3. Komentariši ispod: „Koliko mikroservisa ima tvoj trenutni projekat?“

Autor: Dušan Antonijević – saradnik ITNetwork.rs
Hvala na čitanju! Podeli tekst sa kolegama.

Banner

Banner

Možda će vam se svideti i