Alexey Naidenov. ITooLabs. Udviklingscase på Go (Golang) telefonplatform. Del 1

Alexey Naydenov, administrerende direktør ITooLabs, fortæller om udviklingen af ​​en telekommunikationsplatform til teleoperatører i programmeringssproget Go (Golang). Alexey deler også sin erfaring med at implementere og drive platformen i en af ​​de største asiatiske teleoperatører, som brugte platformen til at levere voicemail-tjenester (VoiceMail) og Virtual PBX (Cloud PBX).

Alexey Naidenov. ITooLabs. Udviklingscase på Go (Golang) telefonplatform. Del 1

Alexey Naydenov (i det følgende – AN): - Hej alle! Mit navn er Alexey Naydenov. Jeg er direktør for ITooLabs. Først og fremmest vil jeg gerne svare på, hvad jeg laver her, og hvordan jeg er havnet her.

Hvis du ser på Bitrix24 Marketplace (afsnit "Telefoni"), så er 14 applikationer og 36, der er der (40%), os:

Alexey Naidenov. ITooLabs. Udviklingscase på Go (Golang) telefonplatform. Del 1

Mere præcist er det vores operatørpartnere, men bag alt dette er vores platform (Platform as a Service) - hvad vi sælger til dem for en lille skilling. Faktisk vil jeg gerne tale om udviklingen af ​​denne platform, og hvordan vi kom til Go.

Tallene for vores platform nu:

Alexey Naidenov. ITooLabs. Udviklingscase på Go (Golang) telefonplatform. Del 1

44 operatørpartnere, herunder Megafon. Generelt kan vi rigtig godt lide at tage på forskellige eventyr, og vi har faktisk adgang til 100 millioner abonnenter af 44 operatører her i Rusland. Derfor, hvis nogen har nogle forretningsideer, vil vi altid gerne lytte til dem.

  • 5000 brugervirksomheder.
  • 20 abonnenter i alt. Det hele er b000b - vi arbejder kun med virksomheder.
  • 300 opkald i minuttet i løbet af dagen.
  • 100 millioner ringeminutter sidste år (vi fejrede). Dette tager ikke højde for interne forhandlinger, der er tilgængelige på vores platform.

Hvordan startede det?

Hvordan begynder de rigtige fyre overhovedet at lave deres platform? Vi skal også tage i betragtning, at vi har en historie med "hardcore enterprise"-udvikling, og endda på det mest præcise tidspunkt af året for en virksomhed! Det var det lykkelige tidspunkt, når du kommer til kunden og siger: "Vi har brug for et par servere mere." Og kunden: “Ingen spørgsmål! Vi har ti i stativet.”

Så vi lavede Oracle, Java, WebSphere, Db2 og alt det der. Derfor tog vi selvfølgelig de bedste leverandørløsninger, integrerede dem og forsøgte at komme i gang med det. Vi gik på egen hånd. Dette ville være sådan en intern opstart.

Alt dette startede faktisk i 2009. Siden 2006 har vi på den ene eller anden måde været tæt involveret i operatørløsninger. Vi lavede flere brugerdefinerede virtuelle PBX'er (som den, vi nu har på bestilling): vi kiggede på den, besluttede, at den var god, og besluttede at starte en intern opstart.

Alexey Naidenov. ITooLabs. Udviklingscase på Go (Golang) telefonplatform. Del 1

Vi tog VMWare. Da vi var alene, måtte vi straks opgive den seje leverandør Storage. Vi ved alt om dem: at løfter skal divideres med 3, og prisen skal ganges med 10. Derfor lavede de DirDB og så videre.

Så begyndte det at vokse. En faktureringstjeneste blev tilføjet til dette, fordi platformen ikke længere kunne klare det. Derefter flyttede faktureringsserveren fra MySQL til Mongo. Som et resultat fik vi en fungerende løsning, der behandler alle de opkald, der går dertil:

Alexey Naidenov. ITooLabs. Udviklingscase på Go (Golang) telefonplatform. Del 1

Men et eller andet sted dér, indeni, snurrer det samme leverandørprodukt - det vigtigste nukleare, som vi engang tog. Omkring slutningen af ​​2011 indså vi, at den største flaskehals for os selvfølgelig ville være netop dette produkt - vi ville løbe ind i det. Vi så en mur foran os, som vi løb ind i i fuld galop, efterhånden som flere kunder blev ved med at komme.
Derfor var vi nødt til at gøre noget. Vi foretog naturligvis en del research på forskellige produkter - både open source og leverandører. Jeg vil ikke dvæle ved dette nu - det er ikke det, vi taler om. Den allersidste reservemulighed, vi tænkte på, var at lave vores egen platform.

I sidste ende kom vi til denne mulighed. Hvorfor? Fordi alle leverandør- og open source-produkter blev lavet til at løse problemer, der var 10 år gamle. Nå, hvis 10 år gammel, og nogle flere! Valget blev indlysende for os: enten siger vi farvel til vores gode idé om en ideel service (for partnere, operatører og os selv), eller også gør vi noget af vores eget.

Vi besluttede at gøre noget af vores eget!

Krav til platforme

Hvis du har gjort noget i lang tid (ved at bruge en andens produkt), så opstår tanken langsomt i dit hoved: hvordan ville jeg selv gøre det? Da vi alle er programmører i virksomheden (bortset fra sælgere, er der ingen ikke-programmører), har vores krav udviklet sig for længe siden, og de var klare:

  1. Høj udviklingshastighed. Sælgerproduktet, der plagede os, var først og fremmest ikke tilfredsstillende, fordi alt gik langt og langsomt. Vi ville have det hurtigt - vi havde mange ideer! Vi har stadig mange ideer, men så var idélisten sådan, at det virkede som ti år i forvejen. Nu kun i et år.
  2. Maksimal udnyttelse af flerkernet jern. Det var også vigtigt for os, da vi så, at der kun ville komme flere og flere kerner.
  3. Høj pålidelighed. Noget vi også græd med.
  4. Høj modstand mod fejl.
  5. Vi ønskede at ende med en proces med daglige udgivelser. Til dette havde vi brug for et sprogvalg.

Alexey Naidenov. ITooLabs. Udviklingscase på Go (Golang) telefonplatform. Del 1

Ud fra de krav til produktet, vi har stillet til os selv, vokser kravene til sproget således på en klart logisk måde.

  1. Hvis vi ønsker support til multi-core systemer, så har vi brug for support til parallel eksekvering.
  2. Hvis vi har brug for udviklingshastighed, har vi brug for et sprog, der understøtter konkurrencedygtig udvikling, konkurrencedygtig programmering. Hvis nogen ikke har stødt på forskellen, er det meget enkelt:
    • Parallel programmering handler om, hvordan to forskellige tråde udføres på forskellige kerner;
    • Samtidig eksekvering, eller mere præcist, concurrency support, handler om, hvordan et sprog (eller runtime, det er lige meget) hjælper med at skjule al den kompleksitet, der kommer fra parallel eksekvering.
  3. Høj stabilitet. Vi havde selvfølgelig brug for en klynge, og en bedre en, end vi havde på leverandørens produkt.

Alexey Naidenov. ITooLabs. Udviklingscase på Go (Golang) telefonplatform. Del 1

Vi havde egentlig ikke så mange muligheder, hvis du husker det. For det første Erlang - vi elsker og ved det, det var min personlige, personlige favorit. For det andet er Java ikke engang Java, men specifikt Scala. For det tredje et sprog, som vi på det tidspunkt slet ikke kendte - Go. Den var lige dukket op dengang, eller rettere sagt, den havde allerede eksisteret i omkring to år, men var endnu ikke udgivet.

Gå vundet!

Historien om Go

Vi lavede en platform på det. Jeg vil prøve at forklare hvorfor.

En kort historie om Go. Det startede i 2007, åbnede i 2009, den første version blev udgivet i 2012 (det vil sige, vi begyndte at arbejde allerede før den første udgivelse). Initiativtageren var Google, som ville erstatte, som jeg formoder, Java.

Forfatterne er meget berømte:

  • Ken Thomson, der stod bag Unix, opfandt UTF-8, arbejdede på Plan 9-systemet;
  • Rob Pike, der opfandt UTF-8 med Ken, arbejdede også på Plan 9, Inferno, Limbo på Bell Labs;
  • Robert Giesmer, som vi kender og elsker for at opfinde Java HotSpot Compiler og for sit arbejde med generatoren i V8 (Googles Javascript-fortolker);
  • Og over 700 bidragydere, inklusive nogle af vores patches.

Alexey Naidenov. ITooLabs. Udviklingscase på Go (Golang) telefonplatform. Del 1

Gå: første kig

Vi ser, at sproget er mere eller mindre enkelt og forståeligt. Vi har indlysende typer: i nogle tilfælde skal de deklareres, i andre er de ikke nødvendige (det betyder, at typerne udledes på den ene eller anden måde).

Alexey Naidenov. ITooLabs. Udviklingscase på Go (Golang) telefonplatform. Del 1

Det kan ses, at det er moderne at beskrive strukturer. Det kan ses, at vi har begrebet en pointer (hvor stjernen er). Det kan ses, at der er særlig støtte til at erklære initialisering af arrays og associative arrays.

Det er næsten klart - du kan leve. Lad os prøve at skrive Hej verden:

Alexey Naidenov. ITooLabs. Udviklingscase på Go (Golang) telefonplatform. Del 1

Hvad ser vi? Dette er C-lignende syntaks, semikolon er valgfrit. Det kan være en separator for to linjer, men kun hvis det er to konstruktioner, der er på samme linje.

Vi ser, at parenteser i kontrolstrukturer (i 14. linje) er valgfrie, men krøllede klammeparenteser er altid påkrævet. Vi ser, at indtastningen er statisk. Tim er taget ud det meste af tiden. Dette eksempel er lidt mere kompliceret end den sædvanlige Hej, verden - bare for at vise, at der er et bibliotek.

Hvad ser vi ellers, der er vigtigt? Koden er organiseret i pakker. Og for at bruge en pakke i din egen kode, skal du importere den ved hjælp af importdirektivet - det er også vigtigt. Vi lancerer det - det virker. Store!

Lad os prøve noget mere kompliceret næste: Hej verden, men først nu er det en http-server. Hvad ser vi interessant her?

Alexey Naidenov. ITooLabs. Udviklingscase på Go (Golang) telefonplatform. Del 1

For det første fungerer funktionen som en parameter. Det betyder, at vores funktion er "førsteklasses borger", og du kan lave en masse spændende ting med den i en funktionel stil. Dernæst ser vi noget uventet: importdirektivet linker direkte til GitHub-lageret. Det er rigtigt, sådan er det - desuden er det sådan, det skal gøres.

I Go er den universelle identifikator for en pakke url'en til dens lager. Der er et særligt Goget-værktøj, der henter alle afhængigheder, downloader dem, installerer dem, kompilerer dem og forbereder dem til brug, hvis det er nødvendigt. Samtidig kender Goget til html-meta. Derfor kan du beholde en http-mappe, der vil indeholde links til dit specifikke depot (som vi f.eks. gør).

Hvad ser vi ellers? Http og Json i standardbiblioteket. Der er naturligvis introspektion - refleksion, som skal bruges i kodning/json, fordi vi simpelthen erstatter et eller andet vilkårligt objekt med det.

Vi kører det og ser, at vi har brugbar kode i 20 linjer, som kompilerer, kører og rapporterer den aktuelle gennemsnitlige belastning af maskinen (på den maskine, den er lanceret på).
Hvad er ellers vigtigt, som vi umiddelbart kan se her? Det er kompileret til en statisk binær (buinær). Denne binære fil har ingen afhængigheder overhovedet, ingen biblioteker! Du kan kopiere det til ethvert system, køre det med det samme, og det vil virke.

Flytning på.

Go: Metoder og grænseflader

Go har metoder. Du kan erklære en metode for enhver brugerdefineret type. Desuden er dette ikke nødvendigvis en struktur, men måske et alias af en eller anden type. Du kan erklære et alias for N32 og skrive metoder til, at det kan gøre noget nyttigt.

Og her falder vi i stupor for første gang... Det viser sig, at Go ikke har undervisning som sådan. Dem, der kender Go, vil måske sige, at der er typeinklusion, men det er noget helt andet. Jo før en udvikler holder op med at tænke på det som arv, jo bedre. Der er ingen klasser i Go, og der er heller ingen arv.

Spørgsmål! Hvad har selskabet af forfattere ledet af Google givet os for at afspejle verdens kompleksitet? De gav os grænseflader!

Alexey Naidenov. ITooLabs. Udviklingscase på Go (Golang) telefonplatform. Del 1

En grænseflade er en speciel type, der giver dig mulighed for at skrive enkle metoder, metodesignaturer. Yderligere vil enhver type, for hvilken disse metoder findes (udføres), svare til denne grænseflade. Det betyder, at du ganske enkelt kan beskrive den tilsvarende funktion for én type, for en anden (som svarer til den pågældende grænsefladetype). Dernæst skal du erklære en variabel af typen af ​​denne grænseflade og tildele nogen af ​​disse objekter til den.

For hardcore-fans kan jeg sige, at denne variabel faktisk vil have to pointer: en til dataene, den anden til en speciel tabel med deskriptorer, som er typisk for denne særlige type, for grænsefladen af ​​denne type. Det vil sige, at compileren opretter sådanne deskriptortabeller på tidspunktet for linkning.

Og i Go er der selvfølgelig pointer til at annullere. Ordet interface {} (med to krøllede klammeparenteser) er en variabel, der i princippet giver dig mulighed for at pege på ethvert objekt.
Indtil videre er alt fint, alt er velkendt. Intet overraskende.

Gå: goroutiner

Nu kommer vi til det, der interesserer os: letvægtsprocesser - goroutiner (goroutiner) i Go-terminologi.

Alexey Naidenov. ITooLabs. Udviklingscase på Go (Golang) telefonplatform. Del 1

  1. For det første er de virkelig lette (mindre end 2 KB).
  2. For det andet er omkostningerne ved at skabe sådan en goroutine ubetydelige: du kan oprette tusind af dem i sekundet - intet vil ske.
  3. De betjenes af deres egen skemalægger, som blot overfører kontrol fra en goroutine til en anden.
  4. I dette tilfælde overføres kontrollen i følgende tilfælde:
    • hvis go-udtrykket støder på (hvis goroutinen starter den næste goroutine);
    • hvis et blokerende Input/Out-opkald er aktiveret;
    • hvis affaldsindsamling starter;
    • hvis en operation med kanaler startes.

Det vil sige, at når et Go-program kører på en computer, bestemmer det antallet af kerner i systemet, starter så mange tråde som nødvendigt (hvor mange kerner er i systemet, eller hvor mange du fortalte det). Følgelig vil planlæggeren køre disse lette udførelsestråde på alle disse operativsystemtråde i hver kerne.

Det skal bemærkes, at dette er den mest effektive måde at udnytte jern på. Udover det, der vises, laver vi meget mere. Vi laver for eksempel DPI-systemer, der tillader én enhed at betjene 40 gigabit (afhængig af hvad der sker i disse linjer).

Der, selv før Go, brugte vi nøjagtig det samme skema af netop denne grund: fordi det giver os mulighed for at bevare lokaliteten af ​​processorcachen og reducere antallet af OS-kontekstskift markant (hvilket også tager meget tid). Jeg gentager: dette er den mest effektive måde at bruge jern på.

Dette simple 21 linjers eksempel er et eksempel, der simpelthen laver echo-server. Bemærk venligst, at servefunktionen er ekstremt enkel, den er lineær. Der er ingen tilbagekald, ingen grund til at genere og tænke... Du læser og skriver bare!

På samme tid, hvis du læser og skriver, burde den faktisk blokere - denne goroutine sættes simpelthen i kø og tages af planlæggeren, når udførelse igen bliver mulig. Det vil sige, at denne simple kode kan fungere som en ekkoserver for så mange forbindelser, som OS på den pågældende maskine tillader.

Fortsættes meget snart...

Nogle annoncer 🙂

Tak fordi du blev hos os. Kan du lide vores artikler? Vil du se mere interessant indhold? Støt os ved at afgive en ordre eller anbefale til venner, cloud VPS for udviklere fra $4.99, en unik analog af entry-level servere, som blev opfundet af os til dig: Hele sandheden om VPS (KVM) E5-2697 v3 (6 Cores) 10GB DDR4 480GB SSD 1Gbps fra $19 eller hvordan deler man en server? (tilgængelig med RAID1 og RAID10, op til 24 kerner og op til 40 GB DDR4).

Dell R730xd 2 gange billigere i Equinix Tier IV datacenter i Amsterdam? Kun her 2 x Intel TetraDeca-Core Xeon 2x E5-2697v3 2.6GHz 14C 64GB DDR4 4x960GB SSD 1Gbps 100 TV fra $199 i Holland! Dell R420 - 2x E5-2430 2.2Ghz 6C 128GB DDR3 2x960GB SSD 1Gbps 100TB - fra $99! Læse om Hvordan man bygger infrastruktur corp. klasse med brug af Dell R730xd E5-2650 v4-servere til en værdi af 9000 euro for en krone?

Kilde: www.habr.com

Tilføj en kommentar