Accueil

Articles techniques

A propos de AzureGuru.org

Publier sur AzureGuru.org
 
   Accueil

27

Comment héberger et consommer un service WCF interne dans Windows Azure

Le but de cet article est d'exposer une méthode simple pour héberger et consommer un service WCF interne dans windows Azure.
La connectivité à un service WCF interne depuis un WebRole passe par un InternalEndPoint et une communication inter-rôles qui ne passe pas par le LoadBalancer, au contraire d'un service WCF interne exposé à l'extérieur (ceci fera l'objet d'un nouveau billet). 

Il s'agit dans un premier temps de créer un projet Cloud incluant un WorkerRole (notre service WCF nommé WCFService) et un WCF Service Web Role qui va consommé ce service (nommé WCFServiceWebRole).





Le WorkerRole WCFService :

Le WorkerRole WCFService référence System.serviceModel, inclu la classe où est implémentée la méthode du service et une interface qui expose la méthode WCF.

La classe DemoService.cs : 
 
namespace WCFService
{
    public class DemoService : IDemoService
    {
        public string Echo(string message)
        {
            return "Vous avez dit : " + message;
        }
    }
 } 

L'interface IDemoService :
 
 namespace WCFService
 {
     [ServiceContract]
     public interface IDemoService
     {
         [OperationContract]
         string Echo(string message);
     }
 }

Il faut, au niveau du Rôle, ajouter un Endpoint de type "Internal" que l'on nommera DemoService



La méthode suivante instancie le ServiceHost et le lie avec le Endpoint DemoService (Binding NetTcp) :
La baseAddress est construite dynamiquement à partir du Internal EndPoint DemoService car l'adresse IP et le port ne seront connus qu'en runtime.

        
private void STARTWCFServiceHost()
 {
      var baseAddress = string.Format("net.tcp://{0}", RoleEnvironment.CurrentRoleInstance.
InstanceEndpoints["DemoService"].IPEndpoint);
      var host = new ServiceHost(typeof(DemoService), new Uri(baseAddress));

      host.AddServiceEndpoint(typeof(IDemoService), new NetTcpBinding(SecurityMode.None),"echo");
      host.Open();
 }

Cette méthode doit être appellée dans le OnStart du WorkerRole.
    
public override bool OnStart()
{
    // Set the maximum number of concurrent connections 
    ServicePointManager.DefaultConnectionLimit = 12;

    DiagnosticMonitor.Start("DiagnosticsConnectionString");

    // For information on handling configuration changes
    // see the MSDN topic at http://go.microsoft.com/fwlink/?LinkId=166357.
    RoleEnvironment.Changing += RoleEnvironmentChanging;

    // NEW
 STARTWCFServiceHost();

    return base.OnStart();
}

Le WCF Service Web Role WCFServiceWebRole :

Dans le WebRole, on créé une page web (default.aspx) qui va consommer le service DemoService.
Cette page ultra-simple, contient un TextBox, un Bouton et un Label.



Sur le click du bouton, on se connecte au service WCF de manière classique (instanciation d'un ChannelFactory, puis création du Channel), puis on invoque la méthode Echo du service pour remplir le Label.

  
protected void Button1_Click(object sender, EventArgs e)
{
    var factory = new ChannelFactory< WCFService.IDemoService >(
new NetTcpBinding(SecurityMode.None));
    var channel1 = factory.CreateChannel(GetRandomEndpoint());

    Label1.Text = channel1.Echo(TextBox1.Text);
}

La partie un peu plus complexe est la récupération du Endpoint GetRandomEndPoint :
Comme la communication WCF interne ne passe pas par un LoadBalancer, et si plusieurs instance du WorkerRole WCFService existent, nous allons nous connecter aléatoirement sur une des instances pour distribuer la charge.
Le but est de récupérer tous les EndPoints des WorkerRoles WCFService qui implémentent le EndPoint DemoService et d'en selectionner un aléatoirement.
 
private EndpointAddress GetRandomEndpoint()
{
    var endpoints =
        RoleEnvironment.Roles["WCFService"].Instances.Select
(i => i.InstanceEndpoints["DemoService"]).ToArray();
    var rnd = new Random(System.DateTime.Now.Millisecond);
    return new EndpointAddress(string.Format("net.tcp://{0}/echo", 
endpoints[rnd.Next(endpoints.Count() - 1)].IPEndpoint));
}

Voila, le WebRole consomme le service WCF dans le WorkerRole via un internalEndPoint :


Vous pouvez télécharger le code source ici

Commentaires

Il n'y a encore aucun commentaire, soyez le premier...

Poster un commentaire

Only registered users may post comments.