Yeni bir çağrı merkezi sistemi kurmaya karar verdiğimde, piyasadaki mevcut çözümlerin hiçbirinin ihtiyaçlarımı karşılamadığını fark ettim. Bu nedenle, tamamen kendime ait bir sistem inşa etmeye başladım ve ortaya çıkan projeyi AGPL-3.0 lisansıyla GitHub’da paylaştım. Bu yazıda, sistemin mimarisini ve en çok zamanımı alan kritik hataları detaylı olarak ele alıyorum.
Sistem mimarisi: Güçlü bileşenlerin bir araya gelmesi
Yeni sistemimin temelinde, her biri belirli bir görevi kusursuz şekilde yerine getiren dört ana bileşen bulunuyor. Bu bileşenlerin birbirinden ayrılması, sistemin ölçeklenebilirliğini ve güvenilirliğini önemli ölçüde artırıyor.
- Kamailio (SIP kenar hizmeti): Yüksek çağrı başına saniye (CPS) performansı sunarken, STIR/SHAKEN doğrulama için
secsipidmodülünü kullanıyor. Bu modül, çağrıların kimlik doğrulamasını sağlayarak sahtecilik girişimlerini engelliyor.
- FreeSWITCH (medya işleme): Arka planda çalışan
bgapi originatekomutu sayesinde çağrıları başlatabiliyor vemod_avmdmodülüyle otomatik cevaplama tespiti gerçekleştirebiliyor. Ayrıca, Genişletilebilir Sunucu Dili (ESL) ve her çağrı için ayrı Lua betikleriyle esnek bir yapı sunuyor.
- Go (çağrı motoru): Çağrı hızını kontrol eden ve
SELECT FOR UPDATE SKIP LOCKEDsorgularıyla kuyruk yönetimini sağlayan bir motor. Her çağrı için ayrı durum makineleri oluşturarak, ESL olaylarını temel alıyor ve sistemin akıllı şekilde yönetilmesini sağlıyor.
- PostgreSQL (çok kiracılı veri yönetimi): Satır düzeyinde güvenlik (RLS) politikalarıyla, her işletmenin verilerini tamamen izole ediyor. Veritabanı katmanında uygulanan bu izolasyon, geliştiricilerin her sorguya doğru
tenant_ideklemelerine gerek bırakmıyor.
- React (yönetim arayüzü): Kampanyalar, potansiyel müşteri listeleri, senaryolar ve raporlar için kullanıcı dostu bir konsol sunuyor. Bu arayüz sayesinde sistem, hem teknik olmayan kullanıcılar hem de geliştiriciler tarafından kolayca yönetilebiliyor.
Kamailio’nun FreeSWITCH’in önünde yer alması, birçok kişi tarafından gereksiz görülebilir. Ancak küçük ölçeklerde bu yapı gereksiz gibi görünse de, Kamailio SIP yönlendirme ve CPS yönetimi için idealken, FreeSWITCH medya işleme konusunda üstün performans sağlıyor. Bu ayrım sayesinde, medya katmanını kolayca ölçeklendirebiliyor ve kenar hizmetlerine dokunmadan sistem performansını artırabiliyorum.
Çok kiracılı sistemlerde güvenilir izolasyon
Sistemde her işletme verisi, tenant_id adlı bir alanla etiketleniyor. PostgreSQL’in satır düzeyinde güvenlik politikaları, her API isteğiyle birlikte ayarlanan oturum değişkenlerine dayanıyor. Bu sayede, hatalı bir sorgu bile başka bir kiracının verilerine erişemiyor. Yıllar boyunca birçok sistemde, kiracı izolasyonunun sadece doğru WHERE koşullarıyla sağlandığını gördüm. Ancak veritabanının bu izolasyona doğrudan müdahale etmesi, benim için en güvenilir çözüm oldu.
Geceyarılarını uyutmayan kritik hatalar
Projeyi geliştirirken karşılaştığım en sinir bozucu hatalar, sistemin temel fonksiyonlarını devre dışı bırakıyordu. Bu hataların çoğu, gece geç saatlere kadar süren düzeltme maratonlarına yol açtı.
- "1’e bas" işlemi hiç çalışmadı. Sistemde iç ajan kavramını kaldırıp, doğrudan dış ajanlara yönlendirme yapmaya başladım. Ancak "1’e bas" işlemi için kullanılan koşullu bekletme, hala "uygun ajan sayısına" bağlı kaldı. Bu sayı sıfır olduğunda, sistem hiçbir şey yapmıyordu. Çözüm, "1’e bas" kampanyalarını kapasiteye göre doldurmak ve operatörün eşzamanlı çağrı sayısını sınırlamasını sağlamak oldu.
- MP3 selam dosyaları sessizlik olarak çalındı. FreeSWITCH’in MP3 dosyalarını çözümleyebilmesi için
mod_shoutadlı modülün yüklü olması gerekiyor. Bu modül yüklenmediğinde, ses dosyaları sessizlik olarak çalınıyordu. Modülü yükledikten sonra ses kalitesinin kötü olduğunu fark ettim. Dosyanın 44.1kHz stereo formatından 8kHz mono telekom formatına her çağrıda yeniden örneklenmesi, ses kalitesini ciddi şekilde düşürüyordu. Gerçek çözüm, yükleme sırasında ses dosyalarını ffmpeg yardımıyla 8kHz mono PCM WAV formatına dönüştürmek oldu. Bu sayedemod_sndfile, dosyaları yerel olarak çalabiliyor.
- "1’e bas hiçbir şey yapmıyor" — tam bir gece kaybı. Lua betiklerinde
session:execute("playback", file)komutu, DTMF tuşlarını yutuyordu. Bu nedenle, selam dosyası çalındıktan sonrareadkomutu tarafından DTMF tuşları algılanamıyordu. Çağrı, tuş girişi olmadan otomatik olarak sonlandırılıyordu. Çözüm, çağrı sırasında hem dosyayı çalıp hem de tuş girişini aynı anda alansession:playAndGetDigits()fonksiyonunu kullanmak oldu.
- Cepten cevaplama tespiti için ücret ödemek yerine.... Eski
mod_amdmodülü artık mevcut FreeSWITCH sürümlerinde desteklenmiyor ve bakımlı sürüm olanmod_com_amdticari bir ürüne dönüştü. Bunun yerine,mod_avmdmodülünü (bip tespiti) kullanarak bir çözüm geliştirdim. Yayıncı Lua betiği, mesajı çalarken avmd’yi başlatıyor ve bip sesi algılandığında mesajı yeniden çalıyor. Bu sayede, sesli mesaj kutusuna temiz bir kayıt bırakılabiliyor. Küçük bir hile gibi görünse de, tamamen ücretsiz ve işlevsel bir çözüm sunuyor.
Mevcut durum ve gelecek planları
Proje şu aşamada henüz yayınlanmamış durumda. "1’e bas" ve yayıncı akışları tamamen çalışır durumda olsa da, üretim ortamında kullanılacak bir taşıyıcı bağlantısı henüz kurulmadı. Şu anda Linphone geçidi üzerinden testler yapıyorum ve bu geçidin kendi DTMF sorunları bulunuyor. Ayrıca, Kamailio üzerindeki STIR/SHAKEN imzalama henüz gerçek bir taşıyıcı tarafından doğrulanmadı. Bir de ajan softphone uygulamasının geliştirilmesi gerekiyor.
Eğer gerçek bir dışa arama telekom sistemini hayata geçirmiş biriyseniz, sistemdeki eksiklikleri veya hataları bana bildirmenizden mutluluk duyarım. Sistem henüz üretim ortamında test edilmediği için, gerçek trafiği yönlendirmeden önce olası sorunları tespit etmek ve düzeltmek istiyorum.
Projeyi AGPL lisansıyla ve kendi sunucunuza kurabileceğiniz şekilde yayınladım. Hiçbir ticari amacım yok — sadece ihtiyacımı karşılayan bir sistem bulamadım.
Yapay zeka özeti
Açık kaynaklı bir ViciDial alternatifi inşa eden geliştirici, kullandığı yığını ve geceyarılarını uyutmayan kritik hataları paylaşıyor. PostgreSQL RLS, FreeSWITCH ve Go tabanlı mimariyi keşfedin.