Elixir GenServer kõne vs cast

GenServer.call ei ole mõeldud ainult vastuse tagastamiseks

Olen töötanud kõrvalprojekti kallal, kasutades Elixirit koos sõbraga, kellele see keel on uus. Tal on teatav funktsionaalne programmeerimiskogemus, kuid ükski ei kasuta näitlejamudelit Erlang / Elixir. Kohati oli keeruline seletada tõsiasja, et üksik näitleja siin maailmas saab antud ajahetkel teha ainult ühte asja, ehkki sageli kuulete BEAM VM-ist ja selle võimetest käsitleda samaaegsust. Reaalsus on see, et asjade tegemiseks on sageli vaja mitut näitlejat.

Mõnevõrra sellega on seotud GenServeri valimis- ja helistamiskontseptsioonid. Esmapilgul OTP põhialustega süsteemi loomisel on lihtne mõelda järgmisele:

Dokumentides öeldakse, et casting on asünkroonne. Kuna ma ei vaja selles olukorras vastust, on casting parem kui kõne. Asünkroonne kood tundub lahe. Sünkroonne kood ei tundu lahe. Ma tahan olla lahe.

Kahjuks võib idee, et casting on parem või annab teile eelise, kujunedes väljaulatuvalt probleemiks. Minu arvates on palju turvalisem alustada alati kõnega, mis võimaldab mul töödelda suuri töökoormusi palju ühtlasemalt, muretsemata oma süsteemiosade ülekoormamise pärast. Seda öeldes on cast'it suurepäraseks kasutamiseks õiges stsenaariumis. Kui teie töökoormus võib aga kõikuda ja võib vahel tõusta, võib olla kõige parem hoida asjad kontrolli all kõne või mõne muu vasturõhu abil, et hoida kliente teie süsteemi osade ülekoormamisel.

Eliksiir-lang-veebisaidi ametlikul õppejuhendil on sama teema kohta väike jaotis, mille leiate siit. Kõne kasutamise kohta on selles dokumendis kirjas:

See (kõne) peaks olema vaikimisi valik, kuna serveri vastuse ootamine on kasulik vasturõhu mehhanism.

TLDR; Otsus ülekandmise ja kõne vahel on midagi enamat kui lihtsalt vastuse kindlakstegemine. Kui kahtlete, kasutage kõnet.

Loodetavasti heidab allpool olev rumal analoogia sellele teemale veidi valgust.

See on Bob. Bob on GenServer.

Bob meeldib oma väikeses maailmas lihtsalt kahele asjale.

Talle meeldib teha koristustöid ja kontrollida oma postkasti, kas pole uusi koristustöid.

Üks Bob on Bob, kes oskab nõusid teha.

Tere. Minu nimi on Bob ja ma armastan majapidamistöid!

See on Mary. Mary vihkab majapidamistöid teha.

Talle ei meeldi tegelikult nõusid teha.

Maryl on palju muid asju, millega tegeleda, ja ta soovib oma räpaseid nõusid maha laadida. Ta kuulis Bobust ja tema koristusteenistusest.

Mulle ei meeldi majapidamistöid teha. Eriti roogasid!

Kui Mary vajab roogade valmistamist, saadab ta sõnumi Bobi koristusteenuse postkasti.

Ta saadab Bobile sõnumi kõne abil, mis annab Bobile teada, et Mary ootab töö lõppedes sõnumit.

Nüüd istub Mary ja ootab Bobi vastust. Maarja ei saa muud teha, kui see plaat tuleb puhtaks.

GenServer.call (bob, {: do_dishes,: plate})

Kui Bob saabub teade, et tal tuleb nõu pesta, alustab ta kohe.

Kuni selle hetkeni seisis ta oma postkasti juures, oodates lihtsalt võimalust mõnda nõusid pesta.

Ta armastab seda tõesti nii väga.

Ta ei tee muud, kui ta on pesemise lõpetanud.

Mulle meeldib keskenduda.

Kui Bobi postkasti saabub uus koristusteade, kui ta Mary jaoks nõusid teeb, siis tuleb lihtsalt oodata, kuni ta pesemise lõpetanud on.

Ainus tõeline viis, kuidas Bob oma majapidamisoperatsiooni laiendada võiks, on palgata rohkem endaga sarnaseid inimesi. Kuid praegu on ta töökoormusega kenasti hakkama saanud.

Maarja on praegu tema ainus klient.

Olen vaid lihtne koopamees. Siin pole mitme ülesande täitmist.

Kui Bob lõpetab Maarja koristamise, saadab ta tema postkasti teate, et see on tehtud. Seda seetõttu, et ta saatis sõnumi kõne abil. See käsib Bob Maarjale vastata.

Kui Maarja teab, et roog on valmis, saab ta oma päevaga edasi liikuda. Kõne takistab Maryl teha midagi muud, sealhulgas lisada Bobile rohkem tööd.

Üks vähem roog on mul pesemiseks. Mul on hea meel, et Bob oskab nõusid süüa. Kuid ma pole kuigi produktiivne, kui Bob neid peseb.

Bob on suurepärane nõudepesija ja Mary naudib oma teenuse kasutamist, kuid on päevi, kus nõud on päris suur.

Maryl on oma töö teha ja ta ei saa endale lubada, et oodata, millal Bob iga roa valmis saab, enne kui ta jõuab oma töö juurde.

Ta peab tõesti ütlema, et Bob peseks palju asju ja saaks ikkagi oma töö tehtud. Ta saab oma elu lihtsustamiseks saata Bob'ile koristusteateid, kasutades castinguid.

See võimaldab Maarjal liikuda muude asjade juurde, samal ajal kui Bob nõusid peseb.

Näidendid ei blokeeri ainult Maarja jaoks. Bobut ei saa endiselt nõude pesemise ajal katkestada.

GenServer.cast (bob, {: do_dishes,: fork})

Bob võtab endiselt postkasti sõnumeid samamoodi nagu varem, kui naine kasutab castingut, kuid ta ei tea, et ta ei viitsi öelda, et Mary on roog iga kord puhas. Kui ta on valmis, läheb ta lihtsalt oma postkasti ja vaatab, kas on veel pestavaid nõusid.

Maarja usaldab Bobi lihtsalt selle tegemiseks ja see töötab mõneks ajaks suurepäraselt.

Ma ei saa neist roogadest piisavalt!

Maarja teadmata on Bob suutnud end pisut võlgadesse ajada ja sõbrad soovitasid tal valida koristusteenuse jaoks täiendavaid kliente.

Kõik uued kliendid saadavad koristussõnumeid otseülekande asemel helistamise teel. Nad ei taha oodata, kuni Bob on tehtud täpselt nii, nagu Mary seda ei tee.

Ainus probleem on see, et Bob on aktsepteerinud rohkem tööd, kui ta suudab konkreetsel päeval hakkama saada ja töökoormus ei näita mingit märki sellest, et ta saaks töölt lahkuda.

Maryl pole aimugi, et Bob pingutab. Ta usaldab Bobi. Mary jätkab Bobile koristussõnumite saatmist.

Oh mees. Mul on 500 pestavat nõu ja neid tuleb lihtsalt juurde.

Päeva või kahe pärast hakkab Mary ärrituma, et Bob pole veel kõiki oma roogasid valmis teinud. Ta plaanib sõpradega õhtusööki ja tal pole kahvleid.

(Tavaline GenServer.call oleks praeguseks aegunud, vaid teesklege vaid minuga)

Bob töötab endiselt ööpäevaringselt, kuid ei püsi tempos, mida ta sõnumeid võtab. Ta proovib tõesti anda oma parima, kuid see ei hakka tema klientide heaks tööle.

Mary lakkab pettumustest Bobile koristustööde saatmast.

Ma arvan, et pesen praegu enda nõud.

Paar päeva hiljem tuleb Bob lõpuks töökoormusega hakkama.

Tema ja ta kliendid saavad kokku ja mõistavad, et kõik nad on aeglustumises süüdi. Nad kõik lepivad kokku, et parim viis selle olukorra lahendamiseks on nüüd Bobile sõnumite saatmine kõne abil ja lihtsalt iga roogi ootamine.

Seda lähenemisviisi kasutades suudab Bob pakkuda teenust kõigile oma klientidele, kuid kuigi ta peseb näiteks Maarja jaoks nõusid, ei saa ta oma järjekorda täiendavaid nõusid lisada. See annab teistele klientidele õiglase võimaluse saada roog pesta pärast seda, kui ta on temaga koos teinud. Kui Maarja vajab veel ühte pestud roogi, võib ta saata sõnumi pärast seda, kui Bob on praeguse taotluse täitnud.

Mõelge sellele nii. Kui Bobil on kümme klienti, kes saaksid tema pesuteenust kasutada, ja nad kõik tuginevad üleskutsele suhelda Bobiga - see ütleb meile, et tipptasemel võis Bobil töödelda kokku vaid üheksa või kümme nõudepesu teadet. Selle põhjuseks on asjaolu, et pärast seda, kui klient saadab kõne Bobile, ei saa nad muud teha, kui Bob vastab, et see on tehtud. Kui kasutaksime ülekandmist, võib see arv kasvada nii suureks, kui VM-sätted seda võimaldaksid, potentsiaalselt kogu süsteemi alla viies.

Mul on nüüd järjekorras piiratud arv nõusid, mida pesta. Puhas.

Nüüd on kõik enamasti õnnelikud, kuid on ikka nii, et Mary põeb ikka veel Bobi ootamist, kui tema teade võib postkasti jääda viiendaks, kuna ta teeb tööd teiste klientide heaks. Kuid vähemalt teab ta nüüd, et võib eeldada, et tema roog puhastatakse mõistliku aja jooksul, selle asemel et kuluda tundide või päevadega.

Pikaajalise lahenduse eesmärk on julgustada Bobit palkama endale sõpru, kes aitaksid tema koristustööstuses. Koos võiksid nad töötada koos järelevalvepuuga, et abistada neid töökoormuses.

Kui Bob suudab palgata veel üheksa sõpra ja hoiab kokku oma kümme klienti, teaks ta, et klient ei peaks kunagi ootama rohkemat kui lihtsalt nende pestavat rooga. See teeks tema kliendid ilmselt õnnelikuks.

Mul on hea meel, et Bob sai oma olukorra lahendatud. Olen õppinud olema kannatlikum ja usaldan taas Bobi.Mulle meeldib see väike mootor, mis võiks. Hooray!