L'année dernière, le directeur informatique de l'une des plus grandes exploitations agro-industrielles de Russie nous a contactés. L'approche de l'entreprise mise en œuvre par notre client était impressionnante. Il a été l'un des premiers à mettre en œuvre l'idée d'une entreprise à cycle complet - du champ à l'étagère de l'épicerie. En raison de la disponibilité et de la haute qualité des produits, cette holding est devenue une marque reconnue qu'ils connaissent et choisissent. À cette époque, la holding comprenait plus de 650 points de vente et plus de 20 000 employés répartis dans toute la Fédération de Russie.
Le client devait assurer la livraison la plus rapide des chèques au centre de tous les points de vente au détail en Russie, y compris les stands de nourriture dans les villages reculés avec Internet occasionnel et une informatisation minimale.
Compte tenu des spécificités spécifiées, la solution au problème s'est transformée en une aventure passionnante avec un tambourin, des chamans et des cuisses de lapin face à RabbitMQ. Comment nous avons construit un cluster fédéré de files d'attente et ce que nous avons rencontré - sous la coupe.
À propos des problèmes des clients
Tenir avec un grand nombre de points de vente distribués, opérant dans des conditions de concurrence féroce, exigeait que leurs dirigeants prennent rapidement des décisions de gestion. Pour cela, les managers avaient besoin d'informations sur les contrôles en mode temps réel.
Dans le système actuel, le délai de livraison du chèque du caissier au système central atteint 3 jours. Dans le même temps, les informations sur l'achat parfait n'étaient pas enregistrées périodiquement (perte de chèque).
Il était nécessaire de fournir des informations sur les ventes «ici et maintenant» pour optimiser la livraison des produits aux points de vente et pour répondre rapidement aux changements dans l'équilibre des biens et de la demande. Ces informations doivent être transmises simultanément au SI central de l'exploitation basé sur 1C et à l'ordinateur du marchandiseur dans un magasin / point de vente particulier.
En outre, il était nécessaire d'assurer une réévaluation centralisée et opérationnelle des marchandises sur le réseau, ainsi que de connecter au système de BI de l'exploitation un flux de données en ligne de tous les points de vente.
En conséquence, des critères de réussite du projet ont été définis:
- les chèques frappés à la caisse du magasin doivent être visibles dans le système central 1C au plus 1 seconde à compter de sa «fiscalisation» à la caisse en présence (communication) de communication;
- en cas de défaillance temporaire de la communication, assurer la livraison rapide et garantie des chèques au système central après la restauration du canal de communication.
Pour l'équipe Silver Bullet, c'était une chose très tentante, car à cette époque, nous avions déjà développé notre adaptateur 1C pour RabbitMQ et la capacité de le lancer au combat à de grandes distances et des charges attiraient les esprits geek. Le concept même de «position du chèque au centre en 1 seconde» n'est pas si nouveau, en 2013, nous avons présenté l'idée d'utiliser des files d'attente en 1C, et même testé sur un réseau commercial, mais à l'époque, il s'agissait de béquilles très expérimentales, qui comprenaient, en plus de Rabbit + 1C est toujours C #, WCF et même un peu de C ++.
Bien sûr, nous l'avons tous espionné dans des livres intelligents qui ont été écrits encore plus tôt. Par conséquent, je n'oserai pas juger exactement quand l'idée de lignes dans les projets d'intégration a commencé à envahir le monde.
D'une manière ou d'une autre, la partie théorique et le concept architectural ont prouvé leur efficacité, il en reste un peu - tout faire, tester, corriger les bugs, documenter et déployer. : trollface:
Plonger avec la tête
Personne ne connaît mieux que le propriétaire de l’entreprise ses forces et ses faiblesses. Tous les projets d’intégration commencent donc par un audit des processus du client et une compréhension du point de départ (TEL QUEL). En règle générale, une enquête auprès des entreprises comprend:
- analyse des informations sur la façon dont les processus commerciaux se déroulent actuellement;
- recueillir les exigences du système en interrogeant les employés clés afin de comprendre comment, à leur avis, les processus opérationnels devraient être organisés;
- formalisation et optimisation des processus métiers.
Pour éliminer les divergences, nous utilisons la formalisation des processus commerciaux TELS QUELS et TOUS sous la forme de schémas BPMN. Il est plus facile de le comprendre nous-mêmes et il est plus facile pour le client de ne rien manquer lorsque nous parcourons le diagramme de processus avec lui.
D'après les caractéristiques techniques, l'audit a révélé que:
- les points de vente utilisent des machines Windows - avec des systèmes d'exploitation hétérogènes installés (selon l'année de création) de Windows XP vers Windows 7, 8, 10;
- les caisses enregistreuses exécutent le micrologiciel Frontol avec Windows Embedded à bord;
- le circuit de gestion de la vente au détail utilise des logiciels hétérogènes, comprenant à la fois les solutions des fournisseurs 1C et ses propres développements;
- les canaux de communication sont mis en œuvre sur le principe de «ce qui est, c'est-à-dire» dans la gamme des lignes câblées aux modems sifflets USB;
- les points de vente au détail sont desservis par des sociétés d'impartition locales et non par un service de conservation centralisé;
- le fonctionnement du système dépend dans une large mesure de la facilité de maintenance (bon fonctionnement) de l'ordinateur du gestionnaire de produits à chaque point de vente.

Schéma d'intégration AS-IS
L'audit a également montré que les processus opérationnels de l'entreprise n'avaient pratiquement pas besoin d'être ajustés, mais que l'amélioration de l'infrastructure était nécessaire pour garantir un flux d'informations ininterrompu.
En général, nous avons été confrontés à la tâche de livraison fiable des documents entre les trois composantes du processus: caisse enregistreuse, marchandiseur informatique et central. En même temps, l’ordinateur du marchandiseur est une machine «sous la table». Il peut être activé / désactivé à la demande du marchandiseur. Ou même être éteint 23 heures sur 24. Cependant, en quittant le crépuscule, le marchandiseur doit voir un ensemble réel de prix, de soldes, d'articles en stock, etc.
Choisir une solution, ramasser un râteau et placer des béquilles
L'intégration des files d'attente est depuis longtemps devenue un modèle courant. Lorsque vous devez transférer quelque chose quelque part, avec de nombreux liens, dans un environnement peu fiable et acheminer des flux de données en même temps, vous avez besoin d'événements et de files d'attente. Par conséquent, nous avons choisi RabbitMQ, car il s'intègre facilement dans tout environnement (il nous a semblé), y compris la plate-forme 1C, pour laquelle nous avions déjà notre propre adaptateur pour le protocole AMQP.
RMQ est une sorte de gestionnaire de flux de données et permet une intégration en mode temps «presque réel», tout en conservant une faible connexion des systèmes, résistant aux charges, et ainsi de suite ... Un bon serveur, en un mot, beaucoup a été écrit à ce sujet sur Habré.
L'une des fonctionnalités intéressantes est le clustering prêt à l'emploi et la possibilité de créer des clusters de serveurs distribués qui fonctionnent ensemble.

J'ai toujours aimé les photos avec l'architecture de l'intégration dans les files d'attente. Ils se composent toujours de trois dés, au centre desquels se trouve un courtier de messages. Qu'une telle image soit dans cet article, afin de ne pas violer le canon.
Lors de la construction du schéma, la question s'est posée - où le serveur de files d'attente devrait-il être situé? Dans quelles conditions notre système peut-il se retrouver? Nous avons découvert qu'il y a 5 situations d'urgence dans lesquelles le travail ne doit pas s'arrêter.
- Tous les blocs sont inclus.
- Le centre est déconnecté, il y a accès à un marchandiseur.
- Le marchandiseur est déconnecté, il y a accès au centre.
- Handicapés et marchandiseur et centre.
- Système 1C désactivé.
Les contrôles dans toutes ces situations doivent être rompus, le commerce ne doit pas s'arrêter. Lors de la restauration de la chaîne - les chèques doivent parvenir à l'abonné. Permettez-moi de vous rappeler qu'un point de vente peut également être un stand rural. Aucun serveur distinct n'est installé sur lequel RMQ pourrait être installé. Il s'est avéré que le courtier de messages devait être directement à la caisse. Les serveurs sont un luxe inadmissible, et Rabbit est assez léger et peut fonctionner sur un petit terminal de point de vente. Alors pourquoi pas oui?
Bien sûr, nous n'avons pas fait de POS le seul nœud du cluster RMQ, mais nous avons placé l'un des nœuds du cluster fédéré directement sur le terminal de trading, exécutant Windows Embedded. Dire que c'était un peu plus facile que de le faire, mais nous l'avons fait de manière gaie et imprudente. Ce que je vais vous dire maintenant.
Comment mettre le terminal RMQ Frontol
Je dois dire qu'Erlang et le serveur RMQ lui-même sont arrivés au terminal Windows presque sans problème. Des problèmes sont survenus chez le client, qui devrait interagir avec le serveur à partir du logiciel de caisse enregistreuse.
Le logiciel de caisse enregistreuse Frontol a une assez bonne documentation, à partir de laquelle nous avons découvert qu'il est possible de personnaliser le comportement à l'aide de Javascript. "Yuhu!" - nous avons dit et commencé à google le client JS pour RabbitMQ. Il est rapidement devenu évident qu'un dérapeur nous attendait. Sur le devant, pas tout à fait Javascript. Eh bien, c'est-à-dire formellement, oui, la syntaxe est la même là-bas, mais la machine JavaScript elle-même provient de Windows Script Host, la même que VBScript, cscript.exe, etc. En bref, il est très ancien, spécifique à Microsoft, et aucun client JS de lapin sain d'esprit ne travaillera dessus.
Cependant, dans l'écosystème WSH, vous pouvez utiliser des objets COM et nous nous sommes dirigés vers le client RMQ pour .NET .
Les versions modernes de ce client ne prennent plus en charge le .NET 3.5, qui était à notre disposition sur le terminal de point de vente, mais heureusement, le code source du client est ouvert, et en outre, le github du projet a conservé les balises dans lesquelles .NET 3.5 était toujours pris en charge. Gloire à l'Open Source! Il restait à dégonfler le code source de l'ancienne version du client .NET, à cocher la case Com-Visible et à déployer sur le terminal.
Interaction de paiement Frontol
Le logiciel de caisse enregistreuse a une API qui peut être utilisée pour l'interaction.
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();
Les capacités du JS natif intégré à Windows sont extrêmement médiocres. Par exemple, il n'y a pas Array.indexOf ou JSON.stringify. Mais le monde n'est pas sans bonnes personnes. Nous nous sommes souvenus de la béquille populaire sur navigateur appelée «polyphillas» et nous les avons heureusement intégrés dans la caisse. Mis à part les blagues, tous les tours de magie avec JS ont été intentionnellement minutieusement commentés afin que les générations de futurs administrateurs puissent comprendre clairement et rapidement ce qui se passe, d'où cela vient et comment cela fonctionne.


Il est rapidement devenu clair que l'API JS ne couvre pas une partie de nos cas, cependant, puisque Frontol comprend un SGBD Firebird et qu'il existe un fournisseur ODBC, nous pouvons utiliser Javascript pour contacter directement la base de données du caissier en utilisant Javascript. obtenir les données dont nous avons besoin là-bas.
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)) "
Et enfin, travailler directement avec le serveur de file d'attente de notre JS ressemble à ceci:
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; }
L'image globale de la solution
Les principes suivants ont été posés en architecture:
- Fédération des serveurs RabbitMQ - RMQ - Mode serveur de fédération pour que les événements soient remis à tous les destinataires;
- survie de la caisse locale - si un événement est survenu à la caisse, il doit être livré dans tous les cas, même si pour le moment la caisse n'est pas accessible sur le réseau;
- 2 fournisseurs de données - en mode normal, les données sont livrées via le serveur (l'ordinateur du marchand), si l'ordinateur du marchand n'est pas disponible (à la suite d'un accident ou pour d'autres raisons), le caissier livre la livraison, lorsque l'ordinateur du marchand est allumé, il recevra sa partie des événements plus tard que le centre, mais garanti;
- RMQ - service RabbitMQ serveur avec des ports TCP ouverts pour le clustering et la messagerie;
- Pour garantir la remise garantie des messages, une redondance du flux de données est appliquée. Cela minimise l'impact des connexions réseau entre les nœuds du système;
- dans 1C: Center, il a été décidé d'installer un ensemble de serveurs RMQ en mode HA - haute disponibilité du serveur central, incl. Il y a une double réservation et réplication d'événement, pour garantir la livraison.

Conformément à la solution architecturale, le diagramme de flux de données suivant a été créé:
- Frontol, 1C - points de départ et d'arrivée des échanges - objets sources et récepteurs de messages;
- file d'attente fédérée - un type spécial de file d'attente qui vous permet de créer un système distribué pour envoyer des messages, dans lequel la file d'attente peut être publiée dans le nœud situé à la sortie (en amont), et leur réception à partir de la file d'attente au centre (en aval). Pour la transmission des messages de l'amont vers l'aval, un plug-in spécial (Federation PlugIn) est installé sur le serveur de file d'attente central;
- Pelle - (littéralement "pelle") - un mécanisme pour transmettre des messages d'un objet (file d'attente) à un autre. Les objets peuvent appartenir à un serveur ou différents;
- l'architecture du système permet la gestion du déploiement à distance, c'est-à-dire la possibilité d'installer des serveurs RabbitMQ sur n'importe quel ordinateur du réseau d'attente à partir d'un centre unique;
- la configuration et la connexion à la fédération sont effectuées à l'aide des scripts dits de post-installation, qui sont fournis en standard avec la livraison des serveurs RMQ, avec la configuration nécessaire des paramètres réseau acceptée sur le réseau du Client.
Le circuit résultant fournit les caractéristiques de vitesse ordonnées et fonctionne de manière stable lorsque l'un des composants tombe. Une fois la connexion perdue et rétablie, les données accumulées vont au centre dans les 5 à 10 secondes. En pratique, la technologie des systèmes à couplage lâche a prouvé son efficacité. Tous les événements se déroulent comme dans un même bureau, sans tenir compte des différents types de retards liés à la répartition territoriale et des différents degrés de disponibilité des canaux de communication qui lui sont inhérents.
Brève conclusion
Je voudrais profiter séparément de ce moment incroyable dans lequel nous vivons. Plus récemment, l'utilisation de l'Open Source dans un produit était une sorte d'ascétisme. "Votre logiciel open source fonctionne-t-il?" Alors, comment aimez-vous ce cactus? " Aujourd'hui, c'est une maxime absolue.
Je ne peux pas imaginer une entreprise qui n'a pas de produits open source dans le produit. Grâce à la disponibilité des informations, des logiciels open source, la mise en œuvre des idées commerciales est devenue beaucoup plus facile et plus rapide. Besoin de mettre RMQ sur d'anciens Javascript et Windows personnalisés? Rien de plus simple. Une solution googlé est un peu inappropriée? - voyez comment c'est fait et ajoutez les éléments manquants. Le temps de mise sur le marché lors de l'utilisation de produits ouverts est considérablement réduit. Et tout le monde sait qu'une libération rapide d'une solution signifie un avantage concurrentiel.
Github, Stackoverflow, une documentation et des normes ouvertes permettent de lancer en quelques semaines ce qui nécessitait auparavant de nombreuses années d'expertise dans divers domaines de la connaissance informatique.
Et bien sûr, il est particulièrement agréable que la communauté des surnoms 1C sorte de son monde fermé chaque année et se transforme en informatique mondiale. Par exemple, «1C: Enterprise» est aujourd'hui l'une des langues officielles prises en charge par Github, et les membres de la communauté 1C l'ont «enseignée» à cette langue. Cette histoire mérite probablement un article séparé, je l'écrirai peut-être un jour. En attendant - bonne chance et bonne chance!
Merci pour votre temps!