I just had a “duh” moment. That’s different from a blonde moment in that it is not a momentary lapse in memory or thought process – in fact a “duh” moment is worse because it is the result of habit forming perspectives based on experience that cause us not to “think” about a subject until someone challenges your way of thinking.
Someone asked me about port sharing today and I gave my usual perspective on the subject which is that it is common practice (even recommended) that you (when self-hosting) have a different base address per ServiceHost. This way of thinking is the result of 5 years doing WCF where from the beginning port sharing options were not obvious, and the usual demo code does not use it since we can’t easily distribute the sample and have people run it without turning on port sharing, and the fact is most of my customers don’t self-host so the subject doesn’t come up, and for those customers who do self-host, they have never had issues with opening the required ports for each ServiceHost.
I was left thinking about my answer this evening and realized I’m an idiot. I wasn’t thinking on my feet so well when I answered the question so I stuck to the usual “yes, you can make it work but that is not common practice”. Then, I was haunted by my own answer. The funny thing is that this is such a small feature of WCF and usually I deal with bigger issues, but this little feature is actually really important. REALLY important.
Port sharing means that you can reduce the number of exceptions in the firewall rules. Lots of enterprises have issue with this. Considering each host environment:
- IIS provides port sharing for port 80 and 443 for HTTP/S communications, so we don’t have issues there.
- Windows Activation Service (WAS) allows port sharing for TCP across services as well.
- A windows Service may host multiple services, and we may have multiple windows services in the environment. These can also share ports if you enable TCP port sharing on the machine and for the binding. You should also be able to share HTTP port 80 or 443 with IIS from a self-hosted service, or TCP port 808 (or other port if configured differently in WAS),if desired.
In summary, if you use IIS or WAS you get port sharing (which is why I don’t usually think about this…most customers use IIS/WAS)…but if you self-host you can turn on the TCP port sharing service and share ports across all your services if desired. That includes sharing with IIS/WAS ports if both are present (though, unlikely you have both present otherwise why use a Windows Service?
Now, for the caveats.
- Your deployment of services must include automating or providing instructions to enable port sharing
- You may need to provide some custom configurations for the port sharing service to increase throughput
- Metadata endpoints can’t share the same endpoint address so rather than using /mex for each service you have to make the relative address unique such as /ServiceA/mex and /ServiceB/mex
- Sometimes other services cause the port sharing service to crash…so you need to be ready for that as we are adding a new dependency on the environment. If the service host fails to load you can see in the event viewer this error at times: “The Net.Tcp Port Sharing Service service terminated unexpectedly.” We don’t like that!
Here are a few examples of this last issue:
MY NEW AND IMPROVED RECOMMENDATIONS
- Try to use port sharing to reduce the number of firewall exceptions
- If you own the environment, ensure a predictable machine setup with no conflicting DLLs that could cause port sharing service to crash
- If you don't own the environment, brace yourself that some customers may have software that conflicts and in that case you can’t use port sharing.
- Make your service configuration flexible so that you can switch the deployment easily between port sharing or not and this way your service will work regardless of issues you encounter.
- Don’t hard code ports at client or service as the available port could change.
- Make sure clients are not depending on a single port since if port sharing doesn’t work, you’ll need to have each proxy hit potentially a different address.
This is a link to a GREAT blog post on port sharing including lots of links to other resources for education on the underlying technology, and lots of issues and workarounds. Must read if you want to know more.
http://blogs.msdn.com/b/andreal/archive/2009/04/05/net-tcp-ip-port-sharing.aspx Have a great day!