Introducerea viciului: Accesați canale pe mai multe mașini

Concurența este o modalitate excelentă de a face mai multe lucruri mai repede. Canalele Go sunt perfecte pentru a permite mai multor goutine simultane să comunice în siguranță într-un singur proces, dar dacă dorim să lăsăm mai multe mașini / noduri să comunice într-un mod similar, trebuie să scriem cod complet diferit și să ne integrăm cu cozile de mesagerie, gRPC sau ceva similar altceva. Până acum.

Vice abstractizează tehnologiile de așteptare a mesajelor și vă oferă canale Go vechi, simple, prin care puteți comunica în schimb.

Mai exact, puteți:

La GrayMeta, folosim Vice cu succes de câțiva ani; deci este destul de bine testat în luptă în producție.

Restul acestui articol va explica noțiunile de bază ale Vice și va arăta câteva exemple despre cum să construiți servicii reale.

Scrierea unui serviciu simplu

Să scriem tipul meu de serviciu preferat; cartierul tău prietenos întâmpină.

Un mesaj de întâmpinare e r ia un nume, îl transformă într-un mesaj de salut (înaintând & quot; Hello & quot; ) și returnează șir nou.

Salutarea noastră va fi doar o funcție simplă Go. Va fi nevoie de un context.Context (pentru a permite oamenilor să-l oprească), un canal nume numai pentru primire, un canal salutări numai pentru trimitere, și un canal pentru erori.

Dacă nu ați folosit niciodată contextul pentru a anula lucrurile înainte, verificați Folosirea contextelor pentru a evita scurgerea de goroutine.

Folosind un bloc select , vom aștepta ca cineva să trimită un nume prin canalul names , moment în care vom crea un mesaj de salut și îl vom trimite în jos canal salutări .

Toate canalele comunică felii de octeți [] octet , ceea ce înseamnă că putem face față șirurilor simple pentru cazuri simple sau putem folosi una dintre numeroasele opțiuni de codificare (cum ar fi JSON sau Gob) pentru a transmite mai multe date complexe.

Până în prezent, acesta este tot un cod Go idiomatic, ceea ce este deosebit de interesant atunci când ne uităm la testul de unitate pentru serviciul / funcția Greeter.

Utilizați canale Go normale în teste

Iată un test unitar pentru funcția noastră Greeter :

Pentru a testa funcția Greeter , creăm canalele de care are nevoie și o lansăm cu cuvântul cheie go , astfel încât să ruleze în fundal. Amânăm anularea contextului, astfel încât întâmpinatorul să se oprească când funcția noastră de testare este terminată.

Apoi trimitem șirul & quot; Vice & quot; prin canalul names și citim mesajul de întâmpinare din canalul greetings , pe care îl vom apoi verificați și eșuați dacă este greșit. (Ne convertim la și de la tipurile [] octet și șir aici, dar nimic mai complicat decât atât).

Acest test este un test unitar perfect, nu necesită dependențe externe și conține tot ce trebuie să ruleze.

Hmm, dar acest lucru se poate bloca pentru totdeauna …

O adăugare pe care am putea decide să o includem este aceea de a acoperi situația în care Greeterul nu face ceea ce trebuie să facă. Dacă nu trimite niciodată mesajul de întâmpinare pe canalul greetings , codul nostru de testare se va bloca pentru totdeauna (sau până când go test decide să renunțe la noi).

Deoarece acest lucru este doar un cod Go normal, un bloc selectat în codul nostru de test este tot ce trebuie să adăugăm un timeout:

Acest cod se va bloca până când se întâmplă unul din cele două lucruri; fie treci de 1/2 secundă și raportăm o eroare, fie primim un salut. Oricum ar fi, nu trebuie să așteptăm mult pentru a afla dacă codul nostru funcționează conform așteptărilor și nu trebuie să ne facem griji că testele noastre durează prea mult pentru a fi difuzate.

Adăugarea de cozi

Acum avem implementat serviciul Greeter complet testat, este timpul să adăugăm instalațiile sanitare pentru a-l transforma într-un serviciu care poate funcționa printr-o coadă de mesagerie.

Vice se bazează pe transporturile subiacente (implementează interfața vice.Transport ) pentru a face treaba dezordonată de a interacționa cu cozile.

Vedeți cozile acceptate în repo GitHub

Să aruncăm o privire rapidă la interfața vice.Transport :

Observați că metodele Trimite și Primire returnează canale; acestea sunt canalele pe care le putem transmite în serviciile noastre.

Tot ce trebuie să facem în programul nostru este:

Ne-am configurat contextul să dureze 1 minut, dar este mai logic să fie anulat prin captarea semnalului de terminare, ca atunci când utilizatorul apasă Ctrl + C.

Creăm un transport NSQ (NSQ este coada de mesagerie a lui Bitly, scrisă în întregime în Go) importând pachetul adecvat și cerem Transportului să creeze canalele noastre nume și salutări .

Folosim amânare pentru a opri Transportul , ceea ce este important deoarece unii clienți se înregistrează și își anulează interesul pentru coadă și trebuie să ne asigurăm că totul este curățat. După ce sunăm la Stop , așteptăm ca transportul să se oprească complet, așteptând închiderea canalului Done () . Acest lucru vă asigură că curățarea sa încheiat înainte de a ieși din programul nostru.

Pentru a afla mai multe despre canalele de semnal, citiți Pornirea și oprirea lucrurilor cu un canal de semnal.

Apoi trecem acele canale – împreună cu canalul de eroare de transport – în funcția Greeter .

Și atât. Acum, programul nostru va asculta subiectul NSQ numit „nume” și va trimite răspunsuri la subiectul „salutări”.

Fiecare implementare de transport are o configurație sau o personalizare specifică cozii pe care o puteți face, ale cărei detalii sunt în documentația pentru transportul respectiv.

Compensări

Vice oferă o abstractizare foarte simplă, dar merită să înțelegem compromisurile și compromisurile.

Blocarea și închiderea canalelor?

Dacă un canal Go nu are tampon, acesta se va bloca până când altcineva va citi din acesta. Folosim această natură ca parte a proiectării programelor noastre, dar același lucru nu se aplică atunci când trimitem aceste mesaje peste cozile de mesaje. Atunci când deblocarea unui canal vice se deblochează, nu înseamnă neapărat că mesajul a fost livrat la fel ca în cazul canalelor Go în proces.

În ceea ce privește închiderea, canalele se vor închide când transportul este oprit, așa că veți ști când lucrurile s-au oprit.

Cazuri de utilizare cu latență scăzută

Dacă aveți nevoie de mesaje cu latență redusă foarte rapidă (cum ar fi tranzacționarea pe acțiuni sau joc, etc.), probabil că veți dori să construiți ceva mai scăzut și să lucrați direct cu o tehnologie de coadă specifică. Veți pierde beneficiile Vice, dar ar putea fi un compromis care merită făcut.

Ce se întâmplă cu cazurile de utilizare mai complicate?

Când începeți să vă scufundați în nevoile dvs. pentru o coadă de mesagerie, vă dați seama că aveți câteva lucruri de luat în considerare, cum ar fi:

David Hernandez (și, de fapt, întregul proiect Go) este un mare susținător al valorilor implicite sensibile și acest lucru a fost luat în considerare când a fost proiectat Vice. Deci, în mod implicit, funcționează doar dacă trebuie să modificați comportamentul pe care îl puteți.

Când creați transportul, aveți opțiunea de a-l configura și regla pentru a se potrivi nevoilor dvs. De exemplu, NSQ are conceptul de conectare la consumatori , astfel încât tipul nsq.Transport expune funcția ConnectConsumer , care este livrată cu o valoare implicită sensibilă dar puteți suprascrie dacă doriți să o configurați.

Nu orice tehnologie de coadă are aceleași concepte, așa că nu are sens ca aceste concepte să o transforme în abstractizare.

Concluzie

Vice vă permite să scrieți servicii folosind numai canale Go idiomatice și, ulterior, să le conectați la tehnologii de coadă de mesagerie foarte scalabile, realizând o scară masivă. Are o selecție bună de tehnologii de așteptare pentru a alege, astfel încât să puteți începe astăzi, dar dacă preferatul dvs. lipsește, puteți fi oricând un erou și îl puteți adăuga.

Apropo, mai există o caracteristică a acestui proiect care este foarte utilă atunci când vine vorba de a contribui …

O notă laterală; Teste de interfață

O caracteristică interesantă a acestei baze de cod este utilizarea testelor de interfață. Un test de interfață este codul de testare (de obicei o singură funcție) care preia o interfață precum vice.Transport și o folosește în diferite moduri afirmând că se comportă așa cum era de așteptat.

Codul de testare nu știe nimic despre detaliile implementării; nu-i pasă. Îi pasă doar că metodele de interfață și tipurile returnate fac ceea ce ar trebui.

Pentru ca orice transport să fie considerat bun, trebuie să treacă toate testele.

Deci, dacă doriți să scrieți o implementare Vice pentru tehnologia dvs. preferată de coadă de mesagerie, cu condiția să adăugați următorul test (și să treacă), va fi probabil acceptat.

Ce urmează?