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 гэж?
- Performance
- NATS нь multi-threaded event loop ашигладаг.
- Scalability
- Cluster modeоор scale хийх боломжтой.
- Клиент ямар ч серверт холбогдох боломжтой.
- Олон дата төв (multi-datacenter) дэмждэг.
- Fault Tolerance
- NATS JetStream ашиглан Redis Streams шиг мессеж хадгалах, дахин харах боломжтой.
- Хялбар
- NATS нь хөнгөн, хурдан, ашиглахад хялбар.
- Олон төрлийн messaging загваруудыг дэмждэг
- Pub/Sub → Реал-тайм мессежийн дамжуулалт
- Request/Reply → RPC-д тохирно
- Queue Groups → message queue
- Auto-Pruning
- Storage болон хугацааны хязгаар тогтоож, хуучин мессежийг автоматаар устгах боломжтой.
- Аюулгүй байдал (Security)
- Mutual TLS
- Token-based authentication
- Fine-grained access control
Дүгнэлт
WebSocket суурьтай backend-ийг scale хийх нь бодохгүйгээр хийх зүйл биш билээ. Redis эхний шатанд хангалттай байсан боловч цаашдын боломжийг бодон өөр шийдэл хайхаар болсон. Peer-to-peer нь төвөгтэй болж, scale хийх, хөгжүүлэхэд төвөгтэй болгож байсан.
Харин NATS нь performance, scalability, simplicity-г хослуулсан тул үүнийг сонгож ашиглаж байна.