We have a service that makes NetTcp calls to other services on different servers. I'm trying to optimize it by caching the ChannelFactories, and by increasing maxOutboundConnectionsPerEndpoint.
I have been using GOOGLE.COM (great website, by the way. Check it out if you haven't heard of them) to try to understand how the channel caching works, and I don't think I have it correct.
Reusing the channel factory - good idea.
Caching channels myself - bad idea. Wcf already does this, as long as all of your channels are created from the same factory. - is that right? If you create a new factory each time, it's not cached?
// factory initialization
var address = "net.tcp://something:8888/testservices";
var factory = new ChannelFactory<ITestService>("configname", new EndpointAddress(address));
// do stuff
var client = factory.CreateChannel(); // you can also pass an address here. how does that effect channel caching?
So that handles the factory stuff. Now, I want to increase maxOutboundConnectionsPerEndpoint, which is achieved via a custom binding. The thing that's not clear there is the GroupName. I can't specify distinct group names in configuration because I'm looking up the URL at runtime. Thus, all channel factories are going to have the same default group name. Are they going to share the same pool, does each factory have it's own?
In the end, I would like to create the custom binding in configuration, then create/cache multiple channel factories as needed, and use them to establish channels. And, I need to increase the maxOutboundConnectionsPerEndpoint per endpoint. I may be calling the same service on 20 different machines, and I want up to 50 cached channels for each. Does the code above achieve that?
Thank you for your help. If there is a link that covers this, please forward. I haven't been able to find it.
Related
I'm using WCF to create a connection beween a server app and client app.
Because I'm using NetTcpBinding, I want to keep alive the channel created by:
T proxy = ChannelFactory<T>.CreateChannel();
I bring the proxy instance into my app to communicate with server. At some moment, I renew this proxy, with a different factory. But I want to release resources from the first factory, by disposing it. But I don't wan't to manage factories and keep a reference to.
Is there a way with the proxy instance to retrive the channel associate to dispose it ?
Like ...
var commObj = (ICommunicationObject)proxy;
commObj.Factory.Dispose();
Thanks
Unfortunately, it is not possible, because Channels and Factories are not linked. But I think your approach is not correct. You should keep a reference to the factory and create Channel as needed. Re-using Channel can be a problem in some cases. A channel can be faulted, but the inner factory will still be valid. Creating a factory has a real cost, and some .net 3.5 SP1, factories are internally stored in a static cache.
I have both ends of a bi-directional connected Stream, which I want to do some communication over. The underlying implementation behind the stream isn't important, I want to work at the Stream level...
Rather than implement my own communications protocol for the stream, I want to use all of the existing WCF goodness to wrap the existing stream with with a bi-directional (request/response + callback) WCF communications channel.
My question is, how can I go about doing this...?
UPDATE:
I've gone down the path of implementing a custom transport. I've got this working, but I'm still not totally happy with it...
I've implemented an IDuplexSessionChannel to wrap the stream, along with appropriate IChannelFactory and IChannelListener, and a Binding Element for creating the channel factories. Now, I just pass through the connected stream, and eventually pass these into the transport channel when it is created.
So, I can create the client proxy for accessing the service via the stream as follows:
var callback = new MyCallback();
var instanceContext = new InstanceContext( callback );
var pipeFactory = new DuplexChannelFactory<IMyService>( instanceContext, new StreamBinding(clientStream),
new EndpointAddress("stream://localhost/MyService"));
var serviceProxy = pipeFactory.CreateChannel();
The problem I have is, it seems WCF is set on using a ServiceHost to create the server end of the channel, via a IChannelListener. In my case, I already have a connected stream, and I won't be able to listen for any more incoming connections. I can work around this, but I'd much rather not use a ServiceHost to create the server end of the channel, because I end up with a lot of obscure boilerplate and hacks to make it work.
Questions
I'm looking, therefore, for a better way to take the IDuplexSessionChannels, and wrap these into a Channel proxy at both the server and client ends.
Or maybe a different ServiceHost implementation that doesn't require a IChannelListener.
Really, the problem here is I don't want a single server, multiple client arrangement, I have a 1-1 relationship between my WCF Service and the client. Is there a correct way to instantiate one of these?
To put it yet another way, I want to create the Server-side service instance without using a ServiceHost.
Any suggestions would be appreciated at this stage.
Use a client at both ends. You will need to define your contracts carefully though. If you have ClientA and ClientB at either end of the stream, when ClientA sends a request, ClientB will expect it to look like what it sees as it's defined callback contract and vice versa.
As the title implies I am trying to get an understanding of why in WCF sometimes people choose to "generate proxies" vs using a ChannelFactory to manually create new channel instances. I have seen examples of each, but haven't really found any explanations of WHY you would go for one vs the other.
To be honest I have only ever worked with channels and the ChannelFactory<T> from code I have inherited, ie:
IChannelFactory<IDuplexSessionChannel> channelFactory =
binding.BuildChannelFactory<IDuplexSessionChannel>();
_duplexSessionChannel = channelFactory.CreateChannel(endpointAddress);
So why would I "generate a proxy"? What are the benefits and drawbacks?
The main difference is this:
generating a proxy only requires you to know the URL where the service resides. By generating the proxy, everything else (the service contract and the data contracts involved) will be determined by inspecting the metadata of the service
in order to directly create a ChannelFactory<T>, you must have direct access to the assembly that contains that service contract T for which you're generating a channel factory. This only ever works if you basically control both ends of the channel and you can share the assembly that contains those service contracts. Typically, with a third-party service, this won't be the case - with your own services, yes.
The second important point is this:
creating a generated proxy basically does the two steps that you would do - create a ChannelFactory<T>, and from that, create the actual channel - in a single constructor. You have no control over these two steps.
doing your own Channel creation is beneficial, since the creation of the ChannelFactory<T> is the expensive step - so yo could cache your channel factory instance somewhere. Creating and re-creating the actual channel from the factory is much less involved step which you can do more frequently
So if you do control both ends of the communication, service and client, you do have the option to share the service contracts in a separate assembly, and thus you have more options.
With most third-party services, you just simply don't have that option.
Using a proxy is simpler and easier to understand. You get to deal in terms of simple things - classes and methods on those classes - instead of complex, network-related things like channels.
OTOH, this is not made easier by the design flaw in WCF that prevents the same simple use of a WCF proxy that we could do with ASMX proxies:
using (var client = new MyServiceClient())
{
}
If you use this pattern with WCF, you can lose the original exception when the block is exited due to an exception. client.Dispose() can throw an exception, which will overwrite the exception originally being thrown. A more complex pattern is required.
This may help you:
When to use a proxy?
If you have a service that you know is going to be used by several applications or is generic enough to be used in several places, you’ll want to use the proxy classes.
When to use ChannelFactory?
ChannelFactory class is used to construct a channel between the client and the service without the need of a proxy. In some cases, you may have a service that is tightly bound to the client application. In such a case, you can reference the Interface DLL directly and use ChannelFactory to call your methods using that.
You could also refer following link to understand the difference between Channel Factory and Proxy class
http://ashishkhandelwal.arkutil.com/wcf/channelfactory-over-proxy-class-in-wcf/
The main advantage of the channelFactory is you can create the proxy at runtime dynamically on the fly. With SvcUtil (Add web reference in VS) you create the proxy at design time, so it's implementation is more static.
Consider the following code which is typcial of many ChannelFactory examples:
WSHttpBinding myBinding = new WSHttpBinding();
EndpointAddress myEndpoint = new EndpointAddress(
ConfigurationSettings.AppSettings["HelloWorldServiceURL"]);
ChannelFactory<IHelloWorldService> myChannelFactory =
new ChannelFactory<IHelloWorldService>(myBinding, myEndpoint);
IHelloWorldService proxy = myChannelFactory.CreateChannel();
((IClientChannel)proxy).Open();
HelloWorldDataContract dc = proxy.SayHello();
((IClientChannel)proxy).Close();
Note that when proxy.Open() is called, both the the channel's state and the ChannelFactory's state become "Opened". When proxy.Close() is called, the channel's state becomes "closed", but the ChannelFactory's state remains "Opened".
Should one be closing the ChannelFactory as well? I don't seem to see this in many examples. Also, if possible please explain the difference between having a channel open vs having a channel factory open.
Additionally, I am aware of the IDisposable issue, so it probably can be ignored for the sake of this question unless it has direct impact on the answer.
I found the main answer inaccurate so I am responding here.
Obviously Microsoft has made an absolute mess out of Channles and Factories and Clients. Documentation is not also helpful since they seem to be there just to cover up the mess so I had to resort to testing.
With the performance issues regarding non-cached Channels, implementation changed in v3.5 to address these and added caching but that only complicated the issue.
The point is channel in ChannelFactory is in fact not different from the channel used by IClientChannel when you create a channel using ChannelFactory.CreateChannel(). It is all the same pot. Believe me not? Try:
ChannelFactory<IService> factory = new ChannelFactory<IService>();
// ...
IService service = factory.CreateChannel();
factory.Close();
service.DoIt() // Throws object disposed exception
So really, internally it is all the same channel. I personally have started disposing the channel factories and not client channels and have not encountered any issue. I have also tried doing this in a loop with creation of 100000 client channels, and only closing ChannelFactory.
As you know, the ChannelFactory creates the client channel based on configuration. You may want to create multiple client channels from an existing factory (to the same endpoint as that is locked). If you're done using the factory to create channels, there is no reason not to close it.
But, why might you want to keep it open? Here's an interesting article on WCF clients that says:
Checking the value of the
System.ServiceModel.ICommunicationObject.State
property is a race condition and is
not recommended to determine whether
to reuse or close a channel.
Rather than reuse a channel, you might want to simply create a new one with the channel factory. More on the client architecture is here.
Another option is to use the static CreateChannel method:
msdn.microsoft.com/en-us/library/aa344556.aspx
The answer is already here, but it is spread over several comments and answers and not entirely clear, hence my answer.
Should one close the ChannelFactory as well as the Channel?
No. If you want to create multiple Channels from each ChannelFactory, you should dispose of the ChannelFactory, which will dispose all the Channels it created for you.
If you want to create one channel for each (endpoint, binding) pair, you should use this static function: ChannelFactory<ServiceType>.CreateChannel(binding, endpoint) (which avoids the issue as it does not create a second IDisposable), and you should dispose of the channel it returns.
Disposing of both the channelfactory and any of the channels it created will raise an ObjectDisposed exception.
When working with WCF services, is it better to create a new instance of the service every time you use it? Or is it better to create one and re-use it? Why is either approach better? Is it the same for asynchronous proxies?
Or is it better to create one and re-use it?
Do not start to implement your own pooling implementation. That has already been done in the framework. A WCF proxy uses cached channels factories underneath. Therefore, creating new proxies is not overly expensive (but see Guy Starbuck's reply regarding sessions and security!).
Also be aware that a proxy times out after a certain idle time (10mins by default).
If you want more explicit control you might consider using ChannelFactories and channels directly instead of the "easy to go, full out of the box" ClientBase proxies.
http://msdn.microsoft.com/en-us/library/ms734681.aspx
And a "must read" regarding this topic is:
http://blogs.msdn.com/wenlong/archive/2007/10/27/performance-improvement-of-wcf-client-proxy-creation-and-best-practices.aspx
in addition to the things Guy Starbuck mentioned a key factor would be the security model you're using (in conjunction with the session requirements) - if you don't re-use your proxy, you can't re-use a security sessions.
This means that the client would have to authenticate itself with each call which is wasteful.
If, however, you decide this is what you wish to do, make sure to configure the client to not establish a security context (as you will never use it), this will save you a couple of roundtrips to the server :-)
One more point to consider is channel faults. By design WCF does not allow to use client proxy after unhandled exception happened.
IMyContract proxy = new MyContractClient( );
try
{
proxy.MyMethod( );
}
catch
{}
//Throws CommunicationObjectFaultedException
proxy.MyMethod( );
There is a corollary here to Server Activated Objects in .NET Remoting (one of the technologies that is replaced by WCF), which have two modes, "Single Call" (stateless) and "Singleton" (stateful).
The approach you take in WCF should be based on your performance and scaling requirements in conjunction with the needs of your consumers, as well as server-side design constraints.
If you have to maintain state between calls to the service, then you will obviously want to have a stateful instance, but if you don't you should probably implement it so that it is static, which should scale better (you can more easily load balance, etc).