Alexei Naidenov. ITooLabs. Case de desenvolvimento na plataforma telefônica Go (Golang). Parte 1

Alexey Naidenov, CEO ITooLabs, fala sobre o desenvolvimento de uma plataforma de telecomunicações para operadoras de telecomunicações na linguagem de programação Go (Golang). Alexey também compartilha sua experiência de implantação e operação da plataforma em uma das maiores operadoras de telecomunicações asiáticas, que utilizou a plataforma para fornecer serviços de correio de voz (VoiceMail) e PBX virtual (Cloud PBX).

Alexei Naidenov. ITooLabs. Case de desenvolvimento na plataforma telefônica Go (Golang). Parte 1

Alexey Naydenov (doravante - AN): - Olá a todos! Meu nome é Alexei Naidenov. Eu sou o diretor do ITooLabs. Em primeiro lugar, gostaria de responder o que estou fazendo aqui e como cheguei aqui.

Se você olhar o Bitrix24 Marketplace (seção "Telefonia"), então 14 aplicativos e 36 que estão lá (40%) são nós:

Alexei Naidenov. ITooLabs. Case de desenvolvimento na plataforma telefônica Go (Golang). Parte 1

Mais precisamente, estes são os nossos operadores parceiros, mas por trás de tudo isto está a nossa plataforma (Platform as a Service) - o que lhes vendemos por um pequeno cêntimo. Na verdade, gostaria de falar sobre o desenvolvimento desta plataforma e como chegamos ao Go.

Os números da nossa plataforma agora são:

Alexei Naidenov. ITooLabs. Case de desenvolvimento na plataforma telefônica Go (Golang). Parte 1

44 operadoras parceiras, incluindo MegaFon. De modo geral, adoramos aventuras e, na verdade, temos acesso a 100 milhões de assinantes de 44 operadoras aqui na Rússia. Portanto, se alguém tiver alguma ideia de negócio, ficaremos sempre felizes em ouvi-la.

  • 5000 empresas usuárias.
  • 20 assinantes no total. É tudo b000b – trabalhamos apenas com empresas.
  • 300 chamadas por minuto durante o dia.
  • 100 milhões de minutos de chamadas no ano passado (comemoramos). Isto sem levar em conta as negociações internas que estão na nossa plataforma.

Como isso começou?

Como os caras certos começam a criar sua própria plataforma? Devemos também levar em conta que tivemos um histórico de desenvolvimento de “empresas radicais”, e até mesmo na época do ano mais precisa para uma empresa! Foi aquele momento feliz em que você chega ao cliente e diz: “Precisamos de mais alguns servidores”. E o cliente: “Sim, sem dúvida! Temos um dez na prateleira.

Então fizemos Oracle, Java, WebSphere, Db2 e tudo mais. Portanto, pegamos, é claro, as melhores soluções dos fornecedores, integramos e tentamos decolar com elas. Eles jogaram sozinhos. Seria uma startup tão interna.

Tudo começou em 2009. Desde 2006, estamos intimamente envolvidos nas decisões dos operadores, de uma forma ou de outra. Fizemos vários PABXs virtuais customizados (como o que temos agora encomendados): olhamos, decidimos que era bom e decidimos iniciar uma startup interna.

Alexei Naidenov. ITooLabs. Case de desenvolvimento na plataforma telefônica Go (Golang). Parte 1

Veja o VMWare. Como estávamos caminhando por conta própria, tivemos que abandonar imediatamente o fornecedor legal Storage. Sabemos tudo sobre eles: que as promessas deveriam ser divididas por 3, e o custo deveria ser multiplicado por 10. Portanto, fizemos o DirDB e assim por diante.

Então começou a crescer. A isso foi adicionado o serviço de cobrança, pois a plataforma não dava mais conta. Em seguida, o servidor de cobrança do MySQL mudou para o Mongo. Como resultado, obtivemos uma solução funcional que processa todas as chamadas que vão para lá:

Alexei Naidenov. ITooLabs. Case de desenvolvimento na plataforma telefônica Go (Golang). Parte 1

Mas em algum lugar lá dentro, o mesmo produto do fornecedor está girando - o principal, nuclear, que uma vez pegamos. Aproximadamente no final de 2011, percebemos por nós mesmos que o principal gargalo para nós, é claro, será esse produto específico - vamos nos deparar com ele. Vimos um muro à nossa frente, para o qual corremos a todo galope, enquanto os clientes caminhavam, foram acrescentados.
Conseqüentemente, tínhamos que fazer alguma coisa. É claro que pesquisamos bastante sobre vários produtos - tanto de código aberto quanto de fornecedores. Não vou insistir nisso agora – esse não é o ponto. A última alternativa em que pensamos foi criar nossa própria plataforma.

No final das contas, chegamos a essa opção. Por que? Porque todos os produtos de fornecedores e de código aberto foram feitos para resolver problemas há 10 anos. Bem, se for uma criança de 10 anos e um pouco mais! A escolha tornou-se óbvia para nós: ou dizemos adeus à nossa grande ideia de um serviço ideal (para parceiros, operadores e para nós próprios), ou fazemos algo nosso.

Decidimos fazer algo diferente!

Requisitos da plataforma

Se você faz algo por muito tempo (você explora o produto de outra pessoa), então o pensamento se forma lentamente em sua cabeça: como eu faria isso sozinho? Como somos todos programadores na empresa (exceto vendedores, não há não programadores), nossos requisitos estão formados há muito tempo e eram claros:

  1. Alta velocidade de desenvolvimento. O produto do vendedor, que nos atormentava, não nos agradou em primeiro lugar porque tudo deu certo por muito tempo e devagar. Queríamos rápido – tínhamos muitas ideias! Ainda temos muitas ideias, mas a lista de ideias era tal que parecia que faltavam dez anos. Agora apenas por um ano.
  2. Utilização máxima de ferro multinúcleo. Isso também foi importante para nós, porque vimos que haveria cada vez mais núcleos.
  3. Alta fiabilidade. Aquele que choramos também.
  4. Alta tolerância a falhas.
  5. Queríamos terminar com um processo de lançamento diário. Para fazer isso, precisávamos de uma escolha de idioma.

Alexei Naidenov. ITooLabs. Case de desenvolvimento na plataforma telefônica Go (Golang). Parte 1

Assim, a partir dos requisitos para o produto que apresentamos para nós mesmos, os requisitos para a linguagem crescem de forma claramente lógica.

  1. Se quisermos suporte para sistemas multi-core, precisaremos de suporte para execução paralela.
  2. Se precisamos de velocidade de desenvolvimento, precisamos de uma linguagem que apoie o desenvolvimento competitivo, a programação competitiva. Se alguém ainda não encontrou a diferença, é muito simples:
    • a programação paralela trata de como dois threads diferentes são executados em núcleos diferentes;
    • a execução simultânea, mais especificamente o suporte à simultaneidade, trata de como a linguagem (ou tempo de execução, qualquer que seja) ajuda a esconder toda a complexidade que vem da execução paralela.
  3. Alta estabilidade. Obviamente, precisávamos de um cluster e era melhor do que o que tínhamos no produto do fornecedor.

Alexei Naidenov. ITooLabs. Case de desenvolvimento na plataforma telefônica Go (Golang). Parte 1

Na verdade, não tínhamos muitas opções, se você se lembra. Em primeiro lugar, Erlang - nós adoramos e sabemos disso, era o meu favorito pessoal. Em segundo lugar, Java nem é Java, mas especificamente Scala. Em terceiro lugar, a língua que naquela época não conhecíamos nada - Go. Tinha acabado de aparecer, mais precisamente, já existia há cerca de dois anos, mas ainda não havia sido lançado.

Derrotado, vá!

História de Go

Fizemos uma plataforma sobre isso. Vou tentar explicar o porquê.

Uma breve história do Go. Iniciado em 2007, inaugurado em 2009, a primeira versão foi lançada em 2012 (ou seja, começamos a trabalhar antes mesmo do primeiro lançamento). O iniciador foi o Google, que queria substituir, como suspeito, o Java.

Os autores são muito famosos:

  • Ken Thomson, que estava por trás do Unix, inventou o UTF-8, trabalhou no sistema Plan 9;
  • Rob Pike, que projetou UTF-8 com Ken, também trabalhou em Plan 9, Inferno, Limbo no Bell Labs;
  • Robert Gizmer, que conhecemos e amamos por ter inventado o Java HotSpot Compiler e por trabalhar no gerador em V8 (o interpretador Javascript do Google);
  • E mais de 700 colaboradores, incluindo alguns de nossos patches.

Alexei Naidenov. ITooLabs. Case de desenvolvimento na plataforma telefônica Go (Golang). Parte 1

Vá de relance

Vemos que a linguagem é mais ou menos simples e compreensível. Temos tipos óbvios: em alguns casos eles precisam ser declarados, em outros não (o que significa que os tipos são inferidos de qualquer maneira).

Alexei Naidenov. ITooLabs. Case de desenvolvimento na plataforma telefônica Go (Golang). Parte 1

Percebe-se que está na moda descrever estruturas. Percebe-se que temos o conceito de ponteiro (onde está o asterisco). Pode-se observar que existe um suporte especial para declarar a inicialização de arrays e arrays associativos.

Quase compreensível - você pode viver. Tentando escrever Olá, mundo:

Alexei Naidenov. ITooLabs. Case de desenvolvimento na plataforma telefônica Go (Golang). Parte 1

O que vemos? Esta é uma sintaxe semelhante à C, o ponto e vírgula é opcional. Pode ser um separador para duas linhas, mas somente se forem duas construções que estejam exatamente na mesma linha.

Vemos que os colchetes nas estruturas de controle (na 14ª linha) são opcionais, mas os colchetes são sempre obrigatórios. Vemos que a digitação é estática. Tim na maioria dos casos é exibido. Este exemplo é um pouco mais complicado do que o habitual Olá, mundo - apenas para mostrar que existe uma biblioteca.

O que mais vemos de importante? O código é organizado em pacotes. E para usar o pacote em seu próprio código, você precisa importá-lo usando a diretiva import - isso também é importante. Começamos - funciona. Ótimo!

Vamos tentar algo mais complicado: Olá, mundo, mas agora é um servidor http. O que vemos de interessante aqui?

Alexei Naidenov. ITooLabs. Case de desenvolvimento na plataforma telefônica Go (Golang). Parte 1

Primeiro, a função atua como parâmetro. Isso significa que a função que temos é um “cidadão de primeira classe” e você pode fazer muitas coisas interessantes com ela em um estilo funcional. Vemos o inesperado a seguir: a diretiva import refere-se diretamente ao repositório GitHub. É isso mesmo, é assim - aliás, é assim que deve ser feito.

No Go, o identificador universal de um pacote é a URL do seu repositório. Existe um utilitário Goget especial que acessa todas as dependências, baixa-as, instala-as, compila-as e prepara-as para uso, se necessário. Ao mesmo tempo, Goget conhece o html-meta. Assim, você pode manter um diretório http, que conterá links para seu repositório específico (como nós, por exemplo, fazemos).

O que mais vemos? Http e Json na biblioteca regular. Existe, obviamente, introspecção - reflexão, que deve ser usada na codificação / json, porque simplesmente substituímos algum objeto arbitrário por ela.

Nós o executamos e vemos que temos 20 linhas de código útil que compila, executa e fornece a carga média atual da máquina (na máquina em que está sendo executado).
O que mais é importante do que podemos ver imediatamente aqui? Ele é compilado em um binário estático (buinary). Este binário não tem dependências, nem bibliotecas! Ele pode ser copiado para qualquer sistema, executado imediatamente e funcionará.

Seguindo em frente.

Go: métodos e interfaces

Go tem métodos. Você pode declarar um método para qualquer tipo personalizado. Além disso, esta não é necessariamente uma estrutura, mas pode ser algum tipo de alias. Você pode declarar um alias para N32 e escrever métodos para que ele faça algo útil.

E é aqui que caímos no estupor pela primeira vez... Acontece que Go não tem aulas propriamente ditas. Quem conhece Go pode dizer que existe inclusão de tipo, mas isso é completamente diferente. Quanto mais cedo o desenvolvedor parar de pensar nisso como herança, melhor. Não há classes em Go e também não há herança.

Pergunta! O que a companhia de autores liderada pelo Google nos deu para mostrar a complexidade do mundo? Recebemos interfaces!

Alexei Naidenov. ITooLabs. Case de desenvolvimento na plataforma telefônica Go (Golang). Parte 1

Uma interface é um tipo especial que permite escrever métodos simples, assinaturas de métodos. Além disso, qualquer tipo para o qual esses métodos existam (são executados) corresponderá a esta interface. Isso significa que você pode simplesmente escrever a função correspondente para um tipo, para outro (que corresponde a esse tipo de interface). A seguir, declare uma variável do tipo desta interface e atribua a ela qualquer um desses objetos.

Para os fãs mais dedicados, posso dizer que esta variável conterá na verdade dois ponteiros: um para dados, o outro para uma tabela de descritores especial específica para este tipo específico, para a interface deste tipo. Ou seja, o compilador faz tais tabelas de descritores no momento da vinculação.

E há, é claro, dicas para anular no Go. A palavra interface {} (com duas chaves) é uma variável que permite apontar para qualquer objeto em princípio.
Até agora está tudo em ordem, tudo é familiar. Nada de surpreendente.

Ir: goroutines

Agora chegamos ao que nos interessa: processos leves - goroutines (goroutines) na terminologia Go.

Alexei Naidenov. ITooLabs. Case de desenvolvimento na plataforma telefônica Go (Golang). Parte 1

  1. Primeiro, eles são muito leves (menos de 2 Kb).
  2. Em segundo lugar, o custo de criação de tal goroutine é insignificante: você pode criar mil delas por segundo - nada acontecerá.
  3. Eles são atendidos por seu próprio escalonador, que simplesmente transfere o controle de uma goroutine para outra.
  4. Neste caso, o controle é transferido nos seguintes casos:
    • se uma instrução go for encontrada (se a goroutine iniciar a próxima goroutine);
    • se uma chamada de entrada/saída de bloqueio estiver habilitada;
    • se a coleta de lixo for acionada;
    • se alguma operação com canais for iniciada.

Ou seja, sempre que um programa Go é executado em um computador, ele detecta o número de núcleos no sistema, inicia quantos threads forem necessários (quantos núcleos existem no sistema ou quantos você instruiu). Conseqüentemente, o agendador executará esses threads leves de execução em todos esses threads do sistema operacional em cada núcleo.

Deve-se notar que esta é a forma mais eficiente de utilizar o ferro. Além do que mostramos, fazemos muito mais. Fazemos, por exemplo, sistemas DPI que permitem atender 40 gigabits em uma unidade (dependendo do que acontecer nessas linhas).

Lá, antes mesmo do Go, usávamos exatamente o mesmo esquema por esse motivo: porque permite salvar a localidade do cache do processador, reduzir significativamente o número de trocas de contexto do SO (o que também leva muito tempo). Repito: esta é a forma mais eficaz de utilizar o ferro.

Este exemplo simples de 21 linhas é um exemplo que simplesmente faz o echo-server. Ao mesmo tempo, observe que a função de saque é extremamente simples, é linear. Não há retornos de chamada, não há necessidade de se preocupar e pensar... Basta ler e escrever!

Ao mesmo tempo, se você ler e escrever, ele deverá bloquear - essa goroutine é simplesmente colocada na fila e tomada pelo agendador quando a execução se tornar possível novamente. Ou seja, esse código simples pode atuar como um servidor de eco para quantas conexões o sistema operacional desta máquina permitir.

Continuará muito em breve...

Alguns anúncios 🙂

Obrigado por ficar com a gente. Gostou dos nossos artigos? Quer ver mais conteúdos interessantes? Apoie-nos fazendo um pedido ou recomendando a amigos, nuvem VPS para desenvolvedores a partir de US$ 4.99, um análogo exclusivo de servidores básicos, que foi inventado por nós para você: Toda a verdade sobre VPS (KVM) E5-2697 v3 (6 núcleos) 10 GB DDR4 480 GB SSD 1 Gbps a partir de $ 19 ou como compartilhar um servidor? (disponível com RAID1 e RAID10, até 24 núcleos e até 40 GB DDR4).

Dell R730xd 2x mais barato no data center Equinix Tier IV em Amsterdã? Só aqui 2 x Intel TetraDeca-Core Xeon 2x E5-2697v3 2.6GHz 14C 64GB DDR4 4x960GB SSD 1Gbps 100 TV a partir de US$ 199 na Holanda! Dell R420 - 2x E5-2430 2.2Ghz 6C 128GB DDR3 2x960GB SSD 1Gbps 100TB - a partir de US$ 99! Ler sobre Como construir uma empresa de infraestrutura. classe com o uso de servidores Dell R730xd E5-2650 v4 no valor de 9000 euros por um centavo?

Fonte: habr.com

Adicionar um comentário