RabbitMQ ve Redis ile Gerçek Bir Proje

Erdem Köşk
Kodcular
Published in
4 min readMay 14, 2020

--

Herkese selamlar!

Bu karantina günlerinde yapabildiğim en iyi şeylerden biri şüphesiz kendimi geliştirmeye çalışmak. Bu süreçte kendime kattığım bazı şeyleri dilim döndüğünce sizlere aktarmak boynumun borcu. Bu arada bu proje sadece Redis ile yapılabilirdi. Ancak daha çok şey öğrenmek amaçlandı!

Öncelikle son zamanlarda karşımıza çıkan bu Rabbit MQ nedir diye düşünüyorsanız ufak bir özet geçmeye çalışıyım. Rabbit MQ aslen bir message broker olarak adlandırılabilir. Message broker, iki uygulama arasındaki iletişimin işlenmesi konusunda aracı bir platform görevi görür. RabbitMQ, Gelişmiş Message Queuing Protokolü (AMQP) standardında modellenmiş bu tür açık kaynaklı bir kurumsal mesajlaşma sistemidir. Bu protokollerin detaylarına bakmak isteyenler sizi buraya alalım.

Redis ise bir veri yapısı sunucusudur. Açık kaynak, bellek kullanımlı, anahtar-değer deposudur. Redis “Uzak Sözlük Sunucusu” (İngilizce: “REmote DIctionary Server”) anlamına gelmektedir. Detay için sizi buraya alalım.

Bugün sizlere teorik bilgi vermekten daha çok aslında gerçek hayatta biz bu teknolojinin son nimetlerini nasıl ve nerde kullanırızı anlatmak olacak. Amacım sizlere tek tek kod satırları ile programın tamamını buraya yazmak değil aslında. Çünkü tüm kodlar public şekilde açık şekilde bu adreste bulunuyor olacak. Hatta sizle beraber kod yazmak bu repoyu geliştirmek hepimiz için beraber çalışmayı öğrenmek ve kendimize yeni şeyler katmak adına harika bir macera olacağını düşünüyorum. O yüzden hadi klavye başına :)

Eğer aranızda daha önce socket programlama ile uğraşan birileri varsa aslında birden fazla cihazın birbirleri ile haberleşme teorisini iyi şekilde biliyor yada kullanmış durumdadır. Kullandıkları altyapı ve yaklaşım açısı farklı olasa temelinde yazdığımız iki serveri konuşturacağımız bir proje yapacağız.

Amaç

Hepimiz defalarca mail göndermek için kod yazmışızdır. Her site yaparken bir daha bir daha ve bir daha… Bunu bir paket yapmış olsak bile bu logicleri tekrar tekrar eklemek zorunda kalacağız. Bu yapacağımız projenin temel amacı aslında buna bir son vermek olacak.

Bununla birlikte microservis mimarisinin bu kadar popüler olma nedeninlerinden biri olan “Bir şeyi yap, ama onu iyi yap” sloganına uyan bir yapı hazırlamak. Mail gönderme işlemini tüm sistemimizden soyutlamak…

Evet yanlış duymadınız. Artık mail gönderme işi kendi kodumuzun içinde yer almayacak. Biz hazırladığımız server’a mail atmak istediğimiz kişiyi neler yollamak istediğimize dair bilgileri Rabbit MQ sayesinde gönderiyor olacağız. Bununla beraber Redis ile bu kullanıcıların kara listede olup olmadığına bakacak. Duruma göre onlara mail atıp atmayacağız.

En güzeli de bunun sorumluluğu bizde olmayacak… Harika değil mi :)

Sistemi daha iyi anlatmak gerekirse:

Mesela kullanıcı bizim mail sistemimize dahil olmak istedi yada üye oldu gibi düşünelim. Kullanıcıya buna dair bir mail yollamak istiyoruz. Ancak bu mail kodunu sistemimizin farklı yerlerinde yazmamız yada tekrar etmemiz gerekecekti. Oysa şimdi tek yapmamız gereken RabbitMQ sayesinde bir mesaj göndermek kadar kolay olacak.

Öncelikle RabbitMQ bağlantımızı yapalım:

const amqp = require(‘amqplib/callback_api’);
const config = require(‘../../config’);
const logger = require(‘../plugins/logger.plugin’);
function sendRabbitMQ(queueName, data) {
amqp.connect(config.rabbitmq.url, (error0, connection) => {
if (error0) {
throw error0;
}
connection.createChannel((error1, channel) => {
if (error1) {
throw error1;
}
const queue = queueName;channel.assertQueue(queue, {
durable: false,
});
channel.sendToQueue(queue, Buffer.from(data));
logger.info(‘ [x] Sent %s’, data);
});
setTimeout(() => {
connection.close();
}, 500);
});
}
module.exports = {
sendRabbitMQ,
};

Yukarıdaki bağlantı ile basitçe RabbitMQ ya veri yollayabilecek hale gelmiş olduk.

Şimdi sırada mail atmak istediğimizde eklememiz gereken kod satırında:

rabbitMq.sendRabbitMQ('mailChannel', JSON.stringify({
email: 'testme-app@yandex.ru',
nameSurname: 'Erdem Köşk',
type: 'register',
}));

Voolaa… Mail atmak istediğimiz kullanınıcın mail adresi adı ve maili göndermek istemem sebebimizi (şuan için benim belirlediğim ve yazdığım iki tip var) onu belirtiyoruz. Artık düşünmemize gerek yok.

Daha sonra bu mesaj bizim yazmış olduğumuz consumer servise iletilmiş oluyor. Ve bu servis hali hazırda Redis ve rabbitMQ serverlarını dinliyor durumda.

const amqp = require(‘amqplib/callback_api’);
const config = require(‘../config’);
const mailService = require(‘./mail.service’);
function connectAndListenRabbitMQ() {
amqp.connect(config.rabbitmq.url, (connectionError, connection) => {
if (connectionError) {
console.error(‘[*] RabbitMq’, connectionError.message);
return setTimeout(connectAndListenRabbitMQ, 1000);
}
connection.on(‘error’, (err) => {
if (err.message !== ‘Connection closing’) {
console.error(‘[*] RabbitMq connection error’, err.message);
}
});
connection.on(‘close’, () => {
console.error(‘[*] RabbitMq reconnecting.’);
return setTimeout(connectAndListenRabbitMQ, 1000);
});
console.log(‘[*] RabbitMq connected.’);connection.createChannel((channelError, channel) => {
if (channelError) {
throw channelError;
}
const queue = config.rabbitmq.channel;
channel.assertQueue(queue, {
durable: false,
});
console.log(‘[*] Waiting for messages in %s. Check blacklist from redis: %s. Waiting messages…’, queue, config.considerBlacklist);channel.consume(queue, (data) => {
const mailInfo = JSON.parse(data.content.toString());
if (!mailInfo || !mailInfo.type) {
console.log(‘[x] Wrong paramters from client!’);
return;
}
mailService.sendMail({ mailInfo });console.log(`[x] Mail Message Received [x] Type: ${mailInfo.type}, nameSurname: ${mailInfo.nameSurname}, email: ${mailInfo.email} `);
}, {
noAck: true,
});
});
});
}
module.exports = {
connectAndListenRabbitMQ,
};

Öncelikle gelen bu mail adresi Redis’te baktığımız mapte var mı diye kontrol ediyoruz. Eğer yoksa kişiye maillerini yollamış oluyoruz.

Yeep… İşte karşınızda mail :) Her internet siteniz için buban benzer repolar yapıp daha sonra yazacağınız yüklerden kurtulabilirsiniz.

Aslında temel amacım size bu tarz teorik bilgilerin gerçek hayatta nerelerde kullanabileceğine dair sağlam bir anlatım yapmak.

Umarım hoşunuza gitmiştir. Kodların tamamı için sizi buraya alalım.

Şuan hali hazırda herokuya deploy aldığım ve hali hazırdaki bir projem için kullandığım yapı bu şekilde. Umuyorum size yardımı dokumuştur.

Sevgilerle!

--

--