I have desktop application, that uses WCF services. I have got great usability improve when I implemented async WCF calls.
My question is: what is the best practice to initialize service client?
In previous realization there was single static object with credentials and a public method GetClient(), that was creating new ServiceClient before every call. In application there was commonly used such construction:
using (var svc = ServiceClientFactory.GetClient()) {
var data = svc.CallMethod(...);
some_application_context.specific_attribute = data;
}
so, before any call, was created new client, that was destroyed immediately after operation was finished and received data was used.
My question is: is it the best practice to call client constructor before every call?
I've tried to create single static client object, that is initialized once at startup and destroyed once on application closing, but I haven't got any notional performance gain.
Seems like it works fine, but I wonder if there any not very obvious obstacles in using single client? And what is recommended?
It's kind of a broad question, it depens on a lot of factors and also on style I guess.
When using reliable sessions or sessions in general you have to store the reference of course.
When calling the service many times it might be better to store the reference, or it might not. Better profile it then and there.
I always store a reference and create a property which check if the client is null or in the Faulted State.
Service.ServiceClient ShippingService
{
get
{
if (mService == null || mService.State == CommunicationState.Faulted)
{
mService = new Service.ServiceClient("netTcpService");
mShippingService.Open();
}
return mService;
}
}
You should look at dependency injection for getting your service references. Effectively it would be similar if not the same performance to what your doing now but it would make long term management easier and allow easier unit testing.
Most of the WCF overhead is connection negotiation so singleton vs new on each call won't really end up making a huge difference.
Related
I have an ASP.NET Core application which calls a service from another library. The
service works with an external API, which requires a sessionId. We have to call a Login API method to get the sessionId. How long this sessionId lives and when it can be changed - we don't know. Rule is: sessionId can be valid for 1 request, for 10 requests, for 100 requests, can be valid 1 minute, 10 minutes, 1 day... Nobody knows it.
The service has many methods to call similar APIs:
public class BillRequest
{
private readonly HttpClient client;
public BillRequest()
{
client = new HttpClient
{
BaseAddress = new Uri("https://myapi.com/api/v2/")
};
}
public async Task<List<Dto1>> CustomerBankAccountListAsync(int start, int count)
{
List<KeyValuePair<string, string>> nvc = new List<KeyValuePair<string, string>>
{
new KeyValuePair<string, string>("sessionId", CURRENT_SESSION_ID)
};
var customerStream = await client.PostAsync("List/CustomerBankAccount.json", new FormUrlEncodedContent(nvc));
var customerString = await customerStream.Content.ReadAsStringAsync();
//....
}
public async Task<List<Dto2>> Method2(int start, int count)
{
List<KeyValuePair<string, string>> nvc = new List<KeyValuePair<string, string>>
{
new KeyValuePair<string, string>("sessionId", CURRENT_SESSION_ID)
};
var customerStream = await client.PostAsync("List/Method2.json", new FormUrlEncodedContent(nvc));
var customerString = await customerStream.Content.ReadAsStringAsync();
//....
}
// logic to get SessionId here
public async Task LoginAsync()
{
}
How to implement to save this sessionId inside service?
There are many options to implement:
Call Login method every time before calling a method. Easy to implement, but bad approach, because we have many unnecessary requests then and use the sessionId only once
Save the sessionId on web application level and try to catch exception, when any method gets an 'invalid sessionId' back, and then call Login method, which will return a new sessionId. In this case we have to pass sessionId to constructor of BillRequest class. It works, but I don't like to move responsibility of service to other, because it's internal responsibility of service how to work with API.
Save sessionId inside the service itself and recall Login method inside service, when old sessionId is considered invalid, rewrite it by new etc. But how to save it as "static" in memory? I don't want to save it to any external places (file system, cloud etc), but I can't save to variable of class too, because object of class can be recreated...
I'd suggest certain mental shift here towards functional programming.
Think of sessionID as of a stream of independet values rather than a single object. Then your problem can be redefined in a following (semantically equivalent) way: given a typed stream (string in your case), how to observe its flow and react on incomming changes, which your source code does not control?
Well, there is an answer, proven by an Enterprise™: reactive extensions.
Techinically such a shift impliest that you're dealing with an IObservable<string> inside of your controller, which either can be injected via the standard .NET Core DI approach, or simply defined by the constructor. That's quite flexible, since rX gives your fully testable, unbelivable powerful toolset to deal with taks of this kind; rX is also compatible with native Task and hence, async/await feature. Nice fact is that it is really easy to inject required behavior from an outerworld and decorate exising observable with a more appropriate one: so, you're safe: once 3rd party's service logic changes, you can adopt your codebase almost instantly and painlessly.
What is gonna be inside that IObservable<string>? Well, I can't say, since you did not give enough information. It might be an interval asking remote server whether current sessionID is still valid and in case not - runs relogin procedure and notifies it's subscrivers about new value; it might be a timer responsible for compile-time known rule of expiration, it might be as sophisticated logic as you need: rX is flexible enough not to limit you on what can be achieved with it as long as you deal with (possible infinite) streams.
As a consequence, it means that you don't need any global value. Just subscribe to a stream of session ids and take latest - the one which is currently valid, do the job and dispose your subscription. It is not expensive and won't hit performance; neither would mess up concurency. Wrap rX into Task and await it, if you'd like to stick to a common .NET fashion.
P.S. 99% of what you would need to deliver an implementation is already there; you just need to combine it.
I have a DLL that handles making hundreds of method calls either via WCF or directly to QuickBooks. In each method I have code similar to this:
public Response GetSomethingFromQuickBooks()
{
Response response = new Response();
if (useWCF == true)
{
System.ServiceModel.BasicHttpBinding binding = new System.ServiceModel.BasicHttpBinding();
System.ServiceModel.EndpointAddress endpoint = new System.ServiceModel.EndpointAddress(new Uri(wcfEndpoint));
WCFClient = new ServiceReference.OperationsClient(binding, endpoint);
WCFClient.CreateConnection(opsConnectionDTO);
response = WCFClient.GetSomethingFromQuickBooks();
try
{
WCFClient.Close();
}
catch (Exception)
{
WCFClient.Abort();
}
}
else
{
response = qbManager.GetSomethingFromQuickBooks();
}
return response;
}
I have a couple of questions:
1) Is this the proper way to handle WCF calls on a per method basis?
2) Is there a way I can instantiate the WCF client on a per method basis without having to put duplicate code in each method?
Is this the proper way to handle WCF calls on a per method basis?
Well, if we can conveniently ignore fact that you're talking to a service with hundreds of operations defined on it, there are still some things you could be doing differently.
Spinning up a client channel for each call is excessive. Although low, the cost is still significant. It would be better to have some wrapper or factory which could be depended on to manage the lifecycle of the client channel in a sensible way.
Also, it looks like you're using a service reference to call the service. This is sub-optimal for many reasons and should be done only as a last resort, for example when you don't have access to the service interface definition other than via the service metadata. You should be using a WCF Channel otherwise.
Is there a way I can instantiate the WCF client on a per method basis
without having to put duplicate code in each method?
Setting aside the fact that client channels are generally reusable as long as they are not faulted, you could utilise an IoC container to inject a runtime dependency containing a freshly-initialised client channel implementation. Either that or reimplement WCFClient as a reusable wrapper around the client channel as mentioned before.
I have a client application that consumes a number of services. It's not always immediately obvious when a service is down or incorrectly configured. I own the service side code and hosting for most of the services, but not all of them. It's a real mixed bag of client proxies - different bindings (basichttp/wshttp/nettcp), some have been generated using svcutil.exe, while others are made programatically with ChannelFactory where the contract is in a common assembly. However, I always have access to the address, binding and contract.
I would like to have a single component in my client application that could perform a basic check of the binding/endpoint config and the service availability (to show in some diagnostic panel in the client). As a minimum I just want to know that there is an endpoint at the configured address, even better would be to find out if the endpoint is responsive and supports the binding the client is trying to use.
I tried googling and was surprised that I didn't find an example (already a bad sign perhaps) but I figured that it couldn't be that hard, all I had to do was to create a clientchannel and try to open() and close() catch any exceptions that occur and abort() if necessary.
I was wrong - in particular, with clients using BasicHttpBinding where I can specify any endpoint address and am able to open and close without any exceptions.
Here's a trimmed down version of my implementation, in reality I'm returning slightly more detailed info about the type of exception and the endpoint address but this is the basic structure.
public class GenericClientStatusChecker<TChannel> : ICanCheckServiceStatus where TChannel : class
{
public GenericClientStatusChecker(Binding binding, EndpointAddress endpoint)
{
_endpoint = endpoint;
_binding = binding;
}
public bool CheckServiceStatus()
{
bool isOk = false;
ChannelFactory<TChannel> clientChannelFactory = null;
IClientChannel clientChannel = null;
try
{
clientChannelFactory = new ChannelFactory<TChannel>(_binding, _endpoint);
}
catch
{
return isOk;
}
try
{
clientChannel = clientChannelFactory.CreateChannel() as IClientChannel;
clientChannel.Open();
clientChannel.Close();
isOk = true;
}
catch
{
if (clientChannel != null)
clientChannel.Abort();
}
return isOk;
}
}
[Test]
public void CheckServiceAtNonexistentEndpoint_ExpectFalse()
{
var checker = new GenericClientStatusChecker<IDateTimeService>(new BasicHttpBinding(), new Endpointaddress("http://nonexistenturl"));
// This assert fails, because according to my implementation, everything's ok
Assert.IsFalse(checker.CheckServiceStatus());
}
I also tried a similar technique with a dummy testclient class that implemented ClientBase with the same result. I suppose it might be possible if I knew that all my service contracts implemented a common CheckHealth() method, but because some of the services are outside my control, I can't even do that.
So, is it even possible to write such a simple general purpose generic service checker as this? And if so how? (And if not, why not?)
Thanks!
Have you looked at WCF Discovery?
WCF Discovery allows a client to search for a service based on
different criteria including contract types, binding elements,
namespace, scope, and keywords or version numbers. WCF Discovery
enables runtime and design time discovery. Adding discovery to your
application can be used to enable other scenarios such as fault
tolerance and auto configuration.
For a first attempt, you could query the endpoint to see if it supports the expected contract.
The big benefit is that you can have the client “discover” which service it wants to talk to at runtime. Which removes a lot of the client side configuration errors that you are likely used to seeing.
You need to check out SO-AWARE. It is a web service management tool that can manage SOAP or REST WCF-based service across your organization. Further it has a Test Workbench!
Here are a couple of videos that show it off too:
Part 1
Part 2
To put it in perspective, this is so complex that these people make a living doing it, I don't think it's something you want to realistically build on your own.
So I've decided to up the performance a bit in my WCF application, and attempt to cache Channels and the ChannelFactory. There's two questions I have about all of this that I need to clear up before I get started.
1) Should the ChannelFactory be implemented as a singleton?
2) I'm kind of unsure about how to cache/reuse individual channels. Do you have any examples of how to do this you can share?
It's probably important to note that my WCF service is being deployed as a stand alone application, with only one endpoint.
EDIT:
Thank you for the responses. I still have a few questions though...
1)I guess I'm confused as to where the caching should occur. I'm delivering a client API that uses this code to another department in our company. Does this caching occur on the client?
2)The client API will be used as part of a Silverlight application, does this change anything? In particular, what caching mechanisms are available in such a scenario?
3)I'm still not clear about the design of the GetChannelFactory method. If I have only one service, should only one ChannelFactory ever be created and cached?
I still haven't implemented any caching feature (because I'm utterly confused about how it should be done!), but here's what I have for the client proxy so far:
namespace MyCompany.MyProject.Proxies
{
static readonly ChannelFactory<IMyService> channelFactory =
new ChannelFactory<IMyService>("IMyService");
public Response DoSomething(Request request)
{
var channel = channelFactory.CreateChannel();
try
{
Response response = channel.DoSomethingWithService(request);
((ICommunicationObject)channel).Close();
return response;
}
catch(Exception exception)
{
((ICommenicationObject)channel).Abort();
}
}
}
Use the ChannelFactory to create an instance of the factory, then cache that instance. You can then create communicatino channels as needed/desired from the cached istance.
Do you have a need for multiple channel factories (i.e.., are there multiple services)? In my experience, that's where you'll see the biggest benefit in performance. Creating a channel is a fairly inexpensive task; it's setting everything up at the start that takes time.
I would not cache individual channels - I'd create them, use them for an operation, and then close them. If you cache them, they may time out and the channel will fault, then you'll have to abort it and create a new one anyway.
Not sure why you'd want to usea singleton to implement ChannelFactory, especially if you're going to create it and cache it, and there's only one endpoint.
I'll post some example code later when I have a bit more time.
UPDATE: Code Examples
Here is an example of how I implemented this for a project at work. I used ChannelFactory<T>, as the application I was developing is an n-tier app with several services, and more will be added. The goal was to have a simple way to create a client once per life of the application, and then create communication channels as needed. The basics of the idea are not mine (I got it from an article on the web), though I modified the implementation for my needs.
I have a static helper class in my application, and within that class I have a dictionary and a method to create communication channels from the channelf factory.
The dictionary is as follows (object is the value as it will contain different channel factories, one for each service). I put "Cache" in the example as sort of a placeholder - replace the syntax with whatever caching mechanism you're using.
public static Dictionary<string, object> OpenChannels
{
get
{
if (Cache["OpenChannels"] == null)
{
Cache["OpenChannels"] = new Dictionary<string, object>();
}
return (Dictionary<string, object>)Cache["OpenChannels"];
}
set
{
Cache["OpenChannels"] = value;
}
}
Next is a method to create a communication channel from the factory instance. The method checks to see if the factory exists first - if it does not, it creates it, puts it in the dictionary and then generates the channel. Otherwise it simply generates a channel from the cached instance of the factory.
public static T GetFactoryChannel<T>(string address)
{
string key = typeof(T.Name);
if (!OpenChannels.ContainsKey(key))
{
ChannelFactory<T> factory = new ChannelFactory<T>();
factory.Endpoint.Address = new EndpointAddress(new System.Uri(address));
factory.Endpoint.Binding = new BasicHttpBinding();
OpenChannels.Add(key, factory);
}
T channel = ((ChannelFactory<T>)OpenChannels[key]).CreateChannel();
((IClientChannel)channel).Open();
return channel;
}
I've stripped this example down some from what I use at work. There's a lot you can do in this method - you can handle multiple bindings, assign credentials for authentication, etc. Its pretty much your one stop shopping center for generating a client.
Finally, when I use it in the application, I generally create a channel, do my business, and close it (or abort it if need be). For example:
IMyServiceContract client;
try
{
client = Helper.GetFactoryChannel<IMyServiceContract>("http://myserviceaddress");
client.DoSomething();
// This is another helper method that will safely close the channel,
// handling any exceptions that may occurr trying to close.
// Shouldn't be any, but it doesn't hurt.
Helper.CloseChannel(client);
}
catch (Exception ex)
{
// Something went wrong; need to abort the channel
// I also do logging of some sort here
Helper.AbortChannel(client);
}
Hopefully the above examples will give you something to go on. I've been using something similar to this for about a year now in a production environment and it's worked very well. 99% of any problems we've encountered have usually been related to something outside the application (either external clients or data sources not under our direct control).
Let me know if anything isn't clear or you have further questions.
You could always just make your ChannelFactory static for each WCF Contract...
You should be aware that from .Net 3.5 the proxy objects are pooled for performance reasons by the channel factory. Calling the ICommunicationObject.Close() method actually returns the object to the pool in the hope it can be reused.
I would look at the profiler if you want to do some optimisation, if you can prevent just one IO call being made in your code it could far outweigh any optimisation you will make with the channel factory. Don't pick an area to optimise, use the profiler to find where you can target an optimisation. If you have an SQL database for instance, you will probably find some low hanging fruit in your queries that will get you orders of magnitude performance increases if these haven't already been optimised.
Creating the Channel costs the performance so much. actually , WCF already has the cache mechanism for the ChannelFactory if you use the ClientBase in the client instead of the pure ChannelFactory. But the cache will be expired if you make some anditional operations(Please google it for details if you want).
For the ErOx's issue i got another solution i think it is better. see below:
namespace ChannelFactoryCacheDemo
{
public static class ChannelFactoryInitiator
{
private static Hashtable channelFactories = new Hashtable();
public static ChannelFactory Initiate(string endpointName)
{
ChannelFactory channelFactory = null;
if (channelFactories.ContainsKey(endpointName))//already cached, get from the table
{
channelFactory = channelFactories[endpointName] as ChannelFactory;
}
else // not cached, create and cache then
{
channelFactory = new ChannelFactory(endpointName);
lock (channelFactories.SyncRoot)
{
channelFactories[endpointName] = channelFactory;
}
}
return channelFactory;
}
}
class AppWhereUseTheChannel
{
static void Main(string[] args)
{
ChannelFactory channelFactory = ChannelFactoryInitiator.Initiate("MyEndpoint");
}
}
interface IMyContract { }
}
you can customize the logic and the parameters of the Initiate method yourself if you got another requirement. but this initiator class is not limited only one endpoint. it is powerful for all of the endpoint in your application. hopefully. it works well for you. BTW. this solution is not from me. i got this from a book.
I am attempting to create a singleton service that is used to process incoming requests to an HttpHandler. At the moment the service is being instantiated on every request. I make a call to the static class that holds an instance of the service, implemented as a singleton as below:
public static class ServerApplication {
static Service instance = null;
static readonly object padlock = new object();
/// <summary>
/// Service singleton.
/// </summary>
public static Service Service {
get {
lock (padlock) {
if (instance == null) {
instance = new Service();
}
return instance;
}
}
}
And access it using a call as below in the HttpHandler:
ServerApplication.Service.Process(request);
I have set a breakpoint on the instance = new Service(); line and with multiple requests the
breakpoint is triggered per request.
My aim is a service that exists across requests as it loads and caches lots of data from files and databases that is reused with most requests.
Can anyone see what is going wrong?
A couple of things:
If it's a multiprocessor box, technically, you should mark the shared service instance with the "volatile" keyword or use a call to MemoryBarrier (see http://blogs.msdn.com/brada/archive/2004/05/12/130935.aspx). You didn't specify architecture, so hard to say if this is really the issue, but better safe than sorry.
You should implement a double-check lock (eg, check for null both before and after acquiring the lock on "padlock"). This way you're doing a much cheaper comparison instead of acquiring a lock on all the subsequent reads.
That should cover you on the concurrency fronts. It's also possible (though less likely) that your AppDomain is being unloaded between requests (ie, you wrote a file inside the web directory causing ASP.NET to think your app is stale), which would cause the statics to be reset.
HTTP is designed to make several concurrent connections, I don't know that you'd want to break this, unless you make very few connections on page loads. That said, perhaps you could keep the HttpHandler in the Session?
Generally speaking, if you want a singleton - cannot see if its necessary i usually implement it this way: http://www.vikingworks.dk/page/Creating-a-Singleton-Pattern-i-C.aspx