Alexei Naidenov. ITooLabs. Cas de desenvolupament a la plataforma telefònica Go (Golang). Part 1

Alexey Naidenov, conseller delegat ITooLabs, parla del desenvolupament d'una plataforma de telecomunicacions per a operadors de telecomunicacions en el llenguatge de programació Go (Golang). Alexey també comparteix la seva experiència en desplegar i operar la plataforma en un dels operadors de telecomunicacions asiàtics més grans, que va utilitzar la plataforma per oferir serveis de correu de veu (VoiceMail) i Virtual PBX (Cloud PBX).

Alexei Naidenov. ITooLabs. Cas de desenvolupament a la plataforma telefònica Go (Golang). Part 1

Alexey Naydenov (d'ara endavant - AN): - Hola a tots! Em dic Alexey Naydenov. Sóc el director d'ITooLabs. En primer lloc, m'agradaria respondre què estic fent aquí i com he acabat aquí.

Si mireu el Bitrix24 Marketplace (secció "Telefonia"), llavors 14 aplicacions i 36 que hi ha (40%) som nosaltres:

Alexei Naidenov. ITooLabs. Cas de desenvolupament a la plataforma telefònica Go (Golang). Part 1

Més precisament, aquests són els nostres operadors associats, però darrere de tot això hi ha la nostra plataforma (Platform as a Service), el que els venem per un petit cèntim. De fet, m'agradaria parlar del desenvolupament d'aquesta plataforma i de com vam arribar a Go.

Els números de la nostra plataforma ara són:

Alexei Naidenov. ITooLabs. Cas de desenvolupament a la plataforma telefònica Go (Golang). Part 1

44 operadors socis, inclòs Megafon. En termes generals, ens agrada molt viure diferents aventures i tenim accés real a 100 milions de subscriptors de 44 operadors aquí a Rússia. Per tant, si algú té alguna idea de negoci, sempre estarem encantats d'escoltar-les.

  • 5000 empreses usuàries.
  • 20 subscriptors en total. Tot és b000b: només treballem amb empreses.
  • 300 trucades per minut durant el dia.
  • 100 milions de minuts de trucades l'any passat (ho vam celebrar). Això sense tenir en compte les negociacions internes que hi ha a la nostra plataforma.

Com va començar?

Com comencen els homes adequats a fer la seva pròpia plataforma? També hem de tenir en compte que teníem una història de desenvolupament d'"empresa hardcore", i fins i tot en l'època més precisa de l'any per a una empresa! Va ser aquell moment feliç quan vas al client i dius: "Necessitem un parell de servidors més". I el client: “Sí, cap pregunta! Tenim un deu al bastidor.

Així que vam fer Oracle, Java, WebSphere, Db2 i tot això. Per tant, vam agafar, és clar, les millors solucions de proveïdors, les vam integrar i vam intentar enlairar-s'hi. Jugaven pel seu compte. Seria una startup interna.

Tot va començar l'any 2009. Des de l'any 2006, estem molt implicats en les decisions dels operadors, d'una manera o altra. Vam fer diverses centrals virtuals personalitzades (com les que tenim ara per encàrrec): vam mirar, vam decidir que era bo i vam decidir impulsar una posada en marxa interna.

Alexei Naidenov. ITooLabs. Cas de desenvolupament a la plataforma telefònica Go (Golang). Part 1

Vam agafar VMWare. Com que estàvem sols, vam haver d'abandonar immediatament l'emmagatzematge del venedor genial. D'ells ho sabem tot: que les promeses s'han de dividir per 3, i el cost s'ha de multiplicar per 10. Per això van fer DirDB i així successivament.

Després va començar a créixer. S'hi va afegir un servei de facturació perquè la plataforma ja no podia fer front. Aleshores, el servidor de facturació de MySQL es va traslladar a Mongo. Com a resultat, vam obtenir una solució de treball que processa totes les trucades que hi van:

Alexei Naidenov. ITooLabs. Cas de desenvolupament a la plataforma telefònica Go (Golang). Part 1

Però en algun lloc dins, el mateix producte del venedor està girant: el principal, nuclear, que vam agafar una vegada. Cap a finals de 2011, ens vam adonar que el principal coll d'ampolla per a nosaltres, és clar, seria aquest producte en concret; ens hi trobaríem. Vam veure una paret davant nostre, a la qual vam córrer a tot galop, a mesura que anaven arribant més clients.
En conseqüència, havíem de fer alguna cosa. Per descomptat, vam fer moltes investigacions sobre diversos productes, tant de codi obert com de proveïdors. No m'atendré en això ara, no és aquest el punt. L'última alternativa que vam pensar va ser fer la nostra pròpia plataforma.

Finalment, hem arribat a aquesta opció. Per què? Perquè tots els productes de proveïdors i de codi obert es van fer per resoldre problemes que tenien 10 anys. Bé, si fa 10 anys, i alguns més! L'elecció se'ns va fer evident: o ens acomiadem de la nostra gran idea d'un servei ideal (per a socis, operadors i nosaltres mateixos), o fem alguna cosa pròpia.

Hem decidit fer una cosa diferent!

Requisits de la plataforma

Si fas alguna cosa durant molt de temps (explotes el producte d'una altra persona), aleshores lentament es forma al teu cap el pensament: com ho faria jo mateix? Com que tots som programadors de l'empresa (excepte els venedors, no hi ha programadors), els nostres requisits s'han format durant molt de temps i eren clars:

  1. Alta velocitat de desenvolupament. El producte del venedor, que ens turmentava, no ens va agradar en primer lloc perquè tot va funcionar durant molt de temps i a poc a poc. Volíem ràpid: teníem moltes idees! Encara ens queden moltes idees, però aleshores la llista d'idees era tal que semblava deu anys per davant. Ara només per un any.
  2. Màxima utilització del ferro multinucli. Això també era important per a nosaltres, perquè vam veure que només hi hauria més i més nuclis.
  3. Alta fiabilitat. El que també vam plorar.
  4. Alta tolerància a fallades.
  5. Volíem acabar amb un procés de llançament diari. Per fer-ho, calia triar l'idioma.

Alexei Naidenov. ITooLabs. Cas de desenvolupament a la plataforma telefònica Go (Golang). Part 1

En conseqüència, a partir dels requisits del producte que ens hem presentat, els requisits de la llengua creixen d'una manera clarament lògica.

  1. Si volem suport per a sistemes multinucli, necessitem suport per a l'execució paral·lela.
  2. Si necessitem velocitat de desenvolupament, necessitem un llenguatge que suporti el desenvolupament competitiu, la programació competitiva. Si algú no ha trobat la diferència, és molt senzill:
    • la programació paral·lela tracta de com funcionen dos fils diferents en nuclis diferents;
    • l'execució simultània, més concretament el suport de concurrència, tracta de com el llenguatge (o el temps d'execució, el que sigui) ajuda a ocultar tota la complexitat que prové de l'execució paral·lela.
  3. Alta estabilitat. Evidentment, necessitàvem un clúster i era millor que el que teníem al producte del proveïdor.

Alexei Naidenov. ITooLabs. Cas de desenvolupament a la plataforma telefònica Go (Golang). Part 1

Realment no teníem tantes opcions, si recordeu. En primer lloc, Erlang: ens encanta i ho sabem, era el meu favorit personal i personal. En segon lloc, Java no és ni tan sols Java, sinó concretament Scala. En tercer lloc, una llengua que aleshores no coneixíem gens -Go. Acabava d'aparèixer aleshores, o millor dit, ja feia uns dos anys que existia, però encara no s'havia estrenat.

Va derrotat!

Història de Go

Hi vam fer una plataforma. Intentaré explicar per què.

Una breu història de Go. Iniciat el 2007, obert el 2009, la primera versió es va llançar el 2012 (és a dir, vam començar a treballar fins i tot abans del primer llançament). L'iniciador va ser Google, que volia substituir, com sospito, Java.

Els autors són molt famosos:

  • Ken Thomson, que estava darrere d'Unix, va inventar UTF-8, va treballar en el sistema del Pla 9;
  • Rob Pike, que va dissenyar UTF-8 amb Ken, també va treballar a Plan 9, Inferno, Limbo a Bell Labs;
  • Robert Gizmer, a qui coneixem i estimem per haver inventat el Java HotSpot Compiler i per treballar en el generador a V8 (l'intèrpret de Javascript de Google);
  • I més de 700 col·laboradors, inclosos alguns dels nostres pedaços.

Alexei Naidenov. ITooLabs. Cas de desenvolupament a la plataforma telefònica Go (Golang). Part 1

Aneu d'un cop d'ull

Veiem que el llenguatge és més o menys senzill i entenedor. Tenim tipus evidents: en alguns casos s'han de declarar, en altres no (és a dir, els tipus es dedueixen de totes maneres).

Alexei Naidenov. ITooLabs. Cas de desenvolupament a la plataforma telefònica Go (Golang). Part 1

Es pot veure que està de moda descriure estructures. Es pot veure que tenim el concepte de punter (on hi ha l'asterisc). Es pot veure que hi ha suport especial per declarar la inicialització de matrius i matrius associatius.

Aproximadament comprensible: pots viure. Intentant escriure Hola, món:

Alexei Naidenov. ITooLabs. Cas de desenvolupament a la plataforma telefònica Go (Golang). Part 1

Què veiem? Aquesta és una sintaxi semblant a C, el punt i coma és opcional. Pot ser un separador de dues línies, però només si es tracta de dues construccions que es troben exactament a la mateixa línia.

Veiem que els claudàtors de les estructures de control (a la línia 14) són opcionals, però sempre calen els arrissats. Veiem que l'escriptura és estàtica. Tim en la majoria dels casos es mostra. Aquest exemple és una mica més complicat que l'habitual Hola, món, només per demostrar que hi ha una biblioteca.

Què més veiem important? El codi està organitzat en paquets. I per utilitzar el paquet al vostre propi codi, heu d'importar-lo mitjançant la directiva d'importació, això també és important. Comencem, funciona. Genial!

Anem a provar una cosa més complicada: hola, món, però ara és un servidor http. Què hi veiem interessant aquí?

Alexei Naidenov. ITooLabs. Cas de desenvolupament a la plataforma telefònica Go (Golang). Part 1

En primer lloc, la funció actua com a paràmetre. Això vol dir que la funció que tenim és un "ciutadà de primera classe" i que pots fer-hi moltes coses interessants amb un estil funcional. Veiem l'inesperat següent: la directiva d'importació fa referència directament al repositori de GitHub. Així és, és així, a més, així s'ha de fer.

A Go, l'identificador universal d'un paquet és l'URL del seu repositori. Hi ha una utilitat especial de Goget que s'encarrega de totes les dependències, les descarrega, les instal·la, les compila i les prepara per utilitzar-les si cal. Al mateix temps, Goget sap sobre html-meta. En conseqüència, podeu mantenir un directori http, que contindrà enllaços al vostre repositori específic (com fem nosaltres, per exemple).

Què més veiem? Http i Json a la biblioteca normal. Hi ha, òbviament, introspecció - reflexió, que s'hauria d'utilitzar en la codificació / json, perquè simplement substituïm algun objecte arbitrari.

L'executem i veiem que tenim 20 línies de codi útil que compila, executa i dóna la càrrega mitjana actual de la màquina (a la màquina on s'executa).
Què més és important del que podem veure immediatament aquí? Es compila en un binari estàtic (buinary). Aquest binari no té cap dependència, ni biblioteques! Es pot copiar a qualsevol sistema, executar-lo immediatament i funcionarà.

Canviant de tema.

Go: mètodes i interfícies

Go té mètodes. Podeu declarar un mètode per a qualsevol tipus personalitzat. A més, això no és necessàriament una estructura, però pot ser un àlies d'algun tipus. Podeu declarar un àlies per a N32 i escriure mètodes perquè faci alguna cosa útil.

I aquí és on caiem en un estupor per primera vegada... Resulta que Go no té classes com a tals. Els que coneixen Go poden dir que hi ha inclusió de tipus, però això és completament diferent. Com més aviat el desenvolupador deixi de pensar-ho com a herència, millor. No hi ha classes a Go, ni tampoc hi ha herència.

Pregunta! Què ens va donar la companyia d'autors liderada per Google per mostrar la complexitat del món? Ens han donat interfícies!

Alexei Naidenov. ITooLabs. Cas de desenvolupament a la plataforma telefònica Go (Golang). Part 1

Una interfície és un tipus especial que us permet escriure mètodes senzills, signatures de mètodes. A més, qualsevol tipus per al qual existeixen aquests mètodes (s'executen) correspondrà a aquesta interfície. Això vol dir que simplement podeu escriure la funció corresponent per a un tipus, per a un altre (que correspon a aquest tipus d'interfície). A continuació, declareu una variable del tipus d'aquesta interfície i assigneu-li qualsevol d'aquests objectes.

Per als fanàtics més exigents, puc dir que aquesta variable contindrà en realitat dos punters: un a les dades, l'altre a una taula de descriptors especial que és específica d'aquest tipus en particular, a la interfície d'aquest tipus. És a dir, el compilador fa aquestes taules de descriptors en el moment de l'enllaç.

I, per descomptat, hi ha indicacions per al buit a Go. La interfície de paraula {} (amb dues claus) és una variable que en principi us permet assenyalar qualsevol objecte.
Fins aquí tot està bé, tot és familiar. Res d'estranyar.

Anar: goroutines

Ara arribem al que ens interessa: processos lleugers - goroutines (goroutines) en terminologia Go.

Alexei Naidenov. ITooLabs. Cas de desenvolupament a la plataforma telefònica Go (Golang). Part 1

  1. En primer lloc, són realment lleugers (menys de 2 Kb).
  2. En segon lloc, el cost de crear aquesta goroutina és insignificant: podeu crear-ne mil per segon, no passarà res.
  3. Estan servits pel seu propi programador, que simplement transfereix el control d'una goroutina a una altra.
  4. En aquest cas, el control es transfereix en els casos següents:
    • si es troba una instrucció go (si la goroutina comença la següent goroutina);
    • si s'habilita una trucada d'entrada/sortida de bloqueig;
    • si s'activa la recollida d'escombraries;
    • si s'inicia alguna operació amb canals.

És a dir, sempre que s'executa un programa Go en un ordinador, detecta el nombre de nuclis del sistema, inicia tants fils com calgui (quants nuclis hi ha al sistema o quants li has dit). En conseqüència, el planificador executarà aquests fils d'execució lleugers en tots aquests fils del sistema operatiu de cada nucli.

Cal tenir en compte que aquesta és la manera més eficient d'utilitzar el ferro. A més del que hem demostrat, fem molt més. Fem, per exemple, sistemes DPI que permeten servir 40 gigabits en una unitat (segons el que succeeixi en aquestes línies).

Allà, fins i tot abans de Go, vam utilitzar exactament el mateix esquema per aquest mateix motiu: perquè us permet desar la localitat de la memòria cau del processador, reduir significativament el nombre de canvis de context del sistema operatiu (que també triga molt de temps). Repeteixo: aquesta és la manera més eficaç d'utilitzar el ferro.

Aquest senzill exemple de 21 línies és un exemple que simplement fa echo-server. Al mateix temps, tingueu en compte que la funció de servei és extremadament simple, és lineal. No hi ha devolucions de trucades, no cal molestar-se i pensar... Només llegiu i escriviu!

Al mateix temps, si llegiu i escriviu, en realitat s'hauria de bloquejar: aquesta goroutine simplement es posa a la cua i el planificador l'agafa quan l'execució es torna possible. És a dir, aquest codi senzill pot actuar com a servidor d'eco per a tantes connexions com ho permeti el sistema operatiu d'aquesta màquina.

Continuarà molt aviat...

Alguns anuncis 🙂

Gràcies per quedar-te amb nosaltres. T'agraden els nostres articles? Vols veure més contingut interessant? Doneu-nos suport fent una comanda o recomanant als amics, Cloud VPS per a desenvolupadors des de 4.99 dòlars, un anàleg únic dels servidors d'entrada, que vam inventar per a vosaltres: Tota la veritat sobre VPS (KVM) E5-2697 v3 (6 nuclis) 10 GB DDR4 480 GB SSD 1 Gbps des de 19 dòlars o com compartir un servidor? (disponible amb RAID1 i RAID10, fins a 24 nuclis i fins a 40 GB DDR4).

Dell R730xd 2 vegades més barat al centre de dades Equinix Tier IV a Amsterdam? Només aquí 2 x Intel TetraDeca-Core Xeon 2x E5-2697v3 2.6 GHz 14C 64 GB DDR4 4 x 960 GB SSD 1 Gbps 100 TV des de 199 $ als Països Baixos! Dell R420 - 2x E5-2430 2.2 Ghz 6C 128 GB DDR3 2 x 960 GB SSD 1 Gbps 100 TB - a partir de 99 $! Llegeix sobre Com construir infrastructure corp. classe amb l'ús de servidors Dell R730xd E5-2650 v4 per valor de 9000 euros per un cèntim?

Font: www.habr.com

Afegeix comentari