Implementing a cache in a WCF Service - c#

I have a WCF service that caches certain data and uses it to respond to web requests. To deal with this requirement, I made the service a Singleton (using InstanceContextMode.Single and ConcurrencyMode.Multiple (yes, it's threadsafe)).
I've tried to set the timeout of the service to its maximum using the following binding:
<binding name="WebHttpBinding" receiveTimeout="24.20:31:23.6470000">
<security mode="TransportCredentialOnly">
<transport clientCredentialType="None" />
</security>
</binding>
My problem is that the service instance dies at unpredictable intervals, meaning the first web request to hit will cause the cache to get rebuilt (a very slow process).
Ideally, the cache would rebuild at a set time each day without having to get hit by a web request. I could set the app pool to recycle at a set time, but this still wouldn't resolve the issue of the service not getting instantiated until the first web request. I'd rather not have to make a little scheduled script that sends a request to the service, as that is kind of hacky.
Is there a better strategy for performing caching in a WCF service? What have others done here? Is there a best practice?

There is an MSDN article on Caching Support for WCF Web HTTP Services, an excerpt is quoted below:
The .NET Framework version 4 enables you to use the declarative caching mechanism already available in ASP.NET in your WCF Web HTTP services. This allows you to cache responses from your WCF Web HTTP service operations. When a user sends an HTTP GET to your service that is configured for caching, ASP.NET sends back the cached response and the service method is not called. When the cache expires, the next time a user sends an HTTP GET, your service method is called and the response is once again cached..........
You might also want to look at:
memcached
Windows AppFabric
NCache
Caching Solutions
WCF Caching Solution - Need Advice
Also look at this on Velocity from Microsoft

I have implemented caching at a higher layer inside the webservice.
This way you can decide when to invalidate the cache, and when to deserialize from disk.
To make sure the cache is built before the first webrequest, add some code to global.asax to generate the cache upon load of the web server.
This is much simpler than doing it the "right way"
[OperationContract]
public void GetLargeComplexData();
public GetLargeComplexData()
{
// deserialize last cached data from db or file
...
// Verify the deserialized cache is not invalid
...
// if cache is invalid rebuild
...
//return cached data
...
}

The receiveTimeout isn't going to affect what you're trying to do. You should use AppFabric to keep your service always running. That way, whenever you recycle, AppFabric will automatically warm up your service. Just make sure that your cache gets built when your service is instantiated, not when it's first accessed.

You can use IIS7 application warmup module
http://blogs.iis.net/thomad/archive/2009/10/14/now-available-the-iis-7-5-application-warm-up-module.aspx

An option you can use is to move the cache out of the WCF service and into a dedicated cache service such as Memcached or use Microsoft AppFabric Caching
This allows you to separate the storage of cached data from the WCF service so you have more freedom in your architecture of how the data is managed and accessed.

Related

There was no endpoint listening at Error sometimes

I have hosted my WCF webs services into public server and consumed this service from the WPF application and this app is using around 2500 users for the Login purpose.Most of the time it is working fine. But in some case it gives the following error.
“Error : There was no endpoint listening at …….. that could accept
the message. This is often caused by an incorrect address or SOAP
action”
Any idea why this is happening sometimes. How can I solve this issue? Is it related to port was busy that time?
Thanks in Advance,
You may want to consider monitoring performance counters for your WCF service.
WCF has built-in performance counters that show system metrics associated with WCF Service throttling and security, in addition to the typical Windows counters (cpu, memory, etc.)
To enable performance counters, include <diagnostics performanceCounters="All"/>
in the <system.serviceModel> section of the WCF Service configuration file.
You can then add counters for “ServiceModel” at the Endpoint, Operation and/or Service level.
The following link provides additional information:
http://blogs.microsoft.co.il/idof/2011/08/11/wcf-scaling-check-your-counters/
Good luck.

How to initialize WCF service before first request occurs?

I have a WCF service that uses various config parameters that are located in a database, as well as a cache for better performance. Right now I have a Singleton that holds this information and is initialized on the first call to the Webservice in a lazy loading behavior.
The cache was exenteded lately and so the initialization takes some time, of course resulting in a longer response time on the first service request.
So what would be the most efficient way to do some kind of eager loading initialization of the service before the fist call occurs (probably on application pool start)?
Don't host the service in an asp.net application, but use a self-hosting process (i.e. a console application) or (even better) a WAS (Windows Activation Service) service within IIS.
This is much more reliable and you can initialize service BEFORE first clien call.
See MSDN for details.

Persist object in C# .NET Web Service

Am stuck on what am sure is a fundamental and easy to solve problem in WCF, just need to be guided towards the right way.
I have a large object (which is actually a trained text classifier) that I need to expose through a Web Service in C# .NET. The classifier object can be loaded from disk when the service initially starts, but I don't want to keep loading it from disk for every request (the object that services requests currently occupies about 6 GB in memory, and it takes a while to keep loading it from disk for every request), so instead I want to persist that object in memory throughout all requests to that web service, and the object should only be loaded when the service starts (instead of loading it when the first web request triggers it).
How would I go about doing that?
Thanks for any help!
Probably the easiest way is to create your service as a singleton. This involves specifying InstanceContextMode = InstanceContextMode.Single in a ServiceBehavior attribute on your service class definition.
However it is very questionable if sending a 6GB object over the wire using WCF is advisable. You can run into all sorts of service availability issues with this approach.
Additionally, singletons are not scalable within a host (can be only one instance per host), although you can host multiple singleton services and then load-balance the requests.
The way I've done this in projects that I've had the problem with in the past is to self host the WCF service inside a Windows Service.
I've then set the data storage object up inside the service as a singleton that persists for the life of the service. Each WCF service call then gets the singleton each time it needs to do something with the data.
I would avoid running in IIS simply because you don't have direct control of the service's lifetime and therefore don't have enough control of when things are disposed and instantiated.

WCF Restful service bad performance

My wcf restful service manages to serve only 2 requests/sec!
detailed:
I've created a wcf restful service which exposes only one method via GET verb.
The method makes no logic, and returns immediately.
I've also created a test client in order to check the service throughput and performance, which makes requests by WebHttpRequest.
The service was able to process only 2 requests/sec!
I also made a request to the service through my browser, and the same result: 500ms for one request.
Then I changed the service binding to netTcpBinding and the service was able to process around 2000 requests/sec.
The service was running under a windows service, and hosted by WebServiceHost with WebHtppBinding.
good to mention that both client and the service was running in the same server.
Does it make any sense that wcf restful service has such poor performance?
Would Appreciate any help. Thanks.
No, it makes no sense and probably points to a problem with your testing. How was your REST test client written? Are you aware that, by default, .NET will only allow two open connections to any domain for a "regular" .NET process? It's increased to ten automatically for ASP.NET apps.
That information is documented here in ServicePointManager.DefaultConnectionLimit. You can increase this programatically or through config by adding a higher limit for the domain you're trying to connect to. Config wise this would look something like this:
<system.net>
<connectionManagement>
<add address="www.myserver.com" maxconnection="20" />
</connectionManagement>
</system.net>
You can open up connections for all domains using address="*" if that's your desire.
As for the delay you're seeing, it could be the result of other features that are on by default such as UseNagleAlgorithm or, if your POST'ing, Expect100Continue.

Starting self hosted WCF services on demand

Is it possible to start self hosted WCF services on demand?
I see two options to accomplish this:
Insert a listener in the self hosted WCF's web server and spin up a service host when a request for a specific service comes in, before WCF starts looking for the existence of that endpoint; or
Integrate a web service in process, start a service host for a request if it isn't running yet and redirect the request to that service host (like I suspect IIS does).
I cannot use IIS or WAS because the web services need to run in process with the UI business logic.
Which is feasible and how can I accomplish this?
EDIT:
I cannot just start the service hosts because there are hundreds, most (about 95%) of which are (almost) never used but need to be available. This is for exposing a business logic layer of 900 entities.
You could do a locator service setup. Basically always expose a lightweight service that returns the address of the 'actual' services. Every time the address of a particular service is requested, go ahead and spin it up.
If you're worried about cleaning it up, you could keep a list of the service hosts and wire in some sort of inactivity timeout so you could periodically shut down the service hosts.
There are some design concerns here - the concept of "calling one service before you call another one" is probably considered a bad idea on some level (sounds like coupling the state of two services).
Went the following route:
Create a single service host;
Create a dynamic proxy which implements all service interfaces;
Add a service endpoint for every interface the dynamic proxy implements;
Dispatch to the correct implementation from the dynamic proxy.

Categories