Laden...

[erledigt] WCF Service: erste Anfrage sehr langsam

Erstellt von Pico1184 vor 13 Jahren Letzter Beitrag vor 13 Jahren 6.418 Views
Pico1184 Themenstarter:in
223 Beiträge seit 2009
vor 13 Jahren
[erledigt] WCF Service: erste Anfrage sehr langsam

Hallo zusammen,

es geht um folgendes:

ich habe einen WCF Service im IIS 7 gehostet. Wenn ich meine Client Applikation starte (auf dem gleichen Rechner wie der Service)
beginnt der Client auch gleich eine Anfrage (Backgroundworker) an den WCF Service
und möchte sich Daten abholen!

Nur diese erste Anfrage dauert ungefähr 10 - 15 sek.! Der Benutzer sitzt solange vor einer leeren UI bzw. vor einem leeren DataGrid.
Weitere Anfragen danach gehen um einiges schneller...praktisch kaum eine Verzögerung!

Ist das normal oder läuft bei mir irgendetwas falsch?

Könnte ich dem Abhilfe schaffen indem ich bereits im SplashScreen oder so
den Service das erste mal anfrage oder erledigt man sowas anders??

Grüße Pico

925 Beiträge seit 2004
vor 13 Jahren

Was heißt denn bei dir "erste Anfrage"? Nur nach Änderungen am Code? Dann muss nämlich, soweit ich das weiß, der Code serverseitig erstmal neu kompiliert werden, bevor er eine Antwort senden kann. Das macht der einmal, danach sollte Ruhe sein, solange du nix am Code änderst.

Ist aber nur 'ne Vermutung...

D
216 Beiträge seit 2009
vor 13 Jahren

Ich denke eher, dass es beim ersten Mal nach dem Starten der Client Applikation etwas länger dauert.

Ich kenne mich mit WCF jetzt nicht so aus, aber bei allen sonstigen Sachen, zum Beispiel beim WebClient dauert die erste Anfrage immer so lange, weil der WebClient nach einem globalen Proxy sucht. Also bei deinem Client mal den Proxy auf null setzen, wenn es denn sowas gibt. Kann aber auch sein das ich total daneben liege 😃

699 Beiträge seit 2007
vor 13 Jahren

Hallo,

da dürfte dann der Idle-TimeOut im IIS greifen. Der ist per default bei 20 Minuten eingestellt. Das bedeutet, das der IIS die Instanz dann nach 20 Minuten killt.
Somit muss dann der IIS bei einer neuen Anfrage erst wieder die Instanz starten und compiliert diese auch wieder ( wenn ich das recht in erinnerung habe ).

Hier noch ein bisschen Literatur, wie man den Idle-Timeout höher stellen kann.
Configure Idle Time-Out Settings

Grüße Stephan

Pico1184 Themenstarter:in
223 Beiträge seit 2009
vor 13 Jahren

Was heißt denn bei dir "erste Anfrage"?

erste Anfrage bedeutet bei mir, der erste Aufruf einer Methode am Service nach dem Starten der Client Applikation. Und genau dieser erste Methodenaufruf dauert ca. 10 - 15 sek.

Nur nach Änderungen am Code

Also Serverseitig wurde am Code nicht verändert, und der Service läuft auch dauerhaft im IIS.

Also bei deinem Client mal den Proxy auf null setzen. Was sollte das bringen?
Idle-TimeOut im IIS greifen. Der ist per default bei 20 Minuten eingestellt

Bedeutet der Idle Timeout, dass der WCF Service wenn innerhalb von 20min keine Anfrage kommtdie Service Instanz killt?
Wenn ja wäre es ja so verständlich, dass bei der ersten Client Anfrage eine neue Instanz des WCF Services erstellt werden muss
und dies dann Zeit in Anspruch nimmt.Das wäre dann aber nicht die Lösung meines Problems!

Ich muss verhindern, dass der User letzendlich 15sek vor einem leeren UI sitzt.
Also ist das mit dem SpashScreen eine Lösung??
Könnte ja den Wcf Service schon im Splash Screen aufrufen, dann wird die Service Instanz erstellt
und in meiner main UI hab ich dann keinen stark verzögerten Zugriff auf den Service????
Ist das so gängige Praxis??

Grüße Pico

M
198 Beiträge seit 2010
vor 13 Jahren

in meinem Testclient habe ich das selbe Problem. Wenn ich meine HelloWorld Methode aufrufe braucht er auch so 10s bis er den Antwortstring zurückgibt. Der Service ist auch auf einem IIS/ gehostet.

Ich hatte bei mir das Gefühl, dass die 10s Verzug von der Methode
.Open() kommen. Ich wollte diese mal in einen Backgroundworker auslagern, habe es aber noch nicht geschafft.

Rufe ich dann meine HelloWorld Methode nochmals auf habe ich keinerlei Zeitverzögerung?

Gruss Mike

J
1.114 Beiträge seit 2007
vor 13 Jahren

Das liegt am IIS. Die Probleme hatte ich auch mit klassischen Webservices, und hab die eigentlich immer noch. Das Hochsetzen des Timeouts im IIS hat rein gar nichts bewirkt. Wenn 20 Minuten lang keine Anfrage an den Service kam, hat IIS die Instanz gekillt. Der nächste Client hatte dann Pech und musste 20 Sekunden warten. Ich wusste mir wirklich nicht mehr weiter, und habe letztlich einen blöden Dummy Windows Service laufen, der alle 30 Sekunden eine leere Methode im Webservice aufruft. Dadurch wurde der IIS dann gehindert, nach 20 Minuten die Instanz zu killen.

Das war IIS 6. Wie sich das heute beim IIS 7 verhält, weiss ich nicht.

Aber seitdem meide ich IIS zum Hosten meiner Services, und lagere sie selbst direkt in einem Windows Service ab. Läuft seitdem wesentlich flotter. Liegt aber eher am TCP/IP Binding des WCF Service.

Diese Timeout Geschichte beim IIS kann ich sowieso nicht nachvollziehen. Wenn ich einen Dienst starte, ob IIS oder sonst einer, erwarte ich dass er verfügbar ist, und nicht erst alles neu vorkompiliert werden muss beim ersten Aufruf, nur um serverseitig ein paar Resource zu sparen.

Pico1184 Themenstarter:in
223 Beiträge seit 2009
vor 13 Jahren

Okay was ich aber nicht verstehe ist wenn ich die Client Applikation starte
dauert es ja wie besprochen einige Zeit bis ich die Daten bekomme aber
wenn ich die Applikation dann schließe und gleich danach wieder starte
dauert es wieder genau so lange wie vorher.

Das widerspricht ja dem was vorher gesagt wurde, dass erst nach 20min die Server Instanz gekillt wird!

Also bei mir dauert es egal in welchem Intervall ich die Client App aufrufe bei der ersten Anfrage immer 10-15sek. bis die Daten kommen.

Verstehe ich nicht!!!!!!!

Pico1184 Themenstarter:in
223 Beiträge seit 2009
vor 13 Jahren

Hier mal noch ein Auszug aus der web.config des Services:

Die Client App nutzt den ws2007HttpBinding endpoint....kann es vielleicht daran liegen????


<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBindingConfiguration" maxReceivedMessageSize="9965536">
<readerQuotas maxArrayLength="9965536" />
</binding>
</basicHttpBinding>
<ws2007HttpBinding>
<binding name="WS2007BindingConfiguration" maxReceivedMessageSize="9965536">
<readerQuotas maxArrayLength="9965536" />
</binding>
</ws2007HttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="">
<remove name="sqlWorkflowInstanceStore" />
<remove name="workflowInstanceManagement" />
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
<serviceDiscovery />
<etwTracking profileName="EndToEndMonitoring Tracking Profile" />
<workflowUnhandledException action="AbandonAndSuspend" />
<workflowIdle timeToPersist="10675199.02:48:05.4775807" timeToUnload="10675199.02:48:05.4775807" />
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service name="VisualControl.DistributedServices.StudioService.StudioService">
<clear />
<endpoint address="basic" binding="basicHttpBinding"
bindingConfiguration="BasicHttpBindingConfiguration" name="BasicBindingForSilverlightClients"
contract="VisualControl.DistributedServices.StudioService.IStudioService" listenUriMode="Explicit"
/>
<endpoint address="WS2007" binding="ws2007HttpBinding"
bindingConfiguration="WS2007BindingConfiguration" name="WS2007ForIntranetClients"
contract="VisualControl.DistributedServices.StudioService.IStudioService" />
<endpoint name="DiscoveryEndpoint" listenUriMode="Explicit" kind="udpDiscoveryEndpoint" />
</service>
</services> <diagnostics etwProviderId="217324ec-21d1-4782-bd9e-75f32b5fabc0">
<endToEndTracing propagateActivity="true" messageFlowTracing="true" />
</diagnostics>
</system.serviceModel>
</configuration>

M
198 Beiträge seit 2010
vor 13 Jahren

mich würde noch mal interessieren ob nun bei dir der Aufruf von .Open() so lange dauert oder der erste Aufruf nach .Open()?

Pico1184 Themenstarter:in
223 Beiträge seit 2009
vor 13 Jahren

Ich benutze eine Proxy Klasse welche von System.ServiceModel.ClientBase<TChannel> abgeleitet ist und welche ein Interface
mit den entsprechenden Service Methoden implementiert.

Denke nicht das die Abfrage der Methode solange dauert, eher die Initialisierung / Instanzierung des Services.

Vielleicht hat ja sonst noch jemand eine Idee zu den oben besprochenen Problemen? Wäre echt super!

Wüsste schon gerne wie man so ein Problem umgeht...ahnscheinend liegt es ja an dem Hosting im IIS.

Ich könnte damit leben wenn ich genau wüsste ob es gängige Praxis ist, den Service das erste mal im SplashScreen aufzurufen.
Dann wäre die Instanz erstellt und weitere Abfragen würden keine Zeitverzögerung mehr hervorrufen??????

Grüße Pico

699 Beiträge seit 2007
vor 13 Jahren

Ich könnte damit leben wenn ich genau wüsste ob es gängige Praxis ist, den Service das erste mal im SplashScreen aufzurufen.
Dann wäre die Instanz erstellt und weitere Abfragen würden keine Zeitverzögerung mehr hervorrufen??????

Was sollte an dem verfahren schlecht sein. Wenn man damit erreicht, das der Service sich schon startet, während die Anwendung selbst ja auch am starten ist.

Pico1184 Themenstarter:in
223 Beiträge seit 2009
vor 13 Jahren

Ja klar deshalb war es ja auch mein erster Gedanke......
wollte halt nur nochmal nachfragen damit ich auf der sicheren Seite bin!

Werde dies morgen gleich ausprobieren und berichten wie sich das Ganze dann verhält!

Grüße Pico

M
198 Beiträge seit 2010
vor 13 Jahren

ja ich bin auch der Meinung das es vom IIS Hosting kommt.

Das mit dem Splash Screen ist keine schlechte idee. Kann man den Startprozess
auch in einen Backgroundworker auslagern?

Pico1184 Themenstarter:in
223 Beiträge seit 2009
vor 13 Jahren

Klar kann man das! Ich hab den Aufruf auch in einem Backgroundworker:


using (BackgroundWorker worker = new BackgroundWorker())
{
worker.DoWork += delegate(object sender, DoWorkEventArgs e)
{
IStudioService studioService = ProxyLocator.GetStudioService();
e.Result = studioService.GetAllSignals();
};
worker.RunWorkerCompleted += delegate(object sender, RunWorkerCompletedEventArgs e)
{
if (!e.Cancelled && e.Error == null)
{
List<Signals> signals = e.Result as List<Signals>;
if (signals != null)
{
this.Signals = new ObservableCollection<Signals>;(signals);
this._viewData = CollectionViewSource.GetDefaultView(this.Signals);
this._viewData.Filter = null;
}
}
};
worker.WorkerSupportsCancellation = true;
worker.RunWorkerAsync();
}

M
198 Beiträge seit 2010
vor 13 Jahren

WOW danke für Deine Antwort!

Gruss Mike

Pico1184 Themenstarter:in
223 Beiträge seit 2009
vor 13 Jahren

Also es hat funktioniert, erster Service Aufruf im
SplashScreen dann läuft alles rund!

Danke euch für eure Infos!

Grüße Pico

M
198 Beiträge seit 2010
vor 13 Jahren

und wie macht man das genau

bei mir steht in ner WPF Anwendung



  /// <summary>
        /// OnStartup
        /// </summary>
        /// <param name="e"></param>
        protected override void OnStartup(StartupEventArgs e)
        {
            SplashScreen splash = new SplashScreen("Resources/Images/logo.jpg");
            splash.Show(true, true);

            base.OnStartup(e);

            Assembly assem = Assembly.GetExecutingAssembly();

        }



Muss ich den Backgroundworker vor splash.Show(...); starten?

Gruss Mike

Pico1184 Themenstarter:in
223 Beiträge seit 2009
vor 13 Jahren

Lager den SplashScreen am besten in einen eigenen UI Thread aus und rufe aus der SplashScreen Klasse den Service auf.

Kuck mal dieses Beispiel an: WPF SplashScreen

Grüße Pico

M
198 Beiträge seit 2010
vor 13 Jahren

Danke!