Socket.io pievienošana vairāku vītņu Node.js

Foto: Vidars Nordli-Mathisen vietnē Unsplash

Viens no Mezgla trūkumiem ir tas, ka tas ir ar vienu vītni. Protams, ir arī tam apkārt - proti, modulis, ko sauc par klasteru. Klasteris ļauj mums izplatīt mūsu lietojumprogrammu vairākos pavedienos.

Tomēr tagad parādās jauna problēma. Skatiet, mūsu kods, kas tiek darbināts vairākās instancēs, faktiski ir saistīts ar ievērojamiem negatīvajiem punktiem. Vienai no tām nav globālu valstu.

Parasti gadījumā ar vienu vītni tas daudz neuztrauc. Mums tagad tas visu maina.

Let 's redzēt, kāpēc.

Tātad, kāda ir problēma?

Mūsu lietojumprogramma ir vienkārša tiešsaistes tērzēšana, kas darbojas četros pavedienos. Tas ļauj lietotājam vienlaikus pieteikties savā tālrunī un datorā.

Iedomājieties, ka mums ir kontaktligzdas uzstādītas tieši tā, kā mēs būtu iestatījušas tās vienam pavedienam. Citiem vārdiem sakot, mums tagad ir viena liela globāla valsts ar rozetēm.

Kad lietotājs piesakās savā datorā, vietne izveido savienojumu ar Socket.io instanci mūsu serverī. Kontaktligzda tiek glabāta pavediena # 3 stāvoklī.

Tagad iedomājieties, ka lietotājs dodas uz virtuvi, lai paņemtu uzkodu, un paņem līdzi tālruni - dabiski vēlas, lai īsziņu sūtīšana ar draugiem notiktu tiešsaistē.

Viņu tālrunis tiek savienots ar 4. pavedienu, un kontaktligzda tiek saglabāta pavediena stāvoklī.

Ziņas nosūtīšana no tālruņa lietotājam neko labu nedos. Tikai cilvēki no 3. pavediena varēs redzēt ziņojumu. Tas ir tāpēc, ka 3. pavedienā saglabātās kontaktligzdas kaut kā maģiski netiek glabātas arī 1., 2. un 4. pavedienā.

Smieklīgi, ka pat pats lietotājs neredzēs viņu ziņojumus savā datorā, tiklīdz atgriezīsies no virtuves.

Protams, kad viņi atsvaidzina vietni, mēs varētu nosūtīt GET pieprasījumu un ielādēt pēdējos 50 ziņojumus, bet mēs īsti nevaram apgalvot, ka tas ir “dinamisks” veids.

Kāpēc tas notiek?

Mūsu servera izplatīšana pa vairākiem pavedieniem savā ziņā ir pielīdzināma vairākiem atsevišķiem serveriem. Viņi nezina par otra esamību un, protams, nedalās atmiņā. Tas nozīmē, ka objekts vienā eksemplārā neeksistē.

3. pavedienā saglabātās kontaktligzdas nebūt nav visas kontaktligzdas, kuras lietotājs šobrīd izmanto. Ja lietotāja draugi izmanto dažādus pavedienus, viņi neredzēs lietotāja ziņojumus, ja vien viņi neatsvaidzinās vietni.

Ideālā gadījumā mēs vēlamies paziņot citiem gadījumiem par notikumu lietotājam. Tādā veidā mēs varam būt pārliecināti, ka ikviena pievienotā ierīce saņem tiešraides atjauninājumus.

Risinājums

Mēs varam paziņot par citiem pavedieniem, izmantojot Redis publicēšanas / abonēšanas ziņojumapmaiņas paradigmu (pubsub).

Redis ir atvērtā pirmkoda (licencēts ar BSD) atmiņu datu struktūras krātuve. To var izmantot kā datu bāzi, kešatmiņu un ziņojumu starpnieku.

Tas nozīmē, ka mēs varam izmantot Redis, lai notikumi tiktu sadalīti starp mūsu instancēm.

Ņemiet vērā, ka parasti mēs visu savu struktūru varētu uzglabāt Redisā. Tomēr, tā kā struktūra nav sērijveidojama un tā ir jāuztur “dzīvā” atmiņā, daļu no tās mēs glabāsim katrā instancē.

Plūsma

Tagad padomāsim par darbībām, kurās mēs risināsim ienākošo notikumu.

  1. Pasākums, ko sauc par ziņojumu, nonāk vienā no mūsu kontaktligzdām - šādā veidā mums nav jāklausās par katru iespējamo notikumu.
  2. Objektā, kas nodots šī notikuma apstrādātājam kā arguments, mēs varam atrast notikuma nosaukumu. Piemēram, sendMessage - .on ('ziņojums', ({notikums}) => {}).
  3. Ja šim vārdam ir apstrādātājs, mēs to izpildīsim.
  4. Apdarinātājs var izpildīt nosūtīšanu ar atbildi.
  5. Dispečers nosūta atbildes notikumu uz mūsu Redis krogu. No turienes tas tiek izstarots katram no mūsu gadījumiem.
  6. Katra instance to izstaro savā socketsState, nodrošinot, ka katrs pieslēgtais klients saņems notikumu.

Es zinu, ka tas ir sarežģīti, bet nes mani.

Īstenošana

Šeit ir krātuve ar gatavu vidi, lai mums viss nebūtu jāinstalē un jāiestata pašiem.

Pirmkārt, mēs gatavojamies iestatīt serveri ar Express.

Mēs izveidojam Express lietotni, HTTP serveri un init ligzdas.

Tagad mēs varam koncentrēties uz kontaktligzdu pievienošanu.

Mēs nododam Socket.io servera instanci mūsu funkcijai, kurā mēs iestatām starpplatformas.

onAuth

Funkcija onAuth vienkārši imitē izspēles pilnvarojumu. Mūsu gadījumā tas ir balstīts uz žetoniem.

Personīgi es, iespējams, nākotnē to aizstātu ar JWT, bet tas nekādā veidā netiek izpildīts.

Tagad pāriesim uz onConnection starpprogrammatūru.

onConnection

Šeit mēs redzam, ka mēs izgūstam lietotāja ID, kas tika iestatīts iepriekšējā starpprogrammatūrā, un saglabājam to mūsu socketsState, bet atslēga ir id un vērtība ir rozetes.

Tālāk mēs uzklausām ziņojumu notikumu. Visa mūsu loģika ir balstīta uz to - katrs notikums, ko priekšpiedziņa mums sūta, tiks saukts: ziņojums.

Notikuma nosaukums tiks nosūtīts argumentu objektā - kā minēts iepriekš.

Apstrādātāji

Kā redzat onConnection, īpaši ziņojumu notikuma klausītājā, mēs meklējam apstrādātāju, pamatojoties uz notikuma vārdu.

Mūsu apstrādātāji ir vienkārši objekts, kurā galvenais ir notikuma nosaukums un vērtība ir funkcija. Mēs to izmantosim, lai klausītos notikumus un attiecīgi reaģētu.

Arī vēlāk mēs pievienosim nosūtīšanas funkciju un izmantosim to, lai nosūtītu notikumu vairākās instancēs.

SocketsState

Mēs zinām savas valsts saskarni, bet mums tas vēl jāievieš.

Mēs pievienojam metodes kontaktligzdas pievienošanai un noņemšanai, kā arī notikuma izstarošanai.

Funkcija pievienošana pārbauda, ​​vai štatam ir īpašums, kas ir vienāds ar lietotāja ID. Ja tas tā ir, tad mēs vienkārši pievienojam to mūsu jau esošajam masīvam. Pretējā gadījumā vispirms izveidojam jaunu masīvu.

Noņemšanas funkcija arī pārbauda, ​​vai stāvokļa īpašumos ir lietotāja ID. Ja nē - tas neko nedod. Pretējā gadījumā tas filtrē masīvu, lai noņemtu ligzdu no masīva. Tad, ja masīvs ir tukšs, tas to noņem no stāvokļa, iestatot īpašumu uz nenoteiktu.

Redisa krogs

Lai izveidotu savu pubsub, mēs izmantosim paketi ar nosaukumu node-redis-pubsub.

Notiek nosūtīšanas pievienošana

Ok, tagad atliek tikai pievienot nosūtīšanas funkciju ...

... un pievienojiet klausītāju izejošajai_skulas_ziņai. Tādā veidā katrs gadījums saņem notikumu un nosūta to uz lietotāja kontaktligzdām.

Padarot to visu ar vairākiem pavedieniem

Visbeidzot, pievienosim kodu, kas nepieciešams, lai mūsu serveris būtu daudzpusīgs.

Piezīme: osta ir jānogalina, jo pēc mūsu Nodemon procesa pārtraukšanas ar Ctrl + c tas tur vienkārši karājas.

Ar nelielu labošanu mums tagad ir darba ligzdas visās instancēs. Rezultātā: daudz efektīvāks serveris.

Liels paldies par lasīšanu!

Es novērtēju, ka tas viss sākotnēji varētu šķist milzīgs un grūts, lai visu ņemtu uzreiz. Paturot to prātā, es ļoti aicinu jūs vēlreiz izlasīt kodu kopumā un apdomāt to kopumā.

Ja jums ir kādi jautājumi vai komentāri, nekautrējieties tos ievietot komentāru sadaļā zemāk vai nosūtīt man ziņojumu.

Apskatiet manus sociālos medijus!

Pievienojieties manam biļetenam!

Sākotnēji publicēts vietnē www.mcieslar.com 2018. gada 10. septembrī.