Mesaj Kuyruklama (Messaging Queue)
Aylar sonra tekrar merhaba arkadaşlar, Blogdan uzaktan kaldığım süre içerisinde cevaplayamadığım konu kaldıysa lütfen kusuruma bakmayın deyip hızlıca yazıya giriş yapmak istiyorum.
Bu yazıda, aslında birçok blog ve etkinlikte gerek yakinen tanıdığım/çalıştığım arkadaşlarımın gerekse sektörde bulunan tecrübeli meslektaşlarımın değindiği mesaj kuyruklama (messaging queue) konusuna bir de biz göz atacağız.
Mesaj (İş) Kuyruklamaya Neden İhtiyaç Duyarız
Birçok projede kullanıcıyla direkt bağlantısı olsun ya da olmasın çalıştırılması/yürütülmesi zaman alan bazı işlemler gerçekleştiriyoruz. Buna, sık telaffuz edilen kullanıcı kayıt (register) olduğunda email gönderilmesi örneğini verebileceğimiz gibi, kullanıcının istediği raporu hazırlama, yüklenen bir imajı farklı ebatlarda boyutlandırma, alınan sipariş/satış/rezervasyon gibi bilgilerin kullandığımız diğer yazılımlara aktarımı vb. örnekler de vermemiz mümkün.
Ayrıca sadece çalışması/yürütülmesi zaman alan işlemler değil; belirli aralıklarla çalışması gereken betikler ve üzerinde bir takım iş mantığı yürütüldükten sonra işleme alınması gereken işlemler de gerekli olabilir.
Mesaj Kuyruklamayı Geleneksel Yöntemlerle Nasıl Çözeriz
Yukarıda saydığımız bu ve bu gibi işlemleri kullanıcıyı bekletmeden çalıştırmak için bir dizi önlemler/geliştirmeler almamız elbette mümkün. Bunlardan İlk akla geleni ve bizim de tecrübe ettiğimiz asenkron işlemi simüle etme yöntemidir. Bu yöntemde zamanlanmış görevler (linux için cron) kullanılarak yapılacak işler ilgili tablolardan zaman aralığı vd. bilgilere göre taranıp işlenir (son 5 dakika içindeki yeni kayıtları işlemek gibi). Bir diğer simüle yöntemi ise, bir önceki paragrafta yer alan işlemler (kayıt, sipariş/satış/rezervasyon vd) tamamlandığında bir kaynağa (dosya, sql, no-sql, memory) işlenmesi gereken iş olduğu bildirilip işleme devam edilir ve yine zamanlanmış görevler yardımıyla bunlar işlenir.
Bu yöntem ilk başlarda tabi ki kolay ve uygun görülebilir ama projenizin ikinci yılında 25 adet zamanlanmış göreviniz olduğunda gerek yönetim gerekse işletim maliyetleri açısından işiniz zora girmeye başlayabilir. Tek dezavantaj tabiki bu değildir aşağıdaki soru(n)ları da cevapsız bırakmayacak bir yazılım geliştirmeniz kaçınılmaz olacaktır;
- Yürütülme esnasında hata oluşursa tekrar denenmesi gerekir (tekrar deneme, retry)
- Bazı işler belirli önceliğe göre çalışması gerekebilir (önceliklendirme, priority)
- Bir işin önceliği düşük olsa bile uzun süre kuyrukta kalmaması gerekir (yaşlandırma, aging)
- İşlerin kısa sürede işleme alınması gerekir (sık aralıklarla çalışan cron)
- İki ayrı zamanlanmış görev (cron) aynı iş üzerinde çakışmaması gerekir
- X kaynağı aktarım yaparken bizden HTTP yetkilendirmesi istiyor
- Kuyrukları tek makinede işlemek yeterli olmuyor iki makine işlesin (ölçeklendirme, scaling)
İlk madde için; Hata durumunda diğer işlerin yürütülmesi sorun değilken diğer bir işte kesinlikle sonrakilerinde işlenmemesi gerekiyor olabilir.
Bunlardan özellikle son iki madde gerçekten çok önemli bir sorun teşkil ediyor. Zamanlanmış görevi uzun aralıklarla çalıştırırsanız (1-2 saat gibi) bu süre zarfında 3 tane iş olsa dahi işlenmeyecek, ama sık çalıştırırsanız ve yoğun iş kuyruğu oluşursa iki ayrı zamanlanmış görev aynı işi yapmaya başlayacak. Bunun önüne geçmek için zamanlanmış görev dosyasının sadece bir defa çalışması için “file lock” kullanacaksınız ama zamanlanmış görev dosyası hata fırlatırsa ve kilidi kaldıramazsa başka bir zamanlanmış görev çalışamayacak. Hatta bir defasında veritabanında tuttuğumuz iş (kuyruk) tablosuna is_locked alanı açtığımızı ve zamanlanmış görev çalışırken ilgili satırı işlemeden önce kilitlediğini itiraf etmem de iyi olacaktır.
Son madde için de -kendi kuyruklama yazılımımızı geliştirmeye çalıştığımız için- elbette bizim bir çözüm bulmamız gerekiyor; tek sayıları bir makine çift sayıları ayrı bir makine işlesin (maksimum iki makine tabi ki), random bir iş seçsin, random bir makineye atılsın, saniye bazında aralıklarla çoklu makine çalışsın vs. gibi.
Yukarıda yazılanların hepsinin tecrübe ile sabit olduğunu ve paragraf sayısını artırmanın da bir o kadar mümkün olduğunu bilmenizi isterim.
Ve elbette bunları yapmak bir şekilde mümkün görünüyor da olabilir, ama projemizin asıl amacı iş kuyruklamak ve bunları yönetmek değilse bırakalım bunu ilgili bileşen yapsın. Buna şöyle bakabiliriz; piyasada halihazırda onlarca veritabanı sunucusu var ve çoğunlukla açık kaynak ve biz kendi veritabanı sunucumuzu yazmak yerine -çoğunlukla- bunlardan birini kullanıyoruız.
Mesaj Kuyruklamayı Yeni Nesil* Yöntemlerle Nasıl Çözeriz
Yazının girişinde de bahsettiğim gibi kuyruklamanın nasıl kullanılacağına dair çokça döküman olması, yazının asıl amacı “nasıl kullanırız” yerine “neden kullanmalıyız” sorusuna cevap aramak olması ve saatlerce zaman harcanmasına rağmen kod örneklerinin eksikliği, yetersiz bulmam vd. nedenlerle taslak olarak kalan 26 adet yazı sebebiyle bu kısmı çok uzun tutmayacağım.
Kısaca değinecek olursak; ihtiyacımız olan özelliklerin hemen hepsini karşılayan çözümler/yazılımlar mevcut. Bunlardan birini seçerek başlamak ve proje geliştirme sürecinde iş kuyruklamayı da göz önünde bulundurmak iyi olacaktır. Sonrasında ilgili yerlerde mesaj kuyruklama yazılımına işi -varsa nevi ile birlikte bildirmek- ve listener (consumer) aracılığıyla kuyruğa gelen işleri işlemek olacaktır.
Yazıyı, “neden kullanmalıyız” sorusuna cevap arama kapsamında tutup burada noktalamak istiyorum. Kesin olmamakla birlikte mesaj kuyruklama bileşen/yazılımlarının bize sayfadığı faydaları bir başka yazıda tartışabiliriz diye düşünüyorum.
Herkese keyifli çalışmalar,
* Yeni nesil diye adlandırıyor olmakla birlikte mesaj kuyruklamanın aslında hiç de yeni olmayan bir bileşen olduğunu bilmenizi isterim.