2010-12-06 4 views
4

Ich versuche, die Kommunikationstechnologie nutzen in einem neuen System zu bewerten, jetzt sieht es aus wie unser Remoting einzige Option.Warum ist WCF im Vergleich zu Remoting so langsam? wie WCF Leistung ist schrecklich

Ich habe gebenchmarkt einen WCF-Dienst gehostet in IIS7 Aufruf mit NetTcp, im Vergleich zu einer Remote Schnittstelle in einer Konsolenanwendung gehostet aufrufen. Der WCF-Dienst benötigt ~ 4,5 Sekunden, um 1000 Anforderungen synchron auf einem Endpunkt auszuführen (der einfach eine neue Instanz eines Objekts zurückgibt). Der Remoting-Client benötigt < 0,5 Sekunden, um die gleiche Aufgabe auszuführen. Hier

ist der WCF-Client-Code:

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(); 
    } 
} 

Und eine einfache Konsolenanwendung den Client-Code aufzurufen:

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(); 

Die Datei Web.config für die IIS-Host wie folgt aussieht:

<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> 

Und die Serviceklasse in IIS gehostet:

[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"} 
      }; 
    } 
} 

ich die WCF-Aktivität verfolgt haben und haben den Prozess dauert etwa 5 millisconds gesehen zu vervollständigen (I Animage nicht laden konnte, ist hier ein Akivität Spur aus dem Protokoll)

Von: Die Verarbeitung der Nachricht 5. Übertragung 2010.03.12 15: 35: 58,861
Aktivität Grenze. Start 3/12/2010 15: 35: 58.861
Empfangen einer Nachricht über einen Kanal. Information 3/12/2010 15: 35: 58.861
Zu: Ausführen 'Ria.Spike.News.INewsService.GetNews' Transfer 3/12/2010 15: 35: 58.864
Aktivität Grenze. Suspend 3/12/2010 15: 35: 58.864
Von: Ausführen 'Ria.Spike.News.INewsService.GetNews' Transfer 3/12/2010 15: 35: 58.864
Aktivitätsgrenze. Fortsetzen 2010.03.12 15: 35: 58,864
eine Nachricht über einen Kanal gesendete Informationen 2010.03.12 15: 35: 58,866
Aktivität Grenze. Stoppen 2010.03.12 15: 35: 58,866

Ist das so gut wie es geht: s

Hier ist der Code in Remote diesem Beispiel verwendet.

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(); 

Und eine der TCP-Endpunkt für diesen Kanal Remote in IIS-Hosting:

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

Es wäre von Interesse sein, es zu sehen, ob eine Start-up Strafe für die Version WCF ist.Könnten Sie einen Lauf versuchen, bei dem der sw nicht gestartet wird, bis der Anruf mindestens einmal erfolgt ist, und die Ergebnisse veröffentlichen? –

+0

Hallo Peter, ich habe tatsächlich die 1000 Call Iteration zweimal aufgerufen, um die Starup-Kosten zu reduzieren. Der Zeitunterschied zwischen dem ersten und zweiten war vernachlässigbar. – gav

+0

Was ist Ihre Remoting-Konfiguration? –

Antwort

9

Diese Tests sequentiell, synchron, können nur Gespräche. Ein von IIS gehosteter WCF-Dienst bietet mehr Infrastruktur, um eine höhere Auslastung zu bewältigen, und wird wahrscheinlich Remoting für einen Hochlasttest (einen mit vielen gleichzeitigen Verbindungen) übertreffen.

Ein Remote Endpunkt kann auch in IIS gehostet werden, obwohl die gleichen Vorteile zu erhalten. WCF kann auch in einer Konsole gehostet werden. Sie vergleichen hier wirklich Äpfel mit Orangen.