Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Channel Factory caching #4186

Closed
pmiddleton opened this issue Mar 3, 2020 · 4 comments
Closed

Channel Factory caching #4186

pmiddleton opened this issue Mar 3, 2020 · 4 comments
Labels
feature request Adding new functionality requiring adding an API to the public contract. priority 2 Stack ranked level of priority. P2

Comments

@pmiddleton
Copy link

I'm trying to figure out what the best approach is for caching with the new wcf library now that ClientBase no longer caches.

I have a middleware asp.net core web service which in turn needs to call out to a 3rd party soap service using wcf. The 3rd party service is at a single fixed url https endpoint.

My understanding is that everything in the wcf layer is threadsafe - is this correct? If so am I better off caching the generated clientBase derived object, a channel factory, or a channel proxy?

Calls to the 3rd party service will be sporadic so will I be facing any timeout issues with any of the 3 options? Is it recommended to cache local to where I need to make the calls, or use DI on the channel factor or proxy?

Due to the size of the 3rd party wsdl generating a new clientBase each call is not an option. The creating time is on the order of 500ms.

@StingyJack
Copy link

Your title captures the answer - cache the factory. Just be aware that there isnt a reliable Dispose() on the channels that ChannelFactory creates and it could be leaky. IMO not really worth it, sporadic (subjective) or not.

Some of the word choices are giving me the impression that you are generating code from wsdl while the program is executing and then executing that. Is that what you mean, or are you using "generate" in the same way as you would use "construct an object" or "create a new instance of " and svcutil or some other tool already generated the code thats compiled and that the runtime is using to make new instances ?

@pmiddleton
Copy link
Author

sorry bad use of the word generating in that last sentence, should had said instantiating.

The derived clientbase is part of the code generated by svcutil. The generated reference.cs file, that svcutil produces, is on the order of ~700,000 lines of code. Instantiating a new clientbase on each call was spending ~600-800ms creating a new channel factory.

I need to cache something because that cost is too high for our use case.

@StingyJack
Copy link

That sounds like a web service that has too many functions. I would probably break up the code generated by the wsdl using a script or similar, starting with removing parts you don't use.

@HongGit HongGit added enhancement Not a bug and not a new API, just a product improvement. feature request Adding new functionality requiring adding an API to the public contract. priority 2 Stack ranked level of priority. P2 and removed enhancement Not a bug and not a new API, just a product improvement. labels Mar 13, 2020
@mconnew
Copy link
Member

mconnew commented Aug 20, 2021

@pmiddleton, there are a few ways to solve this problem. I've just added support for caching the ChannelFactory that backs ClientBase<TChannel>. This will enable you to set the static property MyClient.CacheSetting = CacheSetting.AlwaysOn before you instantiate any instances and it will use a single ChannelFactory to back every instance you create. If you are okay with creating a new instance of ChannelFactory every time and it's just the reflection cost you want to avoid, then you can achieve that by caching the ServiceEndpoint. This is retrieved from the property ChannelFactory<TChannel>.Endpoint. You can then pass this to a constructor of ClientBase<TChannel> and it will avoid reflecting over your service interface. This is because ServiceEndpoint contains the ABC for your client, the Address, Binding, and Contract. The contract is represented by the class ContractDescription and contains everything WCF needs to know about your interface, so it can skip reflecting over your interface. I believe you will need to add a new constructor of your generated client, but it's a partial class so do that in a new file. The constructor would simply take a ServiceEndpoint and call base(serviceEndpoint).

@HongGit HongGit closed this as completed Oct 13, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature request Adding new functionality requiring adding an API to the public contract. priority 2 Stack ranked level of priority. P2
Projects
None yet
Development

No branches or pull requests

4 participants