Passer à des espaces de travail plus grands sans faire attendre qui que ce soit
Chaque projet Mythex obtient son propre espace de travail : un petit ordinateur infonuagique où l'agent écrit le code et où l'aperçu de votre application tourne. Nous avions fait passer la mémoire des nouveaux espaces de travail de 1 Go à 2 Go, mais les anciens étaient restés à 1 Go, soit environ un quart d'entre eux le jour où nous avons vérifié. Notre première correction déplaçait un projet vers un espace plus grand lorsqu'on l'ouvrait de nouveau. Dès son premier jour en production, elle a fait attendre une personne sept minutes. Nous avons alors mis une limite de temps stricte, puis retiré le déplacement de l'ouverture d'un projet.
Pourquoi les anciens espaces restaient petits
Notre fournisseur de bacs à sable fixe la taille d'un espace de travail à sa création, et la conserve à chaque pause et reprise. Modifier le gabarit, c'est-à-dire la recette à partir de laquelle les nouveaux espaces sont construits, ne touche que les espaces créés après le changement. Rien ne redimensionne ceux qui existent déjà.
Cela comptait. Un des petits espaces a manqué de mémoire pendant un git push alors que son aperçu démarrait, et il n'a plus répondu pendant 11 minutes. Une publication a échoué à cause de cela.
Première tentative : déplacer le projet au réveil
Les espaces de travail se mettent en pause lorsque personne ne les utilise et se réveillent à l'ouverture du projet. Le réveil semblait être le bon moment pour déplacer un projet, puisque personne ne travaille encore dedans.
Le déplacement fonctionnait ainsi :
- Vérifier la taille. Si l'espace est plus petit que 2 Go, le déplacer. Si sa taille est inconnue, ne rien faire.
- Ne pas perturber une publication. Une publication lit les fichiers de l'espace; si elle est en cours, passer le déplacement.
- Empaqueter le projet. Archiver tout le projet, y compris son historique git, c'est-à-dire chaque point de contrôle du projet, et le fichier
.envde l'application, qui appartient au propriétaire, mais exclure les dépendances installées (node_modules), qui peuvent être réinstallées. - Copier directement. Diffuser l'archive de l'ancien espace vers un nouvel espace de 2 Go, pour qu'elle n'ait jamais à tenir dans la mémoire de notre propre serveur.
- Comparer avant de basculer. Compter les fichiers, lire le dernier point de contrôle et compter les points de contrôle, dans les deux espaces. Basculer seulement si les trois correspondent.
- Garder l'ancien en cas d'échec. Toute erreur ou toute différence jette le nouvel espace et ouvre le projet dans l'ancien, comme avant.
Un détail de la comparaison comptait plus qu'il n'y paraît. La vérification s'exécute sous le compte administrateur, et git refuse de lire un dépôt appartenant à un autre utilisateur. Des deux côtés, elle n'affichait rien, et « rien » correspondait à « rien », donc la vérification réussissait sans comparer le moindre historique. Nous avons dit à git de faire confiance au répertoire, et ajouté un test pour que cela ne se reproduise pas.
Ce qui a mal tourné le premier jour
Le premier jour en production, l'empaquetage d'un projet a atteint une limite de cinq minutes pour une commande, pendant le réveil. Le propriétaire a attendu sept minutes que son espace de travail s'ouvre. Et comme le déplacement avait échoué, le projet était resté petit; la prochaine ouverture aurait donc recommencé et l'aurait fait attendre de nouveau.
Une migration qui oblige quelqu'un à attendre pour ouvrir son propre projet est un mauvais compromis. Tout l'intérêt de la faire au réveil était que personne ne le remarque.
Deuxième tentative : un budget strict
Le même jour, nous avons changé quatre choses :
- Une minute pour tout le déplacement. Chaque étape (vérifier la taille, empaqueter, créer le nouvel espace, copier, décompresser, comparer) se partage un seul budget de 60 secondes. Lorsqu'il est épuisé, le projet s'ouvre dans l'ancien espace.
- Arrêter le travail, pas seulement l'attente. Abandonner de notre côté ne suffit pas si l'archivage continue dans l'espace que le propriétaire est sur le point d'utiliser. Chaque commande d'archivage est maintenant interrompue dans l'espace lui-même, peu avant la fin du budget. Si le nouvel espace arrive après que nous avons abandonné, il est jeté.
- Ne pas faire attendre le propriétaire pendant le nettoyage. La suppression de l'archive temporaire se fait maintenant en arrière-plan.
- Ne pas réessayer à chaque ouverture. Un projet qui n'a pas pu être déplacé est laissé tranquille pendant 24 heures, afin qu'un échec coûte au plus un délai par jour, et non un par ouverture.
Troisième tentative : sortir le déplacement du réveil
Cela ramenait le pire cas à une minute. Mais une minute reste une minute, et nous avons réalisé que le déplacement n'avait pas besoin de se trouver sur le chemin de qui que ce soit.
Aucun espace n'est plus créé à 1 Go. Il ne s'agit donc pas d'un processus continu, mais d'une tâche unique avec une liste fixe d'espaces. La faire dans le réveil signifiait qu'une vraie personne payait pour chaque déplacement lent, et que la seule façon de savoir qu'un espace ne se déplacerait pas était que quelqu'un vienne d'attendre.
Nous avons donc retiré le déplacement du réveil. Ouvrir un projet fait ce qu'il faisait avant. Les petits espaces restants sont traités comme un lot supervisé : personne n'attend, et un espace qui ne peut pas être déplacé apparaît dans le rapport du lot, où nous pouvons le regarder, plutôt que devant la personne qui en est propriétaire.
Ce que nous en retenons
- Le redimensionnement n'est pas toujours possible. Quand une plateforme fixe une taille à la création, augmenter la valeur par défaut n'aide que les nouvelles ressources. Prévoyez pour les anciennes.
- « Personne ne l'utilise encore » signifie quand même que quelqu'un attend. Le travail fait à l'entrée d'un produit est un travail qu'une personne observe.
- Donnez un budget à tout ce qui se trouve sur le chemin d'un utilisateur, et arrêtez le travail quand il est épuisé. Dépasser le délai de notre côté pendant qu'une commande continue ailleurs ne fait que déplacer le problème.
- Une migration ponctuelle appartient à une tâche ponctuelle. La cacher dans les actions de tous les jours la rend moins coûteuse à écrire et plus coûteuse à exécuter.
- Testez vos vérifications de sécurité. Une comparaison qui ne compare rien ressemble exactement à une comparaison réussie.
Si vous construisez sur Mythex, il n'y a rien à faire : le but est simplement d'avoir moins d'espaces qui manquent de mémoire, tout en ouvrant un projet aussi vite qu'avant. La façon dont les espaces de travail se mettent en pause et se réveillent est décrite dans la documentation, sous espace de travail privé. Pour une autre histoire de manque de mémoire, voir le plantage par manque de mémoire caché derrière une étiquette de progression.