Recomendation for proxy lifetime in a WCF service to service scenario?

Sep 6, 2009 at 8:03 PM

Hello,

Nice job for taking the time and record the videos - very instructive and well explained! But ....

I've seen in a previous post that you don't recommend this approach for managing the proxy lifetime in a WCF service to WCF service scenario. Now this is my case and I'd like to know whether I have any chance of reusing a proxy instance in such a scenario. Probably the safest way would be to create the proxy for every service invocation - heavy of course, in a service. Is there a best strategy for handling such scenarios? 

I also didn't find out exactly whether the proxy generated by default is thread-safe. I think the real answer to this problem is not whether it is thread-safe NOW, but what chances we have that MS guys won't change this in the future? 

Now for my critical eye. The issues I have about this proxy is that it is not really type-safe (you'd have to rework your code if the service contract changes, for exl. a method name, parameters), you used reflection (a very very heavy thing for a server supposed to handle thousands of connections), and last but not least it is NOT future-proof - if employed in a large development project and MS guys by any chance decide to do their work properly when generating proxies, I would have to replace some code. And it is clear that whatever approach we take for working round the proxy generated by default will HURT performance, unless the proxy is generating quality code that handles the common scenarios without 10 extra lines of spagetti code! Therefore can I afford to say that the very need of this work (though worth on its own!!!) around such a common problem means that the original .NET proxy generated by the MS guys is "flawed by design"? We've got to get these guys to do their job properly; once we're working with automatically generated code there is no way for us to fix their flaws without introducing performance bottlenecks or reduce type-safety! 

Regards,

Florin Neamtu

Coordinator
Sep 7, 2009 at 3:06 PM

Hi Florin,

Thanks for the comments, appreciate that you took the time to provide feedback.

I'll start by addressing the "flawed by design" comment. I don't think this is the case with Microsoft. Remember, this proxy wrapper is only really useful when you have a session which means TCP, named pipes or WSHttp bindings with secure or reliable sessions. Sessions usually don't apply from ASP.NET to service or from service to service behind the firewall - because you usually must provide credentials for each call and that requires a new factory. So, it applies only to client applications which usually should cache the proxy. You can still acheive acceptable response times while constructing a new proxy for each downstream service behind the firewall, and for cases where you need additional performance (as in a service bus) you would have to create your own proxy pool and handle security in a different way. Anything is possible, but more often than not creating a new proxy each call is acceptable. 

As for the qualities of this proxy wrapper:

  • The default proxy generated by SvcUtil is thread-safe, that is it can be shared across multiple client threads so long as they all use the same channel properties (typical of UI client). This proxy wrapper is also thread-safe, which required additional work to protect channel creation, disposal and proxy recreation.
  • There is an optimization I can do to replace reflection with a delegate, and I'll get to that when I have time, but in the meantime I have tested this with some heavily multithreaded applications used in production and the performance overhead of the reflection call is not even noticeable. So, yes I agree it can be improved, but at the client the current implementation is acceptable in the locations I implemented it. Of course, if the same benchmarks are not acceptable for your particular scenario you can edit the code to implement a delegate model.
  • The proxy base class is reusable fo all proxies, only the derived type must be recreated for each service contract. This is the same as for the MS generated proxy, I don't see any way around this.

I shared this code because I found it useful for my own purposes and with customers, but it is not a product, it is simply a code sample that hopefully will save you time and over time it has grown into more and more functionality. I can't guarantee it is future proof, but I would hope that anyone adopting this is going to test that it works for their scenario very carefully. Consider it a head start for your own coding efforts.