Backend application-ийг scale хийх нь шууд л болчихдог зүйл бол биш билээ, ялангуяа олон WebSocket connection байх үед мөн тэдгээр нь хоорондоо message явуулах хэрэгтэй тохиолдолд бүр ч хүндрэлтэй. Нэг WebSocket сервер бүх хэрэглэгчийг удирдаж чадахгүй, тиймээс бид хэрхэн системээ үр дүнтэй scale хийх вэ?

Horizontal scaling хийхэд хэд хэдэн асуудал гарж болно. Жишээлбэл:

  • User A нь Server X дээр холбогдсон.
  • User B нь Server Y дээр холбогдсон.

Тэд хэрхэн хоорондоо real time харилцах вэ? Гол асуудал нь өөр серверүүд дээр байгаа хэрэглэгчдийн хооронд тасралтгүй, саадгүй харилцааг хэрхэн шийдэх тухай билээ.

Redis Streams: Эхний шийдэл

Анх Redis Streams ашиглаж энэ асуудлыг шийдэхийг оролдсон. Redis Streams нь message queue болон message processing-ийг дэмждэг хүчирхэг өгөгдлийн бүтэц юм. Үүнд хэрэгжүүлэхдээ:

  • Centralized message channel: Бүх microservice-үүд Redis Streamд subscribe хийж, WebSocket сервер мессеж илгээхдээ түүнийг Stream-рүү явуулна (publish). Бусад серверүүд үүнийг шууд мэдэх боломжтой.(subscribe)
  • Message Durability: Redis Streams нь мессежийг хадгалдаг тул түр хугацаанд offline болсон backend алдагдсан мессежээ нөхөн авах боломжтой.

Энэ арга эхний шатанд асуудалгүй боловч stress test хийх үед төсөөлснөөр байгаагүй. Яагаад?

  • Storage overhead: Redis Streams мессежүүдийг хадгалдаг тул өсөхийн хэрээр санах ой болон дискний хэрэглээ огцом нэмэгдсэн.
  • Throughput limit: Redis нь single-threaded, тиймээс олон зэрэг хийгдэх үед тийм ч үр дүнтэй байгаагүй.

Redis Pub/Sub: Илүү хөнгөн хувилбар

Өөр шийдэл хайсан ба Redis Pub/Sub-ийг туршиж үзсэн. Redis Streams-ээс ялгаатай нь Pub/Sub нь мессежийг хадгалахгүй, адилхан real-time-аар бүх subscriber-уудад шууд дамжуулдаг.

  • Improved performance: Мессеж хадгалахгүй тул санах ойн хэрэглээ багасч, throughput нэмэгдсэн.
  • Simpler Design: Redis Streams шиг хадгалалт, санах ойг удирдах шаардлагагүй болсон.

Гэхдээ Pub/Sub нь дараах сул талуудтай:

  • No Message Durability: Subscriber offline байх үед ирсэн мессежүүдийг алдана.
  • Single-Threaded Nature: Redis single thread дээр ажилладаг ба publish, subscribe хүсч байгаа ба олон зэрэг нэг зүйлийг өөрчлөлт хийх шаардлагагүй болхоор single threaded байх нь тийм ч тохиромжтой гэж хараагүй.

Peer-to-Peer Service Discovery

Ер нь өөрөө хийгээд үзвэл гэж бодсоны үндсэн дээр Peer-to-Peer Service Discovery систем бүтээхийг оролдсон. Үндсэн санаа нь microservice-үүдийг хооронд нь шууд холбож, centralized broker xашиглахгүйгээр шууд TCP/IP connection бий болгох юм.

Энэ арга дараах давуу талтай байсан:

  • Шууд холболт: Services-үүд шууд харилцах боломжтой тул latency багассан.
  • Өөрчлөх боломжтой: Messaging layer-ийг өөрийн хэрэгцээнд тохируулж хөгжүүлэх боломжтой болсон.

Гэхдээ дараах асуудлууд гарч ирсэн:

  • Төвөгтэй байдал нэмэгдсэн: Холболтын mechanism, retry механизм, **private network-**уудыг зохицуулах шаардлага гарсан.
  • Scale хийхэд хэцүү болсон: Серверийн тоо өсөх тусам бүх серверүүд хоорондоо холбогдох шаардлагатай болно, n^2 холболт үүснэ гэсэн үг билээ.

NATS-н тухай

Peer-to-Peer загвар хэтэрхий нүсэр санагдсан тул NATS-ийг ашиглаад үзье гэж шийдсэн. NATS бол cloud-native, high performance messaging system бөгөөд Redis болон peer-to-peer загварын сул талуудыг шийдэх боломжтой гэж харсан.

Яагаад NATS гэж?

  1. Performance
    • NATS нь multi-threaded event loop ашигладаг.
  2. Scalability
    • Cluster modeоор scale хийх боломжтой.
    • Клиент ямар ч серверт холбогдох боломжтой.
    • Олон дата төв (multi-datacenter) дэмждэг.
  3. Fault Tolerance
    • NATS JetStream ашиглан Redis Streams шиг мессеж хадгалах, дахин харах боломжтой.
  4. Хялбар
    • NATS нь хөнгөн, хурдан, ашиглахад хялбар.
  5. Олон төрлийн messaging загваруудыг дэмждэг
    • Pub/Sub → Реал-тайм мессежийн дамжуулалт
    • Request/Reply → RPC-д тохирно
    • Queue Groups → message queue
  6. Auto-Pruning
    • Storage болон хугацааны хязгаар тогтоож, хуучин мессежийг автоматаар устгах боломжтой.
  7. Аюулгүй байдал (Security)
    • Mutual TLS
    • Token-based authentication
    • Fine-grained access control

Дүгнэлт

WebSocket суурьтай backend-ийг scale хийх нь бодохгүйгээр хийх зүйл биш билээ. Redis эхний шатанд хангалттай байсан боловч цаашдын боломжийг бодон өөр шийдэл хайхаар болсон. Peer-to-peer нь төвөгтэй болж, scale хийх, хөгжүүлэхэд төвөгтэй болгож байсан.

Харин NATS нь performance, scalability, simplicity-г хослуулсан тул үүнийг сонгож ашиглаж байна.