Sifariş servisi hadisələr dərc edir, qəbul edənlər isə artıq bir neçədir: məktublar, anbar, analitika. Hər birinin öz marağı var: məktublara yalnız ödənişlər lazımdır, anbar bir regionla işləyir, analitikaya isə hər şey lazımdır. Hansı mesajın hansı növbəyə düşəcəyinə kim qərar verir? Bu, exchange-in işidir. Bu dərsdə onun növlərini — direct, fanout, topic və headers — öyrənəcək, abunələr qurmağı mənimsəyəcək, sonra isə mesajın emalı alınmayanda nə etməli olduğuna baxacağıq: bunun üçün RabbitMQ-da dead-letter növbələri, TTL və gecikmə ilə təkrarlar var.

Exchange necə qərar verir

Zənciri xatırlayaq: producer → exchange → binding → növbə → consumer. Exchange heç nə saxlamır: o, mesajın marşrutlaşdırma açarına (routing key) və bağlamalara (binding) baxır, mesajı uyğun növbələrə kopyalayır. Bağlama — «növbə + bağlama açarı» (binding key) cütüdür. Exchange-in növü bu iki açarın necə müqayisə olunduğunu müəyyən edir:

NövQaydaNümunə
directaçarlar dəqiq üst-üstə düşürlog səviyyəsi: error
fanoutaçar nəzərə alınmır, surət hamıya gedirbütün servislər üçün hadisə
topicaçar şablonla müqayisə olunurorder.*.paid
headersaçar yox, başlıqlar müqayisə olunurformat=pdf
Direct dəqiq açarla marşrutlaşdırır və bağlaması olmayan mesajı atır; fanout mesajı bütün növbələrə kopyalayır
Direct dəqiq açarla marşrutlaşdırır və bağlaması olmayan mesajı atır; fanout mesajı bütün növbələrə kopyalayır

direct: dəqiq uyğunluq

Nümunə — səviyyələr üzrə loglar. Xətalar (error) bildiriş növbəsinə, info və warning isə konsola lazımdır:

javascript
import amqp from 'amqplib';

const connection = await amqp.connect('amqp://localhost');
const channel = await connection.createChannel();

await channel.assertExchange('logs', 'direct', { durable: true });
await channel.assertQueue('alerts', { durable: true });
await channel.assertQueue('console', { durable: true });

await channel.bindQueue('alerts', 'logs', 'error');
await channel.bindQueue('console', 'logs', 'info');
await channel.bindQueue('console', 'logs', 'warning');

const send = (level, text) =>
  channel.publish('logs', level, Buffer.from(text));

send('error', 'Payment service is down');
send('info', 'Order 7 created');
send('trace', 'nobody listens to this level');

error açarlı mesaj alerts-ə, info isə console-a düşəcək. Bağlaması olmayan trace isə səssizcə itəcək: exchange onu hara göndərəcəyini bilmir və atır. Belə itkiləri görmək üçün publish-də mandatory bayrağı, exchange-də isə alternate exchange ayarı var.

💡 Bir açara bir neçə növbə bağlasanız, hər biri öz surətini alacaq: direct bunu da bacarır.

fanout: hamıya surət

fanout açarı nəzərə almır və hər mesajı bütün bağlı növbələrə kopyalayır. Bu, modulun birinci dərsindəki ən sadə pub/sub-dır. Abunəçi öz növbəsini elan edir və onu exchange-ə bağlayır: