Alexei Naidenov. ITooLabs. Caso di sviluppo su piattaforma telefonica Go (Golang). Parte 1

Alexey Naidenov, amministratore delegato ITooLabs, parla dello sviluppo di una piattaforma di telecomunicazioni per operatori di telecomunicazioni nel linguaggio di programmazione Go (Golang). Alexey condivide anche la sua esperienza nell'implementazione e nella gestione della piattaforma in uno dei più grandi operatori di telecomunicazioni asiatici, che ha utilizzato la piattaforma per fornire servizi di posta vocale (VoiceMail) e Virtual PBX (Cloud PBX).

Alexei Naidenov. ITooLabs. Caso di sviluppo su piattaforma telefonica Go (Golang). Parte 1

Alexey Naydenov (di seguito - AN): - Ciao a tutti! Mi chiamo Alexey Naidenov. Sono il direttore di ITooLabs. Prima di tutto, vorrei rispondere a cosa sto facendo qui e come sono finito qui.

Se guardi il Marketplace di Bitrix24 (sezione "Telefonia"), allora 14 applicazioni e 36 presenti (40%) siamo noi:

Alexei Naidenov. ITooLabs. Caso di sviluppo su piattaforma telefonica Go (Golang). Parte 1

Più precisamente, questi sono i nostri operatori partner, ma dietro tutto questo c'è la nostra piattaforma (Platform as a Service), ciò che vendiamo loro per un piccolo centesimo. In realtà, vorrei parlare dello sviluppo di questa piattaforma e di come siamo arrivati ​​a Go.

I numeri per la nostra piattaforma ora sono:

Alexei Naidenov. ITooLabs. Caso di sviluppo su piattaforma telefonica Go (Golang). Parte 1

44 operatori partner, tra cui MegaFon. In generale, amiamo andare all'avventura e in realtà abbiamo accesso a 100 milioni di abbonati di 44 operatori qui in Russia. Pertanto, se qualcuno ha qualche idea imprenditoriale, siamo sempre felici di ascoltarlo.

  • 5000 aziende utilizzatrici.
  • 20 abbonati in totale. È tutto b000b: lavoriamo solo con aziende.
  • 300 chiamate al minuto durante il giorno.
  • 100 milioni di minuti di chiamata l'anno scorso (abbiamo festeggiato). Questo senza tener conto delle negoziazioni interne che sono sulla nostra piattaforma.

Come è iniziato?

In che modo i tizi giusti iniziano a creare la propria piattaforma? Va anche tenuto conto del fatto che abbiamo avuto una storia di sviluppo di "impresa hardcore", e anche nel periodo dell'anno più preciso per un'impresa! Era quel momento felice in cui vieni dal cliente e dici: "Abbiamo bisogno di un altro paio di server". E il cliente: “Sì, nessuna domanda! Abbiamo un dieci nel rack.

Quindi abbiamo creato Oracle, Java, WebSphere, Db2 e tutto il resto. Pertanto, abbiamo preso, ovviamente, le migliori soluzioni dei fornitori, le abbiamo integrate e abbiamo cercato di decollare con esse. Hanno giocato da soli. Sarebbe una tale startup interna.

Tutto è iniziato nel 2009. Dal 2006, siamo stati strettamente coinvolti nelle decisioni degli operatori, in un modo o nell'altro. Abbiamo realizzato diversi PBX virtuali personalizzati (come quello che abbiamo ora su ordinazione): abbiamo guardato, deciso che andava bene e deciso di creare una startup interna.

Alexei Naidenov. ITooLabs. Caso di sviluppo su piattaforma telefonica Go (Golang). Parte 1

Prendi VMWare. Dato che stavamo camminando da soli, abbiamo dovuto abbandonare immediatamente il fantastico venditore Storage. Sappiamo tutto su di loro: che le promesse dovrebbero essere divise per 3 e il costo dovrebbe essere moltiplicato per 10. Pertanto, abbiamo fatto DirDB e così via.

Poi ha iniziato a crescere. A questo si è aggiunto il servizio di fatturazione, perché la piattaforma non ce la faceva più. Quindi il server di fatturazione da MySQL è passato a Mongo. Di conseguenza, abbiamo una soluzione funzionante che elabora tutte le chiamate che vanno lì:

Alexei Naidenov. ITooLabs. Caso di sviluppo su piattaforma telefonica Go (Golang). Parte 1

Ma da qualche parte all'interno, gira lo stesso prodotto del venditore: il principale, nucleare, che una volta abbiamo preso. Approssimativamente entro la fine del 2011, ci siamo resi conto che il principale collo di bottiglia per noi, ovviamente, sarà questo particolare prodotto: ci imbatteremo in esso. Abbiamo visto un muro davanti a noi, nel quale siamo corsi al galoppo, mentre i clienti camminavano, sono stati aggiunti.
Di conseguenza, dovevamo fare qualcosa. Naturalmente, abbiamo svolto molte ricerche su vari prodotti, sia open source che vendor. Non mi soffermerò su questo ora - non è questo il punto. L'ultimo fallback a cui abbiamo pensato è stato creare la nostra piattaforma.

Alla fine, siamo arrivati ​​a questa opzione. Perché? Perché tutti i prodotti di fornitori e open source sono stati creati per risolvere problemi 10 anni fa. Bene, se un bambino di 10 anni, e anche di più! La scelta è diventata ovvia per noi: o diciamo addio alla nostra grande idea di un servizio ideale (per i partner, gli operatori e noi stessi), oppure facciamo qualcosa di nostro.

Abbiamo deciso di fare qualcosa di diverso!

Requisiti della piattaforma

Se fai qualcosa per molto tempo (sfrutti il ​​​​prodotto di qualcun altro), allora il pensiero si forma lentamente nella tua testa: come lo farei io stesso? Dato che siamo tutti programmatori in azienda (ad eccezione dei venditori, non ci sono non programmatori), i nostri requisiti sono stati formati da molto tempo ed erano chiari:

  1. Elevata velocità di sviluppo. Il prodotto del venditore, che ci tormentava, non ci andava bene in primo luogo perché tutto ha funzionato a lungo e lentamente. Volevamo in fretta: avevamo molte idee! Abbiamo ancora molte idee, ma poi l'elenco delle idee era tale che sembrava dieci anni avanti. Ora solo per un anno.
  2. Massimo utilizzo del ferro multi-core. Anche questo è stato importante per noi, perché abbiamo visto che ci sarebbero stati sempre più core.
  3. Alta affidabilità. Quello che abbiamo pianto anche noi.
  4. Elevata tolleranza ai guasti.
  5. Volevamo finire con un processo di rilascio giornaliero. Per fare questo, avevamo bisogno di una scelta della lingua.

Alexei Naidenov. ITooLabs. Caso di sviluppo su piattaforma telefonica Go (Golang). Parte 1

Di conseguenza, dai requisiti per il prodotto che ci siamo presentati, i requisiti per la lingua crescono in modo chiaramente logico.

  1. Se vogliamo il supporto per i sistemi multi-core, allora abbiamo bisogno del supporto per l'esecuzione parallela.
  2. Se abbiamo bisogno di velocità di sviluppo, abbiamo bisogno di un linguaggio che supporti lo sviluppo competitivo, la programmazione competitiva. Se qualcuno non ha riscontrato la differenza, allora è molto semplice:
    • la programmazione parallela riguarda il modo in cui due thread diversi vengono eseguiti su core diversi;
    • l'esecuzione concorrente, più specificamente il supporto della concorrenza, riguarda il modo in cui il linguaggio (o il runtime, qualunque cosa) aiuti a nascondere tutta la complessità che deriva dall'esecuzione parallela.
  3. Elevata stabilità. Ovviamente, avevamo bisogno di un cluster ed era migliore di quello che avevamo sul prodotto del fornitore.

Alexei Naidenov. ITooLabs. Caso di sviluppo su piattaforma telefonica Go (Golang). Parte 1

Non avevamo molte opzioni, se ricordi. In primo luogo, Erlang: lo adoriamo e lo sappiamo, era il mio preferito personale. In secondo luogo, Java non è nemmeno Java, ma specificamente Scala. In terzo luogo, la lingua che a quel tempo non conoscevamo affatto: vai. Era appena apparso allora, più precisamente esisteva già da circa due anni, ma non era ancora uscito.

Sconfitto Vai!

Storia di Go

Abbiamo creato una piattaforma su di esso. Cercherò di spiegare perché.

Una breve storia di Go. Iniziato nel 2007, aperto nel 2009, la prima versione è stata rilasciata nel 2012 (ovvero, abbiamo iniziato a lavorare anche prima della prima versione). L'iniziatore è stato Google, che voleva sostituire, come sospetto, Java.

Gli autori sono molto famosi:

  • Ken Thomson, che era dietro Unix, ha inventato UTF-8, ha lavorato al sistema Plan 9;
  • Rob Pike, che ha progettato UTF-8 con Ken, ha lavorato anche a Plan 9, Inferno, Limbo ai Bell Labs;
  • Robert Gizmer, che conosciamo e amiamo per aver inventato il Java HotSpot Compiler e per aver lavorato al generatore in V8 (l'interprete Javascript di Google);
  • E oltre 700 contributori, incluse alcune delle nostre patch.

Alexei Naidenov. ITooLabs. Caso di sviluppo su piattaforma telefonica Go (Golang). Parte 1

Vai a colpo d'occhio

Vediamo che il linguaggio è più o meno semplice e comprensibile. Abbiamo tipi ovvi: in alcuni casi devono essere dichiarati, in altri no (il che significa che i tipi vengono dedotti comunque).

Alexei Naidenov. ITooLabs. Caso di sviluppo su piattaforma telefonica Go (Golang). Parte 1

Si può vedere che è di moda descrivere le strutture. Si può vedere che abbiamo il concetto di puntatore (dove c'è l'asterisco). Si può vedere che esiste un supporto speciale per dichiarare l'inizializzazione di array e array associativi.

Approssimativamente comprensibile: puoi vivere. Sto cercando di scrivere Ciao, mondo:

Alexei Naidenov. ITooLabs. Caso di sviluppo su piattaforma telefonica Go (Golang). Parte 1

Cosa vediamo? Questa è una sintassi simile al C, il punto e virgola è facoltativo. Può essere un separatore per due righe, ma solo se si tratta di due costrutti che si trovano esattamente sulla stessa riga.

Vediamo che le parentesi nelle strutture di controllo (sulla 14a riga) sono facoltative, ma quelle ricci sono sempre obbligatorie. Vediamo che la digitazione è statica. Tim nella maggior parte dei casi viene visualizzato. Questo esempio è leggermente più complicato del solito Hello, world, solo per mostrare che esiste una libreria.

Cos'altro vediamo di importante? Il codice è organizzato in pacchetti. E per utilizzare il pacchetto nel tuo codice, devi importarlo utilizzando la direttiva import: anche questo è importante. Iniziamo: funziona. Grande!

Proviamo qualcosa di più complicato: ciao mondo, ma ora è un server http. Cosa vediamo di interessante qui?

Alexei Naidenov. ITooLabs. Caso di sviluppo su piattaforma telefonica Go (Golang). Parte 1

Innanzitutto, la funzione funge da parametro. Ciò significa che la funzione che abbiamo è un "cittadino di prima classe" e puoi fare molte cose interessanti con essa in uno stile funzionale. Vediamo l'inaspettato successivo: la direttiva import fa riferimento direttamente al repository GitHub. Esatto, è così - inoltre, è così che dovrebbe essere fatto.

In Go, l'identificatore universale di un pacchetto è l'URL del suo repository. Esiste una speciale utility Goget che controlla tutte le dipendenze, le scarica, le installa, le compila e le prepara per l'uso se necessario. Allo stesso tempo, Goget conosce html-meta. Di conseguenza, puoi mantenere una directory http, che conterrà collegamenti al tuo repository specifico (come facciamo, ad esempio, noi).

Cos'altro vediamo? Http e Json nella libreria normale. C'è, ovviamente, l'introspezione - riflessione, che dovrebbe essere usata nella codifica / json, perché semplicemente la sostituiamo con un oggetto arbitrario.

Lo eseguiamo e vediamo che abbiamo 20 righe di codice utile che compila, esegue e fornisce il carico medio corrente della macchina (sulla macchina su cui è in esecuzione).
Cos'altro è importante da quello che possiamo vedere immediatamente qui? Si compila in un binario statico (buinary). Questo binario non ha alcuna dipendenza, nessuna libreria! Può essere copiato su qualsiasi sistema, eseguito immediatamente e funzionerà.

Passando.

Vai: metodi e interfacce

Go ha metodi. Puoi dichiarare un metodo per qualsiasi tipo personalizzato. Inoltre, questa non è necessariamente una struttura, ma può essere un alias di qualche tipo. Puoi dichiarare un alias per N32 e scrivere metodi affinché faccia qualcosa di utile.

Ed è qui che cadiamo per la prima volta in uno stato di torpore ... Si scopre che Go non ha lezioni in quanto tali. Coloro che conoscono Go possono dire che esiste l'inclusione di tipo, ma questo è completamente diverso. Prima lo sviluppatore smette di considerarla un'eredità, meglio è. Non ci sono classi in Go e non c'è nemmeno ereditarietà.

Domanda! Cosa ci ha dato la compagnia di autori guidata da Google per mostrare la complessità del mondo? Ci sono state fornite interfacce!

Alexei Naidenov. ITooLabs. Caso di sviluppo su piattaforma telefonica Go (Golang). Parte 1

Un'interfaccia è un tipo speciale che consente di scrivere metodi semplici, firme di metodo. Inoltre, qualsiasi tipo per il quale questi metodi esistono (vengono eseguiti) corrisponderà a questa interfaccia. Ciò significa che puoi semplicemente scrivere la funzione corrispondente per un tipo, per un altro (che corrisponde a quel tipo di interfaccia). Successivamente, dichiara una variabile del tipo di questa interfaccia e assegnale uno qualsiasi di questi oggetti.

Per i fan più accaniti, posso dire che questa variabile conterrà effettivamente due puntatori: uno ai dati, l'altro a una speciale tabella descrittiva specifica per questo particolare tipo, all'interfaccia di questo tipo. Cioè, il compilatore crea tali tabelle di descrittori al momento del collegamento.

E ci sono, ovviamente, suggerimenti per annullare in Go. La parola interfaccia {} (con due parentesi graffe) è una variabile che in linea di principio consente di puntare a qualsiasi oggetto.
Finora tutto è in ordine, tutto è familiare. Niente di sorprendente.

Vai: goroutine

Ora arriviamo a ciò che ci interessa: processi leggeri - goroutine (goroutine) nella terminologia Go.

Alexei Naidenov. ITooLabs. Caso di sviluppo su piattaforma telefonica Go (Golang). Parte 1

  1. Innanzitutto, sono davvero leggeri (meno di 2 Kb).
  2. In secondo luogo, il costo per creare una tale goroutine è trascurabile: puoi crearne mille al secondo - non succederà nulla.
  3. Sono serviti dal proprio programmatore, che trasferisce semplicemente il controllo da una goroutine all'altra.
  4. In questo caso, il controllo viene trasferito nei seguenti casi:
    • se si incontra un'istruzione go (se la goroutine avvia la goroutine successiva);
    • se è abilitata una chiamata Input/Out bloccante;
    • se viene attivata la raccolta dei rifiuti;
    • se viene avviata qualche operazione con i canali.

Cioè, ogni volta che un programma Go viene eseguito su un computer, rileva il numero di core nel sistema, avvia tutti i thread necessari (quanti core ci sono nel sistema o quanti gli hai detto di fare). Di conseguenza, lo scheduler eseguirà questi thread leggeri di esecuzione su tutti questi thread del sistema operativo in ciascun core.

Va notato che questo è il modo più efficiente per utilizzare il ferro. Oltre a quello che abbiamo mostrato, facciamo molto di più. Realizziamo, ad esempio, sistemi DPI che consentono di servire 40 gigabit in un'unità (a seconda di ciò che accade in queste linee).

Lì, anche prima di Go, abbiamo utilizzato esattamente lo stesso schema proprio per questo motivo: poiché consente di salvare la località della cache del processore, ridurre notevolmente il numero di cambi di contesto del sistema operativo (che richiede anche molto tempo). Ripeto: questo è il modo più efficace per utilizzare il ferro.

Questo semplice esempio di 21 righe è un esempio che fa semplicemente echo-server. Allo stesso tempo, nota che la funzione di servizio è estremamente semplice, è lineare. Non ci sono richiami, non c'è bisogno di preoccuparsi e pensare... Devi solo leggere e scrivere!

Allo stesso tempo, se leggi e scrivi, dovrebbe effettivamente bloccarsi: questa goroutine viene semplicemente messa in coda e presa dallo scheduler quando l'esecuzione diventa nuovamente possibile. Cioè, questo semplice codice può fungere da server echo per tutte le connessioni consentite dal sistema operativo su questa macchina.

Continua molto presto...

Alcuni annunci 🙂

Grazie per stare con noi. Ti piacciono i nostri articoli? Vuoi vedere contenuti più interessanti? Sostienici effettuando un ordine o raccomandando agli amici, cloud VPS per sviluppatori da $ 4.99, un analogo unico dei server entry-level, che è stato inventato da noi per te: Tutta la verità su VPS (KVM) E5-2697 v3 (6 core) 10 GB DDR4 480 GB SSD 1 Gbps da $ 19 o come condividere un server? (disponibile con RAID1 e RAID10, fino a 24 core e fino a 40 GB DDR4).

Dell R730xd 2 volte più economico nel data center Equinix Tier IV ad Amsterdam? Solo qui 2 x Intel TetraDeca-Core Xeon 2x E5-2697v3 2.6GHz 14C 64GB DDR4 4x960GB SSD 1Gbps 100 TV da $199 In Olanda! Dell R420 - 2x E5-2430 2.2Ghz 6C 128GB DDR3 2x960GB SSD 1Gbps 100TB - da $99! Leggi Come costruire Infrastructure Corp. classe con l'utilizzo di server Dell R730xd E5-2650 v4 del valore di 9000 euro per un centesimo?

Fonte: habr.com

Aggiungi un commento