Comment combiner deux plates-formes en une seule et ne pas offenser les utilisateurs. Expérience des développeurs Yandex.Kew



L'année dernière, le service TheQuestion a rejoint Yandex. À cette époque, il y avait déjà un service similaire de questions et réponses - Yandex.Znatoki. Les connaisseurs avaient un large public et beaucoup de questions intéressantes, mais il n'y avait pas assez d'experts pour donner des réponses de haute qualité à ces questions. La Question, au contraire, avait une forte communauté d'experts, mais elle manquait de questions intéressantes. L'étape logique a été de combiner les deux services afin de tirer le meilleur parti de chacun d'eux. Mais comment faire si chaque service a sa propre base technologique, son propre contenu et ses propres utilisateurs?

Aujourd'hui, je vais vous expliquer comment notre équipe a résolu ce problème d'un point de vue technologique. Vous découvrirez quelles options de combinaison nous avons envisagées et lesquelles ont finalement choisi. Je vais vous parler de l '«API d'échange», de la migration de la base de données, de la mise en commun des profils et des tests backend. Et pourtant - à propos de la nuit du déménagement sans le droit de faire une erreur. Vous verrez que nous ne devions pas nous ennuyer.

La tâche de fusionner deux services en un seul n'est pas nouvelle, mais cela ne facilite pas la tâche. L'histoire connaît de nombreux exemples réussis (et pas si) d'intégration, mais, malheureusement, il n'y a pas de «solution miracle» et une instruction claire «faites cela et tout ira bien». Tout dépend beaucoup des spécificités des services combinés et du résultat souhaité.

Dans notre cas, l'objectif était le suivant: que tout le contenu jamais écrit sur chacun des sites soit disponible sur un service unifié, et que ses auteurs puissent le gérer.

Alors, comment combinez-vous les deux services de questions et réponses, qui semblent si similaires, mais si différents par essence? Le transfert de contenu et d'utilisateurs d'un service à un autre est très similaire au transfert d'un ancien appartement à un nouveau.

Seulement dans notre cas, l'utilisateur peut vivre simultanément dans deux appartements (Connoisseurs et TheQuestion), et vous devez le transporter soigneusement dans le troisième. Vous devez déplacer tous les meubles, les plantes, un chat et même du papier peint dans un nouvel appartement (c'est-à-dire des questions, des réponses, des commentaires, des likes), puis l'inviter à déménager.

Comment faire ça? Plusieurs options viennent immédiatement à l'esprit.

Option 1. Très mauvais.
Prenons simplement l'un des services, transférons tout le contenu à un autre (même si ce n'est plus facile) et fermons le service d'origine.

Cette option est très mauvaise du point de vue de l'utilisateur du premier service. Nous venons de démolir son ancienne maison et l'avons forcé à déménager dans une nouvelle. N'importe qui n'aimera pas cette attitude, et au lieu de bouger, il peut simplement aller au coucher du soleil. Pour nous, la principale valeur est la communauté des utilisateurs, nous n'avons donc pas prévu d'offenser qui que ce soit. Et hardiment passé à d'autres options.

Option 2. Mauvais
Ne changeons aucun des services, au lieu de cela, lancez-en un nouveau et intégré et ajoutez-y périodiquement le contenu des deux autres (par exemple, une fois par jour).

Dans ce cas, nous ne semblons pas aggraver l'utilisateur, mais nous ne faisons pas mieux non plus. Son ancien appartement reste inchangé, mais il ne sert à rien de déménager dans un nouvel appartement. Tous les voisins vivent également dans une vieille maison, une fleur qui vient d'être achetée ne sera transportée dans un nouvel appartement qu'après une journée. Un tel service unifié n'a aucune chance de devenir un nouveau foyer.

Option 3. Bon, mais complexe
Ne fermons aucun des services, nous dupliquerons instantanément le contenu et les profils sur le service intégré, et les gens évolueront avec le temps.

Tous les voisins de l'utilisateur (et même le chat) vivent simultanément dans l'ancienne et dans la nouvelle maison. Une fleur que vous venez d'acheter apparaît instantanément dans un nouvel appartement. Exactement ce qui est nécessaire! Cette option est la plus confortable du point de vue de l'utilisateur. Par conséquent, nous l'avons choisi.

Commencez à bouger


Ce que nous avons finalement fait peut être décrit en plusieurs phrases. Nous avons complètement répété l'intégralité du backend de l'API TheQuestion sur la base du backend Connoisseurs, obtenant ainsi un seul backend qui peut fonctionner avec deux (et même trois) sites à la fois. Dans le même temps, le frontend TheQuestion est resté pratiquement inchangé, ce qui signifie que du point de vue des utilisateurs, le site lui-même n'a pratiquement pas changé. Ce projet a reçu le nom interne "swap API". Mais tout d'abord.

Ce que nous avions à l'entrée: deux sites complètement indépendants. Les connaisseurs vivent dans les nuages ​​intérieurs de Yandex. Le backend Connoisseurs est écrit en Python. TheQuestion vit dans les nuages ​​de Microsoft Azure, le backend TheQuestion est écrit en Go. Les services ont un schéma de stockage des données complètement différent dans les bases de données. De plus, TheQuestion a deux applications mobiles (pour Android et iOS), qui devaient également être prises en charge. En général, l'ennemi ne veut pas unir un tel zoo.



Étape 0. Entrez dans le cloud Yandex


À strictement parler, cette étape n'est pas nécessaire pour l '«API de plugin», mais elle simplifie considérablement les étapes suivantes. À ce stade, nous avons complètement abandonné le stockage et les installations externes. TheQuestion a commencé à utiliser les serveurs DNS Yandex. Les services rentme ont été déplacés vers Yandex.Cloud. La base de données a été transférée aux bases de données gérées Yandex. Pendant le déménagement, nous avons également pu trouver et corriger plusieurs erreurs dans TheQuestion, par exemple, des connexions non fermées à Redis dans le code 2015. En bonus, nous avons également reçu une puissance supplémentaire pour TheQuestion.

Étape 1. Migration des données


Quelle que soit l'option que vous souhaitez combiner, nous devons dans tous les cas combiner les données. Pour une seule base de données, ils ont décidé de prendre PostgreSQL - ce SGBD a déjà été utilisé à la fois par Experts et TheQuestion. Afin de ne pas compliquer le projet, ils n'ont pas commencé à créer une troisième base pour le service intégré, mais ont simplement pris la base de données Znatokov et l'ont développée afin qu'elle puisse accepter toutes les données de TheQuestion. Ce fut le premier défi technologique majeur.

Chaque entrée de chaque table de la base de données TheQuestion devait être convertie et placée dans la base de données Expert. Ensuite - corréler chaque colonne de l'une et de l'autre base. De nombreux champs ont dû être convertis de manière non triviale d'un format à un autre. Ainsi, une grande sous-tâche distincte était la conversion du format de stockage de texte (le format réel du stockage de questions ou de réponses) de QML (TheQuestion) en Markdown (Experts).

Nous avons mis en place un processus régulier (plusieurs fois par jour) de transfert de nouvelles données d'une base de données à une autre, mais en même temps nous nous sommes assurés que les données de TheQuestion n'étaient affichées nulle part avant la fin de l'étape suivante. Parce que "plusieurs fois par jour" est loin d'être promis "instantanément", et les données pourraient être dans un état incohérent avec les mêmes données sur TheQuestion, ce qui induirait les utilisateurs en erreur. Alors, pourquoi avons-nous commencé avec la migration des données si le backend n'était pas encore prêt?

Premièrement, nous avons ainsi stabilisé le processus. Deuxièmement, ils ont réduit la quantité de nouvelles données qui devront être transférées à l'avenir, ce qui est important, car tout le contenu importé devait passer par le balisage pour la qualité, le contenu inapproprié, le spam, la fraude.



Étape 2. "Swapping API"


Nous avons donc résolu le premier des problèmes - nous avons appris à prendre le contenu de la base de données TheQuestion et même à l'afficher si vous le souhaitez. Maintenant, il était nécessaire de faire entrer ce contenu dans la base de données intégrée instantanément, et pas plusieurs fois par jour.

Pour ce faire, il a fallu réécrire l'ensemble du backend TheQuestion avec toute la logique nécessaire. Le nom du projet, "Swap API", à proprement parler, ne reflète pas entièrement l'essence. Il serait plus correct de l'appeler "Swap backend". Le fait est que, outre la mise en œuvre directe de tous les «stylos» nécessaires au fonctionnement du front-end TheQuestion, d'autres possibilités ont dû être réalisées. Nous avons été confrontés à plusieurs tâches majeures.

AutorisationYandex dispose d'un système d'autorisation utilisateur centralisé - Yandex.Passport. Et les connaisseurs, bien sûr, ont utilisé le passeport. Pour vous y connecter, vous devez avoir un compte dans Yandex. C'était ça le problème. Tous les utilisateurs de TheQuestion ne se sont pas connectés au site via Yandex (bien qu'il y ait eu une telle opportunité). De nombreux utilisateurs n'avaient pas du tout de connexion Yandex et sont passés par les réseaux sociaux (VKontakte, Facebook ...). Naturellement, nous devions conserver cette fonctionnalité lors du déplacement. Par conséquent, nous avons mis en place une autorisation «sans passeport».

Recherche du site.TheQuestion a implémenté une recherche sur les questions, les réponses, les utilisateurs et les sujets. Pour la recherche, une solution tierce Sphinx a été utilisée. Évidemment, si nous parlons d'un seul service, la recherche doit être la même, c'est-à-dire qu'elle ne peut pas fonctionner sur deux systèmes à la fois. Ainsi, Sphinx a été abandonné au profit d'un moteur de recherche interne prenant en charge les fonctionnalités nécessaires et l'indexation de tout le contenu de TheQuestion.

Envoi de pages en Zen et Turbo . Au moment de l'adhésion, TheQuestion utilisait déjà les technologies Yandex. Les pages Turbo étaient prises en charge, un contenu intéressant tombait dans le flux Zen. Tout cela devait également être pris en charge dans "l'API de remplacement".

Notifications dans le service et les applications, listes de diffusion.Tout ce qui concerne la notification des utilisateurs: abonnements, newsletters avec un contenu intéressant, push sur les likes et les commentaires, bien plus. Tout cela devait être soigneusement transféré et non oublié.

Système d'administration du site . Ce paragraphe fait référence à tout ce qui concerne la gestion interne du service: modération, analyse, etc.

Système d'évaluation unifié des utilisateurs.Cette tâche n'était pas technique mais logique. Formellement, il n'est pas nécessaire de développer un système de notation unifié pour une «API de swap», mais ce système est toujours nécessaire pour le futur service intégré. Sur les deux sites, les utilisateurs ont été évalués pour la quantité et la qualité du contenu créé. Les détails de l'évaluation n'ont pas été divulgués, mais plus vous répondez souvent et mieux aux questions, plus votre évaluation est élevée. Les principes de notation étaient les mêmes pour les deux services, mais la formule elle-même et les facteurs étaient très différents. Il fallait non seulement comparer correctement et honnêtement les utilisateurs de Znatokov et TheQuestion entre eux, mais aussi apprendre à considérer une seule note pour les experts qui ont écrit sur deux services à la fois.

Et réécrivez toutes les API.Qu'on le veuille ou non, cette tâche était la plus importante et la plus difficile. De nombreux processus sur les services étaient similaires, nous les avons donc pris aux connaisseurs et nous n'avons pas écrit à partir de zéro. Mais il y avait aussi beaucoup de nouvelles choses, par exemple, des lignes droites d'utilisateurs ou des ébauches de réponses. En conséquence, nous avons réécrit plus de 100 «plumes» dans la «swap API» et implémenté plus de 50 ressources REST.

Après avoir implémenté toutes les fonctionnalités décrites ci-dessus, il a été possible de commencer à bouger. Mais avant, nous avons fait un tour.

Il est clair qu'avant de commuter et de déployer l '«API de swap» en production, elle devait être très bien testée. Tout d'abord, il fallait le tester fonctionnellement, c'est-à-dire vérifier directement les performances de l'ensemble du site sur la nouvelle API. Deuxièmement, c'est stressant. Nous voulions être sûrs à 100% que notre conception ne «mentirait» pas sous la charge. Naturellement, nous avons régulièrement effectué des «tir de charge», ce qui a montré que nous avons une bonne offre de performances. Mais en matière de performances de service, il est toujours préférable de jouer en toute sécurité. Tous les tests de charge synthétique, même les meilleurs, sont en quelque sorte différents de la charge de production. Par conséquent, nous avons décidé, avant de changer l'API, de remplir la charge de production sur notre stand.

Pour ce faire, chez TheQuestion frontend, nous avons implémenté la duplication de toutes les requêtes GET (c'est-à-dire les requêtes de données, pas les modifications) dans deux API à la fois: la «vieille API» TheQuestion, qui était à l'époque la principale, et la secondaire «swap API». Dans le même temps, le frontend n'a pas attendu de réponse API mineure et n'a pas géré les erreurs, mais de cette façon, nous avons pu tester le backend sur de vrais utilisateurs.



Étape 3. Et puis nous nous sommes souvenus des applications


Non, bien sûr, nous nous sommes souvenus d'eux tout ce temps, mais nous avons été confrontés à un problème. Ceux qui ont travaillé avec des applications mobiles savent que les tracas avec eux sont bien plus qu'avec le site. Cela est dû principalement à la distribution de nouvelles versions.

Tout d'abord, vous devez travailler avec des services externes de l'App Store et de Google Play et attendre que les nouvelles versions passent la vérification (et parfois la vérification peut prendre un temps considérable). Deuxièmement, même si votre application a déjà réussi le test et est apparue dans le magasin, cela ne signifie pas que les utilisateurs effectueront une mise à jour.

Dans le cas de l'interface du site, les développeurs contrôlent eux-mêmes quand une nouvelle version est publiée, et ils savent avec certitude qu'après cela, tous les utilisateurs recevront une version mise à jour du site. Dans le cas des applications, il n'y a pas de telle garantie. Pour obtenir une telle garantie, ils utilisent souvent la «mise à jour forcée» de l'application. Peu de gens aiment cette méthode et, bien sûr, toujours, si possible, vous devez maintenir une compatibilité descendante entre l'application et le backend. Par conséquent, nous avons choisi de faire des changements précisément du côté du backend avec un minimum de changements du front dans les applications. Mais, comme cela arrive souvent, le plan est confronté à une dure réalité.

Certaines modifications ont été beaucoup plus faciles à faire du côté frontal que du serveur principal, par conséquent, dans le processus de développement d'une «API de plug-in», le frontal était légèrement, mais a changé. En particulier, l'ancienne base de données TheQuestion utilisait des ID numériques 64 bits. La base de données Connoisseurs et, par conséquent, la base de données combinée et la nouvelle API pour TheQuestion utilisaient des ID de chaîne 128 bits. En général, pour un frontend écrit en Node.js, cette différence n'est pas significative. Mais pour les applications fortement typées, cela s'est avéré fatal. Nous avons perdu la compatibilité descendante et les anciennes applications ne pouvaient pas fonctionner avec l '"API de plug-in".

À un moment donné, même un projet appelé «API de plugin pour API de plugin» est apparu, dont l'essence était d'écrire une petite couche entre le nouveau backend et les applications qui convertiraient toutes les données dans l'ancien format. Cependant, nous avons rapidement abandonné cette idée. Cette couche se révélerait être une «béquille» très rigide, ce qui, à l'avenir, nous poserait certainement de nombreux problèmes. Par exemple, vous ne pouvez pas simplement prendre et traduire des ID 128 bits en ID 64 bits. Je devrais traduire avec une perte d'informations et, par conséquent, des collisions possibles par ID, ou maintenir une table intermédiaire avec la correspondance des ID anciens et nouveaux (pour tous les éléments de la base de données). À la fois cela et un autre - pas la meilleure solution architecturale.

En plus de l'ID, il y avait un certain nombre d'autres changements qui étaient également beaucoup plus faciles à prendre en charge du côté frontal et de l'application. En conséquence, nous avons décidé de mettre en œuvre des changements dans les applications et d'utiliser toujours la mise à jour forcée. En peu de temps, nous avons développé de nouvelles versions d'applications compatibles avec la «swap API», car il n'y avait pas tellement de changements par rapport au frontal et ils n'étaient pas très sérieux. Envoyé sur l'App Store et Google Play, modéré avec succès et a commencé à attendre.

Étape X. Allons-y!


Donc, tout le code est écrit. Le support avec "l'API de remplacement" est testé et déclenché. De nouvelles versions de l'application ont été testées en magasin et sont prêtes à être publiées. Maintenant, tout cela devait être déployé en production.

Étant donné que la copie de nouvelles données de l'ancienne base de données vers la nouvelle s'effectue de manière asynchrone et prend un certain temps, vous ne pouvez pas basculer le backend (et la base de données en dessous) sur un site de travail. Cela peut entraîner la perte ou l'incohérence des données utilisateur. Par conséquent, nous avons choisi une date, averti les utilisateurs et préparé une plaque «Travaux techniques en cours».

Et puis l'heure est venue, ou plutôt la nuit X. Le plan de déploiement ressemblait à ceci:

  1. Sur le site TheQuestion nous accrochons un talon "Le travail est en cours".
  2. Nous transférons les applications en mode lecture seule. Les utilisateurs peuvent lire le contenu de l'ancienne base de données, mais ne peuvent pas en créer de nouveau.
  3. TheQuestion Readonly. : . , , .
  4. . , .
  5. .
  6. , , API.
  7. API . — , API .
  8. , , .
  9. « », API.
  10. .

Eh bien, ça n'a pas l'air si effrayant. En réalité, tout s'est bien passé. Parmi les surprises que nous avons rencontrées, la publication de l'application dans l'App Store n'a peut-être été que trop longue (l'application a été vérifiée à l'avance, il s'agissait uniquement d'apparaître dans la boutique). Au final, cela a pris plusieurs heures, c'est pourquoi toute l'opération a été un peu retardée.

De plus, dans le processus de changement, il y avait une caractéristique clé qui compliquait tout à plusieurs reprises et augmentait les responsabilités. Le fait est que le processus de commutation n'a pas pu être inversé.

Bien que le processus de copie et de conversion des données de l'ancienne base de données TheQuestion vers la nouvelle base de données intégrée ait été mis en place et débogué pour nous, il n'y a pas eu de processus de copie inverse (de la nouvelle base de données à l'ancienne). Cela signifie que dès que nous ouvrons le site sur «swap API» et que nous démarrons le trafic utilisateur, toutes les questions, réponses, commentaires et likes nouvellement créés ne peuvent plus facilement accéder à l'ancienne base de données TheQuestion. Si quelque chose se passe mal après l'ouverture, par exemple, une seule base de données ne peut pas faire face à la charge, il ne sera pas possible de tout restaurer rapidement.

En fait, bien sûr, j'exagère. Dans tous les cas, nous ne perdrions pas de données utilisateur. Nous avions un plan B et un moyen de sauvegarder manuellement les données d'une nouvelle base de données sur une ancienne. Mais cela prendrait encore un certain temps, et la restauration n'aurait pas eu lieu sans douleur pour les utilisateurs.

Heureusement, le plan A a fonctionné et rien n'a dû être annulé.



Étape finale


Ainsi, le backend a été changé, la base de données a été combinée, les applications mobiles n'ont pas été oubliées. Pour les utilisateurs, rien n'a changé, car le site Yandex.Ku, qui était censé combiner les données des deux sites, n'était pas encore lancé à l'époque. Et pour son lancement, nous devions résoudre un problème de plus.

Au tout début, j'ai écrit que nous devions combiner non seulement les questions et réponses de deux services en un nouveau, mais aussi les utilisateurs. Les utilisateurs auraient dû non seulement voir leur contenu sur Kew, mais aussi le gérer sur Kew. Techniquement, combiner des données et transférer des droits de gestion n'est pas difficile. Il est beaucoup plus difficile de s'assurer que les droits sont transférés à celui à qui ils doivent être transférés.

Lors du passage de Znatokov à Kew, tout est simple: dans les deux cas, le même compte Yandex est utilisé. Mais TheQuestion a son propre compte, qui ne peut pas être autorisé sur Kew. Heureusement, nous y avons pensé au préalable. Bien avant les actions décrites ci-dessus, nous avons permis aux utilisateurs de TheQuestion de lier leurs profils Yandex. Et au moment de la consolidation physique des services, plus de 90% des utilisateurs actifs l'avaient fait. Cela nous a permis de démarrer sans peine la migration du contenu et des utilisateurs.

Total


Lorsque nous avons déménagé, nous voulions sauver chaque utilisateur, nous avons donc consciemment opté pour l'option la plus longue et la plus risquée de combiner les plateformes. Nous avons créé une base technologique unifiée, appris à transporter instantanément du contenu et des profils. Au lieu d'une fermeture inattendue et d'une relocalisation forcée, ils ont conservé la fonctionnalité des anciens services, en ont lancé un nouveau et ont expliqué ses avantages.



Nous avons lancé Yandex.Kew l'année dernière. Aujourd'hui, plus de 80% des auteurs actifs de TheQuestion et Znatokov ont déménagé volontairement dans une nouvelle maison.

All Articles