Improve WCF service performance - c#

My company owns a server with 24 cores and a lot a RAM inside. The OS is Windows 2008 R2 SP1. I deployed on this server a WCF application, hosted in IIS. On the same server I installed a multithreaded client which calls one of the WCF service, as often as possible. I encountered a bottleneck : all the cores on the server are used, but at a very low level, so the CPU consumption doesn't exceed 10 %. My WCF service is configured like this :
<system.serviceModel>
<services>
<service behaviorConfiguration="myBehavior" name="...">
<endpoint address="" binding="netTcpBinding" bindingConfiguration="myBinding" bindingNamespace="..." contract="..."/>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="myBehavior">
<serviceMetadata httpGetEnabled="true"/>
<serviceThrottling maxConcurrentCalls="200" maxConcurrentSessions="200" />
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<netTcpBinding>
<binding name="myBinding" maxBufferPoolSize="2147483647" maxBufferSize="2147483647" maxConnections="2147483647" maxReceivedMessageSize="2147483647" portSharingEnabled="false" transactionFlow="false" listenBacklog="2147483647">
<security mode="None">
<message clientCredentialType="None"/>
<transport protectionLevel="None" clientCredentialType="None"/>
</security>
<reliableSession enabled="false"/>
<readerQuotas maxDepth="64" maxStringContentLength="204800" maxArrayLength="204800" maxBytesPerRead="4096" maxNameTableCharCount="16384"/>
</binding>
</netTcpBinding>
</bindings>
My service has also the following attributes : InstanceContextMode.Single and ConcurrencyMode.Multiple. Did anyone encounter a similar problem ? I searched the solution for days, but I didn't find it yet :(
Thank you in advance !

I'm not sure how you're measuring the performance bottleneck but no matter how many client calls you generate, the service will only handle 200 calls at a time. The netTcpBinding is uses sessions so the throttle there is the maxConcurrentSessions="200" setting. You've configured the service as a multi-threaded singleton which is limited to 200 simultaneous calls by the maxConcurrentCalls="200" setting. The CPU load will also depend on how much work is performed during each call and whether it is IO bound or not. Review the serviceThrottling element documentation and try increasing both settings to see if your throughput improves.
If your sevice implementation allows, I would recommend you try configuring the service with InstanceContextMode.PerSession and ConcurrencyMode.Single to compare throughput with your current configuration. IIS 7x hosts WCF services using the Windows Process Activation Service (WAS). WAS is designed to handle concurrency. A singleton configuration negates the value of using WAS.

Related

Not able to communicate with WCF service running on separate computer using net.tcp

I am not able to communicate with another computer that is in my local area network over a net.tcp connection unless I turn the security mode off. If I set the security mode to "None", communication works fine. With the service model configuration set up as below on both ends of the wire, I get the error message "The server has rejected the client credentials".
The WCF service is being hosted in a Windows service on the remote computer. From what I have seen in various documentation, my configuration is set up correctly. Any ideas on what I might be doing wrong? Wild suggestions welcomed.
<system.serviceModel>
<bindings>
<netTcpBinding>
<binding name="NetTcpBinding_ITcpService">
<security mode="Transport">
<transport clientCredentialType="Windows" />
</security>
<!--Communication works if I do this
<security mode="None" />
-->
</binding>
</netTcpBinding>
</bindings>
<client>
<endpoint address="net.tcp://199.198.3.5:8520/TcpService"
binding="netTcpBinding"
bindingConfiguration="NetTcpBinding_ITcpService"
contract="TcpServiceReference.ITcpService"
name="NetTcpBinding_ITcpService">
</endpoint>
</client>
</system.serviceModel>

WCF - unable to stop net.tcp binding (hosted on IIS)

I have working WCF service on IIS with configured net.tcp endpoint. After disable page on IIS I'm still able to run request to my service o.O.
Disabling application pool works as expected (service is no longer available).
<system.serviceModel>
<services>
<service name="xyz.Service.Authentication.Implementation.AuthenticationService">
<endpoint binding="netTcpBinding"
bindingConfiguration="NetTcpBinding"
contract="xyz.Service.Authentication.Model.IAuthenticationService"/>
</service>
</services>
<bindings>
<netTcpBinding>
<binding name="NetTcpBinding" sendTimeout="00:00:30"
transactionFlow="false"
portSharingEnabled="false"
maxReceivedMessageSize="18000">
<security mode="Transport">
<transport clientCredentialType="Windows" protectionLevel="Sign"/>
</security>
</binding>
</netTcpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceAuthorization principalPermissionMode="UseWindowsGroups"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
Is it a bug or a feature ?
I had similar problem and I found out that:
Stopping Web Site does not stop the net.tcp service
Disable App Pool disables service but does not free the port, port is still used by SMSvcHost.exe
Restarting after does not helps too.
The only way to free port ( to be used by something else ) was to delete net.tcp binding in IIS.
I spent time on this, because received wrong answers from net.tcp service. It took me while, to find out - it's not from my service, but from old disabled one. This could save time to someone else.

Can I configure a WCF service and consume a different on in the same application?

I'm trying to host on a website both the creation of a WCF service to send JSON data back to the client-side, as well as consume a different webservice used for cross application data exchange (it's a medical app, the data I need is hosted in an old ASMX webservice somewhere else)
My problem is the app is behind SSL, and basic authentication (which will go when we deploy to live), the service I'm consuming is over http and the rediculous amount of settings I need in the web.config are getting in each others way.
The web.config looks like this now
<behaviors>
<endpointBehaviors>
<behavior name="AJAXEndpoint" >
<webHttp/>
</behavior>
</endpointBehaviors>
</behaviors>
<services>
<service name="MyNamespace.Service.ACSvc">
<endpoint
behaviorConfiguration="AJAXEndpoint"
address="" binding="wsHttpBinding" bindingConfiguration="UsernameWithTransport"
contract="MyNamespace.Service.IACSvc">
</endpoint>
</service>
</services>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true"
multipleSiteBindingsEnabled="true" />
<bindings>
<basicHttpBinding>
<binding name="wsAbbVieSoap">
<security mode="Transport" />
</binding>
</basicHttpBinding>
<wsHttpBinding>
<binding name="UsernameWithTransport">
<security mode="Transport">
<transport clientCredentialType="Basic" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<client>
<endpoint address="http://somewhere.else.com/externalservice.asmx"
binding="basicHttpBinding" bindingConfiguration="wsAbbVieSoap"
contract="AbbvieService.wsAbbVieSoap" name="wsAbbVieSoap" />
</client>
Over various iterations, I've had my service working, but the external service not working or neither service working.
What I want
My service - HTTPS, Basic authentication, response in JSON
External service - HTTP, Anonymous, SOAP response
These services are not aware of each other and have nothing to do with each other. They're separate parts of the same website - one (mine) for my own clientside scripts, and the other (external) for me to call serverside for various business uses.
Any help appreciated

How to configure WCF service deployed on IIS and remote client to authenticate from remote client PC?

I'm a noob; please help me understand this authentication config / bindings stuff that confuses me so much.
I have a C# WCF service deployed on IIS 7 on Win 2008. My client is a Windows Forms C# app. My client works just fine when it's running from the same server where the WCF service is running, but when I try to run my client from a remote PC, I get the following exception...
System.ServiceModel.Security.SecurityNegotiationException: The caller was not authenticated by the service.
I've read a few posts about these issues, and know that my problem is because my service and client are configured to use Windows authentication, which I guess is the default when using Visual Studio to create the service, and to add the service reference to the client. Below is my config before I made any changes, when it was still set to Windows (with irrelevant bits removed)...
Web.Config
<system.web>
...
<authentication mode="Windows"/>
...
<system.serviceModel>
<services>
<service name="MCLaborServer.LaborService" behaviorConfiguration="MCLaborServer.LaborServiceBehavior">
<!-- Service Endpoints -->
<endpoint address="" binding="wsHttpBinding" contract="MCLaborServer.ILaborService">
<!--
Upon deployment, the following identity element should be removed or replaced to reflect the
identity under which the deployed service runs. If removed, WCF will infer an appropriate identity
automatically.
-->
<identity>
<dns value="localhost"/>
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="MCLaborServer.LaborServiceBehavior">
<!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
<serviceMetadata httpGetEnabled="true"/>
<!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
And from the App.Config on the client...
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="WSHttpBinding_ILaborService" closeTimeout="00:01:00"
openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
bypassProxyOnLocal="false" transactionFlow="false" hostNameComparisonMode="StrongWildcard"
maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true"
allowCookies="false">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<reliableSession ordered="true" inactivityTimeout="00:10:00"
enabled="false" />
<security mode="Message">
<transport clientCredentialType="Windows" proxyCredentialType="None"
realm="" />
<message clientCredentialType="Windows" negotiateServiceCredential="true"
algorithmSuite="Default" establishSecurityContext="true" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<client>
<endpoint address="http://<myDnsNameGoesHere>/MCLaborServer/LaborService.svc"
binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_ILaborService"
contract="LaborService.ILaborService" name="WSHttpBinding_ILaborService">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
</client>
</system.serviceModel>
So, first I changed "authentication mode="None"" in the web.config, and set "security mode="None"" in the client's app.config, and set both the clientCredentialType="None" for message and transport. I also commented out the "identity" sections in both the web.config and client's app.config. That broke it completely though and now the client running locally won't even work; it gives a "The remote server returned an unexpected response: (405) Method Not Allowed" error.
So what can I do to turn security off so that I can connect using a remote client? I do have anonymous access enabled by the way in IIS for my application.
I'd also like to ask, what's the best practice way to configure this so I can make webservice calls on a remote client over the internet in a semi-secure fashion without using SSL or doing anything that would cost money. I'm not really that concerned about security of the data because it's not really sensitive data, but still I'd like to make sure the server isn't open to attacks.
Also, I read that I can use Windows authentication, and then explicitly specify credentials in code, like below. If I do that, will it still work remotely? And if so, does that end up making my Windows credentials for the server be sent over the wire in an insecure fashion, so then I'd be open to getting my credentials hijacked?
SomeService.ServiceClient someService = new SomeService.ServiceClient();
someService.ClientCredentials.Windows.ClientCredential.UserName="windowsuseraccountname"
someService.ClientCredentials.Windows.ClientCredential.Password="windowsuseraccountpassword"
I've read through the following posts / links, but still am confused. Thanks for any help!
WCF error: The caller was not authenticated by the service
How to fix "The caller was not authenticated by the service"?
http://msdn.microsoft.com/en-us/library/aa291347(v=vs.71).aspx
http://www.devx.com/codemag/Article/33342/1763/page/2
We ran into similar issues when setting up low security WCF services that ran across domains. One of the biggest problems (if you can call it that) is that WCF is configured to be very secure by default. Because our application was entirely within a secure network, we did not want to have to bother with a lot of complicated certificates. Our workaround was to create a custom binding that allowed us to use username/password authentication for our services without any encryption. We based our implementation off of Yaron Naveh's Clear Username Binding. I would recommend that you have a look at that (and at his blog post introducing it).
Some good resources for learning about WCF Bindings and Security:
MSDN - Windows Communication Foundation Bindings Overview
MSDN - System-Provided Bindings
MSDN - Security Overview
MSDN - Programming WCF Security
MSDN - WCF Security Fundamentals
MSDN - Choosing a Transport
I fixed this by changing binding to basicHttpBinding, changing authentication to Forms and turning security off.

isOneWay WCF Services

I'm attempting to create a process that verifies data within a database and notifies users of errors. My initial thought was to create a web service that is triggered when the user saves the web form. That web service would begin the process of validating the data and populating another table with information about what information it believes is invalid. From the beginning I had intended for this web service to return instantly prior to the actual completition of the data verification. The data verification is going to be a longer process and isn't intended to be form validation. It's also okay if it were to happen to fail since the process will be refreshed every evening also so I’m not concerned about that.
OneWay services seems like the most logical choice for this. I have already written the service and everything is working great without OneWay being present. However the moment I add OneWay the process no longer works. What is particularly puzzling to me is I have a line that outputs a log file at the very beginning of the web service method and it occasionally writes the log when I call the service. Not every time, but sometimes. I also have multiple log statements that get outputted and it has never made it past the first line once isOneWay is enabled. It seems like the code is just being arbitrarily halted. Has anyone ever run into this before? My next option is to create a network queue task that receives the web service call directly and adds it to its queue and I was hoping to avoid doing that.
A bit more background information, I am new to WCF services but not web services in general. The web application is written in ASP.Net and is calling the webservice via HttpGet.
I'm open to other architecture suggestions and any input is greatly appreciated.
Here is the ServiceModel element from the web.config:
<system.serviceModel>
<bindings>
<customBinding>
<binding name="WebHttpBinding_Service">
<textMessageEncoding maxReadPoolSize="64" maxWritePoolSize="16"
messageVersion="Soap12" writeEncoding="utf-8">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
</textMessageEncoding>
<httpTransport authenticationScheme="Negotiate,Ntlm"/>
</binding>
</customBinding>
<webHttpBinding>
<binding name="webHttpBinding_IISAuthen">
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Windows" />
</security>
</binding>
</webHttpBinding>
</bindings>
<services>
<service name="Namespace.Service" behaviorConfiguration="Namepsace.ServiceBehavior">
<endpoint address="" behaviorConfiguration="Namespace.ServiceAspNetAjaxBehavior"
binding="webHttpBinding" bindingConfiguration="webHttpBinding_IISAuthen" contract="Namespace.Service" />
</service>
</services>
<behaviors>
<endpointBehaviors>
<behavior name="Namespace.ServiceAspNetAjaxBehavior">
<enableWebScript />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="Namespace.ServiceBehavior">
<!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
<serviceMetadata httpGetEnabled="true" />
<!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
<client>
<endpoint binding="customBinding" bindingConfiguration="WebHttpBinding_Service"
contract="Service" name="WebHttpBinding_Service" />
</client>
</system.serviceModel>
When running into problems like these in WCF, where something stops working when changing the configuration, I would definitely start by tracing the running service. WCF has a great tracing mechanism which you start by editing the configuration. You can read all about configuring it here.
I discovered the problem. It may seem odd but the service was being run within the same project and that seemed to be causing the problem with using it as a one way service. I moved it out into its own project everything worked as expected.
I thank everyone for their time, the tracing will certainly prove to be useful in the future.

Categories