Les traductions sont fournies par des outils de traduction automatique. En cas de conflit entre le contenu d'une traduction et celui de la version originale en anglais, la version anglaise prévaudra.
Optimisation de l’autoscaling d’un service Amazon ECS
Un service Amazon ECS est un ensemble géré de tâches. Chaque service est associé à une définition de tâche, à un nombre de tâches souhaité et à une stratégie de placement facultative.
L’autoscaling d’un service Amazon ECS fonctionne via le service Application Auto Scaling. Application Auto Scaling utilise CloudWatch les métriques comme source pour le dimensionnement des métriques. Il utilise également des CloudWatch alarmes pour définir des seuils indiquant quand il faut étendre ou dédimensionner votre service.
Vous indiquez les seuils de mise à l’échelle. Vous pouvez définir une cible métrique, appelée mise à l’échelle du suivi de cible. Vous pouvez également spécifier des seuils, appelés mise à l’échelle par étapes.
Une fois que vous avez configuré Application Auto Scaling, celui-ci calcule en permanence le nombre de tâches souhaité pour le service. Il indique également à Amazon ECS lorsque le nombre de tâches souhaité doit changer, soit en l’augmentant, soit en le réduisant horizontalement.
Pour utiliser efficacement l’autoscaling du service, vous devez choisir une métrique de mise à l’échelle appropriée. Dans les sections suivantes, nous expliquons comment choisir une métrique.
Caractérisation de votre application
Pour dimensionner correctement une application, vous devez connaître les conditions dans lesquelles vous devez soit augmenter, soit réduire horizontalement votre application.
En substance, vous devez augmenter horizontalement votre application si la demande prévue dépasse la capacité disponible. À l’inverse, vous pouvez réduire horizontalement votre application pour réduire les coûts lorsque les ressources dépassent la demande.
Identification d’une métrique d’utilisation
Pour effectuer une mise à l’échelle efficace, vous devez identifier une métrique indiquant l’utilisation ou la saturation. Cette métrique doit présenter les propriétés suivantes pour être utile à la mise à l’échelle.
-
La métrique doit être corrélée à la demande. Lorsque vous maintenez les ressources stables mais que la demande change, la valeur de la métrique doit également changer. La métrique doit augmenter ou diminuer lorsque la demande augmente ou diminue.
-
La valeur de la métrique doit évoluer proportionnellement à la capacité. Lorsque la demande reste constante, l’ajout de ressources supplémentaires doit entraîner une modification proportionnelle de la valeur de la métrique. Ainsi, le doublement du nombre de tâches devrait entraîner une diminution de 50 % de la métrique.
Le meilleur moyen d’identifier une métrique d’utilisation consiste à effectuer des tests de charge dans un environnement de préproduction tel qu’un environnement intermédiaire. Les solutions de test de charge commerciales et open source sont largement disponibles. Ces solutions peuvent généralement générer une charge synthétique ou simuler le trafic utilisateur réel.
Pour démarrer le processus de test de charge, vous devez d’abord créer des tableaux de bord pour les indicateurs d’utilisation de votre application. Ces indicateurs incluent l'utilisation du processeur, l'utilisation de la mémoire, I/O les opérations, la profondeur des I/O files d'attente et le débit du réseau. Vous pouvez collecter ces statistiques avec un service tel que CloudWatch Container Insights. Vous pouvez également les collecter en utilisant Amazon Managed Service for Prometheus avec Amazon Managed Grafana. Au cours de ce processus, veillez à collecter et à représenter graphiquement les métriques relatives aux temps de réponse ou aux taux d’achèvement des tâches de votre application.
Lorsque vous effectuez un test de charge, commencez par un faible taux de requêtes ou d’insertion de tâches. Maintenez ce débit pendant plusieurs minutes afin de permettre à votre application de prendre la température. Ensuite, augmentez lentement le taux et maintenez-le stable pendant quelques minutes. Répétez ce cycle en augmentant le taux à chaque fois jusqu'à ce que les délais de réponse ou de traitement de votre demande soient trop lents pour atteindre vos objectifs de niveau de service ()SLOs.
Pendant le test de charge, examinez chacune des métriques d’utilisation. Les indicateurs qui augmentent en fonction de la charge sont les meilleurs candidats pour vous servir de meilleurs indicateurs d’utilisation.
Identifiez ensuite la ressource qui atteint la saturation. Dans le même temps, examinez également les métriques d’utilisation afin de déterminer laquelle se stabilise en premier à un niveau élevé. Vous pouvez également examiner laquelle atteint le pic, puis bloque votre application en premier. Par exemple, si l’utilisation de l’UC augmente de 0 % à 70-80 % à mesure que vous ajoutez de la charge, puis qu’elle reste à ce niveau une fois que vous ajoutez encore plus de charge, on peut affirmer sans risque de se tromper que l’UC est saturé. Selon l’architecture de l’UC, il se peut qu’il n’atteigne jamais 100 %. Supposons, par exemple, que l'utilisation de la mémoire augmente à mesure que vous ajoutez de la charge, puis que votre application se bloque soudainement lorsqu'elle atteint la limite de mémoire de la tâche ou de l' EC2 instance Amazon. Dans ce cas, il est probable que la mémoire ait été entièrement consommée. Plusieurs ressources peuvent être consommées par votre application. Par conséquent, choisissez la métrique qui représente la ressource qui s’épuise en premier.
Enfin, réessayez de tester la charge après avoir doublé le nombre de tâches ou d' EC2instances Amazon. Supposons que l’indicateur clé augmente ou diminue de moitié par rapport au taux précédent. Si tel est le cas, la métrique est proportionnelle à la capacité. Il s’agit d’un bon indicateur d’utilisation pour l’autoscaling.
Examinons maintenant ce scénario hypothétique. Supposons que vous soumettiez une application à un test de charge et que vous constatiez le résultat suivant : l’utilisation de l’UC atteint finalement 80 % à 100 requêtes par seconde. Lorsque vous ajoutez de la charge, l’utilisation de l’UC n’augmente plus. Cependant, cela ralentit la réponse de votre application. Ensuite, vous exécutez à nouveau le test de charge, en doublant le nombre de tâches tout en maintenant le taux à sa valeur maximale précédente. Si vous constatez que l’utilisation moyenne de l’UC tombe à environ 40 %, l’utilisation moyenne de l’UC est un bon candidat pour une métrique de mise à l’échelle. D’un autre côté, si l’utilisation de l’UC reste à 80 % après l’augmentation du nombre de tâches, l’utilisation moyenne de l’UC n’est pas une bonne métrique de mise à l’échelle. Dans ce cas, vous devrez effectuer des recherches supplémentaires afin de trouver une métrique appropriée.
Modèles d’application et propriétés de mise à l’échelle courants
Vous pouvez exécuter des logiciels de toutes sortes sur AWS. De nombreuses charges de travail sont développées en interne, tandis que d’autres sont basées sur des logiciels open source populaires. Quelle que soit leur origine, nous avons observé certains modèles de conception courants pour les services. La manière dont vous effectuez une mise à l’échelle efficace dépend en grande partie du modèle.
Serveur efficace lié à lUC
Le serveur efficace lié à l’UC n’utilise pratiquement aucune ressource autre que l’UC et le débit réseau. Chaque requête peut être traitée par l’application seule. Les requêtes ne dépendent pas d’autres services tels que les bases de données. L'application peut traiter des centaines de milliers de demandes simultanées et peut en utiliser plusieurs efficacement CPUs pour ce faire. Chaque requête est traitée soit par un thread dédié avec une faible surcharge de mémoire, soit par une boucle d’événements asynchrone qui s’exécute sur chaque UC qui traite les requêtes. Chaque réplica de l’application est également capable de traiter une requête. La seule ressource susceptible d’être épuisée avant l’UC est la bande passante du réseau. Dans les services liés à l’UC, l’utilisation de la mémoire, même au débit maximal, ne représente qu’une fraction des ressources disponibles.
Vous pouvez utiliser l’autoscaling basée sur l’UC pour ce type d’application. L’application bénéficie d’une flexibilité maximale en termes de mise à l’échelle. Vous pouvez le redimensionner verticalement en lui fournissant des EC2 instances Amazon ou Fargate v CPUs plus grandes. Et vous pouvez également la mettre à l’échelle horizontalement en ajoutant d’autres réplicas. L’ajout de réplicas supplémentaires, ou le doublement de la taille de l’instance, réduit de moitié l’utilisation moyenne de l’UC par rapport à la capacité.
Si vous utilisez la EC2 capacité d'Amazon pour cette application, pensez à la placer sur des instances optimisées pour le calcul, telles que la famille c5 orc6g.
Serveur efficace lié à la mémoire
Le serveur efficace lié à la mémoire alloue une quantité importante de mémoire par requête. En cas de simultanéité maximale, mais pas nécessairement de débit, la mémoire est épuisée avant que les ressources d’UC ne soient épuisées. La mémoire associée à une requête est libérée lorsque celle-ci prend fin. Des requêtes supplémentaires peuvent être acceptées dans la limite de la mémoire disponible.
Vous pouvez utiliser l’autoscaling basé sur la mémoire pour ce type d’application. L’application bénéficie d’une flexibilité maximale en termes de mise à l’échelle. Vous pouvez le dimensionner à la fois verticalement en lui fournissant des ressources de mémoire Amazon EC2 ou Fargate plus importantes. Et vous pouvez également la mettre à l’échelle horizontalement en ajoutant d’autres réplicas. L’ajout de réplicas supplémentaires ou le doublement de la taille de l’instance peut réduire de moitié l’utilisation moyenne de la mémoire par rapport à la capacité.
Si vous utilisez la EC2 capacité d'Amazon pour cette application, pensez à la placer sur des instances optimisées pour la mémoire, telles que la famille r5 orr6g.
Certaines applications limitées en mémoire ne libèrent pas la mémoire associée à une requête lorsqu’elle se termine, de sorte qu’une réduction de la simultanéité n’entraîne pas une réduction de la mémoire utilisée. Pour cela, nous vous déconseillons d’utiliser la mise à l’échelle basée sur la mémoire.
Le serveur basé sur les travailleurs
Le serveur basé sur les travailleurs traite une requête pour chaque thread de travail individuel l’une après l’autre. Les threads de travail peuvent être des threads légers, tels que des threads POSIX. Il peut également s’agir de threads plus lourds, tels que des processus UNIX. Quel que soit le type de thread, il existe toujours un nombre maximal de connexions simultanées que l’application peut prendre en charge. Généralement, la limite de simultanéité est définie proportionnellement aux ressources de mémoire disponibles. Si la limite de simultanéité est atteinte, l’application place des requêtes supplémentaires dans une file d’attente du backlog. Si la file d’attente du backlog est débordée, l’application rejette immédiatement les requêtes entrantes supplémentaires. Les applications courantes qui correspondent à ce modèle incluent le serveur Web Apache et Gunicorn.
La simultanéité des requêtes est généralement le meilleur indicateur pour dimensionner cette application. Étant donné qu’il existe une limite de simultanéité pour chaque réplica, il est important de procéder à une augmentation horizontale avant que la limite moyenne ne soit atteinte.
Le meilleur moyen d'obtenir des mesures de simultanéité des demandes est de demander à votre application de les communiquer à CloudWatch. Chaque réplica de votre application peut publier le nombre de requêtes simultanées sous forme de métrique personnalisée à une fréquence élevée. Nous recommandons de régler la fréquence au moins une fois par minute. Une fois que plusieurs rapports ont été collectés, vous pouvez utiliser la simultanéité moyenne comme métrique de mise à l’échelle. Vous calculez cette métrique en divisant la simultanéité totale par le nombre de réplicas. Par exemple, si la simultanéité totale est de 1 000 et que le nombre de réplicas est de 10, la simultanéité moyenne est de 100.
Si votre application se trouve derrière un Application Load Balancer, vous pouvez également utiliser la métrique ActiveConnectionCount de l’équilibreur de charge comme facteur dans la métrique de mise à l’échelle. Vous devez diviser la métrique ActiveConnectionCount par le nombre de réplicas pour obtenir une valeur moyenne. Vous devez utiliser la valeur moyenne pour la mise à l’échelle, par opposition à la valeur de comptage brute.
Pour que cette conception fonctionne de manière optimale, l’écart type de la latence de réponse doit être faible à des taux de requêtes bas. Nous recommandons que, pendant les périodes de faible demande, la plupart des requêtes soient traitées dans un délai court et qu’il n’y ait pas beaucoup de requêtes dont le traitement prend beaucoup plus de temps que la moyenne. Le temps de réponse moyen devrait être proche du 95e centile du temps de réponse. Dans le cas contraire, des dépassements de files d’attente pourraient en résulter. Cela entraîne des erreurs. Nous vous recommandons de fournir des réplicas supplémentaires si nécessaire pour atténuer le risque de débordement.
Serveur en attente
Le serveur en attente effectue un certain traitement pour chaque requête, mais son fonctionnement dépend fortement d’un ou de plusieurs services en aval. Les applications de conteneurs font souvent un usage intensif des services en aval tels que les bases de données et autres services d’API. La réponse de ces services peut prendre un certain temps, en particulier dans les scénarios de haute capacité ou de concurrence élevée. En effet, ces applications ont tendance à utiliser peu de ressources d’UC et à utiliser leur simultanéité maximale en termes de mémoire disponible.
Le service en attente convient soit au modèle de serveur limité à la mémoire, soit au modèle de serveur basé sur le travailleur, selon la conception de l’application. Si la simultanéité de l’application n’est limitée que par la mémoire, l’utilisation moyenne de la mémoire doit être utilisée comme métrique de mise à l’échelle. Si la simultanéité de l’application est basée sur une limite de travail, la simultanéité moyenne doit être utilisée comme métrique de mise à l’échelle.
Le serveur basé sur Java
Si votre serveur basé sur Java est lié à l’UC et s’adapte proportionnellement aux ressources d’UC, il convient peut-être au modèle de serveur efficace lié à l’UC. Si tel est le cas, l’utilisation moyenne de l’UC peut être appropriée comme métrique de mise à l’échelle. Cependant, de nombreuses applications Java ne sont pas liées à l’UC, ce qui les rend difficiles à mettre à l’échelle.
Pour de meilleures performances, nous vous recommandons d’allouer autant de mémoire que possible au segment de machine virtuelle Java (JVM). Les versions récentes de la JVM, y compris la mise à jour 191 ou ultérieure de Java 8, définissent automatiquement la taille du tas aussi grande que possible pour tenir dans le conteneur. Cela signifie qu’en Java, l’utilisation de la mémoire est rarement proportionnelle à l’utilisation des applications. À mesure que le taux de requêtes et la simultanéité augmentent, l’utilisation de la mémoire reste constante. Pour cette raison, nous ne recommandons pas de dimensionner les serveurs Java en fonction de l’utilisation de la mémoire. Au lieu de cela, nous recommandons généralement une mise à l’échelle en fonction de l’utilisation de l’UC.
Dans certains cas, les serveurs basés sur Java rencontrent un épuisement de la mémoire avant d’épuiser l’UC. Si votre application risque de s’épuiser en cas de forte simultanéité, le nombre moyen de connexions constitue la meilleure métrique de mise à l’échelle. Si votre application est susceptible de s’épuiser en tas à haut débit, le taux de requêtes moyen est la meilleure métrique de mise à l’échelle.
Serveurs qui utilisent d’autres environnements d’exécution avec récupérateur de mémoire
De nombreuses applications serveur sont basées sur des environnements d’exécution qui effectuent le récupérateur de mémoire, tels que .NET et Ruby. Ces applications serveur peuvent correspondre à l’un des modèles décrits précédemment. Cependant, comme pour Java, nous ne recommandons pas de dimensionner ces applications en fonction de la mémoire, car l’utilisation moyenne de la mémoire observée n’est souvent pas corrélée au débit ou à la simultanéité.
Pour ces applications, nous vous recommandons une mise à l’échelle en fonction de l’utilisation de l’UC si l’application est liée à l’UC. Dans le cas contraire, nous vous recommandons d’effectuer une mise à l’échelle en fonction du débit moyen ou de la simultanéité moyenne, en fonction des résultats de vos tests de charge.
Processeurs de tâches
De nombreuses charges de travail impliquent un traitement de tâches asynchrone. Il s’agit notamment des applications qui ne reçoivent pas de requêtes en temps réel, mais qui s’abonnent à une file d’attente pour recevoir des tâches. Pour ces types d’applications, la métrique de mise à l’échelle appropriée est presque toujours la profondeur de la file d’attente. La croissance des files d’attente indique que le travail en attente dépasse la capacité de traitement, tandis qu’une file d’attente vide indique qu’il y a plus de capacité que de travail à effectuer.
AWS les services de messagerie, tels qu'Amazon SQS et Amazon Kinesis Data Streams, fournissent des CloudWatch métriques qui peuvent être utilisées pour le dimensionnement. Pour Amazon SQS, ApproximateNumberOfMessagesVisible c’est la meilleure métrique. Pour Kinesis Data Streams, pensez à utiliser la métrique MillisBehindLatest publiée par la bibliothèque client Kinesis (KCL). Cette métrique doit être moyennée pour tous les consommateurs avant d’être utilisée à des fins de mise à l’échelle.