Sobre o cluster do servidor 1C

Um cluster é um tipo de
sistema paralelo ou distribuído que:
1. consiste em vários
computadores interconectados ;
2. Usado como
recurso único e unificado de computador

Gregory F. Pfister, “Em busca de clusters”.


Dado: existe um aplicativo comercial (por exemplo, um sistema ERP) com o qual milhares (possivelmente dezenas de milhares) de usuários trabalham simultaneamente.

É necessário:
  1. Torne o aplicativo escalável, para que, com um aumento no número de usuários, seja possível devido ao aumento dos recursos de hardware para fornecer o desempenho necessário do aplicativo.
  2. Torne o aplicativo resistente a falhas de componentes do sistema (software e hardware), perda de conexão entre componentes e outros possíveis problemas.
  3. Use os recursos do sistema da maneira mais eficiente possível e forneça o desempenho desejado do aplicativo.
  4. Facilite a implantação e administração do sistema.

Para resolver esses problemas, usamos a arquitetura de cluster na plataforma 1C: Enterprise.

Não alcançamos imediatamente o resultado desejado.

Neste artigo, falaremos sobre que tipo de clusters são, como escolhemos o tipo de cluster que mais nos convém e como nosso cluster evoluiu de versão para versão, e quais abordagens nos permitiram criar um sistema que serve dezenas de milhares de usuários simultâneos.

imagem

Como Gregory Pfister, autor da epígrafe deste artigo, escreveu em seu livro "Em busca de clusters", o cluster não foi inventado por nenhum fabricante específico de hardware ou software, mas por clientes que não tinham o poder de um computador ou precisavam de redundância. Isso aconteceu, segundo Pfister, nos anos 60 do século passado.
Tradicionalmente, distingue os seguintes tipos principais de clusters:

  1. Clusters de failover (HA, clusters de alta disponibilidade)
  2. Clusters de balanceamento de carga (LBC)
  3. Clusters de computação (Clusters de computação de alto desempenho, HPC)
  4. (grid) , . grid- , . grid- HPC-, .

Para resolver nossos problemas (resistência à falha dos componentes do sistema e uso eficiente dos recursos), precisávamos combinar a funcionalidade de um cluster à prova de falhas e um cluster com balanceamento de carga. Não chegamos a essa decisão imediatamente, mas a abordamos evolutivamente, passo a passo.

Para aqueles que não estão atualizados, mostrarei brevemente como os aplicativos de negócios 1C são organizados. São aplicativos escritos em uma linguagem orientada ao assunto , "aprimorada" para a automação de tarefas de negócios contábeis. Para executar aplicativos escritos nesse idioma, um tempo de execução da plataforma 1C: Enterprise deve estar instalado no computador.

1C: Enterprise 8.0


A primeira versão do servidor de aplicativos 1C (ainda não um cluster) apareceu na plataforma versão 8.0. Antes disso, 1C trabalhava na versão cliente-servidor, os dados eram armazenados em um arquivo DBMS ou MS SQL e a lógica de negócios trabalhava exclusivamente no cliente. Na versão 8.0, foi feita uma transição para a arquitetura de três camadas "cliente - servidor de aplicativos - DBMS".

O servidor 1C na plataforma 8.0 era COM +um servidor que pode executar o código do aplicativo em 1C. O uso do COM + nos forneceu transporte pronto, permitindo que os aplicativos clientes se comuniquem com o servidor pela rede. Muitas coisas na arquitetura da interação cliente-servidor e os objetos de aplicativo disponíveis para o desenvolvedor do 1C foram projetados levando em consideração o uso do COM +. Naquele momento, a tolerância a falhas não era incorporada à arquitetura e uma falha no servidor fazia com que todos os clientes fossem desligados. Quando o aplicativo do servidor travou, o COM + o levantou quando o primeiro cliente o acessou, e os clientes começaram seu trabalho desde o início - a partir da conexão com o servidor. Naquele momento, todos os clientes eram atendidos por um processo.
imagem

1C: Empresa 8.1


Na próxima versão, queríamos:

  • Fornecer tolerância a falhas para nossos clientes, para que acidentes e erros de alguns usuários não levem a acidentes e erros de outros usuários.
  • Livre-se da tecnologia COM +. O COM + funcionava apenas no Windows e, naquele momento, a possibilidade de trabalhar no Linux já estava se tornando relevante.

Ao mesmo tempo, não queríamos desenvolver uma nova versão da plataforma do zero - ela consumiria muitos recursos. Queríamos aproveitar ao máximo nossas conquistas, bem como manter a compatibilidade com aplicativos desenvolvidos para a versão 8.0.

Portanto, na versão 8.1, o primeiro cluster apareceu. Implementamos nosso protocolo para chamada de procedimento remoto (acima do TCP), que parecia quase COM + para o consumidor final (ou seja, praticamente não precisamos reescrever o código responsável pelas chamadas cliente-servidor). Ao mesmo tempo, tornamos o servidor implementado na plataforma C ++ independente, capaz de trabalhar no Windows e no Linux.

O servidor monolítico versão 8.0 foi substituído por 3 tipos de processos - um processo de trabalho que atende clientes e 2 processos de serviço que suportam a operação do cluster:

  • O rphost é um fluxo de trabalho que atende clientes e executa o código do aplicativo. Um cluster pode ter mais de um fluxo de trabalho, diferentes fluxos de trabalho podem ser executados em diferentes servidores físicos - devido a essa escalabilidade ser alcançada.
  • ragent - um processo de agente do servidor que inicia todos os outros tipos de processos, bem como uma lista principal de clusters localizados neste servidor.
  • O rmngr é um gerenciador de cluster que controla a operação de todo o cluster (mas o código do aplicativo não funciona nele).

Sob o corte, está o diagrama de operação desses três processos no cluster.
image

Durante a sessão, o cliente trabalhou com um fluxo de trabalho, a queda no fluxo de trabalho significou para todos os clientes aos quais esse processo atendeu, a sessão foi encerrada de forma anormal. Os demais clientes continuaram trabalhando.
imagem

1C: Empresa 8.2


Na versão 8.2, queríamos que os aplicativos 1C pudessem ser executados não apenas no cliente nativo (executável), mas também no navegador (sem modificar o código do aplicativo). Nesse sentido, em particular, surgiu a tarefa de dissociar o estado atual do aplicativo da conexão atual com o fluxo de trabalho do rphost e torná-lo sem estado. Como resultado, surgiu o conceito de uma sessão e os dados da sessão que precisavam ser armazenados fora do fluxo de trabalho (porque eram sem estado). Foi desenvolvido um serviço de dados da sessão que armazena e armazena em cache as informações da sessão. Outros serviços também apareceram - um serviço de bloqueios transacionais gerenciados, um serviço de pesquisa de texto completo etc.

Essa versão também apresentou várias inovações importantes - tolerância a falhas aprimorada, balanceamento de carga e um mecanismo de redundância de cluster.

tolerância ao erro


Como o processo de trabalho ficou sem estado e todos os dados necessários para o trabalho foram armazenados fora do cliente atual - conexão do fluxo de trabalho, no caso de uma falha no fluxo de trabalho, o cliente mudou para outro fluxo de trabalho "ativo" na próxima vez em que acessou o servidor. Na maioria dos casos, essa opção era invisível para o cliente.

O mecanismo funciona assim. Se a chamada do cliente para o fluxo de trabalho, por algum motivo, não puder ser concluída até o final, a parte do cliente poderá, após receber um erro de chamada, repetir essa chamada restabelecendo a conexão com o mesmo fluxo de trabalho ou com outro. Mas você nem sempre pode repetir uma ligação; Repetir a chamada significa que enviamos a chamada para o servidor, mas não recebemos o resultado. Tentamos repetir a chamada, enquanto fazemos a segunda chamada, avaliamos qual foi o resultado da chamada anterior no servidor (informações sobre isso são armazenadas no servidor nos dados da sessão), porque se a chamada tiver tempo para "herdar" (fechar a transação, salvar os dados da sessão) etc.) - é impossível repeti-lo, isso levará à inconsistência dos dados. Se a chamada não puder ser repetida, o cliente receberá uma mensagem sobre um erro irrecuperável,e o aplicativo cliente terá que reiniciar. Se você não conseguiu "herdar" a chamada (e essa é a situação mais comum, porque muitas chamadas não alteram dados, por exemplo, relatórios, exibição de dados em um formulário etc.) e aquelas que alteram dados não têm uma transação ou até que uma alteração nos dados da sessão seja enviada ao gerente - não há rastreamento da chamada) - ela pode ser repetida sem risco de inconsistência dos dados. Se o fluxo de trabalho travar ou uma conexão de rede for interrompida, essa chamada será repetida e esse "desastre" para o aplicativo cliente ocorrerá completamente despercebido.que alteram os dados - até que a transação seja confirmada ou até que a alteração nos dados da sessão seja enviada ao gerente - não há rastreamento da chamada) - ela pode ser repetida sem risco de inconsistência dos dados. Se o fluxo de trabalho travar ou uma conexão de rede for interrompida, essa chamada será repetida e esse "desastre" para o aplicativo cliente ocorrerá completamente despercebido.que alteram os dados - até que a transação seja confirmada ou até que a alteração nos dados da sessão seja enviada ao gerente - não há rastreamento da chamada) - ela pode ser repetida sem risco de inconsistência dos dados. Se o fluxo de trabalho travar ou uma conexão de rede for interrompida, essa chamada será repetida e esse "desastre" para o aplicativo cliente ocorrerá completamente despercebido.

Balanceamento de carga


A tarefa de balanceamento de carga no nosso caso é a seguinte: um novo cliente entra no sistema (ou um cliente que já está trabalhando faz outra chamada). Precisamos escolher para qual servidor e fluxo de trabalho enviar a chamada do cliente para fornecer velocidade máxima ao cliente.

Essa é uma tarefa padrão para um cluster com balanceamento de carga. Existem vários algoritmos típicos para resolvê-lo, por exemplo:


Para o nosso cluster, escolhemos um algoritmo essencialmente próximo ao Tempo de resposta mínimo. Temos um mecanismo que coleta estatísticas sobre o desempenho dos fluxos de trabalho em todos os servidores no cluster. Faz uma chamada de referência para cada processo do servidor no cluster; a chamada de referência envolve um subconjunto das funções do subsistema de disco, memória, processador e avalia a rapidez com que essa chamada é feita. O resultado dessas medições, em média nos últimos 10 minutos, é um critério - qual servidor no cluster é o mais produtivo e preferido para enviar conexões de clientes a ele em um determinado período de tempo. As solicitações dos clientes são distribuídas de forma a melhor carregar o servidor mais produtivo - carregue aquele que tiver sorte.

A solicitação do novo cliente é endereçada ao servidor mais produtivo no momento.

Na maioria dos casos, uma solicitação de um cliente existente é endereçada a esse servidor e ao fluxo de trabalho ao qual sua solicitação anterior foi endereçada. Um conjunto extenso de dados no servidor está associado a um cliente que trabalha; transferi-lo entre processos (e mais ainda entre servidores) é bastante caro (embora possamos fazer isso também).

Uma solicitação de um cliente existente é transferida para outro fluxo de trabalho em dois casos:

  1. Não há mais processo: o fluxo de trabalho com o qual o cliente interagiu anteriormente não está mais disponível (o processo caiu, o servidor ficou indisponível etc.).
  2. : , , , , . , , – . – (.. ).



Decidimos aumentar a resiliência do cluster recorrendo ao esquema ativo / passivo . Houve uma oportunidade de configurar dois clusters - trabalhando e reserva. Se o cluster primário não estiver disponível (problemas de rede ou, por exemplo, manutenção agendada), as chamadas do cliente serão redirecionadas para o cluster de backup.

No entanto, esse design foi bastante difícil de configurar. O administrador teve que montar manualmente dois grupos de servidores em clusters e configurá-los. Às vezes, os administradores cometem erros ao definir configurações conflitantes, como não havia mecanismo centralizado para verificar as configurações. Mas, no entanto, essa abordagem aumentou a tolerância a falhas do sistema.
imagem

1C: Empresa 8.3


Na versão 8.3, reescrevemos substancialmente o código do servidor responsável pela tolerância a falhas. Decidimos abandonar o esquema de cluster Ativo / passivo devido à complexidade de sua configuração. Apenas um cluster tolerante a falhas permaneceu no sistema, consistindo em qualquer número de servidores - isso é mais próximo do esquema Ativo / Ativo , no qual as solicitações de um nó com falha são distribuídas entre os nós de trabalho restantes. Devido a isso, o cluster ficou mais fácil de configurar. Várias operações que aumentam a tolerância a falhas e melhoram o balanceamento de carga foram automatizadas. Das inovações importantes:

  • « »: , , . , «» .
  • , , .
  • , , , , , :

imagem

imagem

A ideia principal desses desenvolvimentos é simplificar o trabalho do administrador, permitindo que ele configure o cluster em termos familiares a ele, no nível de operação do servidor, não diminuindo, e também para minimizar o nível de "controle manual" do trabalho do cluster, fornecendo mecanismos de cluster para resolver a maioria das tarefas de trabalho e possíveis problemas " no piloto automático ".

imagem

Três links de tolerância a falhas


Como você sabe, mesmo que os componentes do sistema separadamente sejam confiáveis, podem surgir problemas onde os componentes do sistema causam um ao outro. Queríamos minimizar o número de locais críticos para o desempenho do sistema. Uma consideração adicional importante foi a minimização de alterações nos mecanismos aplicados na plataforma e a exclusão de alterações nas soluções aplicadas. Na versão 8.3, havia 3 links para garantir a tolerância a falhas "nas articulações":

imagem
  1. , HTTP(S), -. - -. , HTTP -, ( HTTP) libcurl .
  2. , .
  3. - . 1, - . - . , . , – . - (, , , ) – .
  4. , rmngr. 20 ( ) — , .. . 1: .



Graças ao mecanismo de tolerância a falhas, os aplicativos criados na plataforma 1C: Enterprise sobrevivem com êxito a vários tipos de falhas de servidores de produção no cluster, enquanto a maioria dos clientes continua trabalhando sem reiniciar.

Há situações em que não podemos repetir a chamada ou um travamento do servidor captura a plataforma em um momento muito infeliz, por exemplo, no meio de uma transação e não está muito claro o que fazer com eles. Tentamos garantir a sobrevivência estatisticamente boa do cliente quando os servidores caem no cluster. Como regra, a perda média de clientes por falha do servidor é de alguns por cento. Nesse caso, todos os clientes "perdidos" podem continuar trabalhando no cluster após reiniciar o aplicativo cliente.

A confiabilidade do cluster de servidores 1C na versão 8.3 aumentou significativamente. Há muito tempo não é incomum a introdução de produtos 1C, onde o número de usuários que trabalham simultaneamente chega a vários milhares. Existem implementações em que 5.000 e 10.000 usuários trabalham simultaneamente - por exemplo, a introdução no Beeline , onde o aplicativo 1C: Trade Management atende a todos os pontos de venda da Beeline na Rússia ou a implementação de Linhas de Negócios na transportadora de carga , em que o aplicativo, criado de forma independente pelos desenvolvedores do departamento de TI das linhas de negócios na plataforma 1C: Enterprise, atende a todo o ciclo de transporte de carga. Nossos testes de carga de cluster interno simulam a operação simultânea de até 20.000 usuários.

Concluindo, gostaria de listar brevemente o que mais é útil em nosso cluster (a lista está incompleta):

  • , . , , .
  • – , , , ( – , ..) . , , (, ) , ERP, , ERP.
  • – , (, , ..). , , , , , .

All Articles