2009-04-24 4 views
22

Ich habe eine Reihe von .NET Webservices in einer IIS-Anwendung ausgeführt. Diese Webservices werden von einer anderen IIS-Anwendung (Frontend) genutzt. Der erste Anruf ist ziemlich langsam, etwa 5 bis 10 Sekunden. Danach sind es nur noch Millisekunden. Der erste Anruf wird als Leistungsproblem betrachtet.ASMX Web Service langsam erste Anfrage

Wir haben eine Anwendung ausprobiert, die alle diese Webdienste aufruft, aber das löst offensichtlich nichts. Es ist also nicht der Standard-Anwendungsrecycle, der das Problem darstellt. Ich habe eine Anwendung erstellt, die den Dienst mehrmals initialisiert und die Zeit misst, die zum Erstellen einer Instanz benötigt wird. Bevor ich diese Anwendung starte, stelle ich sicher, dass meine Webservice-Anwendung gestartet/recycelt wird, dann starte ich die Anwendung. Die erste Initialisierung dauert zwischen 2 und 4 Sekunden, alle anderen sind nur Millisekunden.

Ein anderer Gedanke ist, dass wir eine Seite in der Frontend-Anwendung erstellen, die alle Webservices initiiert und die wir diese Seite aufrufen, bevor sich Benutzer dort befinden. Ich halte dies nicht für eine elegante Lösung, was könnte ich sonst noch versuchen?

+0

Was passiert bei der Site-Initialisierung? – jro

Antwort

34

Die Verzögerung, die auftritt, wenn ein Client einen Webdienst zum ersten Mal aufruft, ist darauf zurückzuführen, dass standardmäßig eine XmlSerializers-DLL für den Webdienst kompiliert werden muss. Dies verursacht die 2-4 Sekunden für den ersten Anruf. Dies ist natürlich der Fall, wenn die Webservice-Anwendung bereits ausgeführt wird. Wenn dies nicht der Fall ist, müssen Sie eine Wiederverwendung durchführen. In diesem Fall könnten die anderen Antworten helfen.

Um den ersten Aufruf zu beschleunigen, können Sie die XmlSerializers-DLL zur Kompilierzeit erstellen. Sie können dies tun, indem Sie Ihren Projektbuild 'Generiere Serialisierungsassembly' auf 'Ein' setzen. Dies generiert eine MyApplication.XmlSerializers.dll, die die Webservice-Informationen enthält. Jetzt fiel der anfängliche Anruf auf 300 ms, vermutlich das Laden der DLL. Alle Anrufe danach dauern 0 ms.

Klicken Sie in Visual Studio mit der rechten Maustaste auf Ihr Projekt und wählen Sie "Eigenschaften". Gehe zum Tab "Erstellen". Dort haben Sie im Abschnitt "Ausgabe" die Option "Serialisierungsassembly generieren". Wenn Sie den Wert auf "On" ändern, wird die Serialisierungsassembly während der Kompilierungszeit generiert.

+1

Interessant. Die Standardeinstellung von "Auto" sollte dies zur Kompilierzeit gemäß den Dokumenten tun. Ich frage mich, ob Sie eine der Sites vorkompilieren? Precompiling sowohl Client/Server sollte alle Ihre Startprobleme, die ich denke, zu lösen. Jetzt, wo ich verstehe, dass Sie einen Webservice von einer anderen Web-App aus aufrufen ... wollte ich Sie nur davor warnen. Die Leistung ist schrecklich und skaliert überhaupt nicht. Die Serialisierung von Objekten-> Seife über http und von Seife-> Objekten ist grob. –

+0

Also, wenn ich das richtig verstehe, sollten Sie immer eine XmlSerializers DLL für Webservices generieren, die die Anfangslastleistung ohne Downside verbessert, außerdem gibt es jetzt 2 DLLs? – freggel

+0

Das ist perfekt, danke. Speziell für die Berichterstattung wird dies einen großen Unterschied ausmachen. http://stackoverflow.com/questions/751762/slow-startup-of-sql-reporting-services-2008-in-native-mode – Praesagus

9

Wenn Sie den Webservice das erste Mal aufrufen oder das erste Mal nach einer langen Verzögerung, muss der Webdienst gestartet werden. Hier sehen Sie die Verzögerung. Danach ist es schon gestartet und wird sehr schnell auf Anrufe reagieren. Dies ist das Standardverhalten von Webdiensten.

Sie könnten IIS so konfigurieren, dass keepalive = true ist - was die Leistung verbessern kann.

Weitere Informationen wie angefordert.

Es könnte sein, dass die Serialisierungsassemblys zur Laufzeit erstellt werden. Sie können die Einstellungen der Serialisierungsassembly mithilfe der Dropdown-Liste unten im Bereich "Erstellen" des Eigenschaftenfensters für das Projekt ändern.

Es könnte sein, dass Sie Ihren Webdienst so geschrieben haben, dass er viele Operationen beim Start der Anwendung ausführt, was beim ersten Aufruf einer Methode für den Dienst geschehen würde.

Es kann sein, dass die Operation sehr langsam ist, aber Sie dann die Antwort zwischenspeichern, was nachfolgende Aufrufe schneller macht.

+0

Das ist ein sehr schöner Vorschlag. Leider haben die Systemadministratoren eine Richtlinie für den täglichen Neustart. –

+1

@Smazy: Kennen Sie ihre Argumentation für die Politik? Es klingt, als hätten sie immer noch die Angst vor Win95/98. Müssen alle Computer formatiert werden und muss das Betriebssystem alle 3 Monate erneut installiert werden? :-D – STW

+0

Hallo Praesagus, weitere Informationen hinzugefügt wie gewünscht. – Fenton

4

Das ist typisch, da ASP.NET-Anwendungen kompilieren und das bin \ Verzeichnis auf erste Anforderung in Arbeitsspeicher laden.

Dinge zuerst zu tun:

alle nicht benötigten DLL in Ihrem bin-Verzeichnis entfernen. (Ich habe gesehen, Leute versenden nunit.dll)

Precompile Ihre ASP.NET-App, so dass IIS nicht benötigt wird. Siehe "VS 2008 Web Deployment Project Support Released"

+0

sein Personenprofil haben eine schlechte Verbindung –

+1

Offen gesagt, na und? –

2

Nicht sicher, ob dies langsames Hochdrehen des WS auf "das allererste Mal" lösen wird, da ich annimmt, dass eine Ladung Kompilieren und .net DLLs geladen werden, aber Sie fast alle eliminieren können future cold beginnt damit, sicherzustellen, dass der Anwendungspool, in dem sich der WS befindet, korrekt konfiguriert ist.

Standardmäßig hat IIS6 im Leerlauf, nach einer Anzahl von Minuten oder "recycle" -Ereignissen "Respawn", die das WS jedes Mal neu starten. Wenn Sie zufrieden sind, ist der Service stabil, dann werden diese nicht benötigt.

Sicherzustellen, dass der WS seinen eigenen dedizierten Anwendungspool hat (er teilt keinen unangemessenen Pool), ist ebenfalls eine starke Empfehlung.

5

Ich habe kürzlich festgestellt, dass wir in unseren ASMX-Dateien nur auf den Klassennamen verwiesen haben. Wir haben die Service-Implementierung in einer anderen Assembly für jede ASMX-Datei. Dies führt dazu, dass .NET Framework den gesamten Ordner "bin" durchsucht, der nach der Assembly sucht, die die Implementierung enthält. Wenn Ihre Webservice-Anwendung wächst, wird dies mehr Zeit in Anspruch nehmen. Dies kann gelöst werden, indem nicht nur der Klassenname in Ihre ASMX-Definition aufgenommen wird, sondern auch der Name der Assembly.

Unsere ASMX sah wie folgt aus:

<%@ WebService Language=”C#” CodeBehind=”MyService.cs” Class=”MyWebservice” %>

Wenn Sie es ändern, um die Montage enthalten, die die Implementierung enthält es so aussehen würde. Dies ersparte uns 10% unserer anfänglichen Belastung der Webservice-Anwendung.

<%@ WebService Language=”C#” CodeBehind=”MyService.cs” Class=”MyWebservice, MyWebservice.Implementation.Assembly” %>

+0

Danke für das Update auf diese! –

1

Nach mehreren Stunden von insane Tests, ich bin in der Lage, die WebService zu reduzieren Erstausstrahlungen Ausführungszeit Minimum von zwei Host in der gleichen IP-Klasse auf blanke (unter 300 ms) ....

Ich erlebte zunächst eine erste Verzögerung von 2-3 Sekunden beim ersten Webservice-Anruf, als jeden nachfolgenden Anruf aus dem gleichen Prozess als sehr schnell.

Der Schlüssel zum Verständnis der Verzögerung in meinem Fall war, wie Client WEB Proxy !!

Das ist meine neue Bindung in app.config-Datei:

<basicHttpBinding> 
    <binding name="CreateContextSoap" closeTimeout="00:01:00" openTimeout="00:01:00" 
     receiveTimeout="01:00:00" sendTimeout="01:00:00" allowCookies="false" 
     bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard" 
     maxBufferSize="16777216" maxBufferPoolSize="524288" maxReceivedMessageSize="16777216" 
     messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered" 
     useDefaultWebProxy="false"> 
     <readerQuotas maxDepth="32" maxStringContentLength="1048576" maxArrayLength="16384" 
      maxBytesPerRead="65536" maxNameTableCharCount="16384" /> 
     <security mode="None"> 
     <transport clientCredentialType="None" proxyCredentialType="None" 
      realm="" /> 
     <message clientCredentialType="UserName" algorithmSuite="Default" /> 
     </security> 
    </binding> 
    </basicHttpBinding> 

Die erste webcall Ausführung Ich nehme viel langsamer zu sein, weil Transportkanal braucht Proxy-Konfiguration bei der Initialisierung, um zu entdecken, um Internet transparent zu verbinden . Dies wird in der Regel nicht in Intranet-Umgebung benötigt, so habe ich diese Bindung Einstellungen geändert Verwendung des Standard-Proxy (automatisch aus dem Explorer-Einstellungen entdeckt) zu vermeiden:

bypassProxyOnLocal = "false"

useDefaultWebProxy = "false "

Die Verbindungszeit für den ersten Anruf wird jetzt um einen großen Betrag reduziert. Hoffe, das hilft.

0

Entschuldigung für das Necro-Add, aber das war ein ständiger Kampf für mich auch, und ich wollte einige Informationen zum Bild hinzufügen. VisualStudio selbst fügt der Zeit eine ziemlich große Komponente hinzu. Hier ist die Grundprüfung, einen nackten Knochen Formen App beteiligt und einen bereits laufenden WebService intern auf einem Firmenserver gehostet (mit Serialisierungsassembly für alle Tests auf true gesetzt generieren):

Running in VS, Debug: 
    First Call: 400 ms to set up client object, 450 to call function 
    Second Call: 1 ms to set up client object, 14 to call function 
Running as .exe, Release: 
    First Call: 20 ms to set up client object, 70 to call function 
    Second call: 1 ms to set up client object, 4 to call function 
Running the Debug's .exe file outside of vs: 
    First Call: 20 ms to set up client object, 80 to call function 
    Second call: 1 ms to set up client object, 4 to call function 
Running as Release within VS: 
    Similar results to Debug in VS -- very slow 

Kurzgeschichte? Visual Studio fügt dem Bild einen großen Teil der Zeit hinzu. Statt ~ 90 ms dauert es fast eine Sekunde. Wenn Sie also eine Leistungsoptimierung durchführen, stellen Sie sicher, dass Sie Ihre Tests außerhalb der VisualStudio-Umgebung durchführen.