Dodajanje Socket.io v večnamenski Node.js

Fotografijo Vidar Nordli-Mathisen na Unsplash

Ena od pomanjkljivosti Node je, da je enojna. Seveda obstaja pot okoli nje - in sicer modul, imenovan grozd. Grozd nam omogoča, da svojo aplikacijo razširimo na več niti.

Zdaj pa se predstavlja nov problem. Glej, naša koda, ki se izvaja v več primerih, ima dejansko nekaj slabih strani. Eden od njih je, da ni svetovnih držav.

Običajno to v primeru z enim navojem ne bi motilo veliko skrbi. Za nas zdaj vse spremeni.

Poglejmo, zakaj.

Kaj je torej problem?

Naša aplikacija je preprost spletni klepet, ki teče na štiri teme. To uporabniku omogoča istočasno prijavo v telefon in računalnik.

Predstavljajte si, da imamo vtičnice nastavljene točno tako, kot bi jih nastavili za eno nit. Z drugimi besedami, zdaj imamo eno veliko globalno stanje z vtičnicami.

Ko se uporabnik prijavi v svoj računalnik, spletno mesto odpre povezavo z primerom Socket.io na našem strežniku. Vtičnica je shranjena v stanju niti 3.

Zdaj si predstavljajte, da uporabnik odhaja v kuhinjo po prigrizek in vzame s seboj telefon - seveda želi, da bi s prijatelji prijateljem ohranil v spletu.

Njihov telefon se poveže z nitjo 4 in vtičnica se shrani v stanje niti.

Pošiljanje sporočila iz njihovega telefona uporabniku ne bo koristilo. Sporočilo si bodo lahko ogledali le ljudje iz teme # 3. To je zato, ker vtičnice, shranjene na niti # 3, nekako niso čarobno shranjene tudi na niti 1, # 2 in # 4.

Smešno je, da tudi sam uporabnik ne bo več videl sporočil v računalniku, ko se vrne iz kuhinje.

Seveda, ko osvežimo spletno mesto, lahko pošljemo zahtevo GET in prejmemo zadnjih 50 sporočil, vendar res ne moremo reči, da je to "dinamičen" način, kajne?

Zakaj se to dogaja?

Širjenje našega strežnika po več niti je na nek način enako kot več ločenih strežnikov. Ne vedo drug za drugega in zagotovo ne delijo spomina. To pomeni, da predmet na enem primerku ne obstaja na drugem.

Vtičnice, shranjene v niti # 3, niso nujno vse vtičnice, ki jih uporabnik trenutno uporablja. Če so uporabniki uporabnikov v različnih nitih, ne bodo videli uporabnikovih sporočil, razen če bodo osvežili spletno mesto.

V idealnem primeru bi radi o dogodku obvestili uporabnika. Tako smo lahko prepričani, da vsaka povezana naprava prejme posodobitve v živo.

Rešitev

Druge teme lahko obvestimo s Redisovo paradigmo objavljanja / naročanja sporočil (pubsub).

Redis je odprta koda (BSD-licencirana) shramba podatkov v strukturi pomnilnika. Uporablja se lahko kot baza podatkov, predpomnilnik in posrednik sporočil.

To pomeni, da lahko uporabimo Redis za razporeditev dogodkov med našimi instancami.

Upoštevajte, da bi verjetno celotno strukturo shranili znotraj Redisa. Ker pa struktura ni serijska in jo je treba ohraniti "živo" v pomnilniku, bomo del nje shranili na vsak primer.

Pretok

Razmislimo zdaj o korakih, v katerih bomo obravnavali dohodni dogodek.

  1. Sporočilo, ki se imenuje, prihaja v eno od naših vtičnic - na ta način nam ni treba poslušati vsakega možnega dogodka.
  2. Znotraj predmeta, ki je kot argument posredovan upravljavcu tega dogodka, lahko najdemo ime dogodka. Na primer, sendMessage - .on ('sporočilo', ({dogodek}) => {}).
  3. Če obstaja ime za obdelavo tega imena, ga bomo izvedli.
  4. Obdelovalec lahko odpre odgovor z odgovorom.
  5. Odprema pošlje odzivni dogodek v naš Redis pubsub. Od tam ga oddajajo vsi naši primeri.
  6. Vsak primerek ga odda v svoje socketsState, s čimer zagotovi, da bo vsak povezan odjemalec sprejel dogodek.

Videti je zapleteno, vem, ampak imej me.

Izvajanje

Tu je pripravljeno odlagališče z okoljem, da nam ni treba vsega namestiti in nastaviti.

Najprej bomo s Expressom postavili strežnik.

Izdelamo aplikacijo Express, HTTP strežnik in init vtičnice.

Zdaj se lahko osredotočimo na dodajanje vtičnic.

Strežnik primerka Socket.io prenesemo na našo funkcijo, v kateri nastavimo vmesne vire.

onAuth

Funkcija onAuth preprosto posnema pooblastilo za posmeh. V našem primeru temelji na žetonu.

Osebno bi ga v prihodnosti verjetno nadomestil z JWT, vendar ga nikakor ne uveljavlja.

Zdaj pa preidimo na vmesno programsko opremo onConnection.

onConnection

Tu vidimo, da pridobimo id uporabnika, ki je bil nastavljen v prejšnji vmesni program, in ga shranimo v naše vtičniceState, pri čemer sta ključ id in vrednost matrika vtičnic.

Nato poslušamo dogodek s sporočilom. Naša celotna logika temelji na tem - vsak dogodek, ki nam ga pošlje sogovornik, se bo imenoval: message.

Ime dogodka bo poslano znotraj predmeta argumentov - kot je navedeno zgoraj.

Rokovalci

Kot lahko vidite v storitvi OnConnection, natančneje v poslušalcu za dogodek sporočila, iščemo oskrbnika, ki temelji na imenu dogodka.

Naši upravljavci so preprosto predmet, v katerem je ključ ime dogodka, vrednost pa funkcija. Uporabili ga bomo za poslušanje dogodkov in se ustrezno odzvali.

Kasneje bomo dodali dispečersko funkcijo in jo uporabili za pošiljanje dogodka preko primerkov.

SocketsState

Vmesnik naše države poznamo, vendar ga še moramo izvajati.

Dodamo metode za dodajanje in odstranjevanje vtičnice, pa tudi za oddajanje dogodka.

Funkcija doda preveri, ali ima država lastnost, ki je enaka ID-ju uporabnika. Če je tako, ga preprosto dodamo v naš že obstoječi niz. V nasprotnem primeru najprej ustvarimo nov niz.

Funkcija odstranjevanja preveri tudi, ali ima država v lastnostih id uporabnika. Če ne - nič ne naredi. V nasprotnem primeru filtrira matriko in tako odstrani vtičnico iz matrike. Če je matrika prazna, jo odstrani iz stanja, lastnost pa nastavi na nedefinirano.

Redis's pubsub

Za ustvarjanje naše pubsub bomo uporabili paket, imenovan node-redis-pubsub.

Dodajanje pošiljke

V redu, preostane vam le še dodajanje dispečerske funkcije ...

… In dodajte poslušalca za odhodno_socket_message. Tako vsak primerek prejme dogodek in ga pošlje v vtičnice uporabnika.

Izdelava je vse več niti

Na koncu dodamo še kodo, ki je potrebna, da je naš strežnik večnamenski.

Opomba: Pristanišče moramo ubiti, ker po prekinitvi procesa Nodemon s Ctrl + c tam samo visi.

Z malo nastavitve imamo zdaj delovne vtičnice na vseh stopnjah. Kot rezultat: veliko bolj učinkovit strežnik.

Najlepša hvala za branje!

Cenim, da bi se lahko na začetku vse zdelo pretirano in naporno, da bi vse to prevzeli naenkrat. Glede na to vas močno spodbujam, da kodo ponovno preberete v celoti in jo razmislite kot celoto.

Če imate kakršna koli vprašanja ali komentarje, jih prosimo, da jih postavite v spodnji del komentarjev ali mi pošljete sporočilo.

Oglejte si moje socialne medije!

Pridružite se mojemu glasilu!

Prvotno objavljeno na www.mcieslar.com 10. septembra 2018.