Alexei Naidenov. ITooLabs. Caz de dezvoltare pe platforma telefonică Go (Golang). Partea 1

Alexey Naidenov, CEO ITooLabs, vorbește despre dezvoltarea unei platforme de telecomunicații pentru operatorii de telecomunicații în limbajul de programare Go (Golang). Alexey împărtășește, de asemenea, experiența sa de implementare și operare a platformei într-unul dintre cei mai mari operatori de telecomunicații asiatici, care a folosit platforma pentru a furniza servicii de mesagerie vocală (VoiceMail) și Virtual PBX (Cloud PBX).

Alexei Naidenov. ITooLabs. Caz de dezvoltare pe platforma telefonică Go (Golang). Partea 1

Alexey Naydenov (în continuare - AN): - Salutare tuturor! Numele meu este Alexey Naidenov. Sunt directorul ITooLabs. În primul rând, aș dori să răspund ce fac aici și cum am ajuns aici.

Dacă te uiți la Bitrix24 Marketplace (secțiunea „Telefonie”), atunci 14 aplicații și 36 care există (40%) suntem noi:

Alexei Naidenov. ITooLabs. Caz de dezvoltare pe platforma telefonică Go (Golang). Partea 1

Mai exact, aceștia sunt operatorii noștri parteneri, dar în spatele tuturor acestor lucruri se află platforma noastră (Platform as a Service) - ceea ce le vindem pentru un bănuț mic. De fapt, aș dori să vorbesc despre dezvoltarea acestei platforme și despre cum am ajuns la Go.

Numerele pentru platforma noastră acum sunt:

Alexei Naidenov. ITooLabs. Caz de dezvoltare pe platforma telefonică Go (Golang). Partea 1

44 de operatori parteneri, inclusiv MegaFon. În general, ne place să mergem în aventuri și, de fapt, avem acces la 100 de milioane de abonați ai 44 de operatori aici, în Rusia. Prin urmare, dacă cineva are câteva idei de afaceri, suntem întotdeauna bucuroși să le ascultăm.

  • 5000 de companii utilizatori.
  • 20 de abonați în total. Totul este b000b - lucrăm doar cu companii.
  • 300 de apeluri pe minut în timpul zilei.
  • 100 de milioane de minute de apel anul trecut (am sărbătorit). Asta fără a ține cont de negocierile interne care sunt pe platforma noastră.

Cum a început?

Cum încep tipii potriviți să-și creeze propria platformă? De asemenea, trebuie să ținem cont de faptul că am avut o istorie de dezvoltare a „întreprinderii hardcore”, și chiar în cea mai exactă perioadă a anului pentru o întreprindere! Era acel moment fericit când vii la client și îi spui: „Avem nevoie de încă două servere”. Iar clientul: „Da, nicio întrebare! Avem zece în raft.

Așa că am făcut Oracle, Java, WebSphere, Db2 și toate astea. Prin urmare, am luat, bineînțeles, cele mai bune soluții pentru furnizori, le-am integrat și am încercat să decolăm cu ele. S-au jucat singuri. Ar fi un astfel de startup intern.

Totul a început în 2009. Din 2006, ne-am implicat îndeaproape în deciziile operatorilor, într-un fel sau altul. Am realizat mai multe PBX virtuale personalizate (cum ar fi cele pe care le avem acum la comandă): ne-am uitat, am decis că este bine și am decis să stârnim un startup intern.

Alexei Naidenov. ITooLabs. Caz de dezvoltare pe platforma telefonică Go (Golang). Partea 1

Luați VMWare. Din moment ce mergeam pe cont propriu, a trebuit să abandonăm imediat vânzătorul cool Storage. Știm totul despre ele: că promisiunile ar trebui împărțite la 3, iar costul să fie înmulțit cu 10. Prin urmare, am făcut DirDB și așa mai departe.

Apoi a început să crească. La aceasta s-a adăugat și serviciul de facturare, deoarece platforma nu a mai făcut față. Apoi serverul de facturare de la MySQL s-a mutat la Mongo. Ca rezultat, am obținut o soluție funcțională care procesează toate apelurile care ajung acolo:

Alexei Naidenov. ITooLabs. Caz de dezvoltare pe platforma telefonică Go (Golang). Partea 1

Dar undeva înăuntru, același produs de vânzător se învârte - cel principal, nuclear, pe care l-am luat cândva. Aproximativ până la sfârșitul anului 2011, ne-am dat seama singuri că principalul blocaj pentru noi, desigur, va fi acest produs special - ne vom întâlni cu el. Am văzut un zid în fața noastră, în care am alergat în plin galop, în timp ce clienții mergeau, s-au adăugat.
În consecință, a trebuit să facem ceva. Desigur, am făcut destul de multe cercetări pe diverse produse - atât open source, cât și cele ale furnizorilor. Nu mă voi opri acum asupra acestui lucru - nu acesta este ideea. Ultima soluție la care ne-am gândit a fost să ne facem propria platformă.

Până la urmă, am ajuns la această opțiune. De ce? Pentru că toate produsele furnizorilor și open source au fost făcute pentru a rezolva probleme în urmă cu 10 ani. Ei bine, dacă un copil de 10 ani, și ceva mai mult! Alegerea a devenit evidentă pentru noi: fie ne luăm rămas bun de la ideea noastră minunată de serviciu ideal (pentru parteneri, operatori și noi înșine), fie facem ceva propriu.

Am decis să facem ceva diferit!

Cerințe ale platformei

Dacă faci ceva timp îndelungat (exploatezi produsul altcuiva), atunci încet-încet se formează în capul tău gândul: cum aș face eu însumi? Deoarece suntem cu toții programatori în companie (cu excepția vânzătorilor, nu există non-programatori), cerințele noastre au fost formate de mult timp și au fost clare:

  1. Viteză mare de dezvoltare. Produsul vânzătorului, care ne chinuia, nu ni s-a potrivit în primul rând pentru că totul s-a rezolvat mult timp și încet. Ne-am dorit rapid – aveam o mulțime de idei! Mai avem o mulțime de idei, dar atunci lista de idei a fost de așa natură încât părea că urmează zece ani. Acum doar de un an.
  2. Utilizarea maximă a fierului multinucleu. Acest lucru a fost important și pentru noi, pentru că am văzut că vor fi doar din ce în ce mai multe nuclee.
  3. Fiabilitate ridicată. Acela am plâns și noi.
  4. Toleranță ridicată la erori.
  5. Am vrut să încheiem un proces de lansare zilnic. Pentru a face acest lucru, aveam nevoie de o alegere a limbii.

Alexei Naidenov. ITooLabs. Caz de dezvoltare pe platforma telefonică Go (Golang). Partea 1

În consecință, din cerințele pentru produsul pe care ni l-am prezentat pentru noi, cerințele pentru limbă cresc într-un mod clar logic.

  1. Dacă vrem suport pentru sisteme multi-core, atunci avem nevoie de suport pentru execuția paralelă.
  2. Dacă avem nevoie de viteză de dezvoltare, avem nevoie de un limbaj care să sprijine dezvoltarea competitivă, programarea competitivă. Dacă cineva nu a întâlnit diferența, atunci este foarte simplu:
    • programarea paralelă se referă la modul în care două fire diferite rulează pe nuclee diferite;
    • execuția concurentă, mai precis suportul concurent, se referă la modul în care limbajul (sau timpul de execuție, oricare ar fi) ajută la ascunderea întregii complexități care provine din execuția paralelă.
  3. Stabilitate ridicată. Evident, aveam nevoie de un cluster și era mai bun decât ceea ce aveam pe produsul furnizorului.

Alexei Naidenov. ITooLabs. Caz de dezvoltare pe platforma telefonică Go (Golang). Partea 1

Nu prea aveam multe opțiuni, dacă vă amintiți. În primul rând, Erlang - ne place și îl știm, a fost preferatul meu personal, personal. În al doilea rând, Java nu este nici măcar Java, ci mai precis Scala. În al treilea rând, limba pe care la acea vreme nu o știam deloc - Go. Tocmai apăruse atunci, mai exact, exista deja de vreo doi ani, dar nu fusese încă lansat.

Învins Go!

Istoria lui Go

Am făcut o platformă pe el. Voi încerca să explic de ce.

O scurtă istorie a lui Go. Început în 2007, deschis în 2009, prima versiune a fost lansată în 2012 (adică am început să lucrăm chiar înainte de prima lansare). Inițiatorul a fost Google, care a vrut să înlocuiască, după cum bănuiesc, Java.

Autorii sunt foarte celebri:

  • Ken Thomson, care era în spatele Unix, a inventat UTF-8, a lucrat la sistemul Plan 9;
  • Rob Pike, care a proiectat UTF-8 cu Ken, a lucrat și la Plan 9, Inferno, Limbo la Bell Labs;
  • Robert Gizmer, pe care îl cunoaștem și îl iubim pentru că a inventat Java HotSpot Compiler și pentru că a lucrat la generatorul din V8 (interpretul Google Javascript);
  • Și peste 700 de colaboratori, inclusiv unele dintre patch-urile noastre.

Alexei Naidenov. ITooLabs. Caz de dezvoltare pe platforma telefonică Go (Golang). Partea 1

Du-te dintr-o privire

Vedem că limbajul este mai mult sau mai puțin simplu și ușor de înțeles. Avem tipuri evidente: în unele cazuri trebuie declarate, în altele nu (adică tipurile sunt oricum deduse).

Alexei Naidenov. ITooLabs. Caz de dezvoltare pe platforma telefonică Go (Golang). Partea 1

Se poate observa că este la modă să descrii structuri. Se poate observa că avem conceptul de pointer (unde este asteriscul). Se poate observa că există suport special pentru declararea inițializării matricelor și matricelor asociative.

Aproximativ de înțeles - poți trăi. Încerc să scriu Salut, lume:

Alexei Naidenov. ITooLabs. Caz de dezvoltare pe platforma telefonică Go (Golang). Partea 1

Ce vedem? Aceasta este sintaxă asemănătoare C, punctul și virgulă este opțional. Poate fi un separator pentru două linii, dar numai dacă acestea sunt două constructe care sunt exact pe aceeași linie.

Vedem că parantezele din structurile de control (pe linia a 14-a) sunt opționale, dar sunt întotdeauna necesare cele ondulate. Vedem că tastarea este statică. Tim în majoritatea cazurilor este afișat. Acest exemplu este puțin mai complicat decât obișnuitul Hello, world - doar pentru a arăta că există o bibliotecă.

Ce altceva vedem important? Codul este organizat în pachete. Și pentru a utiliza pachetul în propriul cod, trebuie să îl importați folosind directiva de import - acest lucru este, de asemenea, important. Începem - funcționează. Grozav!

Să încercăm ceva mai complicat: Bună, lume, dar acum este un server http. Ce vedem interesant aici?

Alexei Naidenov. ITooLabs. Caz de dezvoltare pe platforma telefonică Go (Golang). Partea 1

În primul rând, funcția acționează ca un parametru. Aceasta înseamnă că funcția pe care o avem este un „cetățean de primă clasă” și poți face o mulțime de lucruri interesante cu ea într-un stil funcțional. Vedem în continuare neașteptat: directiva de import se referă direct la depozitul GitHub. Așa este, așa este – mai mult, așa trebuie făcut.

În Go, identificatorul universal al unui pachet este adresa URL a depozitului său. Există un utilitar Goget special care se ocupă de toate dependențele, le descarcă, le instalează, le compilează și le pregătește pentru utilizare, dacă este necesar. În același timp, Goget știe despre html-meta. În consecință, puteți păstra un director http, care va conține link-uri către depozitul dvs. specific (cum facem noi, de exemplu).

Ce mai vedem? Http și Json în biblioteca obișnuită. Există, evident, introspecție - reflecție, care ar trebui folosită în codificare / json, pentru că pur și simplu înlocuim un obiect arbitrar.

Îl rulăm și vedem că avem 20 de linii de cod util care compilează, rulează și oferă încărcarea medie curentă a mașinii (pe mașina pe care rulează).
Ce altceva este important din ceea ce putem vedea imediat aici? Compilează într-un singur binar static (buinary). Acest binar nu are deloc dependențe, nici biblioteci! Poate fi copiat pe orice sistem, rulează imediat și va funcționa.

Trecând mai departe.

Go: metode și interfețe

Go are metode. Puteți declara o metodă pentru orice tip personalizat. Mai mult, aceasta nu este neapărat o structură, dar poate fi un alias de un anumit tip. Puteți declara un alias pentru N32 și puteți scrie metode pentru ca acesta să facă ceva util.

Și aici cădem în stupoare pentru prima dată... Se dovedește că Go nu are cursuri ca atare. Cei care cunosc Go pot spune că există includere de tip, dar aceasta este complet diferită. Cu cât dezvoltatorul încetează să se mai gândească mai devreme la asta ca moștenire, cu atât mai bine. Nu există clase în Go și nici moștenire.

Întrebare! Ce ne-a oferit compania de autori condusă de Google pentru a afișa complexitatea lumii? Ni s-au oferit interfețe!

Alexei Naidenov. ITooLabs. Caz de dezvoltare pe platforma telefonică Go (Golang). Partea 1

O interfață este un tip special care vă permite să scrieți metode simple, semnături de metode. Mai mult, orice tip pentru care aceste metode există (sunt executate) va corespunde acestei interfețe. Aceasta înseamnă că puteți scrie pur și simplu funcția corespunzătoare pentru un tip, pentru altul (care corespunde acelui tip de interfață). Apoi, declarați o variabilă de tipul acestei interfețe și atribuiți-i oricare dintre aceste obiecte.

Pentru fanii hardcore, pot spune că această variabilă va conține de fapt două indicatoare: unul către date, celălalt către un tabel special de descriptori care este specific acestui tip special, către interfața de acest tip. Adică, compilatorul realizează astfel de tabele de descriptori în momentul conectării.

Și există, desigur, indicii către void în Go. Interfața cuvântului {} (cu două acolade) este o variabilă care vă permite să indicați în principiu orice obiect.
Până acum, totul este în ordine, totul este familiar. Nimic surprinzător.

Go: goroutine

Acum ajungem la ceea ce ne interesează: procese ușoare - goroutine (goroutine) în terminologia Go.

Alexei Naidenov. ITooLabs. Caz de dezvoltare pe platforma telefonică Go (Golang). Partea 1

  1. În primul rând, sunt cu adevărat ușoare (mai puțin de 2 Kb).
  2. În al doilea rând, costul creării unei astfel de gorutine este neglijabil: puteți crea o mie de ele pe secundă - nu se va întâmpla nimic.
  3. Acestea sunt deservite de propriul programator, care pur și simplu transferă controlul de la o rutină la alta.
  4. În acest caz, controlul este transferat în următoarele cazuri:
    • dacă se întâlnește o instrucțiune go (dacă goroutine începe următoarea goroutine);
    • dacă este activat un apel de intrare/ieșire de blocare;
    • dacă colectarea gunoiului este declanșată;
    • dacă se începe o operațiune cu canale.

Adică, ori de câte ori un program Go este rulat pe un computer, detectează numărul de nuclee din sistem, pornește câte fire de execuție este necesar (câte nuclee are sistemul sau câte i-ai spus). În consecință, planificatorul va rula aceste fire ușoare de execuție pe toate aceste fire de execuție ale sistemului de operare din fiecare nucleu.

Trebuie remarcat faptul că acesta este cel mai eficient mod de a utiliza fierul. Pe lângă ceea ce am arătat, facem mult mai mult. Realizăm, de exemplu, sisteme DPI care permit deservirea a 40 de gigabiți într-o unitate (în funcție de ceea ce se întâmplă în aceste linii).

Acolo, chiar înainte de Go, am folosit exact aceeași schemă tocmai din acest motiv: pentru că vă permite să salvați localitatea cache-ului procesorului, să reduceți semnificativ numărul de comutări de context OS (ceea ce durează, de asemenea, foarte mult timp). Repet: acesta este cel mai eficient mod de a utiliza fierul.

Acest exemplu simplu de 21 de linii este un exemplu care face pur și simplu echo-server. În același timp, rețineți că funcția de servire este extrem de simplă, este liniară. Nu există apeluri inverse, nu trebuie să vă deranjați și să vă gândiți... Doar citiți și scrieți!

În același timp, dacă citiți și scrieți, ar trebui să se blocheze - această rutină este pur și simplu pusă în coadă și preluată de planificator atunci când execuția devine din nou posibilă. Adică, acest cod simplu poate acționa ca un server de eco pentru atâtea conexiuni câte va permite sistemul de operare de pe această mașină.

Va continua foarte curand...

Câteva reclame 🙂

Vă mulțumim că ați rămas cu noi. Vă plac articolele noastre? Vrei să vezi mai mult conținut interesant? Susține-ne plasând o comandă sau recomandând prietenilor, cloud VPS pentru dezvoltatori de la 4.99 USD, un analog unic al serverelor entry-level, care a fost inventat de noi pentru tine: Întregul adevăr despre VPS (KVM) E5-2697 v3 (6 nuclee) 10GB DDR4 480GB SSD 1Gbps de la 19 USD sau cum să partajezi un server? (disponibil cu RAID1 și RAID10, până la 24 de nuclee și până la 40 GB DDR4).

Dell R730xd de 2 ori mai ieftin în centrul de date Equinix Tier IV din Amsterdam? Numai aici 2 x Intel TetraDeca-Core Xeon 2x E5-2697v3 2.6GHz 14C 64GB DDR4 4x960GB SSD 1Gbps 100 TV de la 199 USD in Olanda! Dell R420 - 2x E5-2430 2.2Ghz 6C 128GB DDR3 2x960GB SSD 1Gbps 100TB - de la 99 USD! Citește despre Cum se construiește infrastructura corp. clasa cu folosirea serverelor Dell R730xd E5-2650 v4 in valoare de 9000 euro pentru un ban?

Sursa: www.habr.com

Adauga un comentariu