WCF Optimal performance settings - asp.net

Hi i am creating an API using WCF. My question can be broken down into two seperate ones
1) I have quite a few calls, for instance i have calls relating to the customer, products, orders, employees.
My question is should all this go into one public interface class e.g
public interface IRestService
public class RestService : IRestService
Or should I have one for each call e.g
public interface ICustomer
public class Customer : ICustomer
public interface IProducts
public class Products: IProducts
2) If you have an API which will be accessed by tens of thousands of users and thousands of users concurrently, how would you set up, what will your web config settings be for instance in terms of throttling. Also what setting would you give your InstanceContextMode, or ConcurrencyMode. Finally what type of binding would it be, bearing in mind websites and mobile phones can access the api.

For the sake of good practice, I would break up the API into separate interfaces so you have the option of splitting them into separate implementations in the future. You can still have just one service class implement all of the interfaces, like this:
public class RestService : ICustomer, IProducts, IOrders
However, it sounds as if you'd probably want to make them separate implementations anyway.
In terms of concurrency settings, ask yourself what resources need to be used on each call. If your service class's constructor can be written without any lengthy startup, then use PerCall. If you need to initialize expensive resources, then I'd recommend InstanceContextMode.Single with ConcurrencytMode.Multiple and make sure you write thread-safe code. Eg: make sure you lock() on any class properties or other shared resources before you use them.
Database connections would not count as "expensive to initialize", though, because ADO will do connection pooling for you and eliminate that overhead.
Your throttling settings will be revealed by testing, as Ladislav mentions. You'd want to stress-test your service and use the results to get an idea of how many machines you'd need to service your anticipated load. Then you'll need a dedicated load balancer to route requests as either round-robin, or something that checks the health of each server. Load balancers can be set up to GET a "systemhealth.asp" page and check the results. If you return an "OK" then that machine stays in the pool, or can be temporarily removed from the pool if it times out or returns any other status.
Your binding would need to be WebHTTPBinding for REST. BasicHTTPBinding is meant for SOAP interfaces and doesn't support [WebGet], for example.
If it doesn't have to be a REST service, then you can get a bit more performance by using NetTcpBinding.

If you really have few operations, single service can be used. Generally services are logical collection of related operations but the number of operations should be limited. Usually if your service have more than 20 operations you should think about refactoring.
Do you plan to use REST service? I guess you do because of your first interface example. In such case you need WebHttpBinding (or similar custom binding) with default InstanceContextMode (PerCall) and ConcurrencyMode (Single) values. Only other meaningful combination for REST service is InstanceContextMode.Single and ConcurrencyMode.Multiple but it will create your service as singleton which can have impact on your service implementation. My rule of thumb: Don't use singleton service unless you really need it.
Throttling configuration is dependend on your service implementation and on performance of your servers. What does thousands concurrent users really mean for you? Processing thousands of requests concurrently requires good server cluster with load balancer or hosting in Azure (cloud). All is also dependend on the speed of processing (operation implementation) and size of messages. The correct setting for MaxConcurrentInstances and MaxConcurrentCalls (should be same for PerCall instancing) should be revealed by performance testing. Default values for service throttling have changed in WCF 4.

Related

Can two parallel WCF requests get handled by the same thread when ConcurrencyMode = Multiple

I have a WCF service with ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Multiple). I want to use ThreadStatic variable to srore data.
I start worrying about is it possible two parallel requests for the same or different operationContracts get handled by the same thread serverside, because if this happens my ThreadStatic variable will get overriden.(I.e. something like the thread changing between HttpHandlers and HttpModules in ASP.NET)
I made a spike service with the same ServiceBehaviour and maxConcurrentCalls="2". After that a wcf client called the service with 50 parallel requests and my worry did not occur. However this is not a 100% proof.
Thank in advance!
Irrespective of the ConcurrencyMode, a ThreadStatic value will persist when your request terminates and the thread is returned to the thread pool. The same thread can be reused for a subsequent request, which will therefore be able to see your ThreadStatic value.
Obviously this won't be true for two concurrent requests, because by definition they will be executed on different threads.
From comments:
Also by definition MSDN says: 'The service instance is multi-threaded. No synchronization guarantees are made. Because other threads can change your service object at any time, you must handle synchronization and state consistency at all times.' So it is not so obvious:)
This means that a single instance of your service class can be accessed concurrently by multiple requests. So you would need to handle synchronization for any accesses to instance members of the service class.
However ThreadStatic members are by definition only used by one thread (and hence one request) at a time, so don't need synchronization.
The direct answer to your question is Joe's answer.
However you mention in the comments you are using an ambient design pattern. That pattern is already implemented in WCF as the OperationContext and is specifically designed to be extensible. I highly recommend using OperationContext over any custom thread storage.
See Where to store data for current WCF call? Is ThreadStatic safe?
I wanted to add to Joe's answer here because I would recommend that you use some sort of correlation for your requests if you're needing to store state. The threading model will become very convoluted and unreliable in production.
Further, now imagine you have two IIS servers hosting this service and a hardware or software load balancer forward facing so that you can consume it. To ensure that the correct state is gathered you'll need correlation because you never know which server the service will be started on. In the post below I mocked up a simplified version of how that might work. One thing to keep in mind is that the SessionState would need to be kept in a shared location to all instances of the service, an AppFabric Cache server for example.
Global Variable between two WCF Methods

WCF Routing/ESB Architecture?

I've been working on building a set of enterprise services using WCF 4 within my organization and could use some guidance. The setup/architecture I've designed thus far is similar to a lightweight custom ESB. I have one main "broker" service (using wsHttp), that connects to three underlying netTcp services. Both the broker and underlying services share a common assembly that contains the model, as well as the contract interfaces. In the broker service I can choose which operations from the underlying services I want to expose. The idea is that potentially we can have a core of set of services and few different brokers on top of them depending on the business need. We plan on hosting everything (including the netTcp services) in IIS 7.5 leveraging AppFabric and WAS.
Here's my question, is such a design good practice and will it scale? These services should be able to handle thousands of transactions per day.
I've played around with the routing in WCF 4 in lieu of the broker service concept I've mentioned, however, have not seen much value in it as it just simply does a redirect.
I'm also trying to figure out how to optimize the proxies that the broker service (assuming this practice is advisable) has to the underlying services. Right now I simply have the proxies as private members within the brokers main class. Example:
private UnderlyingServiceClient _underlyingServiceClient = new UnderlyingServiceClient();
I've considered caching the proxy, however, am concerned that if I run into a fault that the entire proxy at that point would be faulted and cannot be reused (unless I catch the fault and simply re-instantiate).
My goal with these services is to ensure that the client consuming them can get "in and out" as quickly as possible. A quick request-reply.
Any input/feedback would be greatly appreciated.
If i understand you correctly, you have a handful of "backend" services, possibly on separate computers. Then you have one "fontend" service, which basically acts like a proxy to the backend, but fully customizable in code. We are doing this exact setup with a few computers in a rack. Our frontend is IIS7, backend is a bunch of wcf services on several machines.
One, will it scale? Well, adding more processing power on the backend is pretty easy, and writing some load balancing code isn't too bad either. For us, the problem was the frontend was getting bogged down, even though it was only acting as a proxy. We ended up adding a couple more front end computers, "brokers" as you call them. That works very well. People have suggested that I use Microsoft ForeFront for automatic load balancing, but I have not researched it yet.
Two, should you cache the proxy? I would say definitely yes, but it kind of sucks. These channels DO fault occasionally. I have a thread always running in the background. Every 3 seconds, it wakes up, checks all the wcf services and wcf clients in the app. Any that are faulted get destroyed and recreated.
check host channels: ...
while(true)
{
try{if(MyServiceHost.State!=System.ServiceModel.CommunicationState.Opened) {ReCreate();}} catch{}
System.Threading.Thread.Sleep(3000);
}
check client channels: ...
private static ChannelFactory<IMath> mathClientFactory = new ChannelFactory<IMath>(bindingHttpBin);
while(true)
{
try
{
if(MyServiceClient.State==System.ServiceModel.CommunicationState.Faulted)
{
EndpointAddress ea = new EndpointAddress(ub.Uri);
ch = WcfDynamicLan.mathClientFactory.CreateChannel(ea);
}
}
catch{}
System.Threading.Thread.Sleep(3000);
}
On the client, I not only cache the channel, but also cache the ChannelFactory. This is just for convenience though to make the code for creating a new channel shorter.

Will my WCF service be scaleable using a singleton?

My ASP .Net C# web application allows its users to send files from their account on my server to any remote server using FTP. I have implemented a WCF service to do this. The service instantiates a class for each user that spawns a worker thread which performs the FTP operations on the server. The client sends a command to the service, the service finds the worker thread assigned to the client and starts the FTP commands. The client then polls the service every two seconds to get the status of the FTP operation. When the client sends the "disconnect" command, the class and the worker thread doing the FTP operations is destroyed.
The FTP worker thread needed to persist between the client's queries because the FTP processing can take a long time. So, I needed a way for the client to always get the same instance of the FTP class between calls to the service. I implemented this service as a singleton, thus:
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
public class UserFtpService : IUserFtpService
{
private SortedDictionary<string, UserFTPConnection> _clients = new SortedDictionary<string, UserFTPConnection>();
...
}
Where "UserFTPConnection" is the class containing the worker thread and the user's account name is used for the indexing in the dictionary.
The question I have is this: In the books I have read about WCF, the singleton instance is called "the enemy of scalability." And I can see why this is so. Is there a better way to make sure the client gets the same instance of UserFTPConnection between queries to the WCF service other than using a singleton?
Actually here your first problem is synchronizing the access to this static object. Dictionary<TKey, TValue> is not thread safe so you must ensure that only one thread is accessing it at the same time. So you should wrap every access to this dictionary in a lock, assuming of course you have methods that are writing and others that are reading. If you are only going to be reading you don't need to synchronize. As far as singleton being the enemy of scalability, that's really an exaggerated statement and pretty meaningless without a specific scenario. It would really depend on the exact scenario and implementation. In your example you've only shown a dictionary => so all we can say is that you need to ensure that no thread is reading from this dictionary while other is writing and that no thread is writing to this dictionary while other thread is reading.
For example in .NET 4.0 you could use the ConcurrentDictionary<TKey, TValue> class which is thread safe in situations like this.
One thing's for sure though: while the singleton pattern might or might not be an enemy of scalability depending on the specific implementation, the singleton pattern is the arch-enemy of unit testability in isolation.
If you are going to use a singleton, I'd recommend also setting ConcurrencyMode to ConcurrencyMode.Multiple. For example...
[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple, InstanceContextMode = InstanceContextMode.Single)]
public class UserFtpService : IUserFtpService
{
}
If you don't do this, your WCF service will be a singleton but only allow one thread to access at a time, which would certainly effect performance. Of course you will need to ensure thread safety of collections (as in previously mentioned answer).

ASP.NET A static object to hold connection with a DB. Is it a good idea?

I'm wondering if it is a good approach in the ASP.NET project if I set a field which "holds" a connection to a DB as a static field (Entity Framework)
public class DBConnector
{
public static AdServiceDB db;
....
}
That means it'll be only one object for entire application to communicate with a DB. I'm also wondering about if that object will be refreshing data changes from DB tables, or maybe it shouldn't be static and I shoud create a connection dyniamically. What do You think ?
With connection pooling in .NET, generally creating a new connection for each request is acceptable. I'd evaluate the performance of creating a new one each time, and if it isn't a bottleneck, then avoid using the static approach. I have tried it before, and while I haven't run into any issues, it doesn't seem to help much.
A singleton connection to a database that is used across multiple web page requests from multiple users presents a large risk of cross-contamination of personal information across users. It doesn't matter what the performance impact is, this is a huge security risk.
If you don't have users or personal information, perhaps this doesn't apply to your project right now, but always keep it in mind. Databases and the information they contain tend to evolve in the direction of more specifics and more details over time.
This is why you should not use a singleton design pattern with your database connection
Hope it helps
Is using a singleton for the connection a good idea in ASP.NET website
Bad idea. Besides the potential mistakes you could make by not closing connections properly and so forth, accessing a static object makes it very difficult to unit test your code. I'd suggest using a class that implements an interface, and then use dependency injection to get an instance of that class wherever you need it. If you determine that you want it to be a singleton, that can be determined in your DI bindings, not as a foundational point of your architecture.
I would say no.
A database connection should be created when needed to run a query and cleaned up after that query is done and the results are fetched.
If you use a single static instance to control all access to the DB, you may lose out on the automatic Connection Pooling that .NET provides (which could impact performance).
I think the recommendation is to "refresh often."
Since none of the answers have been marked as an answer and I don't believe any have really addressed question or issue thereof...
In ASP.NET, you have Global or HttpApplication. The way this works is that IIS will cache instances of your "application" (that is an instance of your Global class). Normally (default settings in IIS) you could have up to 10 instances of Global and IIS will pick any one of these instances in order to satisfy a request.
Further, keep in mind that, there could be multiple requests at any given moment in time. Which means multiple instances of your Global class will be used. These instances could be ones that were previously instantiated and cached or new instances (depending on the load your IIS server is seeing).
IIS also has a notion of App Pools and worker processes. A Worker process will host your application and all the instances of your Global classes (as discussed earlier). So this translates to an App Domain (in .NET terms).
Just to re-cap before moving on…
Multiple instances of your Global class will exist in the Worker process for your application (in IIS). Each one waiting to be called upon by IIS to satisfy a request. IIS will pick any one of these instances. They are effectively threads that have been cached by IIS and each thread has an instance of your Global class. When a request comes in, one of these threads is called upon to handle the request-response cycle. If multiple requests arrive simultaneously, then multiple threads (each contains an instance of your Global class) will be called upon to satisfy each of those requests.
Moving on…
Since there will be only one instance of a static class per App Domain you'll effectively have one instances of your class shared across all (up to 10) instances of Global. This is a bad idea because when multiple simultaneous requests hit your server they'll either be blocked (if your class’s methods use locks) or threads will be stepping on each other’s toes. In other words, this approach is not inherently thread-safe and if you make it thread safe using thread synchronization primitives then you’re unnecessarily blocking threads, negatively impacting performance and scalability of your web application, with no gain whatsoever.
The real solution (and I use this in all my ASP.NET apps) is to have an instance of your BLL or DAL (as the case may be) per instance of Global. This will ensure the following:
1. Multiple threads are not an issue since IIS guarantees one request-response per instance of Global) at any given moment in time. So you’re code is inherently threads-safe.
2. You only have up to 10 instances of your BLL/DAL up and running at any given moment in time ensuring that you're not constantly creating and disposing instances of (typically) large objects to satisfy each request, which on busy sites is huge
3. You get really good performance well due to #2 above.
You do have to ensure that your BLL/DAL is truly stateless or that you reset any state at the start of each Request-Response cycle. You can use the BeginRequest event in Global to do that is you need to.
If you go down this route, be sure to read my blog post on this
Instantiating Business Layers – ASP.NET

Static fields in an ASP.NET Webservice

Is a static variable in a webservice shared between all running invocations of the webservice on a server?
In my case I want a server-wide sync-lock, and I beleive I can accomplish that with a single
private static Object syncHandle = new Object();
Is that correct?
Yes, they are all shared per AppDomain which is why, in general, they should not be used!
They should not be used, in general, because they are so unlikely to be used properly. Also because there are safer alternatives, like HttpContext.Cache, or even Session state.
Still, if you encapsulate all access to these static members, and if you handle locking correctly, then you'll have a safe implementation that may then turn out to be a bottleneck, with all threads contending for the shared resource. It's really better to do without.
Also, you seem to mean ASMX web services, but you should specify ASMX or WCF.
I believe they are shared as long as they are running in the same process. So two people requesting from the same server would have the same instance of the object. However, you can run different applications in a computer different process on IIS, in which case I'm pretty sure that instances to objects wouldn't be shared.
They are all shared unless you have a Web Garden. A web garden is multiple host process handling a single application. In this case each host will have its own static data.

Resources