tags:

views:

624

answers:

4

I'm new to WCF services and wondered what the best way to tackle the following would be.

I have many clients (~200 - ~500) that are all making requests of my service fairly constantly during the working day. Most requests involve interrogation of an underlying database to feed the correct response back.

What I'm concerned with is the potential number of database connections spawned from the incoming requests. If all clients make simultaneous requests then the database server will be hit hard. I'd like to avoid a silly number of connections to the database if possible.

Would it be better to restrict the number of concurrent connections to the WCF service and hence inadvertently reduce the possible number of database connections?

I've looked at making the service a singleton that spawns threads to do the database transaction so I can control the number of threads but is this overkill and would restricting connections to the service suffice?

Many thanks for any advice.

+3  A: 

If you're using ADO to connect to your database, it should to provide a connection pooling mechanism, so you don't need to deal with this.

Please, read this article for more information: ADO.NET Connection Pooling at a Glance

Rubens Farias
Thanks Rubens, I'll configure my connection settings and stress test my service.
Andy
+1  A: 

We have a similar scenario and we solve it using only one conection from our WebService to the DB and using MARS from SqlServer that works perfectly and pretty fast. Sql Server really knows how to handle concurrent queries you don't must think in that.

You avoid with that the overhead of open and close the connections (obviosly that connection pooling helps in this case)

Remember also to add in your web service something like:

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

And in the config:

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

This option is inside

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

Hope this helps :)

MarcosMeli
I don't think the InstanceContextMode=Single is a very good idea - it makes your service class a singleton, and thus a potential bad bad bottleneck. I wouldn't ever do that. The throttling behavior itself will be sufficient to prevent too many concurrent database connections.
marc_s
For us the singleton is perfect, if your code don't have any lock what is the problem to let run it on the same object ? In fact we avoid the Service object creation on every call and in the stress testing we get better perfomance with the singleton. Our service only do SELECT queryes on the DB we dont see any scenario where the singleton give us problems.With your solution only 16 queries or 10 will be handled at the same time, what is the problem to let the Sql Server to handle 100 or more ?, the query must be really expensive to avoid that.
MarcosMeli
This is actually exactly the suggestion I needed. I have a WCF service hosted by a Windows service where resources are limited and I want to synchronize access to those resources myself. The "Multiple" concurrency setting was what I was missing. Thanks.
scottmarlowe
+2  A: 

As Marcos already mentioned - WCF has a built-in service throttling capability, which you can tweak on the server. This prevents that your database server will be flooded with too many requests at once.

The defaults are:

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

See the MSDN docs on ServiceThrottlingBehavior for more details.

This means that a maximum of 16 calls are handled concurrently by WCF - that is, IF your WCF service class allows multiple callers at once!

Contrary to Marcos, I would not recommend making your WCF service class a singleton. The common best practice is to have a simple WCF service class, and use it in a per call fashion - e.g. each incoming request will get its own, totally separate, newly created instance of your WCF service class - up to a maximum as defined by the service throttling behavior and controlled by the WCF runtime.

If you make your WCF service class a singleton, you have to either set its ConcurrencyMode to Multiple - but then you need to use extreme caution not to let two simultaneous threads in your class change the same values from under one another; multi-threading safe programming is a major challenge! Or you don't set the concurrency mode to Multiple, but then your one and only WCF Service class instance can only handle requests in a serial fashion, one at a time - not very scalable!

Per-call and one service instance per request is definitely the much easier way to go. That with service throttling in place, and with ADO.NET connection pooling makes for a very powerful and well behaved environment!

Also see Dan Rigsby's excellent blog post on WCF service throttling for even more detail.

marc_s
Thanks Marc. With Rubens' post and yours I'm more confident that I won't be overloading the database and can offer more control to the end users in that respect.
Andy
A: 

I agree with MarcosMeli. Lot of folks are staying away fron Singelton pattern. I would rather advise/recommend to use Singleton pattern if theere is no lock/concurrency (critical section) code in the business logic. Singleton would avoid unnecessary creation (instancing)/garbage collection to CLR.

Krishnb