locked
Ajout d'une WorkflowExtention partagée via web.config RRS feed

  • Question

  • Bonjour,

    Je souhaite ajouter des fonctionnalités à mon service de workflow et m'en servir dans une CodeActivity.

    Les spécifications de ce bloc de code sont potentiellement très variables et je souhaite donc passer par l'ajout d'une extention (WorkflowExtension) à mon service (WorkflowService) lui-même hébergé sur AppFabric..

    Par contre, il faut que cette extension soit partagée par TOUTES LES INSTANCES de TOUS LES SERVICES de workflow en cours d'exécution.
    et je souhaite bien entendu pouvoir ajouter cette extention via le fichier de web.config.

    J'ai bien trouvé une piste avec IServiceBehavior et BehaviorExtensionElement mais j'aimerais votre avis sur le sujet.

    Pour info, le contexte de mon projet est expliqué ici :

        "Débloquer plusieurs workflows en attente d'un événement ?"
        http://social.msdn.microsoft.com/Forums/fr-FR/wwffr/thread/a4e02763-6de9-4a65-a982-5f2bfb2daabf

    D'avance merci

    Damien

     

    vendredi 22 octobre 2010 13:14

Réponses

  • Bonjour Jeremy,

    et merci pour votre réponse,

    En regardant de + près dans l'aide de WF, j'ai trouvé ça :

     

    • Extensibilité de l'hôte du service de workflow
    • Utilisez la méthode Add pour ajouter une extension pour chaque instance du service de workflow. Le délégué spécifié est appelé pour créer une extension lorsqu'une instance du service de workflow est créée ou chargée à partir d'un magasin de persistance. Utilisez la méthode Add pour ajouter une extension pour chaque hôte du service de workflow. Une instance de l'extension est partagée pour toutes les instances du service de workflow.

     

    Donc, il me semble qu'il est possible de partager à toutes les instances de mon service de workflow - une seule et même instance de cette extension.

    Il me semble d'ailleurs que c'est ce que votre code propose, puisqu'on ajoute bien l'extension à l'hôte de service, et non à une instance de workflow.

     

    Par contre, il me semble que partager cette même instance à toutes les instances de tous les services hébergés par mon hôte (AppFabric dans mon cas ? c'est ça ?) me semble plus difficile...

    host.WorkflowExtensions.Add<MyExtension>(() => new MyExtension());

    Re,

    Voici la réponse à la première partie de votre message : partie citée ici. J'ai découopé ma réponse afin de faire claire, je vous donne la suite dans un autre message.

    Vous avez bien compris la subtilité entre instance de workflow et host et c'est bien à ce niveua qu'il y a souci :(

    Vous allez avoir plusiueurs hôtes : un par serveur de l'appfabric :( et donc si vous coulez utiliser votre extension telle une seule et unique instance dans l'appfabric, il faudra utiliser le cache de la fabrique pour que votre extension atteigne cette partie qui doit être commune.

    D'où une architecture un peu particulière où votre extension serrait en fait un proxy rendant accessible un singleton présent dans le cache de votre appfrabric. Ceci me semble tout à fait envisagable et l'implémentation ne doit pas être des plus compliquées ;)



    Jérémy Jeanson MVP, MCP, MCTS http://blogs.codes-sources.com/JeremyJeanson/ (French or English spoken)
    • Marqué comme réponse Damzz lundi 25 octobre 2010 14:34
    lundi 25 octobre 2010 12:30
    Modérateur
  • Vous parliez d'AppFabric et de son cache, or je compte utiliser AppFabric, mais pas le cache.

    En fait, cette extension doit permettre aux utilisateurs de compléter un référentiel partagé. Le support de ce référentiel est un simple fichier xml.  Ce support a été choisi pour son extensibilité la structure du référentiel change souvent). Seulement, l'inconvénient, c'est que je dois gérer les accès concurrents sur le fichier. Je passe pour cela par un ReaderWriterLockSlim qui protège des accès concurrents des multiples threads d'un processus.... mais - si j'ai bien compris - pas des autres processus (les autres instances de mon service de workflow). Du coup, si mon instance d'extension est partagée par toutes les instances de mon service, il n'y aura pas de problème.
    Seulement, d'autres services peuvent utiliser mon extension, et là, je ne vois vraiment pas comment gérer les accès concurrents sur le fichier.
    Je pense finalement que ce n'est pas le bon choix, et que je ferai mieux de faire un service WCF autonome en mode Singleton (InstanceContextMode.Single +  ConcurrencyMode.Multiple).

    Voilà, vous savez tout

    Merci encore

    Damien


    Dexième partie :

    Si votre extension doit impérativement acceder à un unique fichier Xml, effectivement on passe dan un autre mode...

    Celui d'une programmation où l'on doit sécuriré les accès à une ressources unique. Je distinguerai deux cas :

    1) sans AppFabric : d'où programmation à l'ancienne avce un seul service WCF, mais on ne pourra avoir qu'un serveur pour heberger ce service et garantire que ce serra bien un singleton

    2) finalement ne pas utiliser d'etension, mais coder des activités qui utilisent le cache de l'appfabric pour manipuler un vrai singleton dans toute l'appfabric. ce singleton étant chargé des acces à l'unique fichier Xml. Je n'ai pas encore utilisé l'appfabric pour cela, mais ça me semble être un fonctionnement facil à mettre en oeuvre car peu complexe. Là on a vraiment l'utilité de l'appfabric avec x serveurs.


    Jérémy Jeanson MVP, MCP, MCTS http://blogs.codes-sources.com/JeremyJeanson/ (French or English spoken)
    • Marqué comme réponse Damzz lundi 25 octobre 2010 14:35
    lundi 25 octobre 2010 12:45
    Modérateur

Toutes les réponses

  • Bonjour Dams,

    Qu'entendez vous par "cette extension soit partagée". Si l'idée est de partager une unique instance de l'extension, ce ne serra pas possible de base, hors mis ci cette extenstion utilise la chache de l'appfabric.

    Par contre il est tout à fait possible avec les fichiers de configuration de .net 4 et plus particulièrement de WCF4 de définir une configuration"par défaut" qui serrat utilisée par l'ensemble des services. Cette configuration pourra donc votre extension via son behavior.

    Si vous avez besoin d'informations l'implémentation du BehaviorExtensionElement, voici un petit exemple pour un classe extension : MyExtensition

    1 : l'implémentation de IServiceBehavior

    public class MyExtensionBehavior : IServiceBehavior
    {
      public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
      {
        WorkflowServiceHost host = serviceHostBase as WorkflowServiceHost;
    	if(host!=null)
    	{
        	host.WorkflowExtensions.Add<MyExtension>(() => new MyExtension());
    	}
      }
    }
    

    2 : l'impleémentation du BehaviorExtensionElement

    public class MyExtensionElement : BehaviorExtensionElement
    {
      public override Type BehaviorType
      {
        get { return typeof(MyExtensionBehavior); }
      }
    
      protected override object CreateBehavior()
      {
        return new MyExtensionBehavior();
      }
    }
    

    3 : le fichier de configuration pour un service (à modifier pour appliquer le behavior comme behavior par défaut dans votre cas)

    <system.serviceModel>
     <extensions>
      <behaviorExtensions>
       <add name=“MyExtension“ type="MyLib.WF4.MyExtensionElement, MyLib.WF4"/>
      </behaviorExtensions>
     </extensions>
     <services>
      <service name="MyService“ behaviorConfiguration="MyWorkflowBehavior">
      </service>
     </services>
     <behaviors>
      <serviceBehaviors>
       <behavior name="MyWorkflowBehavior">
        <MyExtension />
       </behavior>
      </serviceBehaviors>
     </behaviors>
    </system.serviceModel>
    
    Ces 3 élémént sont rarements réprésenté ensemble. Les retrouver ici devrait vous faciliter la tâche ;)
    Jérémy Jeanson MVP, MCP, MCTS http://blogs.codes-sources.com/JeremyJeanson/ (French or English spoken)
    lundi 25 octobre 2010 08:32
    Modérateur
  • Bonjour Jeremy,

    et merci pour votre réponse,

    En regardant de + près dans l'aide de WF, j'ai trouvé ça :

    • Extensibilité de l'hôte du service de workflow
    • Utilisez la méthode Add pour ajouter une extension pour chaque instance du service de workflow. Le délégué spécifié est appelé pour créer une extension lorsqu'une instance du service de workflow est créée ou chargée à partir d'un magasin de persistance. Utilisez la méthode Add pour ajouter une extension pour chaque hôte du service de workflow. Une instance de l'extension est partagée pour toutes les instances du service de workflow.

    Donc, il me semble qu'il est possible de partager à toutes les instances de mon service de workflow - une seule et même instance de cette extension.

    Il me semble d'ailleurs que c'est ce que votre code propose, puisqu'on ajoute bien l'extension à l'hôte de service, et non à une instance de workflow.

    host.WorkflowExtensions.Add<MyExtension>(() => new MyExtension());

    Par contre, il me semble que partager cette même instance à toutes les instances de tous les services hébergés par mon hôte (AppFabric dans mon cas ? c'est ça ?) me semble plus difficile...

    Vous parliez d'AppFabric et de son cache, or je compte utiliser AppFabric, mais pas le cache.

    En fait, cette extension doit permettre aux utilisateurs de compléter un référentiel partagé. Le support de ce référentiel est un simple fichier xml.  Ce support a été choisi pour son extensibilité la structure du référentiel change souvent). Seulement, l'inconvénient, c'est que je dois gérer les accès concurrents sur le fichier. Je passe pour cela par un ReaderWriterLockSlim qui protège des accès concurrents des multiples threads d'un processus.... mais - si j'ai bien compris - pas des autres processus (les autres instances de mon service de workflow). Du coup, si mon instance d'extension est partagée par toutes les instances de mon service, il n'y aura pas de problème.
    Seulement, d'autres services peuvent utiliser mon extension, et là, je ne vois vraiment pas comment gérer les accès concurrents sur le fichier.
    Je pense finalement que ce n'est pas le bon choix, et que je ferai mieux de faire un service WCF autonome en mode Singleton (InstanceContextMode.Single +  ConcurrencyMode.Multiple).

    Voilà, vous savez tout

    Merci encore

    Damien

    lundi 25 octobre 2010 10:36
  • Bonjour Jeremy,

    et merci pour votre réponse,

    En regardant de + près dans l'aide de WF, j'ai trouvé ça :

     

    • Extensibilité de l'hôte du service de workflow
    • Utilisez la méthode Add pour ajouter une extension pour chaque instance du service de workflow. Le délégué spécifié est appelé pour créer une extension lorsqu'une instance du service de workflow est créée ou chargée à partir d'un magasin de persistance. Utilisez la méthode Add pour ajouter une extension pour chaque hôte du service de workflow. Une instance de l'extension est partagée pour toutes les instances du service de workflow.

     

    Donc, il me semble qu'il est possible de partager à toutes les instances de mon service de workflow - une seule et même instance de cette extension.

    Il me semble d'ailleurs que c'est ce que votre code propose, puisqu'on ajoute bien l'extension à l'hôte de service, et non à une instance de workflow.

     

    Par contre, il me semble que partager cette même instance à toutes les instances de tous les services hébergés par mon hôte (AppFabric dans mon cas ? c'est ça ?) me semble plus difficile...

    host.WorkflowExtensions.Add<MyExtension>(() => new MyExtension());

    Re,

    Voici la réponse à la première partie de votre message : partie citée ici. J'ai découopé ma réponse afin de faire claire, je vous donne la suite dans un autre message.

    Vous avez bien compris la subtilité entre instance de workflow et host et c'est bien à ce niveua qu'il y a souci :(

    Vous allez avoir plusiueurs hôtes : un par serveur de l'appfabric :( et donc si vous coulez utiliser votre extension telle une seule et unique instance dans l'appfabric, il faudra utiliser le cache de la fabrique pour que votre extension atteigne cette partie qui doit être commune.

    D'où une architecture un peu particulière où votre extension serrait en fait un proxy rendant accessible un singleton présent dans le cache de votre appfrabric. Ceci me semble tout à fait envisagable et l'implémentation ne doit pas être des plus compliquées ;)



    Jérémy Jeanson MVP, MCP, MCTS http://blogs.codes-sources.com/JeremyJeanson/ (French or English spoken)
    • Marqué comme réponse Damzz lundi 25 octobre 2010 14:34
    lundi 25 octobre 2010 12:30
    Modérateur
  • Vous parliez d'AppFabric et de son cache, or je compte utiliser AppFabric, mais pas le cache.

    En fait, cette extension doit permettre aux utilisateurs de compléter un référentiel partagé. Le support de ce référentiel est un simple fichier xml.  Ce support a été choisi pour son extensibilité la structure du référentiel change souvent). Seulement, l'inconvénient, c'est que je dois gérer les accès concurrents sur le fichier. Je passe pour cela par un ReaderWriterLockSlim qui protège des accès concurrents des multiples threads d'un processus.... mais - si j'ai bien compris - pas des autres processus (les autres instances de mon service de workflow). Du coup, si mon instance d'extension est partagée par toutes les instances de mon service, il n'y aura pas de problème.
    Seulement, d'autres services peuvent utiliser mon extension, et là, je ne vois vraiment pas comment gérer les accès concurrents sur le fichier.
    Je pense finalement que ce n'est pas le bon choix, et que je ferai mieux de faire un service WCF autonome en mode Singleton (InstanceContextMode.Single +  ConcurrencyMode.Multiple).

    Voilà, vous savez tout

    Merci encore

    Damien


    Dexième partie :

    Si votre extension doit impérativement acceder à un unique fichier Xml, effectivement on passe dan un autre mode...

    Celui d'une programmation où l'on doit sécuriré les accès à une ressources unique. Je distinguerai deux cas :

    1) sans AppFabric : d'où programmation à l'ancienne avce un seul service WCF, mais on ne pourra avoir qu'un serveur pour heberger ce service et garantire que ce serra bien un singleton

    2) finalement ne pas utiliser d'etension, mais coder des activités qui utilisent le cache de l'appfabric pour manipuler un vrai singleton dans toute l'appfabric. ce singleton étant chargé des acces à l'unique fichier Xml. Je n'ai pas encore utilisé l'appfabric pour cela, mais ça me semble être un fonctionnement facil à mettre en oeuvre car peu complexe. Là on a vraiment l'utilité de l'appfabric avec x serveurs.


    Jérémy Jeanson MVP, MCP, MCTS http://blogs.codes-sources.com/JeremyJeanson/ (French or English spoken)
    • Marqué comme réponse Damzz lundi 25 octobre 2010 14:35
    lundi 25 octobre 2010 12:45
    Modérateur
  • D'où une architecture un peu particulière où votre extension serrait en fait un proxy rendant accessible un singleton présent dans le cache de votre appfrabric. Ceci me semble tout à fait envisagable et l'implémentation ne doit pas être des plus compliquées ;)

    Merci Jérémy,

    Je vais faire pareil, c'est à dire un post pour chaque citation ;-)

    Ok, bien compris l'architecture en question. En fait, je me fourvoyais sur un point, j'imaginais - et je ne sais pas pourquoi du reste - que 2 services ne partageaient pas le même hôte, ce qui est bien sûr complètement faux. Donc partager l'extension entre deux services différents ne pose aucun problème. Finalement, ce que je veux faire est possible assez facilement sur un seul et même serveur via le mécanisme d'extension illustré par votre exemple.

     

    lundi 25 octobre 2010 14:21
  • Dexième partie :

    Si votre extension doit impérativement acceder à un unique fichier Xml, effectivement on passe dan un autre mode...

    Celui d'une programmation où l'on doit sécuriré les accès à une ressources unique. Je distinguerai deux cas :

    1) sans AppFabric : d'où programmation à l'ancienne avce un seul service WCF, mais on ne pourra avoir qu'un serveur pour heberger ce service et garantire que ce serra bien un singleton

    2) finalement ne pas utiliser d'etension, mais coder des activités qui utilisent le cache de l'appfabric pour manipuler un vrai singleton dans toute l'appfabric. ce singleton étant chargé des acces à l'unique fichier Xml. Je n'ai pas encore utilisé l'appfabric pour cela, mais ça me semble être un fonctionnement facil à mettre en oeuvre car peu complexe. Là on a vraiment l'utilité de l'appfabric avec x serveurs.

    Je résume pour être sûr de bien comprendre :
    Dans le cache de l'appFabric, je peux stocker j'imagine tout type d'objet. Il est donc possible d'y stocker une instance d'un singleton WCF et je dois juste développer un proxy qui permet d'y accéder via une clef fixée par configuration ou dans le code.

    En fait, je n'avais pas envisagé le cas où un deuxième serveur serait nécessaire pour cette application...
    C'est vrai qu'il faut y penser, d'autant que le serveur sera certes dédié aux services WCF et WF, hébergés via AppFabric et/ou IIS/WAS...
    mais il va prendre de l'ampleur au fil du temps et donc se posera à un moment la question de venir le renforcer avec un deuxième...

    Je vais réfléchir à tout ça, c'est peut-être prématuré le cache de l'AppFabric.

    Merci encore en tout cas

    Damien

     

     

    lundi 25 octobre 2010 14:34
  • Arg, Attention : je parlais d'un proxy donnant accès à l'instance d'une classe , pas frocément d'un proxy WCF.

    L'idée est de coder une classe qui donne acces simplement à l'unique instance de la classe qui elle est réellement chargée de gérer le fichier xml.

    Ce n'est pas toujorus facil à présenter quand on parle programamtion pour nos amis les serveurs ;)


    Jérémy Jeanson MVP, MCP, MCTS http://blogs.codes-sources.com/JeremyJeanson/ (French or English spoken)
    lundi 25 octobre 2010 14:39
    Modérateur
  • Oui oui, je l'avais bien compris comme ça.

    Il se peut en effet que la classe en question (avec son unique instance partagée) soit un proxy WCF, mais ce n'est pas obligatoire.

    Dans ce cas, je développe un proxy de proxy .... non ?

     

     

    lundi 25 octobre 2010 16:17