Meilleures pratiques de développement web (création d’applications cloud Real-World avec Azure)

par Rick Anderson, Tom Dykstra

Télécharger corriger le projet ou télécharger le livre électronique

Le livre électronique Building Real World Cloud Apps with Azure est basé sur une présentation développée par Scott Guthrie. Il explique 13 modèles et pratiques qui peuvent vous aider à développer des applications web pour le cloud. Pour plus d’informations sur le livre électronique, consultez le premier chapitre.

Les trois premiers modèles portaient sur la mise en place d’un processus de développement agile ; le reste concerne l’architecture et le code. Celui-ci est une collection de bonnes pratiques de développement web :

Ces pratiques sont valables pour tous les développements web, pas seulement pour les applications cloud, mais elles sont particulièrement importantes pour les applications cloud. Ils travaillent ensemble pour vous aider à tirer le meilleur profit de la mise à l’échelle hautement flexible offerte par l’environnement cloud. Si vous ne suivez pas ces pratiques, vous rencontrez des limitations lorsque vous essayez de mettre à l’échelle votre application.

Niveau Web sans état derrière un équilibreur de charge intelligent

Le niveau Web sans état signifie que vous ne stockez pas de données d’application dans la mémoire du serveur web ou le système de fichiers. Le fait de conserver votre niveau Web sans état vous permet à la fois d’offrir une meilleure expérience client et d’économiser de l’argent :

  • Si la couche web est sans état et qu’elle se trouve derrière un équilibreur de charge, vous pouvez répondre rapidement aux modifications du trafic d’application en ajoutant ou en supprimant dynamiquement des serveurs. Dans l’environnement cloud où vous ne payez que pour les ressources du serveur tant que vous les utilisez réellement, cette capacité à répondre aux changements de la demande peut se traduire par d’énormes économies.
  • Une couche Web sans état est architecturalement beaucoup plus simple pour effectuer un scale-out de l’application. Cela vous permet également de répondre plus rapidement aux besoins de mise à l’échelle et de dépenser moins d’argent en développement et en test dans le processus.
  • Les serveurs cloud, comme les serveurs locaux, doivent être corrigés et redémarrés à l’occasion ; et si la couche Web est sans état, le réacheminement du trafic lorsqu’un serveur tombe temporairement en panne ne provoquera pas d’erreurs ou de comportement inattendu.

La plupart des applications réelles doivent stocker l’état d’une session web ; le main point ici est de ne pas le stocker sur le serveur web. Vous pouvez stocker l’état d’autres manières, par exemple sur le client dans des cookies ou côté serveur hors processus dans ASP.NET état de session à l’aide d’un fournisseur de cache. Vous pouvez stocker des fichiers dans le stockage d’objets blob Azure Windows au lieu du système de fichiers local.

Pour vous donner un exemple de la facilité avec laquelle il est possible de mettre à l’échelle une application dans Windows Azure Web Sites si votre niveau web est sans état, consultez l’onglet Mettre à l’échelle pour un site web Windows Azure dans le portail de gestion :

Onglet Mettre à l’échelle

Si vous souhaitez ajouter des serveurs web, vous pouvez simplement faire glisser le curseur instance nombre vers la droite. Définissez-le sur 5 et cliquez sur Enregistrer. En quelques secondes, vous avez 5 serveurs web dans Windows Azure qui gèrent le trafic de votre site web.

Cinq instances

Vous pouvez tout aussi facilement définir le nombre de instance sur 3 ou 1. Lorsque vous effectuez un scale-back, vous commencez à économiser de l’argent immédiatement, car Windows Azure facture à la minute, pas à l’heure.

Vous pouvez également indiquer à Windows Azure d’augmenter ou de diminuer automatiquement le nombre de serveurs web en fonction de l’utilisation du processeur. Dans l’exemple suivant, lorsque l’utilisation du processeur est inférieure à 60 %, le nombre de serveurs web diminue à un minimum de 2, et si l’utilisation du processeur dépasse 80 %, le nombre de serveurs web est augmenté jusqu’à un maximum de 4.

Mettre à l’échelle par utilisation du processeur

Ou que se passe-t-il si vous savez que votre site ne sera occupé que pendant les heures de travail ? Vous pouvez indiquer à Windows Azure d’exécuter plusieurs serveurs pendant la journée et de réduire à un seul serveur les soirs, les nuits et les week-ends. La série suivante de captures d’écran montre comment configurer le site web pour exécuter un serveur en dehors des heures creuses et 4 serveurs pendant les heures de travail de 8 h à 17 h.

Mettre à l’échelle par planification

Définir les heures de planification

Horaire diurne

Horaire de la semaine

Planification du week-end

Et bien sûr, tout cela peut être effectué dans des scripts ainsi que dans le portail.

La capacité de votre application à effectuer un scale-out est presque illimitée dans Windows Azure, tant que vous évitez les obstacles à l’ajout ou à la suppression dynamique de machines virtuelles serveur, en conservant la couche Web sans état.

Éviter l’état de session

Dans une application cloud réelle, il n’est souvent pas pratique d’éviter de stocker une forme d’état de session utilisateur, mais certaines approches ont davantage d’incidence que d’autres sur les performances et l'extensibilité. Si vous devez stocker un état, la meilleure solution consiste à veiller à ce qu’il reste de petite taille et à le stocker dans des cookies. Si ce n’est pas possible, la meilleure solution consiste à utiliser ASP.NET’état de session avec un fournisseur pour le cache distribué en mémoire. La pire solution du point de vue des performances et de l’extensibilité consiste à utiliser un fournisseur d’état de session s'appuyant sur une base de données.

Utiliser un CDN pour mettre en cache des ressources de fichiers statiques

CDN est un acronyme pour Content Delivery Network. Vous fournissez des ressources de fichiers statiques telles que des images et des fichiers de script à un fournisseur CDN, et le fournisseur met ces fichiers en cache dans les centres de données du monde entier afin que, partout où les utilisateurs accèdent à votre application, ils obtiennent une réponse relativement rapide et une faible latence pour les ressources mises en cache. Cela accélère le temps de chargement global du site et réduit la charge sur vos serveurs web. Les CDN sont particulièrement importants si vous atteignez un public largement distribué géographiquement.

Windows Azure a un CDN et vous pouvez utiliser d’autres CDN dans une application qui s’exécute dans Windows Azure ou dans n’importe quel environnement d’hébergement web.

Utiliser la prise en charge asynchrone de .NET 4.5 pour éviter de bloquer les appels

.NET 4.5 a amélioré les langages de programmation C# et VB afin de simplifier la gestion asynchrone des tâches. L’avantage de la programmation asynchrone n’est pas seulement pour les situations de traitement parallèle telles que lorsque vous souhaitez lancer plusieurs appels de service web simultanément. Il permet également à votre serveur web de fonctionner plus efficacement et plus fiable dans des conditions de charge élevée. Un serveur web ne dispose que d’un nombre limité de threads et, dans des conditions de charge élevée, lorsque tous les threads sont en cours d’utilisation, les demandes entrantes doivent attendre que les threads soient libérés. Si le code de votre application ne gère pas les tâches telles que les requêtes de base de données et les appels de service web de manière asynchrone, de nombreux threads sont inutilement liés pendant que le serveur attend une réponse d’E/S. Cela limite la quantité de trafic que le serveur peut gérer dans des conditions de charge élevée. Avec la programmation asynchrone, les threads qui attendent qu’un service web ou une base de données retournent des données sont libérés pour traiter de nouvelles demandes jusqu’à ce que les données soient reçues. Dans un serveur web occupé, des centaines ou des milliers de demandes peuvent alors être traitées rapidement, ce qui, sinon, attendrait que les threads soient libérés.

Comme vous l’avez vu précédemment, il est aussi facile de réduire le nombre de serveurs web qui gèrent votre site web que de les augmenter. Par conséquent, si un serveur peut obtenir un débit plus élevé, vous n’en avez pas besoin autant et vous pouvez réduire vos coûts, car vous avez besoin de moins de serveurs pour un volume de trafic donné que vous ne le feriez autrement.

La prise en charge du modèle de programmation asynchrone .NET 4.5 est incluse dans ASP.NET 4.5 pour Web Forms, MVC et l’API web ; dans Entity Framework 6 et dans l’API Stockage Azure Windows.

Prise en charge asynchrone dans ASP.NET 4.5

Dans ASP.NET 4.5, la prise en charge de la programmation asynchrone a été ajoutée non seulement au langage, mais également aux infrastructures MVC, Web Forms et API web. Par exemple, une méthode d’action de contrôleur MVC ASP.NET reçoit des données d’une requête web et transmet les données à une vue qui crée ensuite le code HTML à envoyer au navigateur. Souvent, la méthode d’action doit obtenir des données à partir d’une base de données ou d’un service web afin de les afficher dans une page web ou d’enregistrer les données entrées dans une page web. Dans ces scénarios, il est facile de rendre la méthode d’action asynchrone : au lieu de retourner un objet ActionResult, vous retournez Task<ActionResult> et marquez la méthode avec le mot clé asynchrone. À l’intérieur de la méthode, lorsqu’une ligne de code démarre une opération qui implique un temps d’attente, vous la marquez avec le mot clé d’attente.

Voici une méthode d’action simple qui appelle une méthode de dépôt pour une requête de base de données :

public ActionResult Index()
{
    string currentUser = User.Identity.Name;
    var result = fixItRepository.FindOpenTasksByOwner(currentUser);

    return View(result);
}

Voici la même méthode qui gère l’appel de base de données de manière asynchrone :

public async Task<ActionResult> Index()
{
    string currentUser = User.Identity.Name;
    var result = await fixItRepository.FindOpenTasksByOwnerAsync(currentUser);

    return View(result);
}

Sous le couvre, le compilateur génère le code asynchrone approprié. Lorsque l’application effectue l’appel à FindTaskByIdAsync, ASP.NET effectue la FindTask demande, puis déroule le thread de travail et le rend disponible pour traiter une autre requête. Une fois la FindTask demande terminée, un thread est redémarré pour continuer à traiter le code qui arrive après cet appel. Pendant l’intervalle entre le moment où la FindTask demande est lancée et le moment où les données sont retournées, vous disposez d’un thread disponible pour effectuer un travail utile qui, sinon, serait lié en attendant la réponse.

Il y a une certaine surcharge pour le code asynchrone, mais dans des conditions de faible charge, cette surcharge est négligeable, tandis que dans des conditions de charge élevée, vous pouvez traiter les demandes qui seraient autrement tenues en attente de threads disponibles.

Il a été possible d’effectuer ce type de programmation asynchrone depuis ASP.NET 1.1, mais il était difficile d’écrire, sujet aux erreurs et difficile à déboguer. Maintenant que nous avons simplifié le codage pour cela dans ASP.NET 4.5, il n’y a aucune raison de ne plus le faire.

Prise en charge asynchrone dans Entity Framework 6

Dans le cadre de la prise en charge asynchrone dans la version 4.5, nous avons fourni une prise en charge asynchrone des appels de service web, des sockets et des E/S de système de fichiers, mais le modèle le plus courant pour les applications web est d’atteindre une base de données, et nos bibliothèques de données ne prenaient pas en charge async. À présent, Entity Framework 6 ajoute la prise en charge asynchrone de l’accès à la base de données.

Dans Entity Framework 6, toutes les méthodes qui provoquent l’envoi d’une requête ou d’une commande à la base de données ont des versions asynchrones. L’exemple ci-dessous montre la version asynchrone de la méthode Find .

public async Task<FixItTask> FindTaskByIdAsync(int id)
{
    FixItTask fixItTask = null;
    Stopwatch timespan = Stopwatch.StartNew();

    try
    {
        fixItTask = await db.FixItTasks.FindAsync(id);
        
        timespan.Stop();
        log.TraceApi("SQL Database", "FixItTaskRepository.FindTaskByIdAsync", timespan.Elapsed, "id={0}", id);
    }
    catch(Exception e)
    {
        log.Error(e, "Error in FixItTaskRepository.FindTaskByIdAsynx(id={0})", id);
    }

    return fixItTask;
}

Et cette prise en charge asynchrone fonctionne non seulement pour les insertions, les suppressions, les mises à jour et les recherches simples, elle fonctionne également avec les requêtes LINQ :

public async Task<List<FixItTask>> FindOpenTasksByOwnerAsync(string userName)
{
    Stopwatch timespan = Stopwatch.StartNew();

    try
    {
        var result = await db.FixItTasks
            .Where(t => t.Owner == userName)
            .Where(t=>t.IsDone == false)
            .OrderByDescending(t => t.FixItTaskId).ToListAsync();

        timespan.Stop();
        log.TraceApi("SQL Database", "FixItTaskRepository.FindTasksByOwnerAsync", timespan.Elapsed, "username={0}", userName);

        return result;
    }
    catch (Exception e)
    {
        log.Error(e, "Error in FixItTaskRepository.FindTasksByOwnerAsync(userName={0})", userName);
        return null;
    }
}

Il existe une Async version de la ToList méthode, car dans ce code, il s’agit de la méthode qui provoque l’envoi d’une requête à la base de données. Les Where méthodes et OrderByDescending configurent uniquement la requête, tandis que la ToListAsync méthode exécute la requête et stocke la réponse dans la result variable.

Résumé

Vous pouvez implémenter les meilleures pratiques de développement web décrites ici dans n’importe quel framework de programmation web et tout environnement cloud, mais nous disposons d’outils dans ASP.NET et Windows Azure pour faciliter la tâche. Si vous suivez ces modèles, vous pouvez facilement effectuer un scale-out de votre niveau web, et vous réduirez vos dépenses, car chaque serveur sera en mesure de gérer plus de trafic.

Le chapitre suivant examine comment le cloud active les scénarios d’authentification unique.

Ressources

Pour plus d’informations, consultez les ressources suivantes.

Serveurs web sans état :

CDN:

Programmation asynchrone :

Pour obtenir d’autres meilleures pratiques en matière de développement web, consultez les ressources suivantes :