Architekt systemówArchitekt systemowy

Jak prawidłowo zorganizować interakcje między mikrousługami, aby zminimalizować powiązania (loose coupling) i maksymalizować skalowalność?

Zdaj rozmowy kwalifikacyjne z asystentem AI Hintsage

Odpowiedź.

Minimalizacja powiązań (loose coupling) między mikrousługami to jedna z głównych zasad nowoczesnej architektury. Osiąga się to poprzez asynchroniczną interakcję (poprzez kolejki wiadomości lub szyny zdarzeń), rezygnację z bezpośrednich synchronizowanych wywołań HTTP bez potrzeby oraz wydzielenie wyraźnych kontraktów API.

Popularnym sposobem jest użycie brokerów wiadomości (RabbitMQ, Kafka, NATS), gdzie mikrousługi publikują zdarzenia o swoim stanie, a subskrybenci na nie reagują.

Przykład publikacji i przetwarzania zdarzenia w Kafka na Node.js:

// producer.js const { Kafka } = require('kafkajs') const kafka = new Kafka({ clientId: 'order-service', brokers: ['kafka01:9092'] }) const producer = kafka.producer() await producer.connect() await producer.send({ topic: 'orders', messages: [ { value: JSON.stringify({orderId: 123}) } ] }) await producer.disconnect() // consumer.js const consumer = kafka.consumer({ groupId: 'payment-group' }) await consumer.connect() await consumer.subscribe({ topic: 'orders', fromBeginning: true }) await consumer.run({ eachMessage: async ({ topic, partition, message }) => { const order = JSON.parse(message.value.toString()) // przetwarzanie zamówienia }})

Kluczowe cechy:

  • Mikrousługi komunikują się przez sformalizowane API lub pośrednika (kolejkę, szynę)
  • Każda usługa ma swoją bazę danych (Database per Service), aby uniknąć blokad i konkurencji
  • Możliwe jest podłączenie nowych usług w locie bez zmiany istniejących

Pytania z pułapką.

Pytanie: Czy można używać wspólnej bazy danych dla kilku mikrousług, jeśli to jeden duży projekt?

Nie, narusza to zasadę niezależności, prowadzi do tight coupling, pogarsza skalowalność i utrzymywalność. Należy używać oddzielnych baz danych lub schematów.

Pytanie: Czy synchronizowane interakcje HTTP między usługami są dopuszczalną praktyką w przypadku skalowania systemu?

Synchronizowane wywołania HTTP źle się skalują i mogą stać się wąskim gardłem. Zaleca się zastosowanie mechanizmów asynchronicznych i tylko w przypadku absolutnej konieczności uciekać się do synchronizowanych wywołań.

Pytanie: Czy można skalować mikrousługę tylko przez zwiększenie liczby jej instancji, nie zmieniając architektury systemu?

Nie, proste zwiększenie liczby instancji nie rozwiązuje problemów powiązań czy wąskich gardeł w architekturze. Konieczna jest analiza bottlenecków, wdrażanie kolejek, pamięci podręcznej i podział odpowiedzialności usług.