Exporter (0) Imprimer
Développer tout

Meilleures pratiques pour la création de services à grande échelle sur les services Azure Cloud Services

Mis à jour: janvier 2014

Auteurs : Mark Simms et Michael Thomassy

Auteurs collaborateurs : Jason Roth et Ralph Squillace

Réviseurs : Brad Calder, Dennis Mulder, Mark Ozur, Nina Sarawgi, Marc Mercuri, Conor Cunningham, Peter Carlin, Stuart Ozer, Lara Rubbelke et Nicholas Dritsas.

Le cloud computing consiste en une informatique distribuée ; l'informatique distribuée nécessite une planification et un déploiement réfléchis, quelle que soit la plateforme choisie. L'objectif de ce document est de fournir des conseils avisés sur des scénarios client réels de création d'applications évolutives dans Azure et la Base de données SQL, en tirant profit de l'approche Plateforme en tant que service (PaaS) ; ces applications sont créées en tant que services Azure Cloud Services, à l'aide de rôles Web et de travail.

ImportantImportant
REMARQUE : toutes les meilleures pratiques contenues dans ce document découlent des engagements profonds pris auprès des clients qui exécutent un code de production dans Azure. Ce document présente la plateforme Services de cloud computing Azure (PaaS) basée sur la version 1.6 du Kit de développement logiciel (SDK) ; il ne couvre pas les fonctionnalités à venir telles que les Sites Web Azure et les Machines virtuelles Azure (IaaS).

Ce document traite des concepts de conception sous-jacents pour générer des applications Azure, des principales fonctions, limites et fonctionnalités de la plateforme Azure, ainsi que des meilleures pratiques pour l'utilisation des principaux services Azure. Une attention particulière est portée à ces applications adaptées à une banque de données distribuées de façon globalement cohérente (par opposition aux modèles de données multi-locataires strictement cohérents ou à grande densité).

La transition de vos applications et services vers Azure peut être intéressante pour de nombreuses raisons, notamment :

  • les économies ou les consolidations des dépenses d'investissement en dépenses d'exploitation (capex en opex) ;

  • la réduction des coûts (et l'amélioration de l'efficacité) en faisant mieux correspondre la demande et la capacité ;

  • l'amélioration de la réactivité et du délai de mise sur le marché en réduisant ou supprimant les limitations liées à l'infrastructure ;

  • l'élargissement du public visé vers de nouveaux marchés, tels que les appareils mobiles ;

  • l'avantage d'une évolution massive du cloud computing en créant des applications qui peuvent prendre en charge un public international dans des centres de données répartis dans différents points géographiques.

Il existe de nombreuses et excellentes raisons techniques de développer de nouvelles applications ou de déplacer tout ou partie d'une application existante vers Azure. Lorsque l'environnement offre un grand nombre de choix d'implémentations, il est important d'évaluer attentivement votre modèle d'application afin de sélectionner l'approche d'implémentation appropriée. Certaines applications sont adaptées aux services Azure Cloud Services (approche de plateforme en tant que service, ou PaaS), alors que d'autres peuvent bénéficier d'une approche partielle ou complète d'infrastructure en tant que service (ou IaaS), telles que les machines virtuelles Azure. Enfin, certaines exigences applicatives peuvent être satisfaites en combinant les deux.

Votre application doit présenter un ou plusieurs des trois aspects essentiels suivants afin d'optimiser les avantages des services Azure Cloud Services. (Tous ces aspects ne doivent pas être présents dans votre application ; une application peut très bien dégager un important retour sur investissement en utilisant à bon escient Azure avec un seul des aspects suivants. Toutefois, une charge de travail qui ne présente aucune de ces caractéristiques n'est probablement pas adaptée aux services Azure Cloud Services.)

Les aspects importants pour l'évaluation d'une application sont :

  • Demande élastique. L'une des propositions de valeur clés de la transition vers Azure est l'évolution élastique, c'est-à-dire la possibilité d'ajouter ou de supprimer des capacités de l'application (montée en charge horizontale et mise à l'échelle) pour mieux correspondre à la demande des utilisateurs dynamique. Si votre charge de travail présente une demande constante et statique (par exemple, un nombre constant d'utilisateurs ou de transactions), cet avantage des services Azure Cloud Services n'est pas optimisé.

  • Utilisateurs et appareils distribués. L'utilisation d'Azure permet de bénéficier d'un accès instantané au déploiement global des applications. Si votre charge de travail dispose d'une base d'utilisateurs captifs exécutée dans un seul emplacement (tel qu'un seul bureau), le déploiement en cloud peut ne pas fournir le retour sur investissement optimal.

  • Charge de travail configurable en partition. Les applications de cloud évoluent par montée en charge horizontale, et par conséquent en ajoutant des capacités par segments plus petits. Si votre application dépend d'une montée en charge verticale (par exemple, des bases de données et entrepôts de données plus volumineux) ou qu'il s'agit d'une charge de travail dédiée spécialisée (par exemple, un stockage haute vitesse unifié et volumineux), elle doit être décomposée (partitionnée) pour que son exécution sur des services avec montée en charge horizontale soit possible dans le cloud. En fonction de la charge de travail, il peut s'agir d'un exercice relativement compliqué.

En résumé : lors de l'évaluation de votre application, vous pouvez obtenir un retour sur investissement élevé dans la transition vers Azure Cloud Services, ou la création de tels services, si votre charge de travail ne présente qu'un des trois aspects ci-dessus, caractéristiques d'un environnement PaaS comme Azure Cloud Services. Les applications qui présentent les trois caractéristiques sont susceptibles d'offrir un fort retour sur investissement.

Alors que de nombreux aspects de la conception d'applications pour Azure sont bien connus dans le cadre d'un développement sur site, il existe plusieurs différences clés dans le comportement de la plateforme et des services sous-jacents. La compréhension de ces différences, et par conséquent de la conception pour la plateforme, et non sur elle, est cruciale pour le déploiement d'applications qui tiennent les promesses de l'évolution élastique dans le cloud.

Cette section présente cinq concepts principaux qui sont des points essentiels de conception pour générer des applications de montée en charge horizontale largement distribuées, à grande échelle pour les environnements PaaS (Plateforme en tant que service) comme les services Azure Cloud Services. La maîtrise de ces concepts vous permettra de créer et de générer des applications qui ne fonctionnent pas simplement sur les services Azure Cloud Services, mais d'en tirer profit au maximum, pour bénéficier autant que possible des avantages de votre investissement. Tous les éléments à prendre en considération et choix de conception présentés plus loin dans ce document se rattachent à l'un de ces cinq concepts.

En outre, il est à noter que lorsque plusieurs de ces éléments et meilleures pratiques sont affichés par l'intermédiaire d'une application .NET., les approches et concepts sous-jacents sont grandement agnostiques du point de vue de la langue ou de la plateforme.

La principale différence du passage d'une application sur site aux services Azure Cloud Services est liée à la façon dont les applications évoluent. La méthode traditionnelle de génération d'applications de grande taille repose sur une combinaison de montée en charge horizontale (serveurs Web sans état et d'applications) et de montée en charge verticale (achat d'un système multicœur/volumineux plus grand, serveur de base de données, génération d'un grand centre de données, etc.). Dans le cloud, la montée en charge verticale n'est pas une option réaliste ; le seul moyen d'obtenir des applications réellement évolutives constitue à recourir à une conception explicitement définie pour la montée en charge horizontale.

Étant donné que nombre des éléments d'une application sur site sont déjà adaptés à la montée en charge horizontale (serveurs Web, serveurs d'applications), la difficulté consiste à identifier les aspects de l'application qui dépendent d'un service de montée en charge verticale et de les convertir (ou mapper) vers une implémentation avec montée en charge horizontale. Le meilleur candidat pour la dépendance à la montée en charge verticale est généralement la base de données relationnelle (SQL Server/Base de données SQL Azure).

Les conceptions relationnelles traditionnelles se sont concentrées autour d'un modèle de données globalement cohérent (montée en charge verticale à serveur unique) avec une cohérence forte et un comportement transactionnel. Traditionnellement, pour que cette banque de stockage puisse évoluer, il suffit de « rendre tous les éléments sans état », afin de reporter la gestion de l'état au serveur SQL Server de montée en charge verticale.

Toutefois, l'extraordinaire évolutivité de SQL Server est accompagnée d'un manque certain d'évolution réellement élastique. Autrement dit, au lieu d'une disponibilité très réactive des ressources, vous devez acheter un plus grand serveur impliquant une phase de migration coûteuse, des capacités largement supérieures à la demande et une montée en charge verticale à chaque fois que vous vous développez. De plus, il existe une courbe de coût exponentielle lors de la mise à l'échelle du matériel de milieu à haut de gamme.

L'architecture sous-jacente des services Azure Cloud Services évoluant par montée en charge horizontale, les applications doivent être conçues pour fonctionner avec des banques de données avec montée en charge horizontale. Cela implique des problèmes de conception tels que le partitionnement explicite des données en plusieurs petits segments (chacun étant adapté à une partition de données ou à une unité de montée en charge horizontale) et la gestion de la cohérence entre les éléments de données distribués. Cela permet d'effectuer une mise à l'échelle à l'aide d'un partitionnement qui éviter nombre des inconvénients de conception liés à la montée en charge verticale.

Le passage de techniques de montée en charge verticale bien connues à la gestion avec montée en charge horizontale des données et des états est généralement l'un des plus grands obstacles lors de la conception pour le cloud. La résolution de ces problèmes et la conception des applications pouvant tirer parti de ces fonctions évolutives et élastiques des services Azure Cloud Services et de la Base de données SQL Azure pour la gestion des données durables constituent l'essentiel de l'objet de ce document.

Dans un monde dans lequel vous exécutez votre propre centre de données, vous disposez d'un degré de contrôle presque infini, juxtaposé à un nombre de choix quasi infini. Tous les éléments, des équipements physiques (climatisation, alimentation électrique, bâtiments) à l'infrastructure (racks, serveurs, stockage, connexions, etc.) à la configuration (topologie de routage, installation du système d'exploitation) sont sous contrôle.

Ce degré de contrôle s'accompagne d'un coût : immobilisation, opérationnel, humain et temps. Le coût de la gestion de tous les détails dans un environnement agile et changeant est au cœur de la transition vers la virtualisation, et représente un aspect essentiel du passage au cloud. En échange de l'abandon d'une partie du contrôle, ces plateformes réduisent le coût du déploiement et de la gestion et offre une meilleure agilité. Elles appliquent une contrainte liée au fait que la taille (capacité, débit, etc.) des composants et services disponibles est limitée à un ensemble fixe d'offres.

À titre de comparaison, une expédition commerciale en gros est essentiellement composée de conteneurs d'expédition. Ces conteneurs peuvent être transportés par différents types de transports (bateaux, trains et camions) et sont disponibles dans différentes tailles standard (jusqu'à 53 pieds de long). Si la quantité de cargaison que vous souhaitez expédier dépasse la capacité du plus grand camion, vous devez utiliser :

  • Plusieurs camions. Cela implique de fractionner (ou partitionner) la cargaison pour qu'elle tienne dans différents conteneurs, et de coordonner le chargement des camions.

  • Une méthode d'expédition spéciale. Pour la cargaison qui ne peut pas être répartie dans des conteneurs standard (trop grand, trop encombrant, etc.), des méthodes hautement spécialisées, telles que des péniches, doivent être utilisées. Ces méthodes sont généralement beaucoup plus coûteuses que les transports maritimes standard.

En ramenant cette comparaison à Azure (et au cloud computing en général), chaque ressource a ses limites. Qu'il s'agisse d'une instance de rôle, d'un compte de stockage, d'un service cloud, voire d'un centre de données, toutes les ressources disponibles dans Azure présentent des limites fixes. Elles peuvent être de grandes dimensions, telles que la quantité de stockage disponible dans un centre de données (ce qui s'apparenterait aux cargos les plus grands qui peuvent transporter plus de 10 000 conteneurs), mais elles sont fixes.

Ainsi, l'approche de la mise à l'échelle consiste à partitionner la charge et à la répartir dans plusieurs unités de montée en charge, qu'il s'agisse de plusieurs machines virtuelles, bases de données, comptes de stockage, services de cloud computing ou centres de données.

Dans ce document, nous utilisons le terme d'unité de montée en charge pour faire référence à un groupe de ressources qui peuvent (a) gérer un niveau défini de charge, et (b) être combinées pour gérer la charge supplémentaire. Par exemple, un compte de stockage Azure a une taille maximale de 100 To. Si vous devez stocker plus de 100 To de données, vous devez utiliser plusieurs comptes de stockage (c'est-à-dire au moins deux unités de montée en charge de stockage).

Les règles de conception générales relatives à la taille de chaque service ou composant central Azure sont décrites dans les sections ultérieures, ainsi que des approches recommandées pour configurer ces services pour une mise à l'échelle supplémentaire.

De grandes quantités de temps, d'énergie et de capital intellectuel ont été investies dans la conception d'applications sur site hautement résilientes. En général, cela entraîne la division de l'application en composants à état bas (serveurs d'applications, connexion) et en composants à état élevé (bases de données, réseaux SAN), chacun étant résistant aux modes de défaillance.

Dans ce contexte, un mode de défaillance fait référence à une combinaison (a) d'observation du système dans un état d'échec, (b) en raison d'une cause d'échec. Par exemple, une base de données inaccessible en raison d'une mise à jour de mot de passe mal configurée est un mode de défaillance ; l'état d'échec est l'incapacité à se connecter (connexion refusée, informations d'identification non acceptées), et la cause de l'échec est une mise à jour de mot de passe qui n'a pas été correctement communiquée au code de l'application.

Les composants à état bas sont résistants grâce à une redondance faiblement couplée, et leur « intégration » dans le système est gérée par les systèmes externes. Par exemple, en plaçant des serveurs Web supplémentaires derrière un programme d'équilibrage de charge, chaque serveur Web est identique aux autres (l'ajout de capacité équivaut alors à cloner une image du serveur Web de base), et leur intégration dans l'application globale est gérée par le programme d'équilibrage de charge.

Les composants à état élevé sont résistants grâce à une redondance étroitement liée, et leur « intégration » est étroitement gérée entre les composants. Exemples :

  • SQL Server. L'ajout d'une instance redondante de SQL Server dans le cadre d'un cluster actif/passif requiert une sélection rigoureuse du matériel compatible (c'est-à-dire identique), et d'un stockage partagé (tel qu'un réseau SAN) pour fournir un basculement transactionnel cohérent entre plusieurs nœuds.

  • Alimentation électrique. L'approvisionnement d'une alimentation électrique redondante constitue un exemple très complexe, qui requiert plusieurs systèmes agissant de concert pour résoudre les problèmes locaux (plusieurs alimentations pour un serveur, avec du matériel intégré permettant de basculer de l'alimentation principale et à l'alimentation secondaire) et au niveau du centre (générateurs de sauvegarde en cas de perte d'alimentation).

Les solutions de résilience basées sur des approches étroitement couplées sont intrinsèquement plus coûteuses que les approches faiblement couplées d'« ajout d'éléments clonés supplémentaires », en exigeant du personnel très expérimenté, du matériel spécialisé, avec une configuration et des test rigoureux. Non seulement, une telle installation est difficile à réaliser correctement, mais elle coûte également cher.

Cette approche qui consiste à s'assurer que les plateformes matérielles sont hautement résilientes peut être considérée comme une « coquille en titane ». Pour protéger le contenu de la coquille, nous l'enduisons d'une couche de titane dur (et cher).

Les essais d'exécution de systèmes à l'échelle (voir http://www.mvdirona.com/jrh/TalksAndPapers/JamesRH_Lisa.pdf pour plus de détails) ont montré que dans tout système suffisamment volumineux (comme les systèmes de données à l'échelle d'Azure), en raison du nombre de pièces physiques en déplacement, certaines parties du système sont toujours à l'arrêt. La plateforme Azure a été conçue de façon à pouvoir fonctionner avec cette limitation, non en dépit de celle-ci, en se reposant sur la récupération automatique à partir d'événements d'échec au niveau du nœud. L'intention de cette conception parcourt tous les principaux services Azure et est essentielle à la génération d'une application qui s'exécute avec le modèle de disponibilité Azure.

La transition vers Azure entraîne une modification de la conversation de résilience d'une demande de redondance de l'infrastructure en une demande de redondance des services. Une grande partie des principaux services qui dominent la planification de la disponibilité sur site « continuent à fonctionner » dans Azure :

  • La Base de données SQL gère automatiquement plusieurs réplicas cohérents de vos données du point de vue transactionnel. Les échecs au niveau des nœuds pour une base de données basculent automatiquement vers le réplica secondaire cohérent ; vous devez comparer la facilité de cette expérience avec le temps et les dépenses requis pour fournir la résilience sur site.

  • Le stockage Azure gère automatiquement plusieurs sauvegardes cohérentes de vos données. (Pour plus d'informations, consultez http://sigops.org/sosp/sosp11/current/2011-Cascais/11-calder-online.pdf.) Les échecs au niveau des nœuds pour un volume de stockage basculent automatiquement vers un serveur secondaire cohérent. Comme avec la Base de données SQL, comparez cette expérience entièrement gérée avec la gestion directe du stockage résilient dans un cluster sur site ou un réseau SAN.

Toutefois, le titre de cette section est disponibilité, et non résilience. La résilience est uniquement une partie du processus global de fourniture en continu de valeur aux utilisateurs dans les limites d'un contrat SLA. Si tous les composants de l'infrastructure d'un service sont sains, mais que le service ne peut pas faire face au volume attendu d'utilisateurs, il n'est pas disponible ou n'offre pas de valeur.

Les charges de travail mobiles ou sociales (telles que les applications Web publiques avec les applications d'appareil mobile) sont susceptibles d'être beaucoup plus dynamiques que celles qui ciblent les publics intéressés, et elles nécessitent une approche plus complexe pour gérer les événements de rafale et les pics de charge. Les principaux concepts à prendre en compte pour la conception de la disponibilité dans les applications Azure sont décrits en détail dans ce document, en fonction de ces sélecteurs de vue :

  • Chaque service ou composant dans Azure fournit un certain contrat de niveau de service (SLA) ; ce contrat SLA ne peut être directement corrélé avec la mesure de disponibilité requise pour exécuter votre application. Comprendre tous les composants de votre système, leur contrat SLA de disponibilité et la façon dont ils interagissent est essentiel pour comprendre la disponibilité globale pouvant être offerte à vos utilisateurs.

    • Évitez les points d'échec uniques qui auront un impact sur votre contrat SLA, tels que les rôles d'instance unique.

    • Composez ou revenez à plusieurs composants pour atténuer l'impact d'un service spécifique hors connexion ou non disponible.

  • Chaque service ou composant dans Azure peut rencontrer un échec, soit transitoire de courte durée soit de longue durée. Votre application doit être écrite de manière à gérer l'échec naturellement.

    • Pour les erreurs temporaires, fournissez des mécanismes appropriés de tentative de reconnexion ou de renvoi des tâches.

    • Pour d'autres événements d'échec, fournissez une instrumentation optimale sur les événements d'échec (signalement de l'erreur aux opérations), et un message d'erreur approprié à l'utilisateur.

    • Dans la mesure du possible, revenez à un service ou flux de travail différent. Par exemple, si une demande d'insertion de données dans la Base de données SQL échoue (pour une raison non temporaire, telle qu'un schéma non valide), écrivez les données dans le stockage d'objets blob dans un format sérialisé. Cela permettrait aux données d'être capturées de façon durable, et d'être envoyées à la base de données une fois le problème de schéma résolu.

  • Tous les services disposeront d'une capacité maximale, soit explicite (via une asymptote de la stratégie d'agrégation ou de la charge maximale) soit implicite (en atteignant la limite d'une ressource système).

    • Concevez votre application afin qu'elle réduise ses capacités naturellement lorsque les limites d'une ressource sont atteintes, et effectue l'action appropriée pour réduire l'impact pour l'utilisateur.

    • Implémentez la logique d'interruption/de tentative pour éviter un effet « convoi » sur des services. Sans mécanisme d'interruption approprié, les services en aval n'ont jamais l'occasion de récupérer après avoir rencontré un événement de charge élevée (car votre application tente continuellement de transmettre plus de charge au service, ce qui déclenche la stratégie d'agrégation ou la défaillance des ressources).

  • Les services qui peuvent rencontrer des événements de rafales rapides doivent pouvoir gérer naturellement le dépassement de leur charge de travail maximale, en général via la fonctionnalité de rejet.

    • De la même façon que le corps humain limite l'afflux sanguin dans les extrémités en cas de grand froid, concevez vos services pour qu'ils laissent de côté les services les moins importants pendant les événements de charge très élevée.

    • Par conséquent, tous les services fournis par votre application n'ont pas la même importance dans l'entreprise, et peuvent être soumis à des contrats SLA différents.

Les concepts généraux seront détaillés davantage dans les sections décrivant les principaux services Azure, ainsi que les objectifs de disponibilité de chaque service ou composant, et les recommandations sur la conception à des fins de disponibilité. N'oubliez pas que le centre de données est toujours un point de défaillance unique pour les grandes applications ; de l'alimentation électrique (exemple ici) aux erreurs système (exemple ici), les problèmes d'infrastructure et d'application entraînent l'arrêt des centres de données. Bien que cela soit relativement rare, les applications qui requièrent les niveaux les plus élevés du temps de fonctionnement doivent être déployées sur plusieurs centres de données redondants.

Le déploiement des applications dans plusieurs centres de données requiert plusieurs fonctions d'infrastructure et d'application :

  • La logique d'application pour acheminer les utilisateurs des services dans le centre de données approprié (basé sur la géographie, le partitionnement utilisateur ou toute autre logique d'affinité).

  • La synchronisation et la réplication de l'état des applications entre les centres de données, avec des niveaux de latence et de cohérence appropriés.

  • Le déploiement autonome des applications, de sorte que les dépendances entre les centres de données sont réduites (autrement dit, évitez une situation où l'échec du centre de données A entraîne la défaillance du centre de données B).

Comme pour la disponibilité, le fait de fournir des solutions de récupération d'urgence (en cas de défaillance du centre de données) requiert d'immenses quantités de temps, d'énergie et de capital. Cette section présente les approches et éléments à prendre en considération pour assurer la continuité d'activité en dépit d'une défaillance du système et d'une perte de données (déclenchées par le système ou l'utilisateur), étant donné que le terme « récupération d'urgence » a pris des connotations spécifiques dans les approches d'implémentation dans la communauté des bases de données.

La continuité d'activité consiste à :

  • gérer l'accès et la disponibilité des systèmes critiques de l'entreprise (applications fonctionnant avec un état durable) en cas d'une défaillance catastrophique de l'infrastructure ;

  • gérer l'accès et la disponibilité des données critiques de l'entreprise (état durable) en cas d'une défaillance catastrophique de l'infrastructure ;

  • gérer la disponibilité des données critiques de l'entreprise (état durable) en cas d'erreur d'opérateur ou de suppression, modification ou altération accidentelle.

Les deux premiers points sont traditionnellement traités dans le contexte de la récupération d'urgence géographique (geo-DR), et le troisième appartient au domaine de la sauvegarde et de la restauration des données.

Azure modifie considérablement la donne pour la disponibilité des systèmes critiques d'entreprise, permettant un déploiement distribué géographiquement et rapide des principales applications dans les centres de données à travers le monde. En effet, le processus de déploiement d'une application distribuée géographiquement est légèrement différent du déploiement d'un seul service cloud.

Le problème principal demeure la gestion de l'accès à l'état durable ; l'accès aux services à état durable (tels que le stockage Azure et la Base de données SQL) dans les centres de données produit généralement des résultats non optimaux en raison d'une latence élevée et/ou variable, et ne satisfait pas l'exigence de continuité d'activité en cas de défaillance du centre de données.

Comme pour la résilience, plusieurs services Azure offrent la réplication géographique automatique, ou disposent d'un plan de mise en œuvre. Par exemple, sauf configuration autre, toutes les écritures dans le stockage Azure (objet blob, file d'attente ou table) sont automatiquement répliquées vers un autre centre de données (chaque centre de données a une destination « miroir » spécifique dans la même zone géographique). Cela réduit considérablement le temps et l'effort requis pour fournir des solutions de récupération d'urgence traditionnelles en plus d'Azure. Une vue d'ensemble des fonctionnalités de géo-réplication des principaux services Azure pour la gestion avec état durable est fournie dans les sections suivantes.

Pour assurer la continuité d'activité en dépit d'une erreur utilisateur ou opérateur, il existe plusieurs éléments supplémentaires à prendre en considération pour concevoir vos applications. Alors que le stockage Azure fournit une fonction d'audit limitée grâce à la fonctionnalité Storage Analytics (décrite dans une section ultérieure), il ne fournit aucune fonction de restauration dans le temps. Les services qui requièrent la résilience pour surmonter une suppression ou modification accidentelle doivent s'orienter vers des approches applicatives, telles que la copie régulière des objets blob dans un autre compte de stockage.

La Base de données SQL fournit des fonctionnalités de base pour gérer des instantanés historiques des données, y compris la copie et l'importation/exportation de la base de données via le fichier bacpac. Ces options sont décrites de manière plus détaillée plus loin dans ce document.

Grâce à l'évolution élastique fournie par la plateforme Azure, la courbe d'approvisionnement peut correspondre étroitement à la courbe de demande (plutôt que d'avoir une grande quantité de capacité supplémentaire pour traiter les pics de charge).

Avec une évolution élastique, le coût des ressources est défini par :

  • le nombre d'unités de montée en charge utilisées dans une solution : ordinateurs virtuels, comptes de stockage, etc. (composition pour l'évolution) ;

  • l'efficacité de l'exécution des tâches réalisées par ces unités de montée en charge.

Nous appelons « densité de l'application » la quantité de travail qui peut être exécutée par une certaine quantité de capacité. Les services et infrastructures les plus denses permettent d'effectuer une plus grande quantité de travail pour un déploiement de ressources donné ; autrement dit, une meilleure densité permet de réduire la capacité déployée (et le coût), ou la capacité à absorber la charge supplémentaire avec la même capacité déployée. La densité est définie par deux facteurs clés :

  • L'efficacité de l'exécution des tâches réalisées dans une unité de montée en charge. Il s'agit de la méthode traditionnelle d'optimisation des performances : gestion des conflits et des verrous de threads, optimisation des algorithmes, paramétrage des requêtes SQL.

  • L'efficacité de la coordination entre les unités de montée en charge. Dans un monde où les systèmes sont constitués de grands nombres de petites unités, le fait de pouvoir les relier efficacement est essentiel pour être efficace. Cela comprend les infrastructures et les outils qui communiquent entre les composants, tels que les piles de messagerie SOAP (notamment WCF, ORM (comme Entity Framework), appels TDS (code client SQL) et sérialisation d'objets (contrats de données ou JSON)).

Outre les techniques d'optimisation traditionnelles utilisées sur un seul ordinateur (ou base de données), l'optimisation des communications et opérations distribuées est essentielle pour fournir un service Azure évolutif et efficace. Ces optimisations clés sont détaillées dans les sections ultérieures :

  • Volumineux plutôt que bavard. Pour chaque opération distribuée (autrement dit, une opération qui entraîne un appel réseau), il existe une certaine surcharge d'encadrement de paquets, de sérialisation, de traitements, etc. Pour réduire la surcharge, essayez d'obtenir un plus petit nombre d'opérations « volumineuses » plutôt qu'un grand nombre d'opérations « bavardes ». Gardez à l'esprit que le traitement par lot d'opérations granulaires augmente la latence et le risque d'éventuelles pertes de données. Quelques exemples du comportement approprié de traitement par lot sont :

    • SQL. Exécutez plusieurs opérations dans un seul traitement.

    • Services REST et SOAP (par exemple WCF). Tirez profit des interfaces d'opérations orientées messages, plutôt qu'un style RPC bavard, et envisagez une approche REST, le cas échéant.

    • Stockage Azure (objets blob, tables, files d'attente). Publiez plusieurs mises à jour dans un lot, plutôt qu'individuellement.

  • Impact de la sérialisation. Le déplacement des données entre les ordinateurs (ainsi que vers ou depuis le stockage durable) nécessite généralement que les données soient sérialisées dans un format de câble. L'efficacité (autrement dit, la durée et l'espace consommé) de cette opération domine rapidement les performances globales de l'application pour les grands systèmes.

    • Tirez profit des infrastructures de sérialisation particulièrement efficaces.

    • Utilisez JSON pour communiquer avec les périphériques, ou pour les applications interopérables (lisibles par l'homme)

    • Utilisez une sérialisation binaire très efficace (par exemple protobuf ou Avro) pour la communication de service à service lorsque vous contrôlez les deux points de terminaison.

  • Utilisez des infrastructures efficaces. De nombreuses infrastructures complètes sont disponibles pour le développement, avec d'importants ensembles de fonctionnalités sophistiquées. L'inconvénient de nombre de ces infrastructures est que vous payez souvent le coût de performances de fonctionnalités que vous n'utilisez pas.

    • Isolez les services et les API clientes derrière les interfaces génériques pour permettre le remplacement ou l'évaluation côte à côte (via des répartiteurs statiques, ou une inversion de conteneur de contrôle). Par exemple, fournissez une couche de mise en cache enfichable en ayant recours à une interface générique plutôt qu'à une implémentation spécifique (telle que la mise en cache Azure).

Dans la section précédente, nous avons présenté les principaux concepts de conception et points de vue pour générer des applications qui tirent parti du tissu de l'architecture de cloud fournie par Azure. Cette section présente les principaux services et fonctionnalités de la plateforme et illustre leurs fonctions, limites de mise à l'échelle et modèles de disponibilité.

Comme chaque composant de service ou d'infrastructure Azure fournit une capacité définie avec un contrat de niveau de service de disponibilité, la compréhension de ces limites et des comportements est essentielle pour faire les choix de conception appropriés pour les objectifs d'évolutivité et les contrats SLA d'utilisateur final. Chacun des principaux services Azure est présenté dans le contexte de quatre principaux points de vue : fonctionnalités et intention, densité, évolutivité et disponibilité.

Un abonnement Azure est l'unité de base d'administration, de facturation et de quotas de service. Chaque abonnement Azure dispose d'un ensemble de quotas par défaut, qui peuvent être augmentés en contactant le support technique, et dont le but est d'éviter tout dépassement ou consommation de ressources accidentels.

Chaque abonnement a un propriétaire de compte, ainsi qu'un ensemble de co-administrateurs, autorisés par le biais de comptes Microsoft (anciennement Live ID), qui disposent d'un contrôle total sur les ressources de l'abonnement via le portail de gestion. Ils peuvent créer des comptes de stockage, déployer des services de cloud computing, modifier des configurations et ajouter ou supprimer des co-administrateurs.

Les API de gestion Azure (services Web REST) fournissent une interface d'automatisation pour créer, configurer et déployer des services Azure (utilisés en toute transparence par le portail de gestion). L'accès à ces API est restreint à l'aide de certificats de gestion.

 

Service Limite par défaut

Services de cloud computing

20

Comptes de stockage

20

Cœurs

20

Serveurs logiques de Base de données SQL

5

TipConseil
Pour connaître les dernières limites applicables aux services et aux abonnements Azure, consultez Limites, quotas et contraintes applicables aux services et abonnements Azure

Un service cloud Azure (anciennement service hébergé) est l'unité de base déploiement et de montée en charge. Chaque service cloud comprend deux déploiements (production et intermédiaire), chacun avec un ensemble de rôles. Le service cloud a une entrée DNS publique (au format nomservice.appcloud.net) pour le déploiement de production, et une entrée DNS de déploiement intermédiaire (au forme interface.appcloud.net).

Chaque déploiement contient un ou plusieurs rôles, soit un rôle Web soit un rôle de travail, qui contiennent quant à eux une ou plusieurs instances (ordinateurs virtuels non durables). Chaque instance contient un instantané identique, immuable et non durable d'un package logiciel pour ce rôle (autrement dit, la même version est déployée sur toutes les instances d'un rôle donné.) Ces instances exécutent une version spécialisée Azure de Windows Server (avec de nombreux services désactivés par défaut pour une sécurité supplémentaire, configurée pour fonctionner correctement avec l'architecture de connexion et de service Azure, etc.). Par défaut, les correctifs de l'architecture Azure leur sont appliqués automatiquement. L'application dynamique des correctifs est gérée via une mise à niveau propagée, décrite ci-dessous.

Les services de cloud computing peuvent être déployés sur n'importe quel centre de données Azure, soit directement (en choisissant la zone de destination lors de la création du service) soit par un groupe d'affinité. Un groupe d'affinité est une référence indirecte à une destination de déploiement qui peut être utilisée pour rationaliser le déploiement de tous les composants d'une application au même centre de données.

Les rôles Web sont préconfigurés avec une instance IIS, qui héberge le code de l'application. Le code de l'application hébergé dans les rôles de travail s'exécute dans l'hôte d'application longue préconfiguré. Chaque service cloud peut comporter jusqu'à 25 rôles. La configuration par défaut des rôles consiste à exécuter du code .NET, mais un rôle peut être configuré pour exécuter n'importe quel code compatible avec Windows Server (Java, Python, Ruby, node.js, etc.). Toutes les fonctionnalités de plateforme mentionnées dans ce document sont disponibles sur toutes les plateformes, mais peuvent nécessiter un développement supplémentaire client-proxy pour cibler les API REST.

Dans un service cloud, toutes les instances se voient affecter des adresses IP privées (dans le bloc 10.x), toutes les connexions sortantes semblent provenir d'une seule adresse IP virtuelle, ou VIP (qui est la VIP du déploiement du service cloud), via le traducteur d'adresses réseau (NAT). Toutes les connexions entrantes doivent traverser des points de terminaison configurés ; ces points de terminaison fournissent l'accès à charge équilibrée aux rôles et ports internes. Par exemple, par défaut, les connexions HTTP/HTTPS entrantes (ports 80 et 443) vers le déploiement du service cloud font l'objet d'un équilibrage de la charge sur toutes les instances disponibles du rôle Web principal.

Notez que la latence entre les services (c'est-à-dire, la traversée NAT depuis un service cloud et par le biais du programme d'équilibrage de charge dans un autre) est beaucoup plus variable que son équivalent sur site, et est l'une des raisons pour lesquelles les connexions entre services groupées ou « volumineuses » sont favorisées pour l'évolutivité.

L'architecture Azure fournit également un service de configuration disponible pour toutes les instances du déploiement du service cloud. Un ensemble statique de clés de configuration attendues est fourni dans la définition du service (dans le cadre du cycle de développement), avec un ensemble initial de valeurs de configuration déployé avec le service lors de sa publication dans Azure. Cet ensemble de valeurs de configuration est disponible en tant que recherche d'exécution sur toutes les instances du déploiement de service, et peut être modifié lors de l'exécution via une interface REST, le portail Azure ou un script PowerShell.

Lorsque la configuration d'exécution est modifiée, toutes les instances peuvent choisir (dans le code de l'application) d'accrocher la notification de modification de configuration et de gérer les mises à jour de configuration en interne. Si le code de l'application n'est pas écrit de sorte à capturer l'événement de modification de configuration, toutes les instances du rôle connaîtront un redémarrage propagé pour mettre à jour leur configuration.

L'état de chaque instance n'est pas durable ; toute configuration apportée à l'image de base Azure (machine virtuelle Windows Server spécialisé) requiert que la configuration au démarrage crée des compteurs de performances, ajuste les paramètres IIS, installe les logiciels dépendants, etc. Ces scripts de configuration sont généralement exécutés en tant que tâche de démarrage définie par la configuration du service cloud.

Dans le service cloud, l'architecture Azure fournit des informations sur la configuration, les adresses IP internes, la configuration du service, etc. Ces informations sont fournies via la classe RoleEnvironment. Tous les processus exécutés sur une instance Azure peuvent accéder aux informations RoleEnvironment pour récupérer la configuration, découvrir la topologie réseau, etc. Vous pouvez également utiliser les API de gestion Azure pour accéder à ces informations en externe.

La structure Azure présente deux concepts essentiels pour la gestion des défaillances d'un composant, la reconfiguration, la mise à niveau ou l'application des correctifs : domaines de mise à niveau et domaines d'erreur

Les domaines de mise à niveau sont des regroupements logiques dans un service Azure ; par défaut, chaque service a cinq (5) domaines de mise à niveau (cette valeur peut être modifiée dans la définition du service cloud). Toute modification ou mise à niveau du service n'affecte qu'un seul domaine de mise à niveau à la fois. Ces modifications incluent l'application de correctifs au système d'exploitation, la modification de la taille des ordinateurs virtuels, l'ajout de rôles ou d'instances de rôle à un service en cours d'exécution, ou la modification de la configuration du point de terminaison.

Cela permet de reconfigurer de façon dynamique un service cloud en cours d'exécution tout en préservant leur disponibilité. Pour les rôles qui contiennent une seule instance, l'architecture Azure ne peut pas fournir la disponibilité lors des opérations de mise à niveau. C'est pourquoi les rôles à instance unique en cours d'exécution ne satisfont pas le contrat SLA Azure.

Les domaines d'erreur sont des regroupements logiques basés sur le matériel sous-jacent. Étant donné que la correspondance directe à une configuration matérielle spécifique n'est pas garantie, vous devez considérer le regroupement logique comme la façon dont l'architecture Azure sépare automatiquement les instances des ressources sous-jacentes qui représentent un point de défaillance unique (tel qu'un serveur physique sous-jacent, un rack, etc.). Pour satisfaire le contrat SLA, Azure doit déployer des instances vers au moins deux domaines d'erreur. Il s'agit de l'autre raison pour laquelle les déploiements de rôle à instance unique ne satisfont pas au contrat SLA Azure.

En bref :

  • L'unité de base de déploiement et de mise à l'échelle dans Azure est le service cloud, qui comprend un ensemble de rôles. Chaque rôle contient un ensemble d'instances de rôles identiques, chacune exécutant une version configurée du cloud spécialisé de Windows Server.

  • Outre la topologie physique (rôles et instances) et le code de l'application, les services de cloud computing définissent une configuration à l'échelle du service. Cette configuration peut être mise à jour au moment de l'exécution.

  • Chaque instance de rôle est non durable (la conservation des modifications, fichiers et autres n'est pas garantie en cas d'événements de redémarrage, de mise à jour corrective et d'échec).

  • Chaque service cloud expose une seule adresse IP virtuelle à la fois pour le trafic entrant et le trafic sortant. Le service cloud expose les points de terminaison, qui fournissent un mappage avec équilibrage de charge (tourniquet) à un rôle et à un port internes.

  • Azure utilise des domaines de mise à niveau pour séparer logiquement les groupes d'instances, et fournir des modifications ou des mises à niveau propagées (tout en conservant la disponibilité).

  • Azure utilise les domaines d'erreur pour regrouper physiquement les instances à distance des points de défaillance uniques (par exemple en exécutant toutes les instances sur le même ordinateur physique sous-jacent).

  • Tirez profit de plusieurs abonnements pour isoler les environnements de développement, de test, intermédiaires et de production.

Chaque rôle contient un ensemble d'une ou plusieurs instances. Chacune de ces instances correspond à une machine virtuelle, qui exécute une version spécialisée de Windows Server. Les instances (machines virtuelles) sont disponibles dans cinq tailles, d'ultra-petit à ultra-grand. Chacune de ces tailles correspond à une certaine quantité d'UC, de mémoire, de stockage et de bande passante.

 

Taille de la machine virtuelle Cœurs d'unité centrale Mémoire Espace disque pour les ressources de stockage local dans les rôles Web et de travail Espace disque pour les ressources de stockage local dans un rôle de machine virtuelle Bande passante allouée (Mbit/s)

Ultra-petit

Partagé

768 MB

19 480 MB

(6 144 Mo sont réservés pour les fichiers système)

20 GB

5

Petit

1

1,75 GB

229 400 MB

(6 144 Mo sont réservés pour les fichiers système)

165 GB

100

Moyen

2

3,5 GB

500 760 MB

(6 144 Mo sont réservés pour les fichiers système)

340 GB

200

Grande

4

7 GB

1 023 000 MB

(6 144 Mo sont réservés pour les fichiers système)

850 GB

400

Ultra-grand

8

14 GB

2 087 960 MB

(6 144 Mo sont réservés pour les fichiers système)

1 890 GB

800

TipConseil
Pour connaître les dernières limites applicables aux services et aux abonnements Azure, consultez Limites, quotas et contraintes applicables aux services et abonnements Azure

À condition qu'au moins deux instances soient déployées dans différents domaines de défaillance et de mise à niveau, Azure fournit les contrats SLA suivants pour les services de cloud computing :

  • 99,95 % de connectivité externe pour les rôles exposés à Internet (dotés de points de terminaison externes)

  • 99,9 % de problèmes d'instances de rôle détectés dans les deux minutes et démarrage des actions correctives

Les tailles et les nombres des instances de rôles peuvent être modifiés dynamiquement dans une application en cours d'exécution (remarque : la modification des tailles des instances de rôle déclenche le redéploiement propagé). Avec l'approche de montée en charge horizontale pour la génération d'applications Azure, plus grand n'est pas nécessairement synonyme de mieux en matière de sélection de tailles d'instance. Cela s'applique à la fois au coût (pourquoi payer pour ce que vous n'utilisez pas) et aux performances (selon que votre charge de travail est liée à l'UC, aux E/S, etc.). Les approches de sélection du nombre d'instances et des tailles d'instance sont présentées plus en détail dans la section Meilleures pratiques de ce document.

Le stockage Azure est le service de données durables de base pour Azure. Il fournit un espace de stockage pour les objets blob (fichiers), les files d'attente et les tables (essentiels pour les valeurs). Le compte de stockage est l'unité de base de mise à l'échelle et de disponibilité, qui fournit les fonctions suivantes. Toutes les communications avec le service de stockage sont basées sur une interface REST sur HTTP.

TipConseil
Pour connaître les dernières limites applicables aux services et aux abonnements Azure, consultez Limites, quotas et contraintes applicables aux services et abonnements Azure

Le contrat SLA de disponibilité du stockage Azure garantit qu'au moins 99,9 % des demandes d'ajout, de mise à jour, de lecture et de suppression de données correctement mises en forme seront traitées correctement, et qu'en outre les comptes de stockage pourront se connecter à la passerelle Internet.

Ces limites sont partagées entre l'utilisation totale du compte de stockage spécifique (c'est-à-dire le nombre d'opérations par seconde) et la bande passante globale est partagée entre les tables, les objets blob et les files d'attente. Si une application dépasse le nombre total d'opérations par seconde, le service peut retourner un erreur de serveur occupé HTTP 503. Les opérations sont spécifiques à chaque aspect du stockage (tables, files d'attente ou objets blob) et sont décrites dans les paragraphes ci-dessous.

Si nous reprenons la métaphore du conteneur d'expédition utilisée plus haut, chaque compte de stockage est un conteneur qui fournit une certaine capacité. Le dépassement de la limite d'un compte unique (conteneur d'expédition) nécessite de recourir à plusieurs comptes dans la même application.

Le stockage Azure fournit la disponibilité et la résilience par défaut ; toutes les écritures ou mises à jour appliquées au stockage Azure sont répliquées de façon transparente et cohérente dans les trois nœuds de mémoire (qui résident dans différents domaines de mise à niveau et d'erreur). L'accès au stockage Azure est contrôlé à l'aide de l'authentification à un facteur unique sous forme de clés d'accès. Chaque compte de stockage dispose d'une clé primaire et d'une clé secondaire, ce qui offre une disponibilité continue lorsque la clé primaire est recréée. Les données du stockage Azure sont automatiquement géorépliquées dans un centre de données « miroir » (sauf si la fonctionnalité est explicitement désactivée à l'aide du portail). La géoréplication est opaque, ce qui permet de tirer profit de la redirection DNS pour basculer les clients vers l'emplacement secondaire en cas de défaillance sur le centre de données principal.

Notez que bien que le stockage Azure fournisse la résilience de données via les réplicas automatisés, cela n'empêche pas le code de l'application (ou les développeurs/utilisateurs) d'endommager les données via une suppression ou mise à jour accidentelle ou involontaire, etc. La conservation de l'intégrité des données en dépit d'une erreur de l'application ou de l'utilisateur nécessite des techniques avancées, telles que la copie de données dans un emplacement de stockage secondaire avec un journal d'audit. Le stockage d'objets blob fournit une fonction d'instantané qui peut créer des instantanés dans le temps en lecture seule des contenus d'objets blob, qui peuvent être utilisés comme base d'une solution d'intégrité des données pour les objets blob.

Le stockage Azure fournit la télémesure via sa fonctionnalité Storage Analytics, la collecte et l'exposition des données d'utilisation relatives à des appels de stockage aux tables, files d'attente et objets blob. La fonctionnalité Storage Analytics doit être activée pour chaque compte de stockage avec une stratégie de collecte (collecte pour tout, uniquement pour les tables, etc.) et une stratégie de rétention (la durée de conservation des données).

Le stockage d'objets blob assure le service de gestion des fichiers dans Azure, offrant une méthode hautement disponible et économique pour stocker les données non structurées en bloc. Le service fournit deux types d'objets blob :

  • Objets blob de blocs. Les objets blob de blocs sont conçus pour gérer des objets blob de données volumineux de façon efficace. Chaque objet blob de bloc est constitué de 50 000 blocs, chacun d'une taille maximale de 4 Mo (avec une taille maximale globale d'objets blob de blocs de 200 Go). Les objets blob de blocs prennent en charge le chargement parallèle pour déplacer efficacement et simultanément des fichiers volumineux d'un réseau à un autre. Des blocs individuels peuvent être insérés, remplacés ou supprimés, mais ne peuvent pas être modifiés sur place.

  • Objets blob de pages. Les objets blob de pages sont conçus pour fournir efficacement des opérations de lecture/écriture aléatoires (par exemple l'accès à un VHD). Chaque objet blob de page a une taille maximale de 1 To, constitué de pages de 512 octets. Des pages individuelles ou des groupes de pages peuvent être ajoutés ou mis à jour, avec une modification sur place.

Les limites de conception du stockage d'objets blob sont répertoriées dans le tableau ci-dessous. N'oubliez pas que toutes ces opérations affectent les limites globales du compte de stockage.

 

Catégorie d'objets blob Limite

Taille maximale d'objet blob (bloc)

200 Go (blocs de 50k)

Taille maximale de bloc

4 MB

Taille maximale d'objet blob (page)

1 To

Taille de page

512 octets

Maximum de bande passante/d'objets blob

480 Mbit/s

Lorsque les limites de taille ou de bande passante d'un seul objet blob, les applications peuvent écrire dans plusieurs fichiers blob concurrents (ou séquentiels). Si votre application dépasse les limites d'un seul compte de stockage, utilisez plusieurs comptes de stockage pour obtenir une capacité supplémentaire.

Les files d'attente Azure fournissent un service de messagerie (répartie) intermédiaire entre les serveurs de publication et les abonnés. Les files d'attente prennent en charge plusieurs serveurs de publication et abonnés simultanés, mais n'exposent pas en mode natif les primitives de messagerie les plus élevées, par exemple le routage serveur de publication/abonné ou basé sur les rubriques. Elles sont généralement utilisés pour distribuer des éléments de travail (comme les messages, documents ou tâches) dans un ensemble d'instances de rôles de travail (ou entre plusieurs services hébergés, etc.).

Les messages de la file d'attente sont automatiquement supprimés après 7 jours s'ils ne sont pas récupérés et supprimés par une application. Les files d'attente fournissent le découplage entre les serveurs de publication et les consommateurs d'informations. Si les deux parties disposent de la clé de compte de stockage et du nom de la file d'attente, elles peuvent communiquer.

 

Catégorie de file d'attente Limite

Nombre maximal de messages dans la file d'attente

Non applicable (jusqu'à la limite du compte de stockage)

Durée de vie maximale d'un message

1 semaine (automatiquement vidée)

Taille maximal des messages

64 kB

Débit maximal

Environ| 500 messages/seconde

Les files d'attente sont prévues pour transmettre des messages de contrôle, pas des données brutes. Si vos messages sont trop volumineux pour tenir dans une file d'attente, refactorisez vos messages pour séparer les données et la commande. Enregistrez les données dans le stockage d'objets blob, avec une référence (URI) aux données et l'intention (autrement dit, ce que vous devez faire avec les données dans le stockage des objets blob) stockées dans un message de la file d'attente.

Pour augmenter le débit d'une file d'attente, regroupez plusieurs messages dans un seul message, puis utilisez la commande Update Message pour suivre la progression des tâches du message d'encapsulation. Une autre technique permet de placer plusieurs messages dans un objet blob avec un pointeur vers l'objet blob dans le message de la file d'attente.

Si votre application nécessite un débit plus élevé que celui fourni par une seule file d'attente, utilisez plusieurs files d'attente simultanées. Dans ce contexte, votre application doit mettre en œuvre le partitionnement et la logique de routage appropriés.

Le stockage de tables Azure fournit un magasin cohérent, évolutif et hautement durable pour les données en colonne (bidimensionnelles). Il fournit une sémantique { clé de partition, clé de ligne } -> { données[] } pour stocker les données et y accéder, comme l'illustre le diagramme suivant. Chaque table est divisée en partitions, qui à leur tour contiennent des entités. Chaque entité peut avoir son propre schéma (plat) ou sa propre liste de propriétés (colonnes).

Chaque partition prend en charge jusqu'à 500 opérations par seconde. Chaque table prend en charge jusqu'au nombre maximal d'opérations disponibles dans le compte de stockage. Comme chaque entité contient non seulement les données réelles mais également les métadonnées de colonnes (puisque chaque entité peut avoir un schéma différent), les longs noms de colonnes ne sont pas recommandés, en particulier pour les approches volumineuses.

 

Catégorie de table Limite

Nombre maximal d'opérations par seconde par partition

500

Taille maximale d'une entité (noms de colonnes + données)

1 MB

Taille maximale d'une colonne (byte[] ou string)

64 kB

Nombre maximal de lignes

Non applicable (jusqu'à la limite du compte de stockage)

Types de données pris en charge

byte[], Boolean, datetime, double, Guid, int32, int64, string

Chaque entité (par exemple une ligne) a une taille maximale de 1 Mo, chaque colonne étant limitée à un maximum de 64 Ko. Les types de données pris en charge sont répertoriés dans le tableau ci-dessus ; pour les types non pris en charge (tels que DateTimeOffset), un proxy de sérialisation est requis dans le code de votre application (par exemple, le stockage de DateTimeOffset dans un format de chaîne standard).

Le stockage des tables permet d'accéder aux données stockées à l'aide de clés associées aux partitions et aux entités, à l'analyse des partitions ou à l'analyse des entités. Il prend en charge la projection de filtre, car une expression de filtre peut être envoyée au stockage de tables dans le cadre de la requête, et exécutée dans le stockage de tables). Le stockage de tables ne fournit pas d'index secondaires, par conséquent toute recherche n'étant pas basée sur la clé de partition ou la clé d'entité requiert une table et/ou une analyse de partition. Pour les partitions contenant un nombre important d'entités, cela a généralement un impact considérable sur les performances.

Tout traitement des requêtes qui prend plus de 5 secondes retourne un jeton de liaison que l'application peut utiliser pour continuer à recevoir les résultats de la requête. Les requêtes qui retournent plus de 1 000 entités doivent tirer profit d'un modèle de pagination pour regrouper les données par segments de 1 000 entités (avec prise en charge en mode natif par l'API de stockage des tables).

Les seules les expressions de requête actuellement prises en charge pour le stockage de tables sont le filtrage et la sélection (sélection de propriétés spécifiques) ; le stockage de table ne fournit aucun regroupement ou le regroupement de serveur sémantique. Pour créer des applications qui exigent des fonctions complètes d'agrégation ou d'analyse, il est souvent plus judicieux de stocker les données dans un format agrégé ou d'utiliser un moteur relationnel, par exemple la Base de données SQL Azure. Certaines applications utilisent une approche hybride, en agrégeant les données du stockage de tables dans une Base de données SQL connexe qui est ensuite utilisée à des fins de requêtes et de rapports.

Le choix d'une fonction de partitionnement appropriée est essentiel à l'utilisation efficace du stockage des tables. Il existe deux principales options pour le type de fonction de partitionnement :

  • Heure. Couramment utilisées pour stocker les données de séries chronologiques, telles que les compteurs de performance de diagnostics d'Azure (utilisation décrite dans la section relative à la télémesure dans ce document), les fonctions de partitionnement basées sur le temps convertissent l'heure actuelle en une valeur représentant une fenêtre de temps (minute actuelle, heure actuelle, etc.).

    Elles permettent de rechercher et de trouver efficacement une partition spécifique (étant donné que la clause de filtre pour le stockage des tables prend en charge >=, <=, etc.), mais peuvent être sujettes à la limitation si la fenêtre temporelle sélectionnée est trop étroite et qu'un événement de pic se produit. Par exemple, si la fonction de partition sélectionnée est la minute actuelle, et qu'un événement de pic se produit, un trop grand nombre de clients peut essayer d'écrire dans la même partition simultanément. Cela n'affecte pas seulement le débit de l'insertion, mais également le débit de la requête.

  • Données. Les fonctions de partitionnement basées sur les données calculent la valeur de partition en fonction d'une ou de plusieurs propriétés des données à stocker (ou récupérer). Le choix d'une fonction de partitionnement basée sur les données appropriée dépend de plusieurs facteurs : modèles de requêtes, densité des clés de partition (nombre d'entités contenues dans une partition), et croissance imprévisible (le rééquilibrage des tables très volumineuses peut être compliqué). Les modèles courants incluent :

    • Champ unique. La clé de partition est un champ unique dans les données sources (par exemple un ID de client pour obtenir des informations de commande).

    • Plusieurs champs. La clé de partition ou de ligne est un composite (en général une concaténation) de plusieurs champs dans les données sources. Lors de la sélection de clés de partition, notez que les opérations par lots nécessitent que toutes les entités se trouvent dans la même partition (c'est-à-dire qu'elles aient la même clé de partition).

    • Champ calculé. La clé de partition est calculée à partir d'un ou de plusieurs champs, selon une fonction déterministe. La distribution de profils utilisateur dans plusieurs partitions constitue un exemple type de ce modèle. L'ID utilisateur est haché par une fonction de hachage conçue pour une distribution relativement uniforme, puis le modulo est appliqué au nombre de partitions souhaitées.

Toute application complexe requiert l'utilisation de plusieurs partitions. Même pour les tables avec un petit nombre total d'entités (par exemple, deux cents), si l'application génère plusieurs milliers de demandes par seconde, plusieurs partitions sont nécessaires :

  • Table unique/Partition unique. Option la plus simple (valeur de clé de partition constante), appropriée pour les charges de travail à petite échelle avec des caractéristiques de débit de données et de requêtes restreintes (< 500 entités/s).

  • Table unique/Plusieurs partitions. Option courante pour la plupart des déploiements. Choisissez soigneusement les clés de partition pour les aligner avec les modèles de requêtes cibles.

  • Plusieurs comptes de stockage/Plusieurs partitions. Si la charge augmente et dépasse 5 000 opérations par seconde, l'utilisation de tables réparties sur plusieurs comptes de stockage est requise.

Une fois le choix effectué, le rééquilibrage (repartitionnement) des données peut s'avérer coûteux, car il implique de lire et copier toutes les entités avec des nouvelles clés de partition, puis de supprimer les anciennes données. Notez qu'il n'existe pas de restriction de taille minimale sur une partition ; les partitions peuvent contenir une seule entité (autrement dit, une ligne).

Si votre application nécessite un débit supérieur à celui fourni par une seule table (après un choix soigneux de la partition), utilisez plusieurs tables simultanément dans différents comptes de stockage. Dans ce contexte, votre application doit implémenter la logique de routage appropriée pour sélectionner le compte de stockage approprié.

Le réseau de diffusion de contenu (CDN) Azure offre un moyen efficace pour mettre en cache le contenu statique (à partir des objets blob ou des sorties d'applications) dans un réseau de mise en cache distribuée globalement. Cela atténue la pression subie par votre application pour envoyer du contenu statique, et améliore l'expérience utilisateur globale.

Le contrat SLA de disponibilité du réseau de diffusion de contenu garantit que les objets mis en cache sont fournis avec une disponibilité de 99,9 % sur une base mensuelle.

L'utilisation du réseau de diffusion de contenu requiert que la fonctionnalité soit activée pour l'abonnement. Ensuite, le contenu des objets blob (de conteneurs disponibles publiquement/avec accès anonyme) et le contenu de sorties d'applications anonyme (par exemple http://www.myapp.com/cdn/somepage.aspx) peuvent être mis en cache.

En général, pour toute application à grande échelle, tout le contenu statique le plus souvent sollicité (images, css, etc.) doit être remis via le réseau de diffusion de contenu avec les stratégies d'expiration du cache appropriées.

Prenons comme exemple une librairie en ligne proposant 1 million de titres. L'inclusion du contenu (images, etc.) de tous les titres dans le réseau de diffusion de contenu est excessivement coûteuse (puisque la majorité du contenu n'est pas fréquemment sollicité, et expire en permanence). Alors qu'en incluant uniquement le contenu le plus sollicité (par exemple, les 50 titres les plus demandés), cela permet de fournir la combinaison équilibrée entre la mise en cache et le coût.

L'un des principaux éléments de diffusion avec succès d'un service à grande échelle est la télémesure : aperçu du fonctionnement, des performances et de l'expérience utilisateur de votre application. Les méthodes de télémesure des applications Azure doivent prendre en compte la montée en charge horizontale/la nature distribuée de la plateforme, et les services de plateforme disponibles pour collecter, analyser et utiliser la télémesure.

Le composant technologique de base pour la collecte et la compréhension de la télémesure dans Azure est Diagnostics Azure (WAD). Le composant Diagnostics Azure comprend un agent qui regroupe les données de différentes instances et les transmet vers un point de collecte central (compte de stockage) ainsi qu'un ensemble de structures et conventions standard pour le stockage et l'accès aux données. L'agent prend en charge plusieurs approches de configuration, notamment du code (.NET), un fichier de configuration incorporé dans le code de projet déployé, ou un fichier de configuration centralisé déployé sur le stockage d'objets blob. La configuration est partiellement dynamique dans la dernière instance, ce qui permet de transmettre les fichiers de diagnostic au stockage d'objets blob, puis aux agents ciblés.

La configuration de Diagnostics Azure fournit plusieurs sources de données ; toutes ces sources de données sont régulièrement collectées, traitées par lot dans une session de suivi d'événements pour Windows (ETW), et publiées sur le compte de stockage cible. L'agent gère les problèmes de connexion temporaires, les nouvelles tentatives, etc. Les sources de données disponibles sont :

  • Compteurs de performance. Sous-ensemble de valeurs des compteurs de performance (UC, mémoire, etc.) capturées dans une session ETW locale, et régulièrement transmis dans le stockage des tables.

  • Journaux d'événements Windows. Sous-ensemble d'enregistrements des événements Windows (application, système, etc.) capturés dans une session ETW locale, et régulièrement transmis dans le stockage des tables.

  • Journaux Azure. Journaux des applications (messages de suivi) émis par le code de l'application (via System.Diagnostics.Trace) et capturés par un écouteur de suivi DiagnosticMonitorTraceListener. Ils sont publiés dans la table des compteurs de performance de Diagnostics Azure dans le compte de stockage de destination.

  • Journaux IIS 7.0. Informations standard de journaux IIS relatives aux requêtes consignées par IIS (rôles Web uniquement). Les journaux sont collectés dans des fichiers locaux, et transmis régulièrement au stockage d'objets blob.

  • Journaux IIS des demandes ayant échoué. Informations IIS relatives aux demandes ayant échoué, collectées dans des fichiers locaux, et régulièrement transmis dans le stockage d'objets blob.

  • Vidages sur indicent. En cas de panne système, les journaux sur l'état du système d'exploitation sont capturés et publiés dans le stockage d'objets blob.

  • Source de données. Le composant Diagnostics Azure peut surveiller des répertoires locaux supplémentaires (tels que les répertoires de journaux du stockage local) et copier régulièrement les données dans un conteneur personnalisé dans le stockage d'objets blob.

Chacune de ces sources de données est configurée avec le sous-ensemble de données à collecter (par exemple, la liste des compteurs de performance) et l'intervalle de collecte/publication. Il existe également plusieurs scripts PowerShell disponibles pour modifier la configuration d'exécution ou forcer une publication immédiate des données depuis les agents vers le compte de stockage cible.

ImportantImportant
Enregistrez la télémesure à un compte de stockage distinct. L'enregistrement de la télémesure et des données d'application dans le même compte de stockage entraînent d'importants problèmes des conflits lors de la montée en charge.

La Base de données SQL Azure fournit la base de données en tant que service, ce qui permet aux applications de rapidement mettre en service les bases de données relationnelles, d'y insérer des données et de les interroger. Elle fournit plusieurs des fonctionnalités SQL Server traditionnelles, tout en faisant abstraction de la charge du matériel, de la configuration, de la mise à jour corrective et de la résilience.

noteRemarque
La Base de données SQL ne fournit pas exactement les mêmes fonctionnalités que SQL Server, et est conçue pour répondre à un ensemble de conditions requises différentes spécialement adaptées aux applications de cloud (évolution élastique, base de données en tant que service pour réduire les coûts de maintenance, etc.). Pour plus d'informations, consultez http://blogs.msdn.com/b/windowsazure/archive/2012/06/26/data-series-sql-server-in-windows-azure-virtual-machine-vs-sql-database.aspx.

Le service s'exécute dans un environnement partagé multi-locataire, avec les bases de données de plusieurs utilisateurs et abonnements qui s'exécutent sur une infrastructure basée sur du matériel de base (montée en charge horizontale et non verticale).

Les bases de données sont mises en service dans les serveurs logiques ; chaque serveur logique contient par défaut jusqu'à 150 bases de données (base de données MASTER incluse). Par défaut, chaque abonnement peut mettre en service cinq (5) serveurs logiques, avec la possibilité d'augmenter ce quota, ainsi que le nombre maximal de bases de données par serveur logique, en contactant le support technique.

Chaque serveur logique se voit affecter un nom DNS public, unique, généré (au format [nom serveur].database.windows.net), chaque serveur logique dans un abonnement partageant la même adresse IP publique. Les serveurs logiques (et les bases de données) sont accessibles via le port SQL standard (TCP/1433), avec une API de gestion REST qui accède au port TCP/833.

Par défaut, l'accès au serveur logique (et à toutes ses bases de données) est limité, à l'aide de règles de pare-feu basées sur l'adresse IP, au portail de gestion Azure ; les règles peuvent être définies sur le serveur logique ou les bases de données individuelles. La configuration de l'accès aux applications Azure et de la connectivité applicative directe en dehors d'Azure (par exemple, pour se connecter à SQL Server Management Studio) nécessite de configurer des règles de pare-feu. Ces règles peuvent être configurées via le portail de gestion Azure à l'aide d'un appel à l'API du service de gestion.

La Base de données SQL fournit la prise en charge de la plupart des fonctionnalités clés présentes dans SQL Server, avec plusieurs exceptions importantes, notamment :

  • Toutes les tables doivent contenir un index cluster (CLUSTERED INDEX) ; les données ne peuvent pas être insérées (INSERT) dans une table de la Base de données SQL tant qu'un index cluster (CLUSTERED INDEX) n'a pas été défini.

  • Aucune prise en charge intégrée de Common Langage Runtime (CLR), aucune mise en miroir de bases de données, aucun Service Broker, aucune compression de données, ni aucun partitionnement des tables.

  • Aucun index XML ; le type de données XML est pris en charge.

  • Aucune prise en charge du chiffrement transparent des données (TDE) ou de l'audit des données.

  • Aucun prise en charge de la recherche en texte intégral.

Chaque base de données, lors de sa création, est configurée avec une limite de taille supérieure. Les seuils de taille actuellement disponibles sont 1 Go, 5 Go, 10 Go, 20 Go, 30 Go, 40 Go, 50 Go, 100 Go et 150 Go (taille maximale actuellement disponible). Lorsqu'une base de données atteint sa limite de taille supérieure, elle rejette les commandes INSERT ou UPDATE supplémentaires (les demandes et suppressions de données restent possibles). La taille d'une base de données peut également être créée (augmentée ou diminuée) en exécutant une commande ALTER DATABASE.

Lorsque les bases de données sont facturées en fonction de la taille moyenne utilisée par jour, les applications pouvant s'attendre à une croissance rapide ou imprévisible peuvent choisir de définir initialement la taille maximale de la base de données à 150 Go. La mise à l'échelle d'une base de données au-delà de 150 Go nécessite une approche avec montée en charge horizontale, décrite plus en détail dans la section ci-dessous.

La Base de données SQL fournit la résilience intégrée pour les défaillances au niveau du nœud. Toutes les écritures dans une base de données sont automatiquement répliquées vers plusieurs nœuds en arrière-plan à l'aide d'une technique de validation de quorum (le nœud principal et au moins un nœud secondaire doivent confirmer que l'activité est consignée dans le journal des transactions avant que la transaction soit considérée comme réussie et envoie un résultat). En cas de défaillance du nœud, la base de données bascule automatiquement vers l'un des réplicas secondaires. Cela provoque une interruption temporaire de connexion pour les applications clientes. Il s'agit de l'une des principales raisons pour lesquelles tous les utilisateurs de la Base de données SQL doivent implémenter une forme de gestion des connexions temporaires (voir ci-dessous pour plus de détails sur ce type d'implémentation).

Le contrat SLA de disponibilité mensuelle est 99,9 % de temps d'exécution, défini comme capacité à se connecter à la Base de données SQL en moins de 30 secondes à un intervalle de 5 minutes. Les événements de basculement décrits dans le paragraphe précédent se produisent généralement en moins de 30 secondes, renforçant la nécessité pour votre application de gérer les défaillances de connexion temporaires.

La Base de données SQL fournit un aperçu de son intégrité et de ses performances dans des vues de gestion dynamique (DMV) ; ces vues DMV contiennent des informations sur les principales caractéristiques du système, telles que les performances des requêtes ou la taille des bases de données et des tables. Les applications sont tenues de collecter et d'analyser régulièrement les informations des principales vues DMV, puis de les intégrer dans l'infrastructure de télémesure et d'analyse plus large.

Il existe plusieurs options de continuité d'activité (sauvegarde, restauration) disponibles pour la Base de données SQL. Les bases de données peuvent être copiées via la fonctionnalité de copie d'une base de données ou le service d'importation/exportation DAC. La fonctionnalité de copie de base de données fournit des résultats transactionnels cohérents, ce qui n'est pas le cas du fichier bacpac (via la service d'importation/exportation). Ces deux options s'exécutent en tant que services basés sur les files d'attente dans le centre de données, et ne fournissent pas de contrat SLA de durée d'exécution pour le moment.

Notez que la copie de base de données et le service d'importation/exportation appliquent une charge considérable sur la base de données source, et peuvent déclencher des événements de conflits ou de limitations des ressources (décrits dans la section Ressources partagées et limitation ci-dessous). Alors qu'aucune de ces approches ne présentent le degré de sauvegarde incrémentielle pris en charge par SQL Server, une nouvelle fonctionnalité est actuellement disponible en version d'aperçu pour activer la fonction de restauration dans le temps. La fonctionnalité de restauration dans le temps permet aux utilisateurs de restaurer la base de données à un point arbitraire dans le temps au cours des dernières 2 semaines.

La seule technique d'authentification actuellement prise en charge est l'authentification SQL, connexions nom d'utilisateur/mot de passe à facteur unique basées sur des utilisateurs inscrits dans la base de données. Active Directory ou les fonctions d'authentification à deux facteurs qui ne sont pas encore disponibles. Le chiffrement de la connexion à la Base de données SQL est fortement recommandé, à l'aide de la prise en charge du chiffrement intégrée dans ADO.NET, ODBC, etc. Les autorisations au niveau de la base de données sont compatibles avec SQL Server. Consultez Gestion des bases de données et des connexions dans Base de données SQL Azure pour une explication détaillée sur la configuration de la sécurité de la Base de données SQL Azure.

La Base de données SQL fournit un ensemble complet de vues de gestion dynamique pour observer les performances des requêtes et l'intégrité de la base de données. Toutefois, aucune infrastructure automatisée n'est fournie pour rassembler et analyser ces données (et des outils familiers comme le générateur de profils en attachement direct et les compteurs de performances au niveau du système d'exploitation ne sont pas disponibles). Les méthodes de collecte et d'analyse sont décrites dans la section Télémesure de ce document.

Comme décrit ci-dessus, la Base de données SQL est un service multi-locataire exécuté sur une infrastructure partagée. Les bases de données de plusieurs locataires partagent les nœuds physiques sous-jacents, qui reposent sur le matériel de base. D'autres utilisateurs du système peuvent utiliser des ressources principales (threads de travail, journal des transactions, E/S, etc.) dans la même infrastructure sous-jacente. L'utilisation des ressources est régie et façonnée pour conserver les bases de données dans les limites définies des ressources. Lorsque ces limites sont dépassées, au niveau d'un locataire ou d'un nœud physique, la Base de données SQL répond en limitant l'utilisation ou en supprimant des connexions. Ces limites sont répertoriées dans le tableau ci-dessous.

 

Ressource Valeur maximale par transaction/session Valeur maximale par nœud physique Limite logicielle Limite matérielle

Threads de travail

N/A

512

305

410

Taille de base de données

Taille maximale configurée jusqu'à 150 Go par base de données

N/A

Aucun

100% ; insertions ou mises à jour non acceptées une fois la limite atteinte

Croissance des journaux de transactions

2 Go par transaction

500 GB

N/A

N/A

Longueur des journaux de transactions

20 % de l'espace total du journal (100 Go)

500 GB

N/A

N/A

Nombre de verrous

1 million par transaction

N/A

N/A

N/A

Tâches système bloquantes

20 secondes

N/A

N/A

N/A

Espace de base de données temporaire

5 GB

N/A

N/A

5 GB

Mémoire

N/A

N/A

N/A

16 Mo pendant plus 20 secondes

Nombre maximal de demandes simultanées

400 par base de données

N/A

N/A

N/A

Lorsque la limite d'une transaction est atteinte, le système répond en annulant la transaction. Lorsqu'une base de données atteint une limite logicielle, les transactions et les connexions sont ralenties ou abandonnées. Lorsqu'une limite matérielle est atteinte, toutes les bases de données (et utilisateurs) du nœud physique sous-jacent sont touchés, ce qui provoque l'interruption des opérations existantes et l'impossibilité de créer d'autres opérations ou connexions jusqu'à ce que la ressource repasse en dessous du seuil de limitation.

Certaines de ces limites génèrent des limites éventuellement non intuitives de la conception et des performances d'une application. Par exemple, la limitation de la croissance du journal des transactions à 2 Go par transaction maximum empêche la création d'un index sur une table volumineuse (où la création de l'index génère plus de 2 Go dans le journal des transactions). Les techniques d'exécution de ces opérations sont décrites dans la section Meilleures pratiques de ce document.

La gestion de ces types d'états de limitation et d'erreurs temporaires requiert la conception soigneuse et l'implémentation de code client ; l'adressage nécessite d'effectuer une montée en charge horizontale de la couche de base de données pour tirer parti de plusieurs bases de données simultanément (la montée en charge horizontale est décrite dans la section suivante).

Le code de l'application cliente SQL doit :

  • Implémenter un code de tentative qui reconnaît les codes d'erreur SQL liés à la limitation et fournit la logique d'interruption appropriée. Sans logique d'interruption quelle qu'elle soit dans votre application, vous pouvez verrouiller la base de données dans un état de limitation permanent en transférant constamment la charge excédentaire à la base de données.

  • Consigner les erreurs de limitation, à l'aide du code de tentative pour distinguer la connexion temporaire, la limitation et la défaillance matérielle (syntaxe, procédures stockées manquantes, etc.). Cela permet d'aider au suivi et à la résolution des problèmes d'applications.

  • Implémenter un modèle de disjoncteur . Lorsqu'une stratégie de tentative correctement choisie (latence d'équilibrage et réponse système par rapport à la fréquence à laquelle l'application effectue une nouvelle tentative), appelez un chemin d'accès au code pour gérer les erreurs non temporaires (c'est-à-dire, faire sauter le disjoncteur). Le code d'application peut alors :

    • Recourir à un autre service ou une autre méthode. Si l'application ne parvient pas à insérer de nouvelles données dans la Base de données SQL (et que les données n'ont pas besoin d'être disponibles immédiatement), les données doivent plutôt être sérialisées dans un DataTable (ou un autre format XML/JSON) et écrites dans un fichier de stockage d'objets blob. L'application peut alors retourner un code de réussite à l'utilisateur (ou l'appel d'API), puis insérer les données dans la base de données ultérieurement.

    • Échouer en silence en renvoyant une valeur NULL, si les données ou le flux de travail sont facultatifs (aucun impact sur l'expérience utilisateur).

    • Échouer rapidement en retournant un code d'erreur si aucune méthode de secours utile/appropriée n'est disponible.

La Base de données SQL peut aisément fournir un grand nombre d'unités de montée en charge (bases de données) relativement petites. L'implémentation d'applications hautement évolutives dans Azure en tirant parti de la Base de données SQL nécessite une approche avec montée en charge horizontale, qui se compose des ressources de plusieurs bases de données pour répondre à une demande variable. Les applications étant traditionnellement ciblées vers la « coquille en titane » que représente un serveur de base de données hautement résilient avec montée en charge verticale, une conception réfléchie est requise pour que les applications utilisent de manière efficace un service de base de données avec montée en puissance horizontale.

Avec la Base de données SQL, comme les autres services principaux Azure, la montée en charge horizontale et la composition sont les clés d'une montée en charge supplémentaire (taille de base de données, débit) et des ressources (threads de travail, etc.). Il existe deux méthodes principales d'implémentation du partitionnement (et par conséquent de montée en charge horizontale) de la Base de données SQL ; ces approches ne sont pas mutuellement exclusives dans une application :

  • Partitionnement horizontal. Dans une approche de partitionnement horizontal, les tables ou les ensembles de données intacts sont divisés dans différentes bases de données. Par exemple, pour une application multi-locataire utilisée par différents ensembles de clients, l'application peut créer une base de données par client. Pour une plus grande application à locataire unique, la table des clients peut résider dans une base de données autre que la table des commandes. La clé de partitionnement est généralement l'identificateur du locataire (par exemple l'ID client). Dans le diagramme ci-dessous, l'ensemble de données est partitionné horizontalement en trois bases de données, à l'aide d'un hachage du courrier électronique en valeur de partition (autrement dit, la clé de partition est le courrier électronique, la fonction de partition utilise un hachage de la clé pour effectuer un mappage à une base de données de destination).

  • Partitionnement vertical. Dans une méthode de partitionnement vertical, un ensemble de données est divisé dans plusieurs tables ou bases de données physiques, selon le partitionnement de schéma. Par exemple, les données des clients et les données des commandes peuvent être réparties dans plusieurs bases de données physiques. Dans le diagramme ci-dessous, l'ensemble de données est partitionné verticalement dans deux bases de données. Les principales données utilisateur (nom, adresse électronique) sont stockées dans la base de données 1, et les informations de profil utilisateur (par exemple l'URI de l'avatar) dans la base de données 2.

De nombreuses applications utilisent une combinaison de partitionnement horizontal et vertical (partitionnement hybride), et incorporeront des services de stockage supplémentaires. Par exemple, dans l'exemple ci-dessus, les images d'avatar pour les utilisateurs ont été enregistrées comme identificateurs dans la base de données, que l'application développerait en URL complète. Cette URL correspond ensuite à une image stockée dans un objet blob.

Lorsque vous utilisez une banque de données relationnelle avec montée en charge horizontale, le calcul de la disponibilité est très différent. Les systèmes avec un plus grand nombre de partitions ont une probabilité plus élevée qu'un certain segment de données soit hors connexion, avec une probabilité nettement inférieure que l'application entière ne soit pas disponible. Les applications doivent prendre en compte la disponibilité partielle des banques de données principales. Avec un modèle de données avec montée en charge horizontale, la disponibilité des données n'est plus une condition tout-ou-rien.

Le repartitionnement des données peut s'avérer très difficile, en particulier si le modèle d'utilisation ou la distribution des données évolue dans le temps. Les clés de partitionnement basées sur une plage, qu'elles soient basées sur un nombre fixe (avec un modulo de hachage des valeurs de partitionnement) ou la distribution des valeurs de partitionnement, requièrent que les données soient rééquilibrées entre les différentes partitions. Les schémas de partition basés sur les plages ont souvent recours aux divisions ou fusions binaires pour simplifier les opérations de rééquilibrage.

Par exemple, les méthodes de partitionnement avec plage fixe (telles que la première lettre du nom) peuvent commencer avec une distribution équilibrée, mais qui peut rapidement se déséquilibrer à cause de nouveaux utilisateurs (chacun apportant son propre nom, qui peut ou non être distribué uniformément dans l'alphabet). Gardez à l'esprit qu'au fil du temps il sera peut-être nécessaire d'ajuster la méthode de partitionnement et que le rééquilibrage des données a un coût.

Les modèles de partitionnement basé sur la recherche sont plus compliqués à implémenter, car ils nécessitent une méthode de recherche hautes performances pour chaque locataire de données ou partition, mais sont plus faciles à rééquilibrer précisément car qu'ils permettent de rééquilibrer individuellement un seul locataire vers une nouvelle partition. Ils permettent également d'ajouter des capacités supplémentaires (nouvelles bases de données, etc.) au système sans devoir copier les données.

Quelle que soit la combinaison des méthodes de partitionnement, la transition vers des bases de données relationnelles partitionnées avec montée en charge horizontale s'accompagne de certaines restrictions nécessitant une approche différente de la gestion des données et des requêtes :

  • Pour optimiser le stockage et la cohérence des « bonnes » conceptions de stockage et de requête de données SQL traditionnelles, utilisez les modèles de données hautement normalisés. Cette approche nécessite un espace de données globalement cohérent, qui tire parti des renvois et des jointures entre les tables. Avec les données réparties dans les nœuds distribués physiquement, les jointures et renvois sont uniquement possibles dans une même partition. La Base de données SQL ne prend pas en charge les requêtes distribuées entre plusieurs bases de données ; la fusion de données doit être gérée au niveau du client, et la dénormalisation et la réplication des données entre les partitions.

  • Les données et métadonnées de référence sont généralement centralisées dans des tables de référence. Dans une approche avec montée en charge horizontale, ces tables de référence, et toutes les données qui ne peuvent pas être séparées par la clé de partitionnement commune, doivent être répliquées sur plusieurs partitions et rester cohérentes.

  • Il n'existe aucun moyen pratique de fournir des transactions distribuées évolutives et performantes entre les partitions ; les données (et les mises à jour de schéma !) ne seront jamais cohérentes du point de vue transactionnel entre les partitions. Le code de l'application doit supposer qu'un degré de faible cohérence existe entre les partitions, et s'y adapter.

  • Le code de l'application doit comprendre la méthode de partitionnement (horizontal, vertical, type de partitionnement) afin de pouvoir se connecter aux partitions appropriées.

  • Les ORM courants (comme Entity Framework) ne comprennent pas naturellement les modèles de données avec montée en charge horizontale ; les applications qui font une utilisation intensive des ORM volumineux peuvent nécessiter une nouvelle conception considérable pour être compatibles avec le partitionnement horizontal. Les conceptions qui isolent les locataires (ensembles de clients) dans une approche partitionnée verticale dans une base de données unique nécessitent généralement moins de retravail de conception au niveau de la couche d'accès aux données. L'inconvénient du modèle de partitionnement purement vertical est que chaque partition est limitée par la capacité d'une seule base de données.

  • Les requêtes qui doivent accéder (en lecture ou en écriture) à plusieurs partitions doivent être implémentées avec un modèle de ventilation-regroupement, où les requêtes sont exécutées sur les partitions cibles, l'ensemble de résultats est agrégé au niveau de la couche d'accès aux données client.

La montée en charge horizontale avec la Base de données SQL est effectuée en partitionnant manuellement les données entre plusieurs Bases de données SQL. Cette approche avec montée en charge horizontale offre la possibilité de bénéficier d'une croissance des coûts quasi linéaire avec mise à l'échelle. La croissance élastique ou la capacité à la demande peut augmenter avec des coûts incrémentiels, si nécessaire. Certaines applications peuvent ne pas prendre en charge ce modèle avec montée en charge horizontale sans nouvelle conception significative.

  • Les mises à jour de schéma ne sont pas assurées d'être cohérentes du point de vue transactionnel, surtout lorsque vous mettez à jour un grand nombre de partitions. Les applications doivent accepter des périodes d'interruption planifiées, ou pour plusieurs versions concurrentes du schéma déployé.

  • Les processus de continuité d'activité (sauvegarde/restauration, etc.) doivent tenir compte de plusieurs partitions de données.

Les recommandations et les meilleures pratiques de conception pour résoudre ces problèmes sont couvertes dans la section Meilleures pratiques pour ce document.

Le reste de ce document illustre les meilleures pratiques pour fournir des applications hautement évolutives avec Azure et la Base de données SQL, en fonction d'expériences réelles et des enseignements que l'on peut en tirer. Chaque meilleure pratique décrit l'optimisation visée et les composants, la méthode d'implémentation, et les compromis inhérents. Comme avec n'importe quelle meilleure pratique, ces recommandations dépendent largement du contexte dans lequel elles sont appliquées. Évaluez l'adéquation de chaque meilleure pratique selon les fonctions des plateformes décrites dans la section précédente.

noteRemarque
Ces expériences sont tirées d'un certain nombre d'engagements envers les clients qui ne respectent pas le modèle OLTP (traitement transactionnel en ligne) classique. Il est important de savoir que certaines de ces meilleures pratiques peuvent ne pas s'appliquer directement aux applications qui requièrent une cohérence des données forte ou stricte. Vous êtes le seul à connaître les exigences précises de votre entreprise concernant l'application et son environnement.

Chaque meilleure pratique est liée à une ou plusieurs caractéristiques d'optimisation :

  • Débit. Procédure d'augmentation du nombre d'opérations (transactions, appels de service, etc.) sur le système et de réduction des conflits.

  • Latence. Procédure de diminution de la latence, à la fois pour les opérations agrégées et individuelles.

  • Densité. Procédure de diminution des points de conflit en répartissant les services à la fois dans des contextes directs (par exemple, le code de l'application dans la Base de données SQL) et des contextes d'agrégation (plusieurs comptes de stockage pour une meilleure mise à l'échelle).

  • Simplicité de gestion. Diagnostics, télémesure et analyse : comment comprendre l'intégrité et les performances des services déployés lors de la mise à l'échelle.

  • Disponibilité. Procédure d'augmentation de la disponibilité globale de l'application en réduisant l'impact des points et des modes de défaillance (la disponibilité sous charge est couverte sous débit/latence/densité).

Comme l'unité de base de montée en charge dans Azure, la conception et le déploiement précis des services hébergés sont essentiels pour fournir des services hautement évolutifs et disponibles.

  • Le nombre d'instances et de domaines de mise à niveau dans un service hébergé peut avoir un impact considérable sur le délai nécessaire pour déployer, configurer, puis mettre à niveau le service hébergé. Vous devez trouver un compromis entre les avantages de performances et d'évolutivité et la complexité accrue requise pour bénéficier de ces avantages. L'amélioration de l'évolutivité et de la flexibilité entraîne généralement l'augmentation des coûts de développement et de gestion d'une solution.

  • Évitez les rôles d'instance unique ; cette configuration ne répond pas aux exigences du contrat SLA Azure. Lors d'un événement d'échec ou de mise à niveau du nœud, un rôle d'instance unique est mis hors connexion. Limitez leur utilisation aux tâches de « maintenance » de priorité basse.

  • Chaque centre de données a une capacité fixe (bien que volumineuse), et peut servir de point de défaillance unique dans de rares circonstances. Les services qui requièrent le plus haut niveau de montée en charge et de disponibilité doivent implémenter une topologie de plusieurs centres de données avec plusieurs services hébergés. Toutefois :

  • Lorsque le niveau de disponibilité le plus élevé n'est pas requis (voir l'élément précédent), vérifiez que les applications et services dépendants sont entièrement contenus dans un même centre de données. Si la solution doit utiliser plusieurs centres de données, utilisez les instructions suivantes :

    • Évitez les appels réseau entre centres de données pour les opérations actives (outre synchronisation entre site délibérée). La latence longue distance entre les centres de données peut varier fortement et produire des caractéristiques de performances de l'application inattendues ou indésirables.

    • Ne disposez que de la fonctionnalité requise minimale d'accès aux services dans un autre centre de données. En général, ces activités sont liées à la continuité d'activité et à la réplication de données.

Pour les applications distribuées à grande échelle, l'accès aux données d'application avec état est essentiel. Le débit et la latence globaux de l'application sont généralement liés par la rapidité à laquelle les données et le contexte requis peuvent être récupérés, partagés et mis à jour. Les services de mise en cache distribuée, tels que la mise en cache Azure et memcached, ont évolué pour répondre à ce besoin. Les applications doivent tirer parti d'une plateforme de mise en cache distribuée. Respectez les consignes suivantes :

  • Tirez profit d'une plateforme de mise en cache distribuée en tant que rôle de travail au sein de votre service hébergé. Cette grande proximité avec les clients de la mise en cache réduit les cloisonnements de latence et de débit présentés par la traversée du programme d'équilibrage de charge. Le Cache dans le rôle sur le service de mise en cache Azure héberge la mise en cache sur les rôles de travail au sein du service cloud.

  • Utilisez la plateforme de mise en cache distribuée comme référentiel principal pour l'accès aux données et objets d'application communs (profil utilisateur et état de session par exemple), soutenu par la Base de données SQL ou une autre banque durable dans une méthode de lecture ou de type « cache-aside ».

  • Les objets cache ont une durée de vie qui affecte leur durée d'activité dans le cache distribué. Les applications définissent la durée de vie sur les objets mis en cache ou configurent une durée de vie par défaut pour le conteneur du cache. Équilibrez le choix de la durée de vie entre la disponibilité (accès au cache), et la sollicitation de la mémoire et la péremption des données.

  • Les caches présentent une sémantique key->byte[] ; notez le risque du chevauchement des écritures pour créer des données incohérentes dans le cache. Les caches distribués ne fournissent généralement pas une API pour les mises à jour atomiques des données stockées, car ils ne tiennent pas compte de la structure des données stockées.

    • Pour les applications qui requièrent la cohérence stricte des écriture simultanées, utilisez une plateforme de mise en cache de distribution qui fournit un mécanisme de verrouillage pour la mise à jour des entités. Dans le cas de la mise en cache Azure, cela peut être implémenté via GetAndLock/PutAndUnlock. Remarque : cela aura un impact négatif sur le débit.

  • Les performances du cache sont délimitées sur la couche applicative par la durée nécessaire pour sérialiser et désérialiser les objets. Pour optimiser ce processus, tirez profit d'un sérialiseur binaire relativement symétrique (même durée requise pour encoder/décoder des données) et hautement efficace, tel que protobuf.

    • Pour utiliser la sérialisation personnalisée avec succès, concevez des objets de transfert de données pour la sérialisation dans le cache, utilisez l'annotation appropriée pour la sérialisation, évitez les dépendances cycliques, puis utilisez les tests unitaires pour effectuer le suivi de la sérialisation efficace.

Par défaut, les connexions entre les couches de service (y compris les connexions entrantes via le programme d'équilibrage de charge) sont soumises à un mécanisme d'allocation de type tourniquet (round-robin), avec mise en attente de connexion limitée. Les diagrammes suivants illustrent le maillage de connexion classique obtenu entre les couches et les services externes (le côté gauche illustre une application de couche Web uniquement). Bien que ce maillage n'affiche aucun problème de performances important pour les protocoles de connexion légers (tels que HTTP), certaines connexions sont soit coûteuses à connecter/initialiser soit une ressource gouvernée (limitée). Par exemple, les connexions de la Base de données SQL appartiennent à cette catégorie. Pour optimiser l'utilisation de ces services et composants externes, il est fortement recommandé de définir l'affinité des appels de ressources sur des instances spécifiques.

Dans le diagramme ci-dessus, la topologie à droite dispose de couches Web et de travail distinctes (rôles) dans le même service hébergé. Cette topologie dispose également de l'affinité implémentée entre les couches Web et Application pour épingler des appels à partir d'instances d'application spécifiques à des bases de données spécifiques. Par exemple, pour demander des données de la base de données 1, les instances Web doivent demander les données via les instances d'application 1 ou 2. Lorsque le programme d'équilibrage de la charge d'Azure implémente uniquement une technique de type tourniquet (round-robin), vous devez concevoir et implémenter soigneusement votre application afin qu'elle dispose de l'affinité.

  • Concevez l'application avec des couches Web et Application distinctes, qui fournissent l'affinité prenant en compte les partitions ou les ressources entre les couches Web et Application.

  • Implémentez la logique de routage qui achemine de manière transparente les appels au sein du service vers une instance de l'application cible. Utilisez les connaissances de la méthode de partitionnement utilisée par les ressources externes ou en aval (telles que la Base de données SQL).

L'implémentation pratique de cette architecture multiniveau requiert une communication de service très efficace entre les couches Web et Application utilisant les protocoles légers et efficaces.

Les techniques de développement d'une application Azure ne sont pas fondamentalement différentes des techniques de développement pour Windows Server. Toutefois, l'architecture élastique met en surbrillance le besoin et l'avantage d'utiliser un code efficace qui utilise les ressources informatiques plus efficacement.

  • Supposons que tous les services, appels réseau et ressources dépendantes sont potentiellement peu fiables et sujets aux modes de défaillance temporaires et continus (par exemple, la procédure d'implémentation de la logique de tentative de la Base de données SQL est couverte ci-après dans cette rubrique :

    • Implémentez les stratégies de nouvelle tentative appropriées sur tous les appels de service (Base de données SQL, stockage, etc.) pour gérer les conditions de défaillance temporaire et la perte de connectivité.

    • Implémentez des stratégies d'interruption dans la logique de nouvelle tentative pour éviter les conséquences de « convoi » (nouvelles tentatives en cascade sur le service qui prolonge des échecs).

    • Implémentez la télémesure complexe côté client pour consigner les messages d'erreur et les événements de défaillance avec des informations contextuelles (service de destination, contexte utilisateur/compte, activité, etc.).

  • Ne créez pas directement les threads pour planifier le travail ; à la place, tirez parti d'une infrastructure de planification et de concurrence telle que .NET Task Parallel Library. Les threads sont des objets relativement lourds et ils sont compliqués à créer et à libérer. Les planificateurs qui fonctionnent sur un pool de threads partagé peuvent planifier et exécuter des tâches plus efficacement. Cette architecture fournit également une sémantique de niveau supérieur pour décrire la liaison et la gestion des erreurs.

  • Optimisez les objets de transfert de données pour la sérialisation et la transmission réseau. Compte tenu de la nature très distribuée des applications Azure, l'évolutivité est délimitée par l'efficacité avec laquelle les différents composants du système peuvent communiquer sur le réseau. Toutes les données transmises sur le réseau pour la communication ou le stockage doivent implémenter la sérialisation textuelle JSON ou un format binaire plus efficace avec des indicateurs appropriés pour réduire la quantité de métadonnées transférée sur le réseau (tel que des noms de champ courts à la volée).

    • Si l'interopérabilité est importante, utilisez le format de texte efficace, tel que JSON, pour l'interopérabilité et les métadonnées intrabandes.

    • Si un débit élevé est important, telle que dans le cadre de communications de service-à-service dans lesquelles vous contrôlez les deux extrémités, envisagez d'utiliser un format binaire compressé très efficace, tel que bson ou protobuf.

      • Évitez le transfert de données (fréquentes) bavardes de petits objets. La communication bavarde entre des services gaspille des ressources système substantielles pour des tâches de surcharge et est vulnérable aux réponses de latence variables.

      • Les tests de sérialisation et de désérialisation des objets doivent être un composant majeur de votre infrastructure de test automatisée. Le test des fonctionnalités garantit que les classes de données sont sérialisables et qu'il n'existe aucune dépendance cyclique. Le test des performances vérifie les durées de latence et les tailles d'encodage requises.

  • Lorsque cela est possible, utilisez des infrastructures légères pour communiquer entre les composants et les services. Plusieurs technologies traditionnelles de la pile .NET fournissent un ensemble complet de fonctionnalités qui peuvent ne pas être alignées avec la nature distribuée d'Azure. Les composants qui fournissent un niveau élevé d'abstraction entre l'intention et l'exécution sont souvent liés à un coût de performances élevé.

    • Lorsque vous n'avez pas besoin de l'interopérabilité des protocoles ou de la prise en charge des protocoles avancée, envisagez d'utiliser l'API Web ASP.NET à la place de WCF pour implémenter des services Web.

    • Lorsque vous n'avez pas besoin de fonctionnalités complètes d'Entity Framework, envisagez d'utiliser un micro-ORM tel que Dapper pour implémenter la couche cliente SQL.

  • Réduisez la quantité de données transmises en dehors du centre de données en activant la compression HTTP dans IIS pour les données sortantes.

  • Définissez l'affinité des connexions entre les couches pour réduire les bavardages et le basculement entre contextes des connexions.

  • Pour réduire la charge sur l'application, utilisez le stockage d'objets blob pour utiliser une grande quantité de contenu statique (> 100 Ko).

  • Pour réduire la charge sur l'application, utilisez le réseau de diffusion de contenu via le stockage d'objets blob pour utiliser le contenu statique, telles que des images ou CSS.

  • Évitez d'utiliser la Base de données SQL pour les données de session. À la place, utilisez la mise en cache distribuée ou des cookies.

Le stockage Azure est le segment principal de données durables dans une application Azure. Alors qu'elles fournissent une expérience très fiable et évolutive « prête à l'emploi », les applications à grande échelle requièrent des instructions de création et d'utilisation appropriées.

  • Utilisez plusieurs comptes de stockage pour une évolutivité supérieure, pour augmenter la taille (> 100 To) ou le débit (> 5 000 opérations par seconde). Vérifiez que votre code d'application peut être configuré pour utiliser plusieurs comptes de stockage, avec les fonctions de partitionnement appropriées pour acheminer le travail vers les comptes de stockage. Concevez la possibilité d'ajouter des comptes de stockage supplémentaires comme modification de configuration, pas comme modification du code.

  • Sélectionnez attentivement les fonctions de partitionnement pour le stockage des tables afin de permettre la mise à l'échelle souhaitée en termes d'insertion et de performances des requêtes. Envisagez l'approche de partitionnement basée sur le temps pour les données de télémesure, avec des clés composites sur des données de ligne pour les données non temporelles. Conservez les partitions dans une plage appropriée pour optimiser les performances ; les partitions très petites limitent la possibilité d'exécuter des traitements par lots (y compris l'interrogation), tandis que les partitions très volumineuses sont coûteuses à interroger (et peut créer des goulets d'étranglement sur les insertions simultanées à grand volume).

    • Le choix de la fonction de partitionnement a également un impact crucial sur les performances des requêtes ; le stockage des tables assure l'efficacité des recherches par {clé de partition, clé de ligne}, avec un traitement moins efficace de {clé de partition, filtre de lignes correspondantes} et {filtre de clés de partition correspondantes, filtre de clés de ligne correspondantes}. Les requêtes nécessitant une table globale analysent ({filtre de clés de ligne correspondantes}).

    • Les partitions peuvent être aussi petites qu'une seule entité, ce qui fournit des performances hautement optimisées pour les charges de travail de recherche uniquement, comme la gestion d'un panier d'achat.

  • Si possible, regroupez les opérations par lots dans le stockage. Les écritures dans les tables doivent être regroupées par lot, généralement à l'aide de la méthode SaveChanges dans l'API cliente .NET. Insérez une série de lignes dans une table, puis validez les modifications dans un lot unique avec la méthode SaveChanges. Les mises à jour du stockage d'objets blob doivent également être validées par lot, à l'aide de la méthode PutBlockList. Comme avec l'API de stockage des tables, appelez PutBlockList sur une plage des blocs, et non sur un bloc blocks individuel.

  • Choisissez des noms de colonnes courts pour les propriétés de table, car les métadonnées (noms de propriété) sont stockées de façon intrabande. Les noms de colonnes dépendent également de la taille de ligne maximale de 1 Mo. Les noms de propriétés excessivement longs gaspillent les ressources système.

Comme décrit dans la section Exploration d'Azure, la base de données SQL fournit la base de données relationnelle clé en main en tant que fonction de service, ce qui fournit un accès évolutif au stockage des données avec montée en charge horizontale. L'utilisation réussie de la Base de données SQL dans des applications à grande échelle requiert de faire soigneusement plusieurs choix en matière de conception et d'implémentation ; les principaux points de conception et les meilleures pratiques sont traités dans cette section.

De nombreuses applications nécessitent une table de métadonnées dans laquelle stocker des informations telles que les informations de routage, de partitionnement et de locataire. Le stockage de ces métadonnées dans une seule base de données crée un point de défaillance unique, ainsi qu'un goulot d'étranglement d'évolutivité. Des banques de métadonnées centrales doivent subir une montée en charge horizontale en combinant les éléments suivants :

  • Mise en cache agressive. Les informations de la base de données de configuration doivent être mises en cache de façon intensive dans un cache distribué (par exemple memcached ou la mise en cache Azure).

    • Méfiez-vous de l'impact d'une tentative intensive pour précharger le cache à partir de plusieurs threads de travail au démarrage de l'application, ce qui entraîne généralement une limitation excessive de charge et de base de données. Si votre application requiert un cache préchargé, déléguez la responsabilité du chargement des données à un rôle de travail dédié (ou une tâche planifiée) avec un taux de chargement configurable.

    • Si les performances ou la fiabilité de l'application dépendent de la présence d'un certain segment de données disponibles dans le cache, votre application doit refuser les demandes entrantes jusqu'à ce que le cache soit prérempli. Tant que les données sont remplies, l'application doit retourner un message ou code d'erreur approprié.

  • Montée en charge horizontale. Partitionnez les données soit verticalement (par table) soit horizontalement (table à segments sur plusieurs partitions) pour répartir la charge sur plusieurs bases de données.

L'évolutivité globale d'une Base de données SQL partitionnée est limitée par l'échelle d'une base de données individuelle (partition) et l'efficacité avec laquelle les partitions peuvent être associées pour une meilleure mise à l'échelle :

  • Comme les limites du journal des transactions n'autorisent pas les transactions les plus volumineuses, par exemple la reconstruction des index, les tables individuelles ne doivent pas dépasser environ 10 Go (notez que cette limite pratique dépend de la taille des index des tables cibles, elle peut donc être de plus ou moins 10 Go pour votre base de données). Pour les tables plus volumineuses, divisez la table en plusieurs tables plus petites et utilisez une vue partitionnée pour fournir une superposition uniforme.

    • Conservez une taille réduite pour les tables individuelles afin de réduire l'impact d'une modification de schéma ou d'une reconstruction d'index lors d'une mise à niveau échelonnée. Les modifications apportées à plusieurs tables plus petites réduisent les temps morts et la latence liés aux opérations de blocage.

    • Ce partitionnement complique les techniques de gestion. Les opérations telles que la reconstruction de l'index doivent être effectuées de manière itérative sur toutes les tables du composant.

  • Gardez les bases de données (partitions) raisonnablement petites. Les opérations de continuité, telles que la copie de la base de données ou les exportations de bases de données supérieures à 50 Go, peuvent prendre plusieurs heures (le service annule les opérations qui s'exécutent pendant plus de 24 heures).

Dans un monde où les services sont fournis en continu, la gestion des mises à jour de bases de données distribuées ou des modifications de schémas nécessite d'être soigneux et attentionné afin que la mise à niveau se fasse en douceur. Toutes les meilleures pratiques traditionnelles de contrôle des opérations de schéma et de métadonnées dans une banque de données de production sont plus importantes que jamais. Par exemple, il est beaucoup plus complexe de déboguer et dépanner une procédure stockée accidentellement supprimée de l'une des 100 bases de données.

Comme les mises à jour de schémas et les modifications de données ne sont pas transactionnellement cohérentes entre les partitions, les mises à jour d'applications doivent être compatibles avec les schémas anciens et nouveaux au cours de la période de transition. Cette spécification signifie généralement que chaque version de l'application doit être au moins compatible avec la version actuelle et la version précédente du schéma.

Le passage à une collection de bases de données avec montée en charge horizontale crée des problèmes de gestion des connexions. Chaque connexion de base de données SQL est une ressource relativement coûteuse, démontrée par l'utilisation intensive du regroupement des connexions dans les API clientes (ADO.NET, ODBC, PHP, etc.). Au lieu que chaque instance d'application conserve plusieurs connexions à un serveur SQL Server central, chaque instance d'application peut éventuellement conserver des connexions à plusieurs serveurs de base de données.

Les connexions étant une ressource coûteuse et parfois rare, les applications doivent gérer correctement les connexions en retournant les connexions regroupées en temps voulu. Le code de l'application doit utiliser la mise à disposition automatique des connexions ; dans .NET, il est recommandé d'inclure toute utilisation de SqlConnection dans une instruction using, par exemple :

using (var conn = new SqlConnection(connStr))
{
    // SQL client calls here
}

Comme expliqué précédemment, les connexions à une Base de données SQL sont soumises à des défaillances temporaires de connexion. La logique de nouvelle tentative doit être utilisée pour toutes les connexions et commandes afin de se protéger contre ces défaillances temporaires (voir les informations supplémentaires ci-dessous).

La Base de données SQL prend en charge uniquement les connexions TCP (et non les canaux nommés), et il est fortement recommandé de chiffrer la connexion entre le code de l'application et la Base de données SQL. Pour empêcher toute tentative de connexion involontaire (telle qu'une tentative d'utilisation des canaux nommés), les applications doivent mettre en forme leurs chaînes de connexion SQL, comme suit :

Server=tcp:{servername}.database.windows.net,1433;Database={database};User ID={userid}@{database};Password={password};Trusted_Connection=False;Encrypt=True;Connection Timeout=30;

Pour les déploiements d'applications à grande échelle, le nombre par défaut de connexions potentielles peut augmenter de manière exponentielle entre un déploiement de service hébergé et les serveurs logiques de Base de données SQL dans un cluster de Bases de données SQL (chacun disposant d'une seule adresse IP externe). Un exemple peut être un service hébergé avec 100 instances, 50 bases de données et le nombre par défaut de connexions, qui est de 100 connexions par défaut dans ADO.NET.

MaxConnections=DatabaseCount*Instance Count*MaxConnectionPoolSize

Reportez-vous à la topologie de réseau pour un service hébergé ; chaque extrémité de la connexion (le service hébergé et les serveurs logiques de Base de données SQL) réside derrière un programme d'équilibrage de la charge d'Azure. . Chaque programme d'équilibrage de la charge d'Azure est une limite supérieure des connexions 64K entre deux adresses IPv4. La combinaison de cette topologie de réseau avec le nombre par défaut de connexions disponibles entraîne des défaillances réseau graves pour les grandes applications.

  • Déployez de grandes applications sur plusieurs services hébergés.

  • Déployez des bases de données dans plusieurs abonnements (non seulement plusieurs serveurs logiques dans le même abonnement) pour disposer d'un plus grand nombre d'adresses IP uniques.

  • Implémentez des applications à plusieurs niveaux pour créer une affinité entre des opérations sortantes sur une instance d'application ciblée (voir la section précédente sur les services hébergés).

  • N'oubliez pas que les pools de connexions sont conservés par chaîne de connexion unique et correspondent à chaque serveur de base de données, base de données et combinaison d'informations de connexion uniques. Utilisez le regroupement de connexions clientes SQL, puis limitez explicitement la taille maximale du pool de connexions SQL. Les bibliothèques clientes SQL réutilisent les connexions selon les besoins ; l'impact d'un petit pool de connexions est l'augmentation éventuelle de la latence tandis que les applications attendent des connexions disponibles.

La liste suivante fournit des recommandations pour réduire le nombre de connexions actives requises :

Le passage à un modèle de données distribuées peut nécessiter d'apporter des modifications à la conception du schéma de base de données, ainsi qu'à certains types de requêtes. Les applications qui nécessitent l'utilisation de transactions distribuées entre plusieurs bases de données peuvent avoir un modèle de données ou une implémentation inappropriés (par exemple, qui essaie de garantir la cohérence globale). Ces conceptions doivent être révisées.

L'utilisation d'une fonctionnalité de génération de séquence centrale doit être évitée pour tout aspect complexe de l'application, en raison des contraintes de disponibilité et d'évolutivité. De nombreuses applications exploitent les séquences pour fournir des identificateurs globaux uniques, à l'aide d'une méthode de suivi centrale pour incrémenter la séquence à la demande. Cette architecture crée un point de conflit global et un goulot d'étranglement avec lesquels chaque composant du système doit interagir. Le goulet d'étranglement pose particulièrement problème pour les applications mobiles potentiellement déconnectées.

À la place, les applications doivent tirer parti des fonctions qui peuvent générer des identificateurs globaux uniques, tels que des GUID, dans un système distribué. Par défaut, les GUID ne sont pas séquentiels, ils peuvent provoquer une fragmentation lorsqu'ils sont utilisés comme index cluster (CLUSTERED INDEX) dans une grande table. Pour minimiser l'impact de la fragmentation des GUID dans un grand modèle de données, partitionnez la base de données, en conservant des partitions relativement petites. La Base de données SQL peut ainsi défragmenter les bases de données automatiquement pendant le basculement du réplica.

Le code de l'application cliente doit tenir compte de plusieurs aspects de la fourniture d'un modèle de données distribué :

  • Clés de partition. Les clés de partition doivent faire partie de chaque classe ou modèle de données, et éventuellement présenter un attribut qui permet la découverte des clés de partition.

  • Télémesure. La couche d'accès aux données doit automatiquement stocker des informations sur tous les appels SQL, notamment la destination, la partition, le contexte, la latence, et les codes d'erreur ou nouvelles tentatives.

  • Requêtes distribuées. L'exécution de requêtes entre partitions introduit plusieurs nouveaux problèmes, y compris le routage, la sélection des partitions et le concept de réussite partielle (certaines partitions renvoient des données correctement, contrairement à d'autres). La couche d'accès aux données doit fournir des délégués pour exécuter les requêtes distribuées selon un modèle de ventilation-regroupement (parallèle) asynchrone, qui retourne un résultat composite. Les requêtes distribuées doivent également prendre en compte les limitations des ressources sous-jacentes :

    • Le degré maximal de parallélisme (pour éviter la sollicitation excessive des threads et des connexions).

    • Le délai de requête maximal (pour minimiser la latence globale frappée d'une requête longue durée ou d'une partition lente).

Il existe également plusieurs tâches de gestion en continu qui doivent être effectuées :

  • Tables de référence. Sans espace de requête globalement cohérent, les données de référence pour les jointures dans les requêtes doivent être copiées vers chaque partition. La conservation et la réplication des données dans les tables de référence dans différentes partitions sont requises pour fournir des données de référence locales raisonnablement cohérentes.

  • Rééquilibrage des partitions. Certaines partitions peuvent devenir déséquilibrées, soit elles consomment trop de ressources et deviennent un point d'engorgement, ou soit elles présentent une utilisation insuffisante et gaspille des ressources. Dans ce cas, les partitions doivent être rééquilibrées afin de réallouer des ressources. La méthode de rééquilibrage dépend fortement de la stratégie et de l'implémentation du partitionnement. Dans la plupart des scénarios, le rééquilibrage se déroule comme suit :

    • Copie des données présentes dans une partition vers une ou plusieurs nouvelles partitions, par le biais d'une méthode de fractionnement/fusion (pour le partitionnement basé sur une plage) ou la copie et le remappage au niveau des entités (pour le partitionnement basé sur la recherche).

    • Mise à jour du mappage de la partition vers la nouvelle partition, puis la compensation des données écrites dans les anciennes partitions pendant la transition.

  • Nettoyage des données. Au fur et à mesure qu'une application se développe et collecte les données, envisagez d'effectuer le nettoyage régulier des anciennes données inutilisées pour augmenter l'espace disponible et la capacité du système principal. Les données nettoyées (supprimées) ne sont pas effacées de façon synchrone de la Base de données SQL ; en revanche, elles sont marquées pour la suppression et nettoyées par un processus en arrière-plan. Une méthode courante pour marquer les données pour la suppression consiste à utiliser une colonne d'indicateur qui peut signaler une ligne comme active, inactive ou marquée pour la suppression. Cela permet de masquer les données pour les requêtes pendant un certain temps, ce qui permet aux données d'être facilement retourner dans l'environnement de production si les utilisateurs indiquent que les données sont toujours nécessaires.

    La suppression de données peut également déclencher la fragmentation, ce qui peut éventuellement nécessiter la reconstruction de l'index pour que les opérations de requête soient efficaces. Les anciennes données peuvent être archivées dans :

    • Une banque en ligne (Base de données SQL secondaire). Cela augmente l'espace disponible dans le système principal mais ne permet pas de réduire les coûts.

    • Une banque hors connexion, telle qu'un fichier bcp ou bacpac dans le stockage d'objets blob. Cela augmente l'espace disponible dans le système principal et réduit les coûts.

    • Le « bit bucket », ou trou noir. Vous pouvez choisir de supprimer définitivement des données du système principal pour augmenter l'espace disponible.

Plusieurs événements courants dans la Base de données SQL peuvent déclencher des défaillances temporaires de connexion, tels que le basculement du réplica. Les applications doivent implémenter le code approprié pour gérer les défaillances temporaires et répondre correctement à l'insuffisance et à la limitation des ressources :

  • Gestion des défaillances temporaires de connexion avec une nouvelle tentative. Le code d'accès aux données doit tirer profit d'une méthode de nouvelle tentative basée sur une stratégie afin de compenser les défaillances temporaires de connexion. La méthode de nouvelle tentative doit détecter les défaillances temporaires de connexion, se reconnecter à la Base de données SQL cible, et réexécuter la commande.

  • Gestion de la limitation avec logique de nouvelle tentative et d'interruption. Le code d'accès aux données doit tirer profit d'une méthode de nouvelle tentative et d'interruption basée sur une stratégie afin de gérer les conditions de limitation. La méthode de nouvelle tentative doit détecter la limitation et progressivement interrompre les tentatives de réexécution de la commande (pour éviter un effet de convoi susceptible de prolonger l'état de limitation).

    • Le code d'accès aux données doit également implémenter la possibilité d'interrompre une autre banque de données, tels que le stockage d'objets blob. Cette autre banque fournit une méthode durable de capture des activités, des données et de l'état, qui évite de perdre des données en cas de limitation ou de problème de disponibilité prolongés.

Les applications .NET peuvent utiliser les infrastructures de logique de nouvelle tentative et d'interruption compatibles avec la Base de données SQL, tels que CloudFx (Cloud Application Framework) et Enterprise Library Transient Fault Handler. Ces infrastructures fournissent des wrappers pour les classes courantes d'accès aux données (telles que SqlConnection et SqlCommand), ainsi que des stratégies qui peuvent être appelées directement.

var retryPolicy = RetryPolicy.Create<SqlAzureTransientErrorDetectionStrategy>(
    retryCount: 3, 
    initialInterval: TimeSpan.FromSeconds(5),
    increment: TimeSpan.FromSeconds(2));
                
using (var conn = new ReliableSqlConnection(connStr))
{
    conn.Open();
    using (var cmd = conn.CreateCommand())
    {

    }
    conn.Close();
}

L'extrait de code précédent montre l'utilisation de la classe ReliableSqlConnection de CloudFx pour gérer les erreurs temporaires de connexion lorsque vous travaillez sur la Base de données SQL.

Accordez une attention particulière à la journalisation des appels d'API aux services, tels que la Base de données SQL, avec des modes de défaillance potentiellement compliqués. Essayez de capturer les parties essentielles des informations de contexte et de performances. Par exemple, toutes les sessions de Base de données SQL portent un identificateur de session, qui peut être utilisé lors des appels au support technique pour permettre d'isoler directement le problème sous-jacent. Il est fortement recommandé que tous les appels, commandes et requêtes dans la Base de données SQL enregistrent :

  • le nom du serveur et de la base de données. Étant qu'il peut exister des centaines de bases de données, le serveur de destination est un élément essentiel pour le suivi et l'isolation des problèmes.

  • Selon le cas, la procédure stockée SQL ou le texte de la commande. Veillez à ne pas laisser passer des informations sensibles dans le fichier journal ; évitez en général de stocker le texte de la commande.

  • La latence de bout en bout de l'appel. Encapsulez l'appel d'un délégué d'expiration à l'aide d'un chronomètre ou de tout autre minuteur léger.

  • Le code de résultat de l'appel (succès ou échec) ainsi que le nombre de tentatives et la cause de l'échec (connexion supprimée, limitation, etc.).

  • L'ID de session de la connexion, accessible via la propriété CONTEXT_INFO() (ou la propriété SessionTracingId si vous utilisez ReliableSqlConnection). Toutefois, ne récupérez pas la propriété d'ID de session de CONTEXT_INFO() sur chaque appel client, car cette commande génère une nouvelle boucle du serveur.

Pour effectuer une utilisation plus efficace de la Base de données SQL, les requêtes et les insertions de données sur la Base de données SQL doivent être regroupées par lot et exécutées de façon asynchrone, si possible. Cela permet non seulement d'améliorer l'efficacité de l'application, mais réduit la charge système globale dans la Base de données SQL (pour un meilleur débit).

  • Insertion par lot. Pour les opérations d'insertion de données continues, telles que l'inscription de nouveaux utilisateurs, les données doivent être regroupées par lot et alignées sur les partitions cibles. Ces lots doivent être écrits régulièrement (et de façon asynchrone) dans la Base de données SQL en fonction de déclencheurs, comme la taille du lot cible ou un intervalle de temps. Pour les tailles de lot inférieures à 100 lignes, les fonctions table sont généralement plus efficaces qu'une copie en bloc.

  • Évitez les interfaces bavardes. Réduisez le nombre de boucles nécessaire à la base de données pour exécuter une requête ou un ensemble d'opérations. Les interfaces bavardes présentent un degré élevé de surcharge, ce qui augmente la charge du système et réduit le débit et l'efficacité. Essayez de fusionner les opérations associées, en général à l'aide d'une procédure stockée pour réduire les boucles.

Dans le cadre d'une approche globale de la continuité d'activité, les données stockées dans la Base de données SQL doivent être régulièrement exportées dans le stockage d'objets blob. Le stockage d'objets blob prend en charge la disponibilité et la géoréplication par défaut.

Implémentez une tâche planifiée qui exporte régulièrement les bases de données dans le stockage d'objets blob. Utilisez un compte de stockage dédié. Cette tâche doit s'exécuter dans le même centre de données que les bases de données cibles, et non à partir d'un bureau ou serveur sur site.

Planifiez la tâche d'exportation pour les périodes de faible activité afin de réduire l'impact sur l'expérience utilisateur. Lors de l'exportation de plusieurs bases de données, limitez le degré d'exportation parallèle afin de minimiser l'impact sur le système.

L'aperçu de l'intégrité, des performances et de l'espace disponibles de vos Bases de données SQL est un composant essentiel de la distribution globale du service. La Base de données SQL fournit des informations brutes requises par l'intermédiaire de vues de gestion dynamique, mais il n'existe actuellement aucune infrastructure clés en main pour capturer, analyser et créer des rapports sur les principales mesures. Pour fournir cette fonction pour la Base de données SQL, tenez compte des recommandations suivantes :

  • Implémentez une tâche régulière de collecte des données de performances clés liées à la charge système, les ressources utilisées (threads de travail, espace de stockage), ainsi que des données dans un référentiel commun. Par exemple, considérez les tables utilisées par Diagnostics Azure. Cette tâche doit collecter les données de toutes les bases de données qui appartiennent à votre application. Cette collecte se produit généralement comme une montée en charge horizontale (collecte des données de plusieurs bases de données simultanément.)

  • Implémentez une tâche régulière d'agrégation de ces informations pour créer des indicateurs de performance clés de l'intégrité et de la capacité de vos bases de données déployées.

Le composant Diagnostics Azure fournit une référence pour collecter des informations d'application et de télémesure au niveau de l'instance. Néanmoins, l'obtention d'un aperçu des applications à grande échelle qui s'exécutent dans Azure requiert la configuration et la gestion soigneuses des flux de données. Contrairement aux applications centralisées avec montée en charge verticale qui peuvent tirer parti des outils complets de diagnostic Windows, le diagnostic dans un système distribué avec montée en charge horizontale doit être implémenté pour que le système soit disponible ; il ne peut pas être ajouté après-coup.

La gestion des erreurs, le suivi contextuel et la capture de télémesure sont essentiels pour fournir une description des événements d'erreur, des causes premières et des résolutions.

  • Ne publiez pas les données et la télémesure de sites actifs dans un même compte de stockage. Utilisez un compte de stockage dédié pour le diagnostic.

  • Créez des canaux distincts pour la télémesure volumineuse (volume élevé, latence élevée, données détaillées) et la télémesure bavarde (faible volume, faible latence et données à valeur élevée).

    • Utilisez les sources standard de Diagnostics Azure, telles que les compteurs de performances et les traces, pour les informations bavardes.

    • Utilisez des bibliothèques de journalisation courantes, telles qu'Enterprise Application Framework Library, log4net ou NLog, pour implémenter la journalisation par lots dans des fichiers locaux. Utilisez une source de données personnalisée dans la configuration du moniteur de diagnostic pour copier ces informations régulièrement dans le stockage d'objets blob.

  • Enregistrez tous les appels d'API aux services externes avec le contexte, la destination, la méthode, les informations d'expiration (latence) et le résultat (succès/échec/tentatives). Utilisez le canal de journalisation volumineuse pour éviter de surcharger le système de diagnostic avec les informations de télémesure.

  • Les données écrites dans le stockage des tables (compteurs de performances, journaux des événements, événements de suivi) sont écrites dans une partition temporelle, de 60 secondes. Si vous essayez d'écrire un trop grand nombre de données (trop de sources ponctuelles, intervalle de collecte trop court), cette partition peut être surchargée. Vérifiez que les pics d'erreur ne déclenchent pas de tentative de volume élevé d'insertions dans le stockage des tables, car cela peut déclencher un événement de limitation.

    • Choisissez les données de valeur élevée pour la collecte dans ces sources, notamment des compteurs de performance clé, des événements critiques/d'erreur ou des enregistrements de suivi.

    • Choisissez un intervalle de collecte approprié (5 à 15 minutes) pour réduire la quantité de données devant être transférée et analysée.

  • Vérifiez que la configuration de la journalisation peut être modifiée pendant l'exécution sans devoir forcer de réinitialisations d'instances. Vérifiez également que la configuration est suffisamment détaillée pour la journalisation d'aspects spécifiques du système, tels que les bases de données, le cache ou d'autres services.

Le composant Diagnostics Azure ne fournit pas de collecte de données pour les services dépendants, tels que la base de données SQL ou un cache distribué. Pour fournir une vue complète de l'application et de ses caractéristiques de performances, ajoutez une infrastructure pour collecter les données pour des services dépendants :

  • Collectez les données de performances clés et d'utilisation des services dépendants, et publiez-les dans le référentiel de Diagnostics Azure comme enregistrements des compteurs de performances.

    • Stockage Azure via Azure Storage Analytics.

    • Base de données SQL via des vues de gestion dynamique.

    • Cache distribué via des compteurs de performances ou des API de contrôle d'intégrité.

  • Analysez régulièrement les données brutes de télémesure pour créer des agrégations et des correctifs cumulatifs (en tant que tâche planifiée).

Afficher:
© 2014 Microsoft