Monday, October 1, 2012

WCF Web Services called from BizTalk

I have a BizTalk orchestration which is calling a WCF Web Service.  Now I'm processing lots of messages at once (about 8,000 at a time) but the web service was a bottle neck.
During testing we noticed that only 10 connections were opened to the web service at any one time.  As a result we were getting timeout issues and orchestrations were getting dehydrated.  We tinkered around in IIS but try as we might we could not figure out a way of increasing the number of connections. 

Then my colleaguse found this article which reports much better performance if you use net.tcp rather than http and the former has binding properties that can control the number of connections. You need to be cautious because there are quite a lot of factors to consider before changing protocols.  The advice is always to perform tests to determine which is the right protocol to use. 

I've not used net.tcp before so there are a couple of things you need to do first.
1. This will only work on Windows Server 2008 and R2

2. You need to install the feature of .Net 3.5 Framework WCF Activation to support non-HTTP protocols.  By default this is not selected, so you will need to go and install it from Server Manager.

3. One you have done that, you can add the net.tcp biding to the web site where your WCF web service is installed.  Note: keep both protocols: net.tcp and http for the web site.  Do this by editing the bindings and adding net.tcp with Binding Information like 80:*. But also go to Advanced Settings and change Enabled Protocols to htp,net.tcp.

4. Next you need to add the binding to the web.config of the WCF web service.  I did this using NotePad.  Keep the original basicHTTP binding in place because that way you can still check the the web service will load in the browser and you can see the WSDL. I've provided an extract from my web.config below.

<bindings> <netTcpBinding> <binding closeTimeout="00:01:00" hostNameComparisonMode="StrongWildcard" maxBufferPoolSize="524288" maxBufferSize="65536" maxConnections="100" maxReceivedMessageSize="65536" name="NetTcpBinding_IADService" openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00" transferMode="Buffered"> <readerQuotas maxArrayLength="16384" maxBytesPerRead="4096" maxDepth="32" maxNameTableCharCount="16384" maxStringContentLength="8192"/> <security mode="None"> <transport clientcredentialtype="None" protectionLevel="None"/> <message clientCredentialType="UserName"/> </security> </binding> </netTcpBinding> </bindings>

<service name="WCFADService.ADService" > <host> <baseAddresses> <add baseAddress="net.tcp://localhost/WCFADService/ADService.svc"/> <add baseAddress="http://localhost/WCFADService/ADService.svc/mex"/> <add baseAddress="http://localhost/WCFADService/ADService.svc"/> </baseAddresses> </host> <endpoint address="" binding="netTcpBinding" contract="WCFADService.IADService" bindingConfiguration="NetTcpBinding_IADService" /> <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" /> </service>

As far as the endpoint url for a net.tcp web service is concerned you can just replace the http:// with net.tcp://

You can test this in the usual way with a console application by using the net.tcp endpoint in the service reference. 

As far as consuming the net.tcp web service in BizTalk is concerned you can use the same consume web service wizard.  That will give you a Custom Binding xml file which you can import into BizTalk.  The magic is then when you click on Configure of the Send Port you get the ability to change the number of connections.
There are two properties here maxConnections and listenBacklog and we set them both to 50.  Sure enough when we tested this out I got 50 simultaneous connections. 

One last point is that running the web service like this hammered the CPU.  You would be well advised to put your web service on another server separate from the BizTalk Server. 

1 comment:

Unknown said...

Thanks a lot for the information...saved a lot of time.. :)