• 12-11-2025, 02:04:15
    #1
    Selamlar,

    Şimdi ana bir adet sunucumuz var.
    Bu sunucumuza saniyede 20 adet sipariş gelecek.
    Bu sunucu saniyede gelen 20 siparişi 10 farklı VDS makinelerine 5 saniye icinde bildirmeli ve neredeyse ve neredeyse asla yığılma olmamalı.

    Şimdi ben şurada şöyle bir şey düşündüm;
    10 Farklı makine her biri -> 1 worker
    Yani 10 workerimiz var.
    10 worker her 5 saniye aralıklarla ana sunucuya istek atsın ve eğer sipariş var ise siparişi işlesin diye düşündüm. Ama bu pek mantıklı gelmedi neden bilmiyorum ama yeteri kadar optimize gelmedi.


    O zaman da şu mimariye geçtim:
    Ana sunucuya sipariş gelir,araya bir tane websocket açarız sipariş geldiğinde ana sunucu websockete şuanda elimde sipariş var diye istek atsın ve bu şekilde sipariş olmadığında boşu boşuna DB istegi olmadan websocketde istekler kalır,siparişler geldiğinde ise websockete aktarılır sipariş işlenir sipariş islendikten sonra response en son ana sunucuya tekrar aktarılır diye düşündüm.
    Bu şekilde hem daha az istek ana makineye ulaşır bu sayede fazla DB sorgusu olmaz ve wss ile anlık olarak wss izlenir siparişler daha hızlı işlenir gibime geldi.

    Sizlere de sorayım,sizce bu mimari uygun mudur?
    Eğer uygun değil ise neden ve nasıl geliştirebilirim?
    Veya daha farklı bir mantık önerebilir misiniz?
  • Kabul Edilen Cevap
    • soylenmezsmt adlı üyeden alıntı: mesajı görüntüle
      Hocam yine rahatsız ediyorum ama ufak bir sorum daha var.
      1 numaralı worker, 1 ID’li siparişi aldı ve şu anda işliyor ise, diğer 9 sunucu boş demektir.
      Diyelim ki bir sipariş daha geldi ve bu da yine 1 numaralı worker’a gitti. Böyle olunca diğer 9 sunucu hâlâ boşta kalıyor ama 1 makine 2 siparişi aynı anda işliyor, bu da servisi yavaşlatıyor.
      Normalde, bu yeni siparişi diğer boş sunuculardan birinin alması gerekirdi.

      Bunun için şöyle yapmak mantıklı mı:
      Bütün worker’ların kendine ait bir WSS bağlantısı olacak, aradaki Redis sunucusu ise sırasıyla veya boşluk-doluluk oranına göre siparişleri rastgele atayacak.
      Böyle yapmak mantıklı mı, yoksa daha mantıklı bir yöntem
      var mı?
      Hocam queue zaten tam olarak istediğin şeyi yapıyor. Competitive consumers pattern’de her worker queue’yu dinler ve queue round-robin(RabbitMQ bu algoritmayı kullanıyor load balancing için) ile mesajları dağıtır, worker bir siparişi işliyorsa ve ack göndermeden yeni mesaj çekmez, yeni sipariş geldiğinde boş olan worker o işi alır. Tek yapman gereken prefetch count’u doğru ayarlamak prefetch=1 yaparak her worker’ın aynı anda sadece 1 sipariş almasını garantilersin, böylece load tam dengeli dağılır. Websocket ile manuel dağıtım yapman gereksiz çünkü queue zaten bunu yapıyor ve battle-tested, sen Redis ile load balancer yazarsan ekstra complexity eklersin, hata riski ortaya çıkar.Kritik işlemler için (ödeme, stok gibi) idempotency kontrolü ve gerekirse distributed lock eklemen iyi olur ama temel load balancing için queue’nun kendi mekanizması yeterli, bu işini görecektir
  • 12-11-2025, 02:15:31
    #2
    soylenmezsmt adlı üyeden alıntı: mesajı görüntüle
    Selamlar,

    Şimdi ana bir adet sunucumuz var.
    Bu sunucumuza saniyede 20 adet sipariş gelecek.
    Bu sunucu saniyede gelen 20 siparişi 10 farklı VDS makinelerine 5 saniye icinde bildirmeli ve neredeyse ve neredeyse asla yığılma olmamalı.

    Şimdi ben şurada şöyle bir şey düşündüm;
    10 Farklı makine her biri -> 1 worker
    Yani 10 workerimiz var.
    10 worker her 5 saniye aralıklarla ana sunucuya istek atsın ve eğer sipariş var ise siparişi işlesin diye düşündüm. Ama bu pek mantıklı gelmedi neden bilmiyorum ama yeteri kadar optimize gelmedi.


    O zaman da şu mimariye geçtim:
    Ana sunucuya sipariş gelir,araya bir tane websocket açarız sipariş geldiğinde ana sunucu websockete şuanda elimde sipariş var diye istek atsın ve bu şekilde sipariş olmadığında boşu boşuna DB istegi olmadan websocketde istekler kalır,siparişler geldiğinde ise websockete aktarılır sipariş işlenir sipariş islendikten sonra response en son ana sunucuya tekrar aktarılır diye düşündüm.
    Bu şekilde hem daha az istek ana makineye ulaşır bu sayede fazla DB sorgusu olmaz ve wss ile anlık olarak wss izlenir siparişler daha hızlı işlenir gibime geldi.

    Sizlere de sorayım,sizce bu mimari uygun mudur?
    Eğer uygun değil ise neden ve nasıl geliştirebilirim?
    Veya daha farklı bir mantık önerebilir misiniz?



    Düşündüğün 1. Yaklaşım — Polling (worker’lar sürekli sorgu atıyor)

    10 VDS makinesi her 5 saniyede bir ana sunucuya “sipariş var mı?” diye soruyor.


    Avantaj:

    • Basit implementasyon.
    • Failover durumu net (worker çökse bile diğerleri devam eder).

    Dezavantaj:

    • Gereksiz istek trafiği (polling overhead).
      → 10 worker × her 5 sn = dakikada 120 istek, saatte 7200 istek, boşuna.
    • Sipariş geldiği an “gecikme” olur (en fazla 5 sn).
    • Ana sunucu gereksiz CPU + DB yükü alır.
    • Gerçek zamanlı sistem değildir.
    Sonuç:
    Bu çözüm çalışır, ama ölçeklenebilir değil ve optimize değil.
    🔹 Düşündüğün 2. Yaklaşım — WebSocket (push-based iletişim)

    Ana sunucuya sipariş gelir, WebSocket üzerinden bağlı worker’lara “yeni sipariş var” bildirimi gönderilir.

    Avantaj:

    • Gerçek zamanlı (zero-delay).
    • Gereksiz sorgu yok, yük minimize.
    • DB’ye fazladan erişim yok.
    • Sipariş anında VDS’e push edilir.

    Dezavantaj:

    • WebSocket bağlantı yönetimi karmaşıktır (özellikle 10+ worker olsa bile).
    • Tek ana sunucu “fan-out” işlemini yapıyorsa, o sunucuya fazla yük binebilir.
    • Eğer ana sunucu down olursa ya da network partition olursa sipariş kaybı yaşanabilir.
    • Tek noktadan hata riski (SPOF – Single Point of Failure).
    Sonuç:
    Polling’e göre çok daha doğru yön, ama doğrudan WebSocket üzerinden dağıtım yapmak ölçeklenebilirlik açısından zayıf kalır.
    Burada bir aracı katman (message broker) gerekir.
    ✅ En Doğru Mimari — Message Queue + Worker Pool + Event-Driven

    Gerçek dünyadaki scalable çözüm şu şekilde olur 👇

    🧩 Bileşenler

    1. Ana API Sunucusu
      • Sipariş alır (HTTP POST).
      • Siparişi direkt DB’ye değil, mesaj kuyruğuna (Queue) atar.
      • (Örn: RabbitMQ, Redis Streams, Kafka, NATS, SQS)
    2. Mesaj Kuyruğu / Broker
      • Gelen siparişleri sıraya koyar.
      • Her siparişi sadece bir worker’a teslim eder (round-robin, fan-out vb.).
      • Geri basınç (backpressure) yönetimi yapar → yığılmayı engeller.
      • Otomatik retry, ACK/NACK yönetimi.
    3. Worker’lar (10 VDS)
      • Her biri kuyruğa abone olur.
      • Yeni sipariş geldiğinde mesajı alır, işler, sonucu geri gönderir (örneğin HTTP callback veya başka bir queue’ya “result” mesajı atar).
    4. Opsiyonel: WebSocket Katmanı (Monitoring için)
      • Ana sunucu, “sipariş işlendi” durumlarını canlı izlemek için WebSocket üzerinden admin/monitor ekranına push edebilir.

    🔄 Akış Örneği:



    Kullanıcı -> Ana Sunucu (HTTP) Ana Sunucu -> Queue (publish) Queue -> Worker (consume) Worker -> Ana Sunucu (result) Ana Sunucu -> WebSocket (client notification)

    💡 Bu Yapının Avantajları

    • Yığılma (backpressure) yok: Queue yönetir.
    • Saniyede 20 sipariş değil, 200 bile olsa sistem kaldırır.
    • Retry ve fault tolerance var.
    • Gerçek zamanlı işleyiş mümkün.
    • DB sadece “sipariş kaydı ve durum” için kullanılır.
    • WebSocket trafiği sadece izleme veya sonuç bildirimi için olur.
  • 12-11-2025, 02:20:17
    #3
    ikinci yaklaşımın ilkinden çok daha iyi ama event-driven düşünmek gerekir, websocket yerine direkt Message Queue (RabbitMQ/Redis/Kafka) kullansan daha reliable olur, siparişler queue’ya düşer, worker’lar kuyruğu dinler, otomatik load balancing yapılır, worker down olsa bile sipariş kaybolmaz, ölçeklendirmesi kolay olur, websocket de olur ama connection management zor, queue bu iş için endüstri standardıdır(BullMQ veya RabbitMQ işini görecektir, Kafka gereksiz olabilir) Polling kesinlikle çok kötü bir pratik zaten, 5 saniye beklemek yerine sipariş geldiği anda push etmek lazım. Lock konusunda da queue düzgün kullanılırsa her sipariş zaten tek worker’a gider, temel seviyede lock gereksiz çünkü queue kendisi koordine eder. Ama kritik işlemlerde (ödeme, stok düşme) veya worker crash sonrası requeue durumlarında idempotency için distributed lock eklemen iyi olur, mümkünse Redis..
  • 12-11-2025, 02:26:04
    #4
    Kurumsal PLUS
    mobileforge adlı üyeden alıntı: mesajı görüntüle
    Düşündüğün 1. Yaklaşım — Polling (worker’lar sürekli sorgu atıyor)

    10 VDS makinesi her 5 saniyede bir ana sunucuya “sipariş var mı?” diye soruyor.


    Avantaj:

    • Basit implementasyon.
    • Failover durumu net (worker çökse bile diğerleri devam eder).

    Dezavantaj:

    • Gereksiz istek trafiği (polling overhead).
      → 10 worker × her 5 sn = dakikada 120 istek, saatte 7200 istek, boşuna.
    • Sipariş geldiği an “gecikme” olur (en fazla 5 sn).
    • Ana sunucu gereksiz CPU + DB yükü alır.
    • Gerçek zamanlı sistem değildir.
    Sonuç:
    Bu çözüm çalışır, ama ölçeklenebilir değil ve optimize değil.
    🔹 Düşündüğün 2. Yaklaşım — WebSocket (push-based iletişim)

    Ana sunucuya sipariş gelir, WebSocket üzerinden bağlı worker’lara “yeni sipariş var” bildirimi gönderilir.

    Avantaj:

    • Gerçek zamanlı (zero-delay).
    • Gereksiz sorgu yok, yük minimize.
    • DB’ye fazladan erişim yok.
    • Sipariş anında VDS’e push edilir.

    Dezavantaj:

    • WebSocket bağlantı yönetimi karmaşıktır (özellikle 10+ worker olsa bile).
    • Tek ana sunucu “fan-out” işlemini yapıyorsa, o sunucuya fazla yük binebilir.
    • Eğer ana sunucu down olursa ya da network partition olursa sipariş kaybı yaşanabilir.
    • Tek noktadan hata riski (SPOF – Single Point of Failure).
    Sonuç:
    Polling’e göre çok daha doğru yön, ama doğrudan WebSocket üzerinden dağıtım yapmak ölçeklenebilirlik açısından zayıf kalır.
    Burada bir aracı katman (message broker) gerekir.
    ✅ En Doğru Mimari — Message Queue + Worker Pool + Event-Driven

    Gerçek dünyadaki scalable çözüm şu şekilde olur 👇

    🧩 Bileşenler

    1. Ana API Sunucusu
      • Sipariş alır (HTTP POST).
      • Siparişi direkt DB’ye değil, mesaj kuyruğuna (Queue) atar.
      • (Örn: RabbitMQ, Redis Streams, Kafka, NATS, SQS)
    2. Mesaj Kuyruğu / Broker
      • Gelen siparişleri sıraya koyar.
      • Her siparişi sadece bir worker’a teslim eder (round-robin, fan-out vb.).
      • Geri basınç (backpressure) yönetimi yapar → yığılmayı engeller.
      • Otomatik retry, ACK/NACK yönetimi.
    3. Worker’lar (10 VDS)
      • Her biri kuyruğa abone olur.
      • Yeni sipariş geldiğinde mesajı alır, işler, sonucu geri gönderir (örneğin HTTP callback veya başka bir queue’ya “result” mesajı atar).
    4. Opsiyonel: WebSocket Katmanı (Monitoring için)
      • Ana sunucu, “sipariş işlendi” durumlarını canlı izlemek için WebSocket üzerinden admin/monitor ekranına push edebilir.

    🔄 Akış Örneği:



    Kullanıcı -> Ana Sunucu (HTTP) Ana Sunucu -> Queue (publish) Queue -> Worker (consume) Worker -> Ana Sunucu (result) Ana Sunucu -> WebSocket (client notification)

    💡 Bu Yapının Avantajları

    • Yığılma (backpressure) yok: Queue yönetir.
    • Saniyede 20 sipariş değil, 200 bile olsa sistem kaldırır.
    • Retry ve fault tolerance var.
    • Gerçek zamanlı işleyiş mümkün.
    • DB sadece “sipariş kaydı ve durum” için kullanılır.
    • WebSocket trafiği sadece izleme veya sonuç bildirimi için olur.
    2. Yaklaşım en mantıklısı ama illa redis vs kullanmasına gerek yok. Yapılan işleme bağlı. Bir workerin işi bitince/boşta olunca workere iş yönlendirerek dağıtımı kendi de yapabilir.
  • 12-11-2025, 02:35:08
    #5
    Tarikkaya adlı üyeden alıntı: mesajı görüntüle
    ikinci yaklaşımın ilkinden çok daha iyi ama event-driven düşünmek gerekir, websocket yerine direkt Message Queue (RabbitMQ/Redis/Kafka) kullansan daha reliable olur, siparişler queue’ya düşer, worker’lar kuyruğu dinler, otomatik load balancing yapılır, worker down olsa bile sipariş kaybolmaz, ölçeklendirmesi kolay olur, websocket de olur ama connection management zor, queue bu iş için endüstri standardıdır(BullMQ veya RabbitMQ işini görecektir, Kafka gereksiz olabilir) Polling kesinlikle çok kötü bir pratik zaten, 5 saniye beklemek yerine sipariş geldiği anda push etmek lazım. Lock konusunda da queue düzgün kullanılırsa her sipariş zaten tek worker’a gider, ekstra lock’a gerek kalmaz genelde distributed lock gibi, worker işi bitince ack gönderir mesaj silinir
    Hocam yine rahatsız ediyorum ama ufak bir sorum daha var.
    1 numaralı worker, 1 ID’li siparişi aldı ve şu anda işliyor ise, diğer 9 sunucu boş demektir.
    Diyelim ki bir sipariş daha geldi ve bu da yine 1 numaralı worker’a gitti. Böyle olunca diğer 9 sunucu hâlâ boşta kalıyor ama 1 makine 2 siparişi aynı anda işliyor, bu da servisi yavaşlatıyor.
    Normalde, bu yeni siparişi diğer boş sunuculardan birinin alması gerekirdi.

    Bunun için şöyle yapmak mantıklı mı:
    Bütün worker’ların kendine ait bir WSS bağlantısı olacak, aradaki Redis sunucusu ise sırasıyla veya boşluk-doluluk oranına göre siparişleri rastgele atayacak.
    Böyle yapmak mantıklı mı, yoksa daha mantıklı bir yöntem
    var mı?
  • 12-11-2025, 02:39:54
    #6
    anlattığın okurken bile kafam karıştı niye bu kadar karışık yapıyorsun ki yada sürekli api yaptırıyorsun ki
    ana server a gelenleri her bir robota id ata ana makina her birisini bir bot / robot a aktarsın atıyorum durumu bekleme ise robotu işlemede yapsın bitince geri true dönsün varsa response dönsün drumunu beklemeye al
  • 12-11-2025, 02:45:02
    #7
    Melihhh adlı üyeden alıntı: mesajı görüntüle
    anlattığın okurken bile kafam karıştı niye bu kadar karışık yapıyorsun ki yada sürekli api yaptırıyorsun ki
    ana server a gelenleri her bir robota id ata ana makina her birisini bir bot / robot a aktarsın atıyorum durumu bekleme ise robotu işlemede yapsın bitince geri true dönsün varsa response dönsün drumunu beklemeye al
    Ana sunucunun sipariş işleme işlemlerinden tamamen uzak ve rahat olması gerekiyor. Saniyede 20-30 istek az bir istek sayısı değil ve olası bir yığılmada ana sunucu gelecsk olan siparişleri mı databaseye kaydetsin,sipariş durumu sorgulamaya mı baksın yoksa bir de siparişleri işlemeye mı yorulsun diye karmaşık mükemmellik yapmaya çalışıyorum hocam. Tabii en sade haliyle.
  • 12-11-2025, 02:50:01
    #8
    Bu cevap, konu sahibi tarafından kabul edilebilir bir cevap olarak işaretlendi.
    soylenmezsmt adlı üyeden alıntı: mesajı görüntüle
    Hocam yine rahatsız ediyorum ama ufak bir sorum daha var.
    1 numaralı worker, 1 ID’li siparişi aldı ve şu anda işliyor ise, diğer 9 sunucu boş demektir.
    Diyelim ki bir sipariş daha geldi ve bu da yine 1 numaralı worker’a gitti. Böyle olunca diğer 9 sunucu hâlâ boşta kalıyor ama 1 makine 2 siparişi aynı anda işliyor, bu da servisi yavaşlatıyor.
    Normalde, bu yeni siparişi diğer boş sunuculardan birinin alması gerekirdi.

    Bunun için şöyle yapmak mantıklı mı:
    Bütün worker’ların kendine ait bir WSS bağlantısı olacak, aradaki Redis sunucusu ise sırasıyla veya boşluk-doluluk oranına göre siparişleri rastgele atayacak.
    Böyle yapmak mantıklı mı, yoksa daha mantıklı bir yöntem
    var mı?
    Hocam queue zaten tam olarak istediğin şeyi yapıyor. Competitive consumers pattern’de her worker queue’yu dinler ve queue round-robin(RabbitMQ bu algoritmayı kullanıyor load balancing için) ile mesajları dağıtır, worker bir siparişi işliyorsa ve ack göndermeden yeni mesaj çekmez, yeni sipariş geldiğinde boş olan worker o işi alır. Tek yapman gereken prefetch count’u doğru ayarlamak prefetch=1 yaparak her worker’ın aynı anda sadece 1 sipariş almasını garantilersin, böylece load tam dengeli dağılır. Websocket ile manuel dağıtım yapman gereksiz çünkü queue zaten bunu yapıyor ve battle-tested, sen Redis ile load balancer yazarsan ekstra complexity eklersin, hata riski ortaya çıkar.Kritik işlemler için (ödeme, stok gibi) idempotency kontrolü ve gerekirse distributed lock eklemen iyi olur ama temel load balancing için queue’nun kendi mekanizması yeterli, bu işini görecektir
  • 12-11-2025, 02:54:54
    #9
    Tarikkaya adlı üyeden alıntı: mesajı görüntüle
    Hocam queue zaten tam olarak istediğin şeyi yapıyor. Competitive consumers pattern’de her worker queue’yu dinler ve queue round-robin(RabbitMQ bu algoritmayı kullanıyor load balancing için) ile mesajları dağıtır, worker bir siparişi işliyorsa ve ack göndermeden yeni mesaj çekmez, yeni sipariş geldiğinde boş olan worker o işi alır. Tek yapman gereken prefetch count’u doğru ayarlamak prefetch=1 yaparak her worker’ın aynı anda sadece 1 sipariş almasını garantilersin, böylece load tam dengeli dağılır. Websocket ile manuel dağıtım yapman gereksiz çünkü queue zaten bunu yapıyor ve battle-tested, sen Redis ile load balancer yazarsan ekstra complexity eklersin, hata riski ortaya çıkar.Kritik işlemler için (ödeme, stok gibi) idempotency kontrolü ve gerekirse distributed lock eklemen iyi olur ama temel load balancing için queue’nun kendi mekanizması yeterli, bu işini görecektir
    Çok teşekkür ediyorum hocam