Websocketdan foydalanib chat xizmati loyihalash

Websocketdan foydalanib chat xizmati loyihalash

1. Kirish

Men bir nechta odam bir muloqot xonasi ichida yig'ilib, xabarlar almashib, rasmlar bo'lishadigan real vaqt chat xizmatini ishlab chiqyapman. Odatdagi messenjery kabi, yangilanish tugmasini bosmasdan ham, qarshidagi odam yuborgan xabar darhol ekranimda ko'rinadi.

Real vaqt chat yaratishda eng dastlabki muammo “kimdir xabar yuborganida, bir xil xonada bo'lgan qolgan odamlarga buning haqida qanday darhol xabar berish kerak?” degan savoldir. Bir xonada o'n kishi bo'lsa va shulardan bittasi xabar yuborsa, qolgan to'qqiz kishining ekranida bu xabar deyarli bir vaqtning o'zida ko'rinishi kerak.

Eng oddiy fikr “xabar matnini to'g'ridan-to'g'ri to'qqiz kishiga real vaqt ichida jo'natish” hisoblanadi. Lekin biz bu usulni tanlamadik. O'rniga xabar matnini yubormasdan faqat “nima bo'ldi” degan engil xabarnoma yuborishni va haqiqiy mazmunni mijoz qaytadan ko'rishi uchun rejalashtirdik.

Bu maqolada nima uchun bunday tanlov qildik, qanday qo'lladik, jarayonda qanday muammo va yechimlar bilan yuzlashganimizni baham ko'rmoqchiman.

2. Undan oldin, web-socket nima?

Asosiy suhbatga o'tishdan oldin, real vaqt aloqa poydevori bo'lgan web-socket (WebSocket) haqida to'g'ridan-to'g'ri tursin.

Biz odatda veb-saytlardan foydalanganda ishlatiladigan an'anaviy aloqa usuli, xat almashish bilan o'xshashdir. Men qiziqayotgan biron narsa bo'lishida, serverga xat, ya'ni so'rov yuboraman, va server bunga javob, ya'ni javob yuboradi. Va bir marta almashgandan so'ng, bu suhbat o'sha yerda tugaydi. Keyingi marta yana biror narsa qiziqtirsa, yangi xat yozib yuborishim kerak.

Bu usulning cheklovlari shundaki, server mendan oldin gapirish imkoniga ega emas. Men so'ramasam, server yangi yangiliklar bo'lganda ham xabar bera olmaydi.

Shuning uchun real vaqt chatda bu usulni ishlatish uchun, mijoz “yang yangi xabar bormi?” deb doimiy ravishda so'rashishi kerak. Bu, nagu yo'l qabul qilish kismi kabi har bir daqiqada eshikni ochib ko'rishni xohlayotgandekdir. Yangi xabar bo'lmasa ham, doimiy ravishda so'rashim kerak shuning uchun katta isrofgarchilik, va so'rash orasi kechikish ham qo'shadi.

Shu bilan birga, web-socket telefon qo'ng'irog'iga o'xshaydi. Bir marta qo'ng'iroq qilib ulanganingizda, u uzilgunga qadar qo'ng'iroq davom etadi. O'sha holatda men birinchi bo'lib gapirishim ham mumkin, qarshidagi odam birinchi bo'lib gapirishi ham mumkin. Ya'ni, serverda yangi yangilik bo'lsa, mijoz so'ramasa ham birinchi bo'lib xabar berishi mumkin.

Ushbu ulanishni davom ettirib, ikkala tarafning erkin ma'lumot almashuvini ta'minlaydigan aloqa usuli web-socketdir va real vaqt chat kabi “server birinchi bo'lib foydalanuvchini xabardor qilishi kerak” xizmatlarga juda mos keladi.

Biz ushbu web-socket ustida, “qaysi manzilga yuboriladi va qaysi manzilga obuna bo'linadi” degan kelishuvni standartlashtirgan STOMP deb nomlangan xabar berish qoidalarini ishlatdik. Telefon simi o'rnatilgan bo'lsa, STOMP esa “kimga qanday mazmunni qanday yetkazishni” bilish odobi ekanligini o'ylab ko'rishingiz mumkin.

3. Texnologiya tanlovi: matn o'rniga faqat “xabarnoma” yuboramiz

3.1. Ulanishda avval shaxsni tasdiqlaymiz

Suhbat mazmuni sezgir ma'lumot bo'lishi mumkin, shuning uchun hech kimni ulashib qo'yish mumkin emas. Shuning uchun, veb-socket ulanishi birinchi marta o'rnatilayotganda foydalanuvchining tokenini tekshirishga qaror qildik. Token yo'q bo'lsa yoki shakli to'g'ri bo'lmasa, yoki tasdiqlash serveri orqali tekshirishni o'ta olmasa, ulanish darhol to'siladi.

Bu yerda bir loyiha tanlovi bormi. Oddiy so'rovlar odatda serverning old qismidagi xavfsizlik filtri orqali tasdiqlanadi. Lekin veb-socket bir marta ulanishgach, doimiy yondashuv bo'lgani uchun har safar tekshirishdan ko'ra, ulanish o'rnatilayotgan paytda bitta marta aniq tekshirish ko'ra tabiiy va samarali edi.

Avvalgi misolga ko'ra telefon suhbati boshlanishida qarshi tomon kimligini tasdiqlashga o'xshaydi.

3.2. Asosiy qaror: matn emas, “xabar” yuboramiz

Endi eng muhim loyiha qaroriga keldik. Kimdir xabar yuborganida, biz o'sha xabar matnini bir xil xona odamlarga tarqatmaymiz. Buning o'rniga, “Ushbu xonada yangi xabar kiritildi” degan signalni yuboramiz. O'sha signaldan foydalanuvchi, o'sha paytgacha oddiy ko'rish usuli bilan yangi xabarni olib, ekranda ko'rsatadi.

Misol uchun, oddiy mesenjerdagi push xabarnoma bilan o'xshash. Push xabarnomada “○○ sizga xabar yubordi” degan qisqa signal mavjud bo'lib, ilovani ochganda asl suhbat mazmunini chaqirishga o'xshaydi.

Dastlab “agar real vaqtda yuborsak, matnni ham birga yuborganimizda bir marta tugamaydi?” deb o'ylash mumkin. Men ham intuitiv ravishda buni oson ko'rdim. Lekin xabar faqat yuborish usulida aniq afzalliklar bor edi va ko'rib chiqib, ushbu usulni tanladik.

Birinchidan, socket orqali oqayotgan ma'lumot engildir. Rasm qo'shilgan katta xabar bo'lsin yoki uzun matn bo'lsin, socket orqali “yangi xabar bor” degan kichik signal faqat oqmoqda. Shuning uchun ko'p odamlar bir vaqtning o'zida muloqot qilganda real vaqt yo'liga bosim kam bo'ladi.

Ikkinchidan, ma'lumotning aniqligi va vakolatni bir yo'ldan boshqarish mumkin. Haqiqiy ma'lumot har doim tasdiqlangan ko'rish yo'li orqali pasayadi. Agar socket orqali matnni yuborsa, socket yo'li va oddiy ko'rish yo'li o'rtasida har xil shakldagi ma'lumotlar chiqishi mumkin, bu esa boshqaruvni qiyinlashtiradi va vakolat tekshirolari kabi mantiq ham ikkita joyda takroran e'tibor berishni talab qiladi.

Uchinchidan, foydalanuvchi kerakli narsalarni olib ketishi mumkin. Xabarnomada “Nima o'zgardi” degan ma'lumot bo'lgani uchun, foydalanuvchi hozir ko'rayotgan ekranning holatiga mos ravishda kerakli ma'lumotni qayta ko'rishi mumkin. Masalan, agar o'sha xonani ko'rmayotgan bo'lsa, xabar matnini olib kelmay, “o'qilmagan belgisi”ni yangilayverishi mumkin.

4. Qo'llash jarayoni: hodisaning turini aniqlash

4.1. Xabarnomada “nima yuz berdi” degan ma'lumot mavjud.

Xabarnoma orqali almashadigan ma'lumotda xabar matnining to'liq ko'rinishi bo'lmaydi. Buning o'rniga, qaysi xonada, qanday maqsadga yo'naltirilgan bo'lsin, qanday hodisa ro'y bergani to'g'risida ma'lumotlar kiritiladi. Aniq qilib aytganda, yuboruvchi, xona identifikatori, ta'sirlangan ob'ektning identifikatori va hodisaning turi.

Bu yerda eng muhim narsa “hodisaning turi”dir. Biz suhbatda yuz berishi mumkin bo'lgan hodisalarni oldindan aniqlab qo'yganmiz. Masalan, quyidagi kabi hodisalar.

  • Yangi xabar kiritilayotganida
  • Agar xabarni o'qigan bo'lsangiz
  • Xabarni tahrir qilish yoki o'chirish holatida
  • Xabarni mustahkamlash, javob berish yoki emojilar bilan munosabat bildirish holatida
  • Xonaga taklif qilish, xona yaratish yoki o'chirish, xonadan chiqish holatida

Shunday qilib, voqealar turini o'nlab turlarga ajratib, belgilangan qiymatlar bilan ifodalash imkonini berildi. Bu usulning afzalliklari, server va mijoz “Bunday voqea yuz beradigan bo'lsa, buni qanday ishlash kerak” degan va'dani aniqlik bilan baham ko'rish imkoniyatidir.

Ogohlantirishga tasodifiy satr kiritish o'rniga oldindan belgilangan voqealar turidan foydalanish orqali, xatolar yoki ao'tiklar bilan bog'liq chalkashliklarni kamaytirish mumkin.

To'g'ri oqim shunday. Bir foydalanuvchi xabar yuborsa, server bir xil xonadagi odamlarga “Yangi xabar ro'yxatga olindi” degan voqealar turini va tegishli xona identifikatorini, yangi xabar identifikatorini o'z ichiga olgan ogohlantirish yuboradi. Ogohlantirishni olgan mijoz “Ah, bu xonada yangi xabar paydo bo'libdi” deb, o'sha xonadagi xabarlarni ko'rib chiqadi va ekranini yangilaydi.

4.2. “O'qilgan” ishlov berish ham bir xil ogohlantirish orqali o'tadi

Bu ogohlantirish tuzilmasining afzalligi shundaki, yangi xabarlarga qo'shimcha ravishda boshqa holat o'zgarishlariga ham bir xil qo'llaniladi. Masalan, foydalanuvchi xabarni o'qiydigan bo'lsa, server o'sha foydalanuvchining oxirgi o'qigan joyini yangilaganidan so'ng, bir xil xona ichida “Xabar o'qildi” degan ogohlantirish yuboradi. Shunda boshqa odamlarning ekranlarida “O'qilgan” belgisi bir xil mexanizm orqali real vaqt rejimida yangilanadi.

Bu erda e'tibor berilgan bir jihat shundaki, allaqachon o'qilgan joydan ko'proq o'qigan paytida yangilanish va ogohlantirish yuboriladi. Foydalanuvchi oldingi xabarni yana ko'rgan taqdirda o'qilgan joy qaytadi belgisi to'g'ri kelmasligini ta'minlash uchun.

Natijada, yangi xabar, xabar tahriri, o'qish yoki har qanday o'zgarishlar “Ogohlantirish yuborish → Mijoz qayta tekshiradi” degan bir xil aniq naqsh bilan biriktirildi. Yangi turdagi voqealar paydo bo'lsa ham, bir xil formatga qo'shish kifoya, shuning uchun funksiyani kengaytirish ham oson bo'ldi.

5. Faqat onlayn foydalanuvchilarga yuboriladi

Socket ogohlantirishlar hozirda ulanishda bo'lgan odamlarga ma'noga ega. Oldin telefon qo'ng'irog'i bilan tasvirlab o'tilganidek, telefonni o'chirgan odamlarga qanchalik gapirsangiz ham, eshitmaydi. Shuning uchun ogohlantirishni yuborishdan oldin, maqsad bo'ladigan har bir foydalanuvchi hozirda ulanishda yoki yo'qligini tekshiramiz.

Server kimning hozirda ulanishda ekanligi haqida ma'lumotga ega, shuning uchun ogohlantirish yuborilayotganda ro'yxatni tekshirib, faqat ulanishda bo'lgan foydalanuvchilarga belgi yuboradi. Ulanmagan foydalanuvchilarga socket orqali yuborishni anglatadi, chunki qabul qiluvchi bo'lmasa, ortiqcha signallarni yuborishdan qochishdir.

Shunday qilib, “yuborishga arziydigan maqsadni” oldindan chiqarish jarayoni, odamlar soni ko'p bo'lgan xonalar uchun samaradorligi oshadi. Bir xonada ko'p odam bo'lishi mumkin, lekin haqiqiy ulanishda bo'lganlar faqat ayrimlar bo'lishi mumkin, shuning uchun ulanishda bo'lganlarni tanlab yuborish orqali behuda uzatishni kamaytirish mumkin.

6. Mutqish muammolar va yechim: xonadan chiqayotganingizda kimga xabar beramiz

Xabar berish strukturasini qo'llayotganda, haqiqatan ham to'g'ri kelgan muammoni baham ko'rmoqchiman.

Aksariyat xabarlar “bu xonadagi hozirgi barcha a'zolarga” yuborilishi mumkin. Shunday qilib, dastlab, xabar yuborish vaqtida xonani identifikatsiyalash orqali hozirgi a'zolarning ro'yxatini ko'rib chiqdik va ularga yuborishga harakat qildik. Yangi xabar, xabarni tahrirlash, o'qish bilan bog'liq vazifalar ham shu tarzda yaxshi ishladi.

Biroq xonani o'chirish yoki xonadan chiqish holatlarida muammolar yuzaga keldi. Xona o'chirilganda yoki bir foydalanuvchi xonadan chiqganda, ushbu jarayon tugagandan keyin a'zolar haqidagi ma'lumotlar o'chib ketgan edi. Ushbu holatda “hozirgi a'zolar ro'yxatini” ko'rib chiqsak, aslida “siz xonadan chiqdiniz”, “bu xona o'chirildi” xabarlarini kimga berish kerakligini topa olmaydigan vaziyat yuzaga kelardi.

Xabar yuborishga harakat qilar ekanmiz, qabul qiluvchining ro'yxatdan allaqachon olib tashlanganini ko'rdik.

Sababini aniqlash uchun, xabar maqsadlarini ko'rib chiqish vaqti bilan a'zolar haqidagi ma'lumotlar o'chishi vaqti o'rtasidagi tafovut muammo bo'lganini tushundik. Odatda “hozir bu xonada kim bor” degan ma'lumotni har safar ko'rish etarli bo'lgan, lekin xonadan chiqish yoki o'chirish holatlari natijani o'zgartiradigan holatlar edi.

Yechim uchun, hodisalar turiga qarab xabar maqsadlarini belgilash usulini ikkiga bo'ldik. Xona o'chirish yoki xonadan chiqish kabi a'zolar haqidagi ma'lumotlarning tartibga solinadigan hodisalar uchun, a'zolar o'chib ketishidan oldin oldindan tayyorlangan maqsadlar ro'yxatini ishlatishga qaror qildik. Teskari esa yangi xabar yoki tahrir kabi oddiy hodisalar uchun, mavjud a'zolar ro'yxatini ko'rib xabar yuboramiz.

Ya'ni “hozirgi holatini ko'rish va yuborish yoki o'chib ketishidan oldin qamrab olingan maqsadlarga yuborish” hodisaning mohiyatiga qarab farqlangan.

Ushbu tajriba orqali, “kimga xabar yuborish”ni hal qilish faqat hozirgi holatni ko'rish bilan kifoyalanmasligini o'rgandim. Hodisning mohiyatiga qarab, ma'lumotlar o'chilishidan oldin yoki keyin qaysi nuqtadagi ma'lumotni ishlatish kerakligini ham hisobga olish kerak.

Oldin hodisalar turini aniq tasniflaganimiz sababli, bunday holda hodisalarga ko'ra farqli tarzda obro'li muomala qilishimizga yordam berdi.

7. Natijalar va qaydlar

Ushbu dizaynni qo'llaganimiz natijasida, soket orqali “nima sodir bo'lmoqda” degan yengil signal keladi va haqiqiy ma'lumotning aniqligi tasdiqlangan ko'rish yo'li bilan ta'minlanadi. Xabarlar turining ko'payishi bilan, yangi hodisalarni oldindan belgilangan tasnifga qo'shib, bunday yuborish usulini takroran foydalanishimiz mumkin, shuning uchun kengaytirish oddiy.

Eng katta dars shuki, “haqiqiy vaqt = barcha ma'lumotlarni haqiqiy vaqt ichida yuborish” degan fikr har doim to'g'ri emasligini tushundim. Balki “o'zgarishlarni tezda xabar qilish, lekin ma'lumotlarni ishonchli yo'l bilan olish” degan yondashuv ancha oddiy va mustahkam edi. Haqiqiy vaqt yo'li va oddiy ko'rish yo'llari har biri yaxshi ish bilan shug'ullanishi uchun vazifalarni taqsimlagandik.

Albatta, hali takomillashtirish kerak bo'lgan joylar ham qolmoqda. Masalan, hozirgi ulanish ma'lumotlarini aniqlash usuli bitta serverga asoslangan, o'sha serverlarni ko'paytirib, ishga tushirganda ulanish ma'lumotlarini serverlar o'rtasida almashish strukturasini qo'shish yana zarur bo'ladi.

Haqiqiy vaqtli suhbatning, bir ko'zga shunaqa oddiy ko'rinadigan funksiyasida “nima, qachon, kimga yuboriladi” degan qarorlar zich joylashganligini o'zim yaratayotganda his etdim. Ushbu maqola shunga o'xshash muammolar bilan shug'ullanayotganlarga kichik bir ma'lumot bo'lishini umid qilaman.

messi

Site footer