2010-01-22 18 views
10

Sono nuovo ai servizi WCF e mi sono chiesto quale sarebbe stato il modo migliore per affrontare quanto segue.Servizio WCF per molti client simultanei e accesso al database

Ho molti clienti (~ 200 - ~ 500) che fanno tutte le richieste del mio servizio abbastanza costantemente durante la giornata lavorativa. La maggior parte delle richieste riguarda l'interrogazione di un database sottostante per alimentare la risposta corretta.

Quello che mi interessa è il numero potenziale di connessioni al database generate dalle richieste in arrivo. Se tutti i client fanno richieste simultanee, il server del database sarà colpito duramente. Mi piacerebbe evitare un numero stupido di connessioni al database, se possibile.

Sarebbe meglio limitare il numero di connessioni simultanee al servizio WCF e quindi ridurre inavvertitamente il numero possibile di connessioni al database?

Ho cercato di rendere il servizio un singleton che genera thread per eseguire la transazione del database in modo da poter controllare il numero di thread ma questo overkill e limitare le connessioni al servizio è sufficiente?

Molte grazie per qualsiasi consiglio.

risposta

13

Come già detto Marcos - WCF ha una funzionalità integrata di limitazione del servizio, che è possibile modificare sul server. Ciò impedisce che il tuo server di database sia inondato da troppe richieste contemporaneamente.

Le impostazioni predefinite sono:

<serviceThrottling 
     maxConcurrentCalls="16" 
     maxConcurrentSessions="10" 
     maxConcurrentInstances="26" /> 

Vedere la MSDN docs on ServiceThrottlingBehavior per maggiori dettagli.

Ciò significa che un massimo di 16 chiamate vengono gestite contemporaneamente da WCF, ovvero, SE, la classe di servizio WCF consente più chiamanti contemporaneamente!

Contrariamente a Marcos, vorrei non consigliare di rendere la classe di servizio WCF un singleton. La best practice comune è di avere una semplice classe di servizio WCF e usarla in modalità call call - ad es. ogni richiesta in entrata otterrà la propria istanza della nuova classe di servizio WCF completamente separata, fino a un massimo definito dal comportamento di limitazione del servizio e controllato dal runtime di WCF.

Se si rende la classe di servizio WCF singleton, è necessario impostarne ConcurrencyMode su Multiple, ma è necessario prestare estrema attenzione a non lasciare che due thread simultanei nella classe cambino gli stessi valori l'uno dall'altro; la programmazione sicura multi-threading è una grande sfida! Oppure non si imposta la modalità di concorrenza su Multiplo, ma la propria e unica istanza della classe Servizio WCF può gestire le richieste solo in modo seriale, una alla volta - non molto scalabile!

Per-call e un'istanza di servizio per richiesta è decisamente la strada più semplice da percorrere. Che con la limitazione del servizio in atto, e con il pool di connessioni ADO.NET rende un ambiente molto potente e ben educato!

Vedere anche Dan Rigsby's excellent blog post on WCF service throttling per ulteriori dettagli.

+1

Grazie Marc. Con il post di Rubens e il tuo sono più fiducioso di non sovraccaricare il database e di offrire un maggiore controllo agli utenti finali a tale riguardo. – Andy

4

Se si utilizza ADO per connettersi al database, è necessario fornire un meccanismo di pool di connessioni, quindi non è necessario gestirlo.

Si prega di leggere questo articolo per ulteriori informazioni: ADO.NET Connection Pooling at a Glance

+1

Grazie Rubens, configurerò le mie impostazioni di connessione e sottoporrò a stress il mio servizio. – Andy

+0

Ciao @Andy, ho visto tutto il post qui ed è stato davvero molto utile per me. Puoi dirmi come eseguire un test di stress sul servizio? C'è qualche software? –

3

abbiamo uno scenario simile e noi risolverlo utilizzando un solo collegamento a dal nostro WebService al DB e utilizzando MARS da SqlServer che funziona perfettamente e piuttosto veloce. Sql Server sa davvero come gestire le query concorrenti a cui non devi pensare.

Si evita con che il sovraccarico di aprire e chiudere le connessioni (obviosly che il pool di connessioni aiuta in questo caso)

Ricorda inoltre di aggiungere il servizio web qualcosa come:

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

E in la configurazione:

<serviceThrottling maxConcurrentCalls="100" 
maxConcurrentSessions="100" 
maxConcurrentInstances="100" /> 

Questa opzione è all'interno

<behaviors> 
     <serviceBehaviors> 
     <behavior name="..."> 

Spero che questo aiuti :)

+1

Non penso che InstanceContextMode = Single sia un'ottima idea - rende la classe di servizio un singleton, e quindi un potenziale collo di bottiglia cattivo. Non lo farei mai. Il comportamento di limitazione stesso sarà sufficiente per impedire troppe connessioni simultanee al database. –

+0

Per noi il singleton è perfetto, se il tuo codice non ha alcun blocco qual è il problema per farlo funzionare sullo stesso oggetto? Evitiamo infatti la creazione dell'oggetto Service su ogni chiamata e durante lo stress test otteniamo prestazioni migliori con il singleton. Il nostro servizio esegue solo query SELECT sul DB, non vediamo alcuno scenario in cui il singleton ci dia problemi. Con la soluzione solo 16 query o 10 saranno gestite contemporaneamente, qual è il problema per consentire al server Sql di gestire 100 o più ?, la query deve essere davvero costosa per evitarlo. – MarcosMeli

+1

Questo è in realtà esattamente il suggerimento di cui avevo bisogno. Dispongo di un servizio WCF ospitato da un servizio Windows in cui le risorse sono limitate e desidero sincronizzare l'accesso a tali risorse da solo. L'impostazione della concomitanza "Multipla" era ciò che mi mancava. Grazie. –

Problemi correlati