No ano passado, o diretor de TI de uma das maiores participações agroindustriais da Rússia entrou em contato conosco. A abordagem aos negócios implementada por nosso cliente foi impressionante. Ele foi um dos primeiros a implementar a ideia de uma empresa de ciclo completo - do campo à prateleira do supermercado. Devido à disponibilidade e alta qualidade dos produtos, essa holding se tornou uma marca reconhecida que eles conhecem e escolhem. Naquela época, a holding incluía mais de 650 pontos de venda e mais de 20.000 funcionários distribuídos em toda a Federação Russa.
O cliente precisava garantir a entrega mais rápida de cheques ao centro a partir de todos os pontos de venda na Rússia, incluindo barracas de comida em vilarejos remotos com Internet ocasional e computadorização mínima.
Considerando as especificidades especificadas, a solução para o problema se transformou em uma emocionante aventura com um pandeiro, xamãs e pernas de coelho na cara do RabbitMQ. Como criamos um cluster federado de filas e o que encontramos - sob o corte.
Sobre problemas do cliente
Manter um grande número de pontos de venda distribuídos, operando nas condições de concorrência acirrada, exigia que seus líderes tomassem prontamente decisões de gerenciamento. Para isso, os gerentes precisavam de informações sobre verificações no modo em tempo real.
No sistema atual, o tempo de entrega do cheque do caixa ao sistema central chegou a 3 dias. Ao mesmo tempo, as informações sobre a compra perfeita não eram registradas periodicamente (perda de cheque).
Era necessário fornecer informações sobre vendas "aqui e agora" para otimizar a entrega de produtos às lojas e responder rapidamente às mudanças no equilíbrio de mercadorias e demanda. Essas informações devem ir simultaneamente para o IS central da exploração, com base em 1C, e para o computador do comerciante em uma determinada loja / ponto de venda.
Além disso, era necessário garantir uma reavaliação centralizada e operacional de mercadorias pela rede, além de conectar ao sistema de BI da holding um fluxo de dados on-line de todas as tomadas.
Como resultado, foram formados critérios para o sucesso do projeto:
- os cheques perfurados no caixa da loja devem estar visíveis no sistema central 1C no máximo 1 segundo a partir do momento de sua “fiscalização” no caixa na presença (comunicação) da comunicação;
- em caso de falhas temporárias de comunicação, assegure a entrega imediata garantida de verificações ao sistema central após a restauração do canal de comunicação.
Para a equipe do Silver Bullet, isso foi muito tentador, pois na época já tínhamos desenvolvido nosso adaptador 1C para o RabbitMQ e a capacidade de iniciá-lo na batalha a grandes distâncias e cargas atraía mentes nerds. O próprio conceito de “posição do cheque no centro em 1 segundo” não é tão novo. Em 2013, apresentamos a ideia de usar filas em 1C e até testamos em uma rede de negociação, mas na época eram muletas muito experimentais, que incluíam, além do Rabbit + 1C ainda é C #, WCF e até um pouco de C ++.
Claro, todos nós o espionamos em livros inteligentes que foram escritos ainda mais cedo. Portanto, não ousarei julgar exatamente quando a idéia de linhas em projetos de integração começou a dominar o mundo.
De uma forma ou de outra, a parte teórica e o conceito de arquitetura provaram sua eficácia, restando apenas um pouco - para fazer tudo, testar, corrigir bugs, documentar e implantar. : trollface:
Mergulhando com a cabeça
Ninguém sabe melhor do que o proprietário da empresa sobre seus pontos fortes e fracos; portanto, todos os projetos de integração começam com uma auditoria dos processos do cliente e com o entendimento do ponto de partida (COMO ESTÁ). Normalmente, uma pesquisa de negócios inclui:
- análise de informações sobre como os processos de negócios estão acontecendo agora;
- coletar requisitos para o sistema entrevistando funcionários-chave para entender como, em sua opinião, os processos de negócios devem ser organizados;
- formalização e otimização de processos de negócios.
Para eliminar discrepâncias, usamos a formalização dos processos de negócios AS IS e TO BE na forma de esquemas BPMN. É mais fácil entendê-lo e é mais fácil para o cliente não perder nada quando passamos pelo diagrama do processo junto com ele.
Pelas características técnicas, durante a auditoria constatou que:
- os pontos de venda usam máquinas baseadas no Windows - com sistemas operacionais heterogêneos instalados (dependendo do ano de criação) do Windows XP ao Windows 7, 8, 10;
- caixas registradoras estão executando o firmware Frontol com o Windows Embedded a bordo;
- o circuito de gerenciamento de varejo utiliza software heterogêneo, incluindo soluções de fornecedores da 1C e seus próprios desenvolvimentos;
- os canais de comunicação são implementados com o princípio de “o que é”, no intervalo de linhas de cabo a modems apito USB;
- os pontos de venda são atendidos por empresas locais de terceirização e não por um serviço centralizado;
- o funcionamento do sistema depende substancialmente da capacidade de manutenção (funcionamento adequado) do computador do gerente de mercadorias em cada tomada.

Esquema de integração AS-IS
A auditoria também mostrou que os processos de negócios da empresa praticamente não precisam ser ajustados, mas é necessário um aprimoramento da infraestrutura para garantir um fluxo ininterrupto de informações.
Em geral, nos deparamos com a tarefa de entrega confiável de documentos entre os três componentes do processo: caixa registradora, comerciante de computadores e escritório central. Ao mesmo tempo, o computador do comerciante é uma máquina "embaixo da mesa". Pode ser ligado / desligado a pedido do comerciante. Ou até mesmo seja desligado 23 horas em 24. No entanto, ao sair do anoitecer, o comerciante deve ver um conjunto real de preços, saldos, itens de estoque etc.
Escolhendo uma solução, coletando um ancinho e colocando muletas
A integração da fila há muito se tornou um padrão comum. Quando você precisa transferir algo para algum lugar, com muitos links, em um ambiente não confiável e rotear fluxos de dados ao mesmo tempo, você precisa de eventos e filas. Portanto, escolhemos o RabbitMQ, porque ele se integra facilmente a qualquer ambiente (pareceu-nos), incluindo a plataforma 1C, para a qual já tínhamos nosso próprio adaptador para o protocolo AMQP.
O RMQ é um tipo de gerenciador de fluxo de dados e permite a integração no modo de tempo “quase real”, mantendo uma conexão fraca de sistemas, suportando cargas e assim por diante ... Um bom servidor, em uma palavra, muito foi escrito sobre isso em Habré.
Um dos recursos interessantes é o clustering pronto para uso e a capacidade de criar clusters de servidores distribuídos que funcionam juntos.

Sempre gostei das fotos com a arquitetura da integração nas filas. Eles sempre consistem em três dados, no centro dos quais é um corretor de mensagens. Deixe que essa imagem esteja neste artigo, para não violar o cânon.
Ao construir o esquema, surgiu a pergunta - onde o servidor da fila deveria estar localizado? Em que condições nosso sistema pode acabar? Descobrimos que existem 5 situações de emergência nas quais o trabalho não deve parar.
- Todos os blocos estão incluídos.
- O centro está desconectado, há acesso a um comerciante.
- O merchandiser está desconectado, há acesso ao centro.
- Desativado e comerciante e centro.
- Sistema 1C desativado.
Os cheques em todas essas situações devem romper, o comércio não deve parar. Ao restaurar o canal - as verificações devem chegar ao assinante. Deixe-me lembrá-lo de que um ponto de venda também pode ser uma barraca rural. Não há nenhum servidor separado instalado no qual o RMQ possa ser instalado. Descobriu-se que o intermediário de mensagens deve estar diretamente no caixa. Os servidores são um luxo inadmissível e o Rabbit é bastante leve e pode funcionar em um pequeno terminal de PDV. Então porque não?
Obviamente, não fizemos do POS o único nó do cluster RMQ, mas colocamos um dos nós do cluster federado diretamente no terminal comercial, executando o Windows Embedded. Dizer isso foi um pouco mais fácil do que fazer, mas fizemos isso de forma alegre e imprudente. O que vou lhe dizer agora.
Como colocar RMQ terminal Frontol
Devo dizer que Erlang e o próprio servidor RMQ chegaram ao terminal do Windows quase sem problemas. Surgiram problemas no cliente, que deve interagir com o servidor a partir do software da caixa registradora.
O software de caixa registradora Frontol possui uma documentação bastante boa, da qual descobrimos que é possível personalizar o comportamento usando Javascript. "Yuhu!" - dissemos e começamos a pesquisar no Google JS o RabbitMQ. Logo ficou claro que uma chatice estava esperando por nós. Na frente, não é exatamente Javascript. Bem, isto é formalmente, sim, a sintaxe é a mesma, mas a máquina JavaScript em si é do Windows Script Host, a mesma que é VBScript, cscript.exe e muito mais. Em resumo, é muito antigo, específico da Microsoft e nem um único cliente JS de coelho sadio funcionará nele.
No entanto, no ecossistema WSH, você pode usar objetos COM e fomos em direção ao cliente RMQ para .NET .
As versões modernas desse cliente não oferecem mais suporte ao .NET 3.5, que estava disponível para nós no terminal POS, mas, felizmente, o código-fonte do cliente está aberto e, além disso, o github do projeto retinha as tags nas quais o .NET 3.5 ainda era suportado. Glória ao código aberto! Restava desinflar o código-fonte da versão antiga do cliente .NET, marque a caixa de seleção Com-Visible e implante no terminal.
Interação de check-out do Frontol
O software de caixa registradora possui uma API que pode ser usada para interação.
function init() { frontol.addEventListener("openDocument", "beforeOpenDocument", true); frontol.addEventListener("closeDocument", "beforeCloseDocument", true); frontol.addEventListener("closeDocument", "afterCloseDocument", false); frontol.addEventListener("closeSession", "beforeCloseSession", true); frontol.addEventListener("closeSession", "afterCloseSession", false); addPolyfills();
Os recursos do JS nativo que está a bordo do Windows são extremamente ruins. Por exemplo, não há Array.indexOf ou JSON.stringify. Mas o mundo não está sem pessoas boas. Lembramos da popular muleta baseada em navegador chamada "polyphillas" e, felizmente, a incorporamos na caixa. Deixando de lado as piadas, todos os truques de mágica com JS foram intencionalmente meticulosamente comentados, para que gerações de futuros administradores possam entender clara e rapidamente o que está acontecendo, de onde veio e como funciona.


Logo ficou claro que a JS-API não cobre parte de nossos casos; no entanto, como o Frontol inclui um DBMS do Firebird e existe um provedor ODBC, podemos usar o Javascript para entrar em contato diretamente com o banco de dados da caixa usando Javascript. obtenha os dados que precisamos lá.
function afterCloseSession() { var connection = getDatabaseConnection(); var qSelect = new ActiveXObject("ADODB.Command"); qSelect.ActiveConnection = connection; qSelect.CommandText = "SELECT ChequeNumber " + "FROM Document " + "WHERE " + " State = 1 " + " AND(ChequeType IN(0, 1, 2)) "
E, finalmente, trabalhar diretamente com o servidor de filas do nosso JS fica assim:
function createRMQConnection() { factory = new ActiveXObject("RabbitMQ.Client.ConnectionFactory"); factory.UserName = rmqUser; factory.Password = rmqPass; factory.VirtualHost = "/"; factory.HostName = "localhost"; try { rmqConnection = factory.CreateConnection(0); } catch (e) { throw new Error(" . !\n" + e.message); } rmqChannel = rmqConnection.CreateModel(); rmqMessageProperties = rmqChannel.CreateBasicProperties(); rmqMessageProperties.ContentType = "text/plain"; rmqMessageProperties.ContentEncoding = "string"; rmqMessageProperties.DeliveryMode = 2; }
A imagem geral da solução
Os seguintes princípios foram estabelecidos na arquitetura:
- Federação de servidores RabbitMQ - RMQ - modo de servidor de Federação para que os eventos sejam entregues a todos os destinatários;
- sobrevivência do caixa local - se um evento ocorreu no caixa, ele deve ser entregue em qualquer caso, mesmo que no momento o balcão não esteja acessível na rede;
- 2 provedores de dados - no modo normal, os dados são entregues através do servidor (o computador do comerciante), se o computador do comerciante estiver indisponível (como resultado de um acidente ou por outros motivos), o caixa fará a entrega, quando o computador do comerciante for ligado, ele receberá sua parte dos eventos depois do centro, mas garantido;
- RMQ - serviço servidor RabbitMQ com portas TCP abertas para armazenamento em cluster e mensagens;
- Para garantir a entrega garantida de mensagens, a redundância do fluxo de dados é aplicada. Isso minimiza o impacto das conexões de rede entre os nós do sistema;
- em 1C: Center, foi decidido instalar um conjunto de servidores RMQ no modo HA - alta disponibilidade do servidor central, incl. Há uma reserva dupla e replicação de eventos, para garantir a entrega.

De acordo com a solução de arquitetura, o seguinte diagrama de fluxo de dados foi criado:
- Frontol, 1C - pontos iniciais e finais da troca - objetos que são fontes e receptores de mensagens;
- fila federada - um tipo especial de fila que permite criar um sistema distribuído para o envio de mensagens, no qual a fila pode ser publicada no nó localizado na tomada (upstream) e seu recebimento da fila no centro (downstream). Para a transmissão de mensagens de upstream para downstream, um plug-in especial (Federation PlugIn) é instalado no servidor da fila central;
- Pá - (literalmente "pá") - um mecanismo para transmitir mensagens de um objeto (fila) para outro. Os objetos podem pertencer a um servidor ou diferente;
- a arquitetura do sistema fornece gerenciamento de implantação remota, ou seja, a capacidade de instalar servidores RabbitMQ em qualquer computador na rede de retenção a partir de um único centro;
- a configuração e a conexão com a federação são realizadas usando os chamados scripts de pós-instalação, que vêm de fábrica com a entrega de servidores RMQ, com a configuração necessária dos parâmetros de rede aceitos na rede do cliente.
O circuito resultante fornece as características de velocidade solicitadas e funciona de maneira estável quando qualquer um dos componentes cai. Depois que a conexão é perdida e restaurada, os dados acumulados vão para o centro dentro de 5 a 10 segundos. Na prática, a tecnologia de sistemas fracamente acoplados provou sua eficácia. Todos os eventos ocorrem como se estivessem em um escritório, sem levar em conta os vários tipos de atrasos associados à distribuição territorial e o grau de disponibilidade dos canais de comunicação inerentes a ele.
Breve conclusão
Gostaria de aproveitar separadamente o tempo maravilhoso em que vivemos. Mais recentemente, o uso de código aberto em um produto foi uma espécie de ascetismo. "O seu software de código aberto funciona?" Então, como você gosta deste cacto? Hoje, essa é uma máxima absoluta.
Não consigo imaginar uma empresa que não tenha produtos de código aberto no produto. Graças à disponibilidade de informações, software de código aberto, a implementação de idéias de negócios se tornou muito mais fácil e rápida. Precisa colocar o RMQ no antigo Javascript personalizado e no Windows? Não há nada mais fácil. Uma solução pesquisada no Google é um pouco inapropriada? - veja como é feito e adicione os desaparecidos. O tempo de colocação no mercado ao usar produtos abertos é reduzido significativamente. E todo mundo sabe que o lançamento rápido de uma solução significa uma vantagem competitiva.
Github, Stackoverflow, documentação e padrões abertos tornam possível lançar em questão de semanas o que anteriormente exigiria muitos anos de experiência em vários campos do conhecimento em informática.
E, claro, é especialmente agradável que a comunidade de apelidos 1C saia do mundo fechado todos os anos e se funda na TI global. Por exemplo, “1C: Enterprise” hoje é um dos idiomas oficiais suportados pelo Github, e as pessoas da comunidade 1C o “ensinaram” a esse idioma. Essa história provavelmente merece um artigo separado, talvez eu o escreva algum dia. Enquanto isso - tudo de melhor e boa sorte!
Obrigado pelo seu tempo!