Nouvelles Chroniques d'Amethyste

Penser au Sens, pas au Verbe

Tâches planifiées sous Windows Azure partie III

Poster un commentaire

Troisième partie d’une série d’articles.

Nous avons abordé l’utilisation de WebJobs pour créer des tâches planifiées.

https://amethyste16.wordpress.com/2014/06/01/taches-planifiees-sous-windows-azure-partie-i/

 

Je propose de revenir sur ce thème afin de l’approfondir un peu.

Au menu de cet article:

  1. J’ai montré les fonctionnalités de base accessibles directement depuis le portail  Mais les WebJobs disposent d’un SDK qui permet de traiter des situations nettement plus sophistiquées comme par exemple déclencher une tâche à chaque fois qu’un blob est alimenté.Et nous verrons que c’est même très simple! Je dois dire qu’en ce qui concerne l’intégration, Microsoft nous a sortit le grand jeu.
  2. Nous verrons également que les WebJobs peuvent très bien être lancés on premises. Et ça c’est magique je trouve.
  3. Ce n’est pas tout, je souhaiterai revenir sur le déploiement des WebJobs. Je suis loin d’avoir tout raconté

Création d’un WebJob avec le SDK

Le SDK est bien entendu un package Nuget. Il est encore en preview, mais cela ne sera peut être plus le cas le jour où vous lirez cet article. En attendant:

Install-Package Microsoft.Azure.WebJobs -pre

 

Note: Preview signifie que rien ne prouve que ce code continue à se compiler demain matin. Microsoft peut décider à tout moment de restructurer le SDK, renommer une classe ou que sais-je et d’ailleurs ils l’ont déjà fait!

 

On va créer une tâche qui surveille un blob. Dès qu’une image y est déposée, la tâche la charge, y applique un filigramme et la redépose dans un autre blob.

Cela suppose que vous disposiez déjà d’un storage Azure, sinon créez le dès maintenant.

 

Partons d’une application console et chargeons le SDK, puis on va créer la classe qui fera le travail:

public class ImageFuncs
{
    public static void AjouterFiligramme(
    [BlobTrigger(@"images-input/{name}")] Stream inputStream,
    [Blob(@"images-output/{name}", FileAccess.Write)] Stream outputStream)
    {
        WebImage image = new WebImage(inputStream);

        // applique filigramme
        image.AddTextWatermark("Copyright untel", fontSize: 20, fontColor: "red");

        // sauvegarde
        var bytes = image.GetBytes();
        outputStream.Write(bytes, 0, bytes.Length);
    }
}

 

Ce n’est pas le code, au demeurant banal, qui est intéressant. Ce sont les paramètres de la méthode et plus particulièrement les deux attributs.

  • BlobTriggerAttribute
  • BlobAttribute

Ces attributs relient un paramètre à un blob Azure en entrée et en sortie.

Examinons rapidement la syntaxe:

[BlobTrigger(@ »images-input/{BlobName} »)]

Elle nous dit que l’on surveille les événement du blob Images-input situé dans le conteneur Input. Nous verrons plus loin quelques variantes.

Il faut également ajouter FileAccess.Write pour que ça marche. Par défaut, c’est à dire sans second paramètre, le jobs considère le Stream comme en lecture seule, c’est à dire qu’il doit déjà exister. Sans le paramètre vous obtenez une erreur 404.

 

Autre difficulté: ne pas oublier de rajouter les dépendances avec la bonne version. En l’occurrence pour cet exemple System.Web.WebPage en version 2.0. Ne pas oublier de les déployer dans le /bin pour qu’elles apparaissent dans le package. Il faut aussi ajouter une référence à System.Web.Helpers.

 

On a donc un code qui exécute une tâche, on a besoin d’un hôte pour l’héberger et l’exécuter. On ajoute ceci dans la méthode Main:

JobHost host = new JobHost();
host.RunAndBlock();

JobHost est chargée d’écouter les triggers, gérer les bindings et appeler la fonction de traitement. La méthode RunAndBlock lance l’hôte bien entendu, mais bloque également le thread tant que l’hôte tourne.

 

Voilà, c’est tout! On a plus qu’à déployer. Admirez la simplicité!

Le webjob est dans cette configuration hébergé non pas par un site Web, mais par une application console.

Parlons déploiement. Il existe plusieurs méthodes, mais qui au fond ne sont pas bien différentes à part une.

Notez que le problème des chaînes de connexion pour permettre au webjob d’accéder au storage et aux logs est abordé plus loin dans un chapitre à part.

Déploiement (première méthode)

Pour déployer sur Azure on créée un zip contenant l’exécutable et ses dépendances.

2014-09-08_22-13-14

Une fois terminé:

2014-09-08_22-16-49

 

Nous avons maintenant besoin d’un blob qui servira de ressource à notre script. Créez un storage si ce n’est déjà fait.

On doit ensuite expliquer au WebJob à qui il devra s’adresser. Nous allons placer dans une variable d’environnement les informations de connexion nécessaires. Dans le panneau de configuration du Website qui va héberger notre tâche, nous trouvons:

2014-09-07_23-30-26

On va créer deux chaînes de connexion appelées:

  1. AzureWebJobsStorage
    Chaîne vers le storage contenant les fichiers à traiter
  2. AzureWebJobsDashBoard
    Chaîne vers le storage qui gère les logs et l’administration

 

Ce sont les noms par défaut attendu par le SDK. On récupère les informations nécessaires ici depuis le portail du storage concerné (cliquer sur MANAGE ACCESS KEY dans la barre de menus du bas):

2014-10-25_18-38-01

Et il s’ouvre la popin:

2014-09-08_22-22-01

On utilisera le format:

DefaultEndpointsProtocol=https;AccountName=NAME;AccountKey=KEY

 

Pour aboutir à cette situation:

2014-09-08_22-47-21

Il n’y a pas d’options storage, on va choisir Custom. On démarre ensuite la tâche et on injecte une image dans l’entrée.

 

Note: si ça ne marche pas du premier coup, n’hésitez surtout pas à vous rendre dans les logs de la tâche pour trouver de l’aide. Le principal problème rencontré a été de bien placer toutes les dépendances dans le package.

 

La surveillance des blobs se fait à une cadence assez lente, environ 10 minutes. Donc allez boire un café une fois le déploiement terminé.

Il peut arriver qu’une tâche soit assez longue. Vous devez savoir deux choses:

  1. dans la configuration gratuite il ne vous est accordé que 2.5 minutes de CPU toutes les 5 minutes
  2. Par défaut le Web Site passe en mode sommeil au bout de 20 minutes. Vous pouvez vous rendre dans la configuration et activer l’option Always on, mais l’option est payante.

2014-09-10_09-14-11

 

Une série de conteneurs seront créés sur le storage Dashboard pour son usage. Ils contiennent les logs et des informations de gestion:

2014-09-08_23-32-41

On peut y accéder soit depuis le site de logs (voir plus loin) soit directement en listant le blog correspondant.

 

Les répertoires input et output sont également automatiquement créés.

Déployer depuis VS

Nous venons de voir un modèle de déploiement à partir d’un fichier zip. Mais il existe des assistants qui font le travail à votre place. Installez le plug-in suivant si nécessaire:

http://visualstudiogallery.msdn.microsoft.com/f4824551-2660-4afa-aba1-1fcc1673c3d0

 

  • Faites un click droit sur votre projet:

2014-09-09_23-33-37

  •  Cliquer sur Publish as Azure WebJob:
  • Créez un profil de déploiement Azure ou choisissez en un existant
  • Cliquez sur Publish

Il ne vous reste plus qu’à attendre la fin du déploiement puis tester.

Ajoutez un fichier image dans le conteneur images-input et attendez 10 minutes que le job se déclenche. Il va automatiquement créer images-output:

2014-10-25_19-42-21

Déployer avec un WebSite

Une autre option est de déployer le WebJobs en même temps que le WebSite. Le WebJobs peut être dans un projet à part ou bien à l’intérieur du projet Web.

 

  • Faites un clic droit sur le projet Web, puis Add.

 

2014-09-09_23-46-11

 

On voit s’afficher deux menus intéressants:

  1. Existing Project as Azure WebJob
  2. New Azure WebJob Project

 

Dans les deux cas on ouvre le formulaire suivant:

 

2014-09-09_23-50-10

 

Si la deuxième option est choisie, un projet de création d’un WebJob sera créé similaire à celui-ci:

 

2014-09-09_23-53-28

 

Dernière option possible: utilisation d’un template de projet. Il existe lui-aussi:

 

2014-09-09_23-54-57

Déploiement depuis une application console

On peut également déployer une application console dans Azure hébergeant un webjob avec une des méthodes précédemment décrites. Le slot du site sera vide bien entendu, mais tous les Webjobs n’ont pas forcément besoin d’une interface graphique. Le lien vers le WebSite affichera ceci:

2014-10-25_18-46-01

Une fois les problème de chaine de connexion réglés:

2014-10-25_18-42-50

Vous n’avez plus qu’à tester.

Déployer on premises

Note: j’ai discuté de cette option avec un consultant Microsoft qui est assez incertain sur la légitimité de ce scénario. En principe il est surtout là pour faciliter le débogage des webjobs. Un webjob n’est pas destiné à servir en on premises. Ca à l’air de fonctionner, donc à voir.

 

Le SDK permet de choisir un autre lieu de déploiement qu’un Web Site et en particulier une application on premises.

On a déjà tout fait en fait. L’exemple précédent présente une application console. Rien ne nous interdit de la lancer telle quel et au bout de 10 minutes:

2014-09-10_14-38-07

Il est possible bien entendu de lancer une méthode à la demande:

JobHost host = new JobHost();
host.RunAndBlock();

MethodInfo meth = typeof(ImageFuncs).GetMethod("AjouterFiligramme");
host.Call(meth);

Comment passer la chaîne de connexion

Nous avons vu une possibilité de déployer la chaîne de connexion depuis le portail dans un paramètre de site. Ce n’est pas la seule et pas la plus pratique dans une optique de déploiement automatisé.

On a au total trois méthodes:

  1. Fichier de configuration
  2. Paramètre de site
  3. JobHostConfiguration

 

JobHostConfiguration est une classe dont on peut passer une instance à JobHost. On pourrait ainsi avoir quelque chose comme:

JobHostConfiguration config = new JobHostConfiguration();
config.DashboardConnectionString = "DefaultEndpointsProtocol=https;AccountName=azertyexpertime;AccountKey=DtHDdRN1Z2l...QtKiiF6RF0a+CzBs9A==";
config.StorageConnectionString = "DefaultEndpointsProtocol=https;AccountName=azertyexpertime;AccountKey=DtHD...tKiiF6RF0a+CzBs9A==";

JobHost host = new JobHost(config);
host.RunAndBlock();

 

Il est possible de placer nos chaînes de connexion dans le fichier de configuration:

<connectionStrings>
<add name="AzureWebJobsDashboard" connectionString="DefaultEndpointsProtocol=https;AccountName=[accountName];AccountKey=[accountkey]"/>
<add name="AzureWebJobsStorage" connectionString="DefaultEndpointsProtocol=https;AccountName=[accountName];AccountKey=[accountKey]"/>
</connectionStrings>

 

Les attributs de liaison en détail

Examinons plus en détail la syntaxe:

[BlobTrigger(@ »images-input/{name} »)]

Images-input est le nom d’un conteneur, {name} est un remplacement pour le nom d’un blob dans ce conteneur. On va donc surveiller dans notre exemple tous les blogs de notre conteneur.

Il est parfois utile de passer la valeur de {name} dans la fonction. C’est tout simple, on créée un paramètre name:

public static void AjouterFiligramme(
[BlobTrigger(@"images-input/{name}.jpg")] Stream inputStream,
[Blob(@"images-output/{name}_water.jpg", FileAccess.Write)] Stream outputStream,
string name)
{
    WebImage image = new WebImage(inputStream);

    // applique filigramme
    image.AddTextWatermark(name, fontSize: 20, fontColor: "red");

    // sauvegarde
    var bytes = image.GetBytes();
    outputStream.Write(bytes, 0, bytes.Length);
}

 

Examinez le code qui précède et ses modifications. Outre le paramètre name, nous recherchons maintenant les fichiers  .jpg et on les renomment avec le suffixe _water.

Vous trouverez ici un article plus complet sur ces options:

http://victorhurdugaci.com/advanced-bindings-with-the-windows-azure-web-jobs-sdk/

 

Il est possible de déclencher d’autres storages Azure à l’aide d’attributs similaires:

  • QueueTriggerAttribute
  • QueueAttribute
  • TableTriggerAttribute
  • TableAttribute
  • ServiceBusTrigger
  • ServiceBus

Pour le service bus il faudra charger un autre package:

Install-Package Microsoft.Azure.Jobs.ServiceBus -Pre

 

Actuellement ces attributs supportent les liaisons (bindings) suivantes:

  • Stream
  • TextReader/Writer
  • String

 

Le site de logs

Les webjobs loguent leur activité et on peut donc en effectuer le suivit d’autant plus que c’est un des seuls moyens de déboguer un job.

Cliquez vers le lien qui vous amène sur le site de logs du WebJob. Si les choses ont mal tournées quelque chose de similaire peut s’afficher:

2014-09-09_23-05-30

On peut par exemple cliquer sur le lien d’un des cas d’échec:

2014-09-09_23-10-11

 

Des informations sur la nature du problème s’affichent.

Si on peut le corriger il est possible de rejouer la séquence en cliquant sur le bouton Replay:

2014-09-09_23-12-11

Un autre clic sur Replay et vous pouvez constater ou non si le problème s’est résolu. Il faut éventuellement atteindre une ou deux minutes pour voir quelque chose se produire.

2014-09-09_23-28-53

 

Si vous regardez en haut de la page, vous verrez ceci:

2014-09-09_23-15-03

Cliquez sur Functions:

2014-09-09_23-16-33

La liste des fonctions installées dans l’espace du WebJob est affichée ainsi que des statistiques.

Pour terminer

Les évolutions du SDK sont annoncées sur ce blog, par exemple la dernière:

http://azure.microsoft.com/blog/2014/09/06/announcing-the-0-5-0-beta-preview-of-microsoft-azure-webjobs-sdk/

 

  • Depuis la dernière version du SDK, seules les méthodes publiques dans les classes publiques seront considérées comme une tâche. Les autres méthodes ne seront pas indexées.
  • On dispose aussi d’un support pour les méthodes asynchrones si la liaison est une Queue.
  • En déploiement sous Azure les WebJobs sont adossés à un WebSite. Cela signifie que leur scalabilité est liée à celle du WebSite. Si vous supprimez le web site, les web jobs hébergés disparaitront également.
  • Un web site est juste un des moyens d’héberger un webjob. On peut le faire depuis une application console que l’on déploie dans Azure
  • L’émulateur n’est pas non plus supporté.
  • Le trigger n’est pas déclenché jusqu’à ce qu’il y ai une sortie, mais une seule fois: lorsqu’un blog est créé ou bien modifié

 

Et vous avez des exemples ici:

https://github.com/Azure/azure-webjobs-sdk-samples

 

 Bibliographie

 

Publicités

Laisser un commentaire

Entrez vos coordonnées ci-dessous ou cliquez sur une icône pour vous connecter:

Logo WordPress.com

Vous commentez à l'aide de votre compte WordPress.com. Déconnexion / Changer )

Image Twitter

Vous commentez à l'aide de votre compte Twitter. Déconnexion / Changer )

Photo Facebook

Vous commentez à l'aide de votre compte Facebook. Déconnexion / Changer )

Photo Google+

Vous commentez à l'aide de votre compte Google+. Déconnexion / Changer )

Connexion à %s