Histoire de l'architecture Dodo IS : le chemin du back office

Habr change le monde. Nous bloguons depuis plus d'un an maintenant. Il y a environ six mois, nous avons reçu un retour tout à fait logique des Khabrovites : « Dodo, tu dis partout que tu as ton propre système. Et c'est quoi ce système ? Et pourquoi une chaîne de pizzas en a-t-elle besoin ?

Nous nous sommes assis, avons réfléchi et réalisé que vous aviez raison. Nous essayons de tout expliquer sur nos doigts, mais cela sort en morceaux et nulle part il n'y a une description complète du système. Ainsi a commencé un long voyage de collecte d'informations, de recherche d'auteurs et d'écriture d'une série d'articles sur Dodo IS. Allons-y!

Remerciements : Merci de nous avoir fait part de vos commentaires. Grâce à lui, nous avons enfin décrit le système, compilé un radar technique et allons bientôt déployer une large description de nos processus. Sans vous, nous serions restés assis là encore 5 ans.

Histoire de l'architecture Dodo IS : le chemin du back office

Série d'articles "Qu'est-ce que Dodo IS ?" raconte :

  1. Premier monolithe de Dodo IS (2011-2015). (En cours...)
  2. Le parcours back office : bases et bus séparés. (Tu es là)
  3. Le cheminement côté client : façade sur socle (2016-2017). (En cours...)
  4. L'histoire des vrais microservices. (2018-2019). (En cours...)
  5. Fini le sciage du monolithe et stabilisation de l'architecture. (En cours...)

Si vous êtes intéressé à savoir autre chose - écrivez dans les commentaires.

Avis sur la description chronologique de l'auteur
J'organise régulièrement une réunion pour les nouveaux employés sur le thème "Architecture système". Nous l'appelons "Intro à Dodo IS Architecture" et cela fait partie du processus d'intégration des nouveaux développeurs. Racontant sous une forme ou une autre notre architecture, ses caractéristiques, j'ai fait naître une certaine approche historique de la description.

Traditionnellement, nous considérons le système comme un ensemble de composants (techniques ou de niveau supérieur), des modules métier qui interagissent les uns avec les autres pour atteindre un objectif. Et si une telle vision est justifiée pour la conception, elle ne convient pas tout à fait à la description et à la compréhension. Il y a plusieurs raisons ici :

  • La réalité est différente de ce qui est sur le papier. Tout ne se passe pas comme prévu. Et nous sommes intéressés par la façon dont cela s'est réellement passé et fonctionne.
  • Présentation cohérente des informations. En fait, vous pouvez aller chronologiquement du début à l'état actuel.
  • Du simple au complexe. Pas universellement, mais dans notre cas, c'est le cas. L'architecture est passée d'approches plus simples à des approches plus complexes. Souvent par complication, les problèmes de vitesse et de stabilité de mise en œuvre ont été résolus, ainsi que des dizaines d'autres propriétés de la liste des exigences non fonctionnelles (ici bien parlé de la complexité contrastée avec d'autres exigences).

En 2011, l'architecture Dodo IS ressemblait à ceci :

Histoire de l'architecture Dodo IS : le chemin du back office

En 2020, c'est devenu un peu plus compliqué et c'est devenu comme ça :

Histoire de l'architecture Dodo IS : le chemin du back office

Comment cette évolution s'est-elle opérée ? Pourquoi différentes parties du système sont-elles nécessaires ? Quelles décisions architecturales ont été prises et pourquoi ? Découvrons-le dans cette série d'articles.

Les premiers problèmes de 2016 : pourquoi les services devraient-ils quitter le monolithe

Les premiers articles du cycle porteront sur les services qui ont été les premiers à se séparer du monolithe. Pour vous mettre en contexte, je vais vous dire quels problèmes nous avions dans le système au début de 2016, que nous avons dû composer avec la séparation des services.

Une seule base de données MySql, dans laquelle toutes les applications qui existaient à l'époque dans Dodo IS écrivaient leurs enregistrements. Les conséquences ont été :

  • Charge importante (avec 85 % des requêtes comptabilisées pour la lecture).
  • La base s'est agrandie. Pour cette raison, son coût et son soutien sont devenus un problème.
  • Point de défaillance unique. Si une application écrivant dans la base de données commençait soudainement à le faire plus activement, les autres applications le ressentaient elles-mêmes.
  • Inefficacité du stockage et des requêtes. Souvent, les données étaient stockées dans une structure qui convenait à certains scénarios mais ne convenait pas à d'autres. Les index accélèrent certaines opérations, mais peuvent en ralentir d'autres.
  • Certains des problèmes ont été résolus par des caches et des répliques en lecture créés à la hâte dans les bases (ce sera un article séparé), mais ils leur ont seulement permis de gagner du temps et n'ont pas fondamentalement résolu le problème.

Le problème était la présence du monolithe lui-même. Les conséquences ont été :

  • Sorties uniques et rares.
  • Difficulté de développement conjoint d'un grand nombre de personnes.
  • Incapacité à intégrer de nouvelles technologies, de nouveaux frameworks et bibliothèques.

Des problèmes avec la base et le monolithe ont été décrits à de nombreuses reprises, par exemple dans le cadre de crashs début 2018 (Soyez comme Munch, ou quelques mots sur la dette technique, Le jour où Dodo IS s'est arrêté. Script asynchrone и L'histoire de l'oiseau Dodo de la famille Phoenix. La grande chute de Dodo IS), donc je ne m'attarderai pas trop. Permettez-moi de dire que nous voulions donner plus de flexibilité lors du développement des services. Tout d'abord, cela concernait ceux qui étaient les plus chargés et les plus rootés de tout le système - Auth et Tracker.

Le chemin du back office : bases et bus séparés

Navigation dans les chapitres

  1. Schéma monolithe 2016
  2. Commencer à décharger le monolithe : séparation de l'authentification et du traqueur
  3. Que fait Auth ?
  4. D'où viennent les chargements ?
  5. Autorisation de déchargement
  6. Que fait Traqueur ?
  7. D'où viennent les chargements ?
  8. Traqueur de déchargement

Schéma monolithe 2016

Voici les principaux blocs du monolithe Dodo IS 2016, et juste en dessous se trouve une retranscription de leurs principales tâches.
Histoire de l'architecture Dodo IS : le chemin du back office
Livraison en caisse. Comptabilisation des courriers, émission d'ordres aux courriers.
Centre d'appels. Acceptation des commandes par l'intermédiaire de l'opérateur.
site. Nos sites Web (dodopizza.ru, dodopizza.co.uk, dodopizza.by, etc.).
Auth. Service d'autorisation et d'authentification pour le back office.
Traqueur. Suivi des commandes dans la cuisine. Service de marquage des états de préparation lors de la préparation d'une commande.
Caisse du Restaurant. Prise de commandes dans un restaurant, interfaces caissières.
Exportations. Téléchargement de rapports dans 1C pour la comptabilité.
Notifications et factures. Commandes vocales en cuisine (par exemple, "Nouvelle pizza arrivée") + impression de factures pour les coursiers.
Chef de quart. Interfaces pour le travail du chef d'équipe : liste des commandes, graphiques de performances, transfert des employés vers l'équipe.
Responsable administratif. Interfaces pour le travail du franchisé et du gérant : accueil des salariés, rapports sur le travail de la pizzeria.
Tableau de bord des restaurants. Affichage des menus sur les téléviseurs des pizzerias.
administrateur. Paramètres dans une pizzeria spécifique : menu, prix, comptabilité, codes promo, promotions, bannières de site Web, etc.
Compte personnel de l'employé. Horaires de travail des employés, informations sur les employés.
Tableau de motivation de cuisine. Un écran séparé qui pend dans la cuisine et affiche la vitesse des pizzaïolos.
Communication. Envoi de sms et email.
Stockage de fichiers. Propre service de réception et d'émission de fichiers statiques.

Les premières tentatives pour résoudre les problèmes nous ont aidés, mais ce n'était qu'un répit temporaire. Ils ne sont pas devenus des solutions système, il était donc clair qu'il fallait faire quelque chose avec les bases. Par exemple, pour diviser la base de données générale en plusieurs bases plus spécialisées.

Commencer à décharger le monolithe : séparation de l'authentification et du traqueur

Les principaux services qui ont ensuite enregistré et lu à partir de la base de données plus que d'autres :

  1. Auth. Service d'autorisation et d'authentification pour le back office.
  2. Traqueur. Suivi des commandes dans la cuisine. Service de marquage des états de préparation lors de la préparation d'une commande.

Que fait Auth ?

Auth est un service par lequel les utilisateurs se connectent au back office (il y a une entrée indépendante séparée côté client). Il est également appelé dans la requête à s'assurer que les droits d'accès requis sont présents et que ces droits n'ont pas changé depuis la dernière connexion. À travers elle, les appareils pénètrent dans la pizzeria.

Par exemple, nous voulons ouvrir un affichage avec les statuts des commandes terminées sur le téléviseur suspendu dans le hall. Ensuite, nous ouvrons auth.dodopizza.ru, sélectionnez "Connexion en tant qu'appareil", un code apparaît qui peut être saisi dans une page spéciale sur l'ordinateur du chef de quart, indiquant le type d'appareil (appareil). Le téléviseur lui-même passera à l'interface souhaitée de sa pizzeria et commencera à afficher les noms des clients dont les commandes y sont prêtes.

Histoire de l'architecture Dodo IS : le chemin du back office

D'où viennent les chargements ?

Chaque utilisateur connecté du back office va à la base de données, à la table des utilisateurs pour chaque requête, extrait l'utilisateur via une requête sql et vérifie s'il a les accès et les droits nécessaires sur cette page.

Chacun des appareils fait de même uniquement avec la table des appareils, en vérifiant son rôle et son accès. Un grand nombre de requêtes vers la base de données maître entraîne son chargement et le gaspillage des ressources de la base de données commune pour ces opérations.

Autorisation de déchargement

Auth a un domaine isolé, c'est-à-dire que les données sur les utilisateurs, les connexions ou les appareils entrent dans le service (pour le moment) et y restent. Si quelqu'un en a besoin, il ira à ce service pour obtenir des données.

C'ÉTAIT. Le plan de travail initial était le suivant :

Histoire de l'architecture Dodo IS : le chemin du back office

Je voudrais expliquer un peu comment cela a fonctionné:

  1. Une demande de l'extérieur arrive au backend (il y a Asp.Net MVC), apporte avec elle un cookie de session, qui est utilisé pour obtenir les données de session de Redis(1). Il contient soit des informations sur les accès, puis l'accès au contrôleur est ouvert (3,4), soit non.
  2. S'il n'y a pas d'accès, vous devez passer par la procédure d'autorisation. Ici, pour des raisons de simplicité, il est affiché dans le cadre du chemin dans le même attribut, bien qu'il s'agisse d'une transition vers la page de connexion. Dans le cas d'un scénario positif, nous obtiendrons une session correctement terminée et accéderons au Backoffice Controller.
  3. S'il existe des données, vous devez en vérifier la pertinence dans la base de données des utilisateurs. Son rôle a-t-il changé, ne devrait-il plus être autorisé sur la page ? Dans ce cas, après avoir reçu la session (1), vous devez vous rendre directement dans la base de données et vérifier l'accès de l'utilisateur à l'aide de la couche logique d'authentification (2). Ensuite, soit sur la page de connexion, soit sur le contrôleur. Un tel système simple, mais pas tout à fait standard.
  4. Si toutes les procédures sont réussies, nous sautons plus loin dans la logique des contrôleurs et des méthodes.

Les données utilisateur sont séparées de toutes les autres données, elles sont stockées dans une table d'appartenance séparée, les fonctions de la couche logique AuthService peuvent très bien devenir des méthodes API. Les limites du domaine sont définies assez clairement : les utilisateurs, leurs rôles, les données d'accès, l'octroi et la révocation de l'accès. Tout semble pouvoir être retiré dans un service séparé.

DEVENIR. Alors ils ont fait :

Histoire de l'architecture Dodo IS : le chemin du back office

Cette approche présente un certain nombre de problèmes. Par exemple, appeler une méthode à l'intérieur d'un processus n'est pas la même chose qu'appeler un service externe via http. La latence, la fiabilité, la maintenabilité, la transparence du fonctionnement sont complètement différentes. Andrey Morevskiy a parlé plus en détail de ces problèmes dans son rapport. "50 nuances de microservices".

Le service d'authentification et, avec lui, le service de périphérique sont utilisés pour le back office, c'est-à-dire pour les services et les interfaces utilisés en production. L'authentification pour les services client (comme un site Web ou une application mobile) se produit séparément sans utiliser Auth. La séparation a pris environ un an, et maintenant nous traitons à nouveau ce sujet, en transférant le système vers de nouveaux services d'authentification (avec des protocoles standard).

Pourquoi la séparation a-t-elle duré si longtemps ?
Il y a eu de nombreux problèmes en cours de route qui nous ont ralentis :

  1. Nous voulions déplacer les données d'utilisateur, d'appareil et d'authentification des bases de données spécifiques au pays en une seule. Pour ce faire, nous avons dû traduire toutes les tables et l'utilisation de l'identifiant int à l'identifiant UUId global (récemment retravaillé ce code Roman Bukin "Uuid - une grande histoire d'une petite structure" et projet open source Primitives). Le stockage des données des utilisateurs (puisqu'il s'agit d'informations personnelles) a ses limites et pour certains pays, il est nécessaire de les stocker séparément. Mais l'identifiant global de l'utilisateur doit l'être.
  2. De nombreuses tables de la base de données contiennent des informations d'audit sur l'utilisateur qui a effectué l'opération. Cela nécessitait un mécanisme supplémentaire de cohérence.
  3. Après la création des api-services, il y a eu une longue et progressive période de transition vers un autre système. La commutation devait être transparente pour les utilisateurs et nécessitait un travail manuel.

Schéma d'enregistrement des appareils dans une pizzeria :

Histoire de l'architecture Dodo IS : le chemin du back office

Architecture générale après l'extraction du service Auth and Devices :

Histoire de l'architecture Dodo IS : le chemin du back office

Noter. Pour 2020, nous travaillons sur une nouvelle version d'Auth, basée sur la norme d'autorisation OAuth 2.0. Cette norme est assez complexe, mais elle est utile pour développer un service d'authentification unique. Dans l'article "Subtilités d'autorisation : un aperçu de la technologie OAuth 2.0» nous Alexey Chernyaev avons essayé de parler de la norme aussi simplement et clairement que possible afin que vous gagniez du temps pour l'étudier.

Que fait Traqueur ?

Maintenant, environ le deuxième des services chargés. Le tracker joue un double rôle :

  • D'une part, sa tâche est de montrer aux employés de la cuisine quelles commandes sont actuellement en cours, quels produits doivent être cuits maintenant.
  • D'autre part, pour numériser tous les processus de la cuisine.

Histoire de l'architecture Dodo IS : le chemin du back office

Lorsqu'un nouveau produit apparaît dans une commande (par exemple, une pizza), il est dirigé vers la station de suivi du déploiement. À cette station, il y a un pizzaiolo qui prend un petit pain de la taille requise et le déroule, après quoi il note sur la tablette de suivi qu'il a terminé sa tâche et transfère la base de pâte roulée à la station suivante - "Initiation" .

Là, le pizzaiolo suivant remplit la pizza, puis note sur la tablette qu'il a terminé sa tâche et met la pizza au four (c'est aussi une station distincte qui doit être notée sur la tablette). Un tel système était dès le début dans Dodo et depuis le tout début de l'existence de Dodo IS. Il vous permet de suivre et de numériser entièrement toutes les transactions. De plus, le traceur suggère comment cuisiner un produit particulier, guide chaque type de produit selon ses schémas de fabrication, mémorise le temps de cuisson optimal pour le produit et suit toutes les opérations sur le produit.

Histoire de l'architecture Dodo IS : le chemin du back officeVoici à quoi ressemble l'écran de la tablette à la station du tracker "Raskatka"

D'où viennent les chargements ?

Chacune des pizzerias a environ cinq tablettes avec un tracker. En 2016, nous avions plus de 100 pizzerias (et maintenant plus de 600). Chacune des tablettes fait une requête au backend une fois toutes les 10 secondes et récupère les données de la table de commande (connexion avec le client et adresse), la composition de la commande (connexion avec le produit et indication de la quantité), la table de comptabilisation des motivations (le le temps de pressage y est enregistré). Lorsqu'un pizzaiolo clique sur un produit sur le tracker, les entrées de tous ces tableaux sont mises à jour. Le tableau des commandes est général, il contient également des insertions lors de l'acceptation d'une commande, des mises à jour d'autres parties du système et de nombreuses lectures, par exemple, sur un téléviseur suspendu dans une pizzeria et montrant les commandes terminées aux clients.

Pendant la période de lutte avec les charges, lorsque tout et tout était mis en cache et transféré vers la réplique asynchrone de la base, ces opérations avec le tracker continuaient à aller vers la base principale. Il ne devrait pas y avoir de décalage, les données doivent être à jour, la désynchronisation est inacceptable.

De plus, l'absence de tables et d'index propres à ceux-ci ne permettait pas d'écrire des requêtes plus spécifiques adaptées à leur utilisation. Par exemple, il peut être efficace pour un tracker d'avoir un index pour une pizzeria sur une table de commande. Nous supprimons toujours les commandes de pizzeria de la base de données du tracker. En même temps, pour recevoir une commande, il n'est pas si important de savoir à quelle pizzeria elle appartient, il est plus important de savoir quel client a passé cette commande. Et signifie là l'index sur le client est nécessaire. Il n'est pas non plus nécessaire que le tracker stocke l'identifiant du reçu imprimé ou des promotions bonus associées à la commande dans le tableau des commandes. Ces informations n'intéressent pas notre service de suivi. Dans une base de données monolithique commune, les tables ne pourraient être qu'un compromis entre tous les utilisateurs. C'était l'un des problèmes d'origine.

C'ÉTAIT. L'architecture d'origine était :

Histoire de l'architecture Dodo IS : le chemin du back office

Même après avoir été séparée en processus distincts, la majeure partie de la base de code est restée commune pour différents services. Tout ce qui se trouvait sous les contrôleurs était unique et vivait dans le même référentiel. Nous avons utilisé des méthodes communes de services, des référentiels, une base commune, dans laquelle se trouvaient des tables communes.

Traqueur de déchargement

Le principal problème avec le tracker est que les données doivent être synchronisées entre différentes bases de données. C'est aussi sa principale différence par rapport à la séparation du service Auth, la commande et son statut peuvent changer et doivent être affichés dans différents services.

Nous acceptons une commande à la caisse du restaurant (c'est un service), elle est stockée dans la base de données avec le statut "Acceptée". Après cela, il devrait se rendre au tracker, où il changera plusieurs fois de statut : de "Cuisine" à "Emballé". Dans le même temps, certaines influences externes de l'interface du caissier ou du gestionnaire d'équipe peuvent se produire avec la commande. Je vais donner les statuts de commande avec leur description dans le tableau :

Histoire de l'architecture Dodo IS : le chemin du back office
Le schéma de modification des statuts de commande ressemble à ceci :

Histoire de l'architecture Dodo IS : le chemin du back office

Les statuts changent entre les différents systèmes. Et ici, le tracker n'est pas un système final dans lequel les données sont fermées. Nous avons vu plusieurs approches possibles pour le partitionnement dans un tel cas :

  1. Nous concentrons toutes les actions de commande dans un seul service. Dans notre cas, cette option nécessite trop de service pour fonctionner avec la commande. Si nous nous y arrêtions, nous obtiendrions le deuxième monolithe. Nous ne résoudrions pas le problème.
  2. Un système passe un appel à un autre. La deuxième option est déjà plus intéressante. Mais avec lui, des chaînes d'appels sont possibles (pannes en cascade), la connectivité des composants est plus élevée, il est plus difficile à gérer.
  3. Nous organisons des événements, et chaque service communique avec un autre à travers ces événements. En conséquence, c'est la troisième option qui a été choisie, selon laquelle tous les services commencent à échanger des événements entre eux.

Le fait que nous ayons choisi la troisième option signifiait que le tracker aurait sa propre base de données, et pour chaque changement de commande, il enverrait un événement à ce sujet, auquel d'autres services s'abonnent et qui tombe également dans la base de données principale. Pour ce faire, nous avions besoin d'un service qui assurerait la livraison des messages entre les services.

À ce moment-là, nous avions déjà RabbitMQ dans la pile, d'où la décision finale de l'utiliser comme courtier de messages. Le diagramme montre la transition d'une commande du caissier du restaurant au traqueur, où elle change son statut et son affichage sur l'interface des commandes du gestionnaire. ACIER:

Histoire de l'architecture Dodo IS : le chemin du back office

Chemin de commande étape par étape
Le chemin de la commande commence à l'un des services source de la commande. Voici la Caissière du Restaurant :

  1. À la caisse, la commande est complètement prête, et il est temps de l'envoyer au tracker. L'événement auquel le tracker est abonné est lancé.
  2. Le traceur, acceptant une commande pour lui-même, l'enregistre dans sa propre base de données, créant l'événement "Commande acceptée par le traceur" et l'envoyant au RMQ.
  3. Plusieurs gestionnaires sont déjà abonnés au bus d'événements par commande. Pour nous, celui qui fait la synchronisation avec une base monolithique est important.
  4. Le gestionnaire reçoit un événement, y sélectionne une donnée qui lui est significative : dans notre cas, il s'agit du statut de la commande "Acceptée par le Tracker" et met à jour son entité de commande dans la base de données principale.

Si quelqu'un a besoin d'une commande à partir des commandes de table monolithiques, vous pouvez également la lire à partir de là. Par exemple, l'interface des commandes dans le gestionnaire d'équipe a besoin de ceci :

Histoire de l'architecture Dodo IS : le chemin du back office

Tous les autres services peuvent également s'abonner pour commander des événements auprès du tracker afin de les utiliser pour eux-mêmes.

Si après un certain temps la commande est prise en charge, son statut change d'abord dans sa base de données (base de données Tracker), puis l'événement "OrderIn Progress" est immédiatement généré. Il entre également dans RMQ, d'où il est synchronisé dans une base de données monolithique et livré à d'autres services. Il peut y avoir divers problèmes en cours de route, plus de détails à leur sujet peuvent être trouvés dans le rapport de Zhenya Peshkov sur les détails de mise en œuvre de la cohérence éventuelle dans le tracker.

Architecture finale après changements dans Auth et Tracker

Histoire de l'architecture Dodo IS : le chemin du back office

Résumant le résultat intermédiaire : Au départ, j'ai eu l'idée de regrouper les neuf années d'histoire du système Dodo IS en un seul article. Je voulais parler rapidement et simplement des étapes de l'évolution. Cependant, en m'asseyant pour le matériel, j'ai réalisé que tout est beaucoup plus compliqué et intéressant qu'il n'y paraît.

En réfléchissant aux avantages (ou à leur absence) d'un tel matériel, je suis arrivé à la conclusion qu'un développement continu est impossible sans des annales complètes des événements, des rétrospectives détaillées et une analyse de mes décisions passées.

J'espère qu'il vous a été utile et intéressant de découvrir notre parcours. Maintenant, je suis confronté à un choix quelle partie du système Dodo IS décrire dans le prochain article : écrire dans les commentaires ou voter.

Seuls les utilisateurs enregistrés peuvent participer à l'enquête. se connecters'il te plait.

Quelle partie de Dodo IS aimeriez-vous connaître dans le prochain article ?

  • 24,1%Premier monolithe de Dodo IS (2011-2015)14

  • 24,1%Premiers problèmes et leurs solutions (2015-2016)14

  • 20,7%Le parcours côté client : façade sur soubassement (2016-2017)12

  • 36,2%L'histoire des vrais microservices (2018-2019)21

  • 44,8%Sciage complet du monolithe et stabilisation de l'architecture26

  • 29,3%À propos des futurs projets de développement du système17

  • 19,0%Je ne veux rien savoir sur Dodo IS11

58 utilisateurs ont voté. 6 utilisateurs se sont abstenus.

Source: habr.com

Ajouter un commentaire