Alexey Naydenov. ITooLabs. Caso de desenvolvemento na plataforma telefónica Go (Golang). Parte 1

Alexey Naydenov, CEO ITooLabs, fálase do desenvolvemento dunha plataforma de telecomunicacións para operadores de telecomunicacións na linguaxe de programación Go (Golang). Alexey tamén comparte a súa experiencia na implantación e operación da plataforma nun dos maiores operadores de telecomunicacións asiáticos, que utilizou a plataforma para ofrecer servizos de correo de voz (VoiceMail) e Virtual PBX (Cloud PBX).

Alexey Naydenov. ITooLabs. Caso de desenvolvemento na plataforma telefónica Go (Golang). Parte 1

Alexey Naydenov (en diante: AN): - Ola a todos! Chámome Alexey Naydenov. Son o director de ITooLabs. En primeiro lugar, gustaríame responder o que estou facendo aquí e como acabei aquí.

Se miras no Bitrix24 Marketplace (sección "Telefonía"), entón 14 aplicacións e 36 que hai (40%) somos nós:

Alexey Naydenov. ITooLabs. Caso de desenvolvemento na plataforma telefónica Go (Golang). Parte 1

Máis precisamente, estes son os nosos socios operadores, pero detrás de todo isto está a nosa plataforma (Platform as a Service), o que lles vendemos por un pequeno centavo. De feito, gustaríame falar do desenvolvemento desta plataforma e de como chegamos a Go.

Os números da nosa plataforma agora:

Alexey Naydenov. ITooLabs. Caso de desenvolvemento na plataforma telefónica Go (Golang). Parte 1

44 operadores socios, incluído Megafon. En xeral, gústanos moito vivir diferentes aventuras e temos acceso real a 100 millóns de subscritores de 44 operadores aquí en Rusia. Polo tanto, se alguén ten algunha idea de negocio, sempre estaremos encantados de escoitalas.

  • 5000 empresas usuarias.
  • 20 subscritores en total. Todo isto é b000b: traballamos só con empresas.
  • 300 chamadas por minuto durante o día.
  • 100 millóns de minutos de chamadas o ano pasado (celebramos). Isto non ten en conta as negociacións internas que están dispoñibles na nosa plataforma.

Como comezou?

Como comezan os mozos correctos a facer a súa plataforma? Tamén debemos ter en conta que temos un historial de desenvolvemento de "empresas hardcore", e mesmo na época máis precisa do ano para unha empresa. Era ese momento feliz cando chegas ao cliente e dis: "Necesitamos un par de servidores máis". E o cliente: “Sen dúbida! Temos dez no rack".

Entón fixemos Oracle, Java, WebSphere, Db2 e todas esas cousas. Por iso, tomamos, por suposto, as mellores solucións de provedores, integrámolas e intentamos despegar con elas. Camiñamos pola nosa conta. Esta sería unha startup interna.

Todo isto comezou realmente en 2009. Desde 2006, estamos moi implicados nas solucións de operadores, dun xeito ou doutro. Fixemos varias PBX virtuais personalizadas (como a que agora temos encomendada): mirámola, decidimos que estaba ben e decidimos comezar unha posta en marcha interna.

Alexey Naydenov. ITooLabs. Caso de desenvolvemento na plataforma telefónica Go (Golang). Parte 1

Collemos VMWare. Xa que estabamos pola nosa conta, tivemos que abandonar inmediatamente o almacenamento xenial do provedor. Sabemos todo deles: que as promesas hai que dividilas por 3, e o custo hai que multiplicarse por 10. Por iso fixeron DirDB e así por diante.

Despois comezou a medrar. A isto engadiuse un servizo de facturación porque a plataforma xa non podía facer fronte. A continuación, o servidor de facturación de MySQL trasladouse a Mongo. Como resultado, obtivemos unha solución funcional que procesa todas as chamadas que van alí:

Alexey Naydenov. ITooLabs. Caso de desenvolvemento na plataforma telefónica Go (Golang). Parte 1

Pero nalgún lugar alí, dentro, ese mesmo produto do vendedor está xirando: o principal, nuclear, que unha vez levamos. Ao redor de finais de 2011, decatámonos de que o principal pescozo de botella para nós, por suposto, sería este produto en particular: atopariamos con el. Vimos un muro diante de nós, no que corríamos a todo galope, mentres seguían chegando máis clientes.
En consecuencia, tiñamos que facer algo. Por suposto, realizamos moitas investigacións sobre varios produtos, tanto de código aberto como de provedores. Non vou determe agora, non é do que estamos a falar. A última opción alternativa na que pensamos foi facer a nosa propia plataforma.

En definitiva, chegamos a esta opción. Por que? Porque todos os produtos de provedores e de código aberto foron feitos para resolver problemas que tiñan 10 anos. Pois se ten 10 anos, e algún máis! A elección fíxose obvia para nós: ou despedimos a nosa gran idea dun servizo ideal (para socios, operadores e nós mesmos), ou facemos algo propio.

Decidimos facer algo propio!

Requisitos da plataforma

Se levas moito tempo facendo algo (usando o produto doutra persoa), entón o pensamento fórmase lentamente na túa cabeza: como o faría eu? Dado que todos somos programadores da empresa (agás os vendedores, non hai ningún programador), os nosos requisitos desenvolvéronse hai moito tempo e foron claros:

  1. Alta velocidade de desenvolvemento. O produto vendedor que nos atormentaba non foi satisfactorio, en primeiro lugar, porque todo saíu longo e lentamente. Queríamos axiña: tiñamos moitas ideas! Aínda nos quedan moitas ideas, pero daquela a lista de ideas era tal que semellaba con dez anos de antelación. Agora só hai un ano.
  2. Máxima utilización do ferro multinúcleo. Isto tamén foi importante para nós, xa que vimos que só habería cada vez máis núcleos.
  3. Alta fiabilidade. Algo co que tamén choramos.
  4. Alta resistencia a fallos.
  5. Queriamos rematar cun proceso de lanzamentos diarios. Para iso necesitabamos unha elección lingüística.

Alexey Naydenov. ITooLabs. Caso de desenvolvemento na plataforma telefónica Go (Golang). Parte 1

En consecuencia, a partir dos requisitos para o produto que nos marcamos, os requisitos para o idioma medran dun xeito claramente lóxico.

  1. Se queremos soporte para sistemas multinúcleo, necesitamos soporte para a execución paralela.
  2. Se necesitamos velocidade de desenvolvemento, necesitamos unha linguaxe que admita o desenvolvemento competitivo, a programación competitiva. Se alguén non atopou a diferenza, é moi sinxelo:
    • A programación paralela trata de como se executan dous fíos diferentes en núcleos diferentes;
    • A execución simultánea, ou máis precisamente, a compatibilidade de concorrencia, trata de como unha linguaxe (ou tempo de execución, non importa) axuda a ocultar toda a complexidade que se deriva da execución paralela.
  3. Alta estabilidade. Obviamente, necesitabamos un clúster e un mellor que o que tiñamos no produto do vendedor.

Alexey Naydenov. ITooLabs. Caso de desenvolvemento na plataforma telefónica Go (Golang). Parte 1

Realmente non tiñamos tantas opcións, se lembras. En primeiro lugar, Erlang, adoro e sábeno, era o meu favorito persoal. En segundo lugar, Java nin sequera é Java, senón específicamente Scala. En terceiro lugar, unha lingua que daquela non coñeciamos nada -Go. Acababa de aparecer entón, ou mellor dito, xa levaba uns dous anos, pero aínda non se estreara.

Vaia gañado!

Historia de Go

Fixemos unha plataforma nela. Intentarei explicar por que.

Breve historia de Go. Comezou en 2007, abriuse en 2009, a primeira versión foi lanzada en 2012 (é dicir, comezamos a traballar mesmo antes da primeira versión). O iniciador foi Google, que quería substituír, como sospeito, Java.

Os autores son moi famosos:

  • Ken Thomson, que estaba detrás de Unix, inventou UTF-8, traballou no sistema Plan 9;
  • Rob Pike, que inventou UTF-8 con Ken, tamén traballou en Plan 9, Inferno, Limbo en Bell Labs;
  • Robert Giesmer, a quen coñecemos e amamos por inventar o compilador Java HotSpot e polo seu traballo no xerador en V8 (o intérprete Javascript de Google);
  • E máis de 700 colaboradores, incluíndo algúns dos nosos parches.

Alexey Naydenov. ITooLabs. Caso de desenvolvemento na plataforma telefónica Go (Golang). Parte 1

Vaia: primeiro ollo

Vemos que a linguaxe é máis ou menos sinxela e comprensible. Temos tipos obvios: nalgúns casos hai que declaralos, noutros non son necesarios (isto quere dicir que os tipos se infiren dun xeito ou doutro).

Alexey Naydenov. ITooLabs. Caso de desenvolvemento na plataforma telefónica Go (Golang). Parte 1

Pódese ver que está de moda describir estruturas. Pódese ver que temos o concepto de punteiro (onde está o asterisco). Pódese ver que hai soporte especial para declarar a inicialización de matrices e matrices asociativas.

Está case claro: podes vivir. Imos tentar escribir Ola, mundo:

Alexey Naydenov. ITooLabs. Caso de desenvolvemento na plataforma telefónica Go (Golang). Parte 1

Que vemos? Esta é unha sintaxe tipo C, o punto e coma é opcional. Pode ser un separador de dúas liñas, pero só se se trata de dúas construcións que están na mesma liña.

Vemos que os corchetes nas estruturas de control (na liña 14) son opcionais, pero sempre se requiren chaves. Vemos que a escritura é estática. Tim é sacado a maior parte do tempo. Este exemplo é un pouco máis complicado que o habitual Ola, mundo, só para mostrar que hai unha biblioteca.

Que máis vemos que é importante? O código está organizado en paquetes. E para usar un paquete no seu propio código, cómpre importalo mediante a directiva de importación, isto tamén é importante. Lanzámolo - funciona. Genial!

Probemos algo máis complicado a continuación: Ola, mundo, pero só agora é un servidor http. Que vemos de interesante aquí?

Alexey Naydenov. ITooLabs. Caso de desenvolvemento na plataforma telefónica Go (Golang). Parte 1

En primeiro lugar, a función actúa como un parámetro. Isto significa que a nosa función é "cidadán de primeira clase" e podes facer moitas cousas interesantes con ela nun estilo funcional. A continuación vemos algo inesperado: a directiva de importación enlaza directamente co repositorio de GitHub. Así é, así é, ademais, así se debe facer.

En Go, o identificador universal dun paquete é o URL do seu repositorio. Hai unha utilidade especial de Goget que buscará todas as dependencias, descargalas, instalalas, compilalas e preparalas para usalas se é necesario. Ao mesmo tempo, Goget sabe sobre html-meta. En consecuencia, pode manter un directorio http que conterá ligazóns ao seu repositorio específico (como facemos nós, por exemplo).

Que máis vemos? Http e Json na biblioteca estándar. Hai, obviamente, introspección - reflexión, que debería usarse en codificación/json, porque simplemente substituímos algún obxecto arbitrario por el.

Executámolo e vemos que temos código útil en 20 liñas, que compila, executa e informa da carga media actual da máquina (na máquina na que se lanza).
Que máis é importante que poidamos ver de inmediato aquí? Compílase nun binario estático (buinario). Este binario non ten dependencias, nin bibliotecas! Podes copialo en calquera sistema, executalo inmediatamente e funcionará.

Seguindo adiante.

Ir: Métodos e interfaces

Go ten métodos. Podes declarar un método para calquera tipo personalizado. Ademais, esta non é necesariamente unha estrutura, senón quizais un alias dalgún tipo. Podes declarar un alias para N32 e escribir métodos para que faga algo útil.

E aquí caemos nun estupor por primeira vez... Resulta que Go non ten clases como tal. Os que coñecen Go poderían dicir que hai inclusión de tipos, pero iso é outra cousa. Canto antes un desenvolvedor deixe de pensar nel como herdanza, mellor. Non hai clases en Go, e tampouco hai herdanza.

Pregunta! Que nos deu a compañía de autores liderada por Google para reflectir a complexidade do mundo? Déronnos interfaces!

Alexey Naydenov. ITooLabs. Caso de desenvolvemento na plataforma telefónica Go (Golang). Parte 1

Unha interface é un tipo especial que che permite escribir métodos simplemente, sinaturas de métodos. Ademais, calquera tipo para o que estes métodos existan (se executen) corresponderá a esta interface. Isto significa que pode simplemente describir a función correspondente para un tipo, para outro (que corresponde a ese tipo de interface). A continuación, declare unha variable do tipo desta interface e asígnelle calquera destes obxectos.

Para os fans incondicionais, podo dicir que esta variable en realidade terá dous indicadores: un para os datos, o outro para unha táboa especial de descritores, que é típico para este tipo en particular, para a interface deste tipo. É dicir, o compilador crea tales táboas de descritores no momento da ligazón.

E en Go, por suposto, hai indicadores para o baleiro. A palabra interface {} (con dúas chaves) é unha variable que en principio permite sinalar calquera obxecto.
Ata agora todo está ben, todo é familiar. Nada sorprendente.

Vaia: goroutines

Agora chegamos ao que nos interesa: procesos lixeiros - goroutines (goroutines) na terminoloxía Go.

Alexey Naydenov. ITooLabs. Caso de desenvolvemento na plataforma telefónica Go (Golang). Parte 1

  1. En primeiro lugar, son realmente lixeiros (menos de 2 KB).
  2. En segundo lugar, os custos de crear unha goroutina deste tipo son insignificantes: podes crear mil deles por segundo, non pasará nada.
  3. Son atendidos polo seu propio programador, que simplemente transfire o control dunha goroutine a outra.
  4. Neste caso, o control transfírese nos seguintes casos:
    • se se atopa a expresión go (se a goroutine comeza a seguinte goroutine);
    • se está activada unha chamada de entrada/saída de bloqueo;
    • se comeza a recollida de lixo;
    • se se inicia algunha operación con canles.

É dicir, sempre que un programa Go se executa nun ordenador, determina o número de núcleos do sistema, lanza tantos fíos como sexa necesario (cantos núcleos hai no sistema ou cantos lle dixeches). En consecuencia, o programador executará estes fíos de execución lixeiros en todos estes fíos do sistema operativo en cada núcleo.

Nótese que esta é a forma máis eficaz de utilizar o ferro. Ademais do que se mostra, facemos moito máis. Facemos, por exemplo, sistemas DPI que permiten que unha unidade sirva 40 gigabits (dependendo do que suceda nestas liñas).

Alí, mesmo antes de Go, usamos exactamente o mesmo esquema precisamente por este motivo: porque nos permite preservar a localización da caché do procesador e reducir significativamente o número de cambios de contexto do SO (o que tamén leva moito tempo). Repito: esta é a forma máis eficaz de utilizar o ferro.

Este sinxelo exemplo de 21 liñas é un exemplo que simplemente fai echo-server. Teña en conta que a función servir é moi sinxela, é lineal. Non hai devolucións de chamada, non hai que preocuparse e pensar... Só ler e escribir!

Ao mesmo tempo, se le e escribe, en realidade debería bloquearse: esta goroutine simplemente ponse nunha cola e toma o programador cando a execución sexa posible de novo. É dicir, este código sinxelo pode actuar como servidor de eco para tantas conexións como o permita o sistema operativo desa máquina.

Para continuar moi pronto...

Algúns anuncios 🙂

Grazas por estar connosco. Gústanche os nosos artigos? Queres ver máis contido interesante? Apóyanos facendo un pedido ou recomendando a amigos, Cloud VPS para desenvolvedores desde 4.99 $, un análogo único de servidores de nivel de entrada, que inventamos nós para ti: Toda a verdade sobre VPS (KVM) E5-2697 v3 (6 núcleos) 10 GB DDR4 480 GB SSD 1 Gbps desde 19 dólares ou como compartir un servidor? (dispoñible con RAID1 e RAID10, ata 24 núcleos e ata 40 GB DDR4).

Dell R730xd 2 veces máis barato no centro de datos Equinix Tier IV en Amsterdam? Só aquí 2 x Intel TetraDeca-Core Xeon 2x E5-2697v3 2.6GHz 14C 64GB DDR4 4x960GB SSD 1Gbps 100 TV desde $199 nos Países Baixos! Dell R420 - 2x E5-2430 2.2Ghz 6C 128GB DDR3 2x960GB SSD 1Gbps 100TB - desde $ 99! Ler sobre Como construír a infraestrutura corp. clase co uso de servidores Dell R730xd E5-2650 v4 por valor de 9000 euros por un centavo?

Fonte: www.habr.com

Engadir un comentario