2010-12-06 4 views
4

J'essaie d'évaluer la technologie de communication à utiliser dans un nouveau système, à l'heure actuelle, il semble que Remoting est notre seule option, car la performance de WCF est terrible.Pourquoi les performances de WCF sont-elles si lentes par rapport à Remoting?

J'ai comparé l'appel d'un service WCF hébergé dans IIS7 à l'aide de nettcp, par rapport à l'appel d'une interface distante hébergée dans une application de console. Le service WCF prend ~ 4,5 secondes pour effectuer 1000 requêtes, synchronousoly sur un endpoint (qui renvoie simplement un nouvel instant d'un objet). Le client à distance prend < 0,5 seconde pour effectuer la même tâche.

Voici le code client WCF:

public class TcpNewsService : INewsService 
{ 
    private INewsService _service = null; 

    Lazy<ChannelFactory<INewsService>> _newsFactory = new Lazy<ChannelFactory<INewsService>>(() => 
    { 
     var tcpBinding = new NetTcpBinding 
      { 
       //MaxBufferPoolSize = int.MaxValue, 
       //MaxBufferSize = int.MaxValue, 
       //MaxConnections = int.MaxValue, 
       //MaxReceivedMessageSize = int.MaxValue, 
       PortSharingEnabled=false, 
       TransactionFlow = false, 
       ListenBacklog = int.MaxValue, 
       Security = new NetTcpSecurity 
       { 
        Mode = SecurityMode.None, 
        Transport = new TcpTransportSecurity 
        { 
         ProtectionLevel = System.Net.Security.ProtectionLevel.None, 
         ClientCredentialType = TcpClientCredentialType.None 
        }, 
        Message = new MessageSecurityOverTcp 
        { 
         ClientCredentialType = MessageCredentialType.None } 
        }, 
       ReliableSession = new OptionalReliableSession { Enabled = false } 
      }; 
     EndpointAddress endpointAddress = new EndpointAddress("net.tcp://localhost:8089/NewsService.svc"); 
     return new ChannelFactory<INewsService>(tcpBinding, endpointAddress); 
    }); 

    public TcpNewsService() 
    { 
     _service = _newsFactory.Value.CreateChannel(); 
     ((ICommunicationObject)_service).Open(); 

    } 

    public List<NewsItem> GetNews() 
    { 
     return _service.GetNews(); 
    } 
} 

Et une application simple de la console pour appeler le code client:

var client = new TcpNewsService(); 

Console.WriteLine("Getting all news"); 

var sw = new System.Diagnostics.Stopwatch(); 
sw.Start(); 

for (int i = 0; i < 1000; i++) 
{ 
    var news = client.GetNews(); 
} 
sw.Stop(); 

Console.WriteLine("Finished in " + sw.Elapsed.TotalSeconds); 
Console.ReadLine(); 

Le fichier web.config pour l'hôte IIS ressemble à ceci:

<system.serviceModel> 
<services> 
    <service behaviorConfiguration="NewsServiceBehavior" name="RiaSpike.News.Service.NewsService"> 
    <endpoint address="" 
      binding="netTcpBinding" 
      bindingConfiguration="tcpBinding" 
      contract="RiaSpike.News.Types.INewsService"> 
    </endpoint> 
    <endpoint address="http://localhost:8094/NewsService.svc" 
      binding="basicHttpBinding" 
      bindingConfiguration="httpBinding" 
      contract="RiaSpike.News.Types.INewsService"> 
    </endpoint> 
    </service> 
</services> 
<behaviors> 
    <serviceBehaviors> 
    <behavior name="NewsServiceBehavior"> 
     <serviceDebug includeExceptionDetailInFaults="true" /> 
    </behavior> 
    </serviceBehaviors> 
</behaviors> 
<bindings> 
    <basicHttpBinding> 
    <binding name="httpBinding"> 
     <security mode="None"> 
     <transport clientCredentialType="None" /> 
     </security> 
    </binding> 
    </basicHttpBinding> 
    <netTcpBinding> 
    <binding name="tcpBinding" portSharingEnabled="false"> 
     <security mode="None"> 
     <transport clientCredentialType="None" /> 
     <message clientCredentialType="None" /> 
     </security> 
     <reliableSession enabled="false" /> 
    </binding> 
    </netTcpBinding> 
</bindings> 

Et la classe de service hébergé dans IIS:

[ServiceBehavior(
    ConcurrencyMode = ConcurrencyMode.Multiple, 
    InstanceContextMode = InstanceContextMode.Single, 
    AddressFilterMode = AddressFilterMode.Any 
)] 

public class NewsService : MarshalByRefObject, INewsService 
{ 

    public List<NewsItem> GetNews() 
    { 
     return new List<NewsItem> 
      { 
       new NewsItem { Descripion = "The Description", Id = 1, Title = "The Title"} 
      }; 
    } 
} 

J'ai retracé l'activité de WCF et ont vu le processus prendre environ 5 millisconds pour terminer (je ne pouvais pas télécharger Animage, voici une trace de acivités du journal)

De: Traitement du message 5. Transfert 3/12/2010 15: 35: 58.861
Limite d'activité. Début 3/12/2010 15: 35: 58.861
Réception d'un message sur un canal. Information 3/12/2010 15: 35: 58.861
Pour: Exécuter 'Ria.Spike.News.INewsService.GetNews' Transfert 3/12/2010 15: 35: 58.864
Limite d'activité. Suspendez 3/12/2010 15: 35: 58.864
De: Exécuter 'Ria.Spike.News.INewsService.GetNews' Transfert 3/12/2010 15: 35: 58.864
Limite d'activité. Résumé 3/12/2010 15: 35: 58.864
Envoyé un message sur un canal Information 3/12/2010 15: 35: 58.866
Limite d'activité. Arrêter 3/12/2010 15: 35: 58,866

Est-ce aussi bon qu'il obtient: s

est ici le code d'accès distant utilisé dans cet exemple.

var iserver = (INewsService)Activator.GetObject(typeof(INewsService), "tcp://127.0.0.1:9000/news"); 
var sw = new System.Diagnostics.Stopwatch(); 
sw.Start(); 

for (int i = 0; i < 1000; i++) 
{ 
    var news = iserver.GetNews(); 
} 

sw.Stop(); 

Console.WriteLine("Finished in " + sw.Elapsed.TotalSeconds); 
Console.ReadLine(); 

Et le point de terminaison TCP pour ce canal d'accès distant d'hébergement dans IIS:

public class Global : System.Web.HttpApplication 
{ 
    private TcpServerChannel _quote; 

    protected void Application_Start(object sender, EventArgs e) 
    { 
     _quote = new TcpServerChannel(9000); 
     if (ChannelServices.RegisteredChannels.Length ==0) 
     { 
      ChannelServices.RegisterChannel(_quote, false);  
     } 


     RemotingConfiguration.RegisterWellKnownServiceType(
     typeof(NewsService), 
     "news", 
     WellKnownObjectMode.SingleCall); 

     _quote.StartListening(null);  
    } 
} 
+0

Il serait intéressant de voir s'il y a une pénalité de démarrage pour la version WCF.Pourriez-vous essayer une course où le sw n'est pas commencé jusqu'à ce que l'appel soit fait au moins une fois et afficher les résultats? –

+0

Salut Peter, j'ai invoqué deux fois l'itération d'appel 1000 à deux reprises pour illiminer le coût de starup. La différence de temps entre le premier et le second était négligeable. – gav

+0

Quelle est votre configuration d'accès à distance? –

Répondre

9

Ce test séquentiel, synchrone, seuls les appels. Un service WCF hébergé par IIS fournit plus d'infrastructure pour gérer une charge plus élevée et dépassera probablement les communications à distance pour un test à charge élevée (un avec beaucoup de connexions simultanées).

Une extrémité distante peut également être hébergée dans IIS pour obtenir les mêmes avantages. WCF peut également être hébergé dans une console. Vous comparez vraiment des pommes à des oranges ici.

Questions connexes