Why callback from wcf service is so slow (especially the first time) - c#

I have a service that sends several callbacks per second to connected clients. Why when the service sends a message do the clients get them a few or more seconds later?
Here are the configuration details:
<bindings>
<wsDualHttpBinding>
<binding name="WSDualHttpBinding_IMyService" receiveTimeout="00:30:00"
sendTimeout="00:30:00" useDefaultWebProxy="false" maxBufferPoolSize="2147483647"
maxReceivedMessageSize="2147483647">
<readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647"
maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
<security mode="None"/>
</binding>
</wsDualHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="Service1Behavior">
<serviceMetadata httpGetEnabled="True"/>
<serviceDebug includeExceptionDetailInFaults="True"/>
<serviceThrottling maxConcurrentCalls="10"
maxConcurrentInstances="10"
maxConcurrentSessions="5" />
</behavior>
</serviceBehaviors>
</behaviors>

What you describe could be related to thread creation time.
See here: WCF service may scale up slowly under load
"Depending on the execution time and number of requests received you may notice the WCF execution time increase linearly by approximately 500ms for each request received until the process has created sufficient IOCP threads to service the requests or sustain the incoming load."
A workaround is provided in the article.

I'm dealing with the same problem, looking at these links to address the issue.
The overview seems that, out-of-the-box, WCF is 'locked down' to prevent DoS vulnerabilities. Essentially, you need to un-throttle the service as described in the links below.
http://theburningmonk.com/2010/05/wcf-improve-performance-with-greater-concurrency/
http://blogs.msdn.com/b/wenlong/archive/2010/02/11/why-are-wcf-responses-slow-and-setminthreads-does-not-work.aspx
http://weblogs.asp.net/sweinstein/archive/2009/01/03/creating-high-performance-wcf-services.aspx

Related

Chart doesn't display long-running WCF service? Timeout issue?

We have a WCF method that generates a json for an amcharts chart. The chart then displays the data.
If the call is made for a short period (ie. 12/1-12/5) then the json is produced quickly and the amcharts chart shows the data.
On the other hand, if the call is made for all year, then the results will take longer to generate. Calling the WCF directly will generate the json in about 6-8 seconds. If the chart calls it, it never loads.
I've already confirmed that the issue isn't the WCF method since a json is eventually returned. I understand that the SP can be optimized, but that's another issue.
We use IIS 6 on Windows Server 2008. The application pool for this particular WCF is set at .Net Framework 4.0 and Integrated.
In terms of the project, we use VS2013 and C#.
What do you recommend?
I tried increasing the timeout setting in web.config, but it didn't help much.
Please try to configure all the related properties.
<bindings>
<basicHttpBinding>
<binding name="myBindingConfig" maxBufferPoolSize="2147483647" maxBufferSize="2147483647"
maxReceivedMessageSize="2147483647" bypassProxyOnLocal="true" openTimeout="00:10:00"
closeTimeout="00:10:00" sendTimeout="00:15:00" receiveTimeout="00:10:00" >
<readerQuotas maxArrayLength="2147483647" maxNameTableCharCount="2147483647"
maxStringContentLength="2147483647" maxDepth="2147483647"
maxBytesPerRead="2147483647" />
<security mode="None" />
</binding>
</basicHttpBinding>
</bindings>
And servicebehavior, enable service debug to see the error in client
<serviceBehaviors>
<behavior name="myServiceBehavior">
<dataContractSerializer maxItemsInObjectGraph="2147483647" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>

Self Hosted WCF Service throws Error Message "405 Method not allowed"

I have a Self Hosted WCF Service, which looks like this:
[ServiceContract]
public interface IService {
[OperationContract]
[WebGet]
List<Data> GetData();
//...and much more Methods
}
My App.config looks like this:
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>
<behaviors>
<serviceBehaviors>
<behavior name="MetaInformation">
<serviceMetadata httpGetEnabled="true"
httpGetUrl="http://localhost:8500/MetaInfo"
httpsGetBinding="" />
<dataContractSerializer maxItemsInObjectGraph="2147483647"/>
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="EndpointBehavior">
</behavior>
</endpointBehaviors>
</behaviors>
<services>
<service behaviorConfiguration="MetaInformation" name="Library.WcfService.ServiceModel">
<endpoint address="http://localhost:8500/Service"
binding="basicHttpBinding"
bindingConfiguration="BasicHttpBindingSettings"
contract="Library.WcfService.IService"
bindingName="BasicHttpBindingSettings"
behaviorConfiguration="EndpointBehavior"/>
</service>
</services>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBindingSettings"
closeTimeout="00:50:00"
openTimeout="00:50:00"
sendTimeout="00:50:00"
maxBufferSize="524288"
transferMode="Streamed"
maxReceivedMessageSize="2147483647"
maxBufferPoolSize="2147483647"
messageEncoding="Text">
<readerQuotas maxDepth="2147483647"
maxStringContentLength="2147483647"
maxArrayLength="2147483647"
maxBytesPerRead="2147483647"
maxNameTableCharCount="2147483647" />
</binding>
</basicHttpBinding>
</bindings>
</system.serviceModel>
<system.web>
<httpRuntime maxRequestLength="102400"/>
</system.web>
When I run this Server and the Client Applications on my local machine, it's working fine.
But when i try to run the Server Application on another PC, I cannot add a Service Reference at the Client because I get this:
405 Method not allowed Metadata contains a reference that can not be resolved : "http://192.168.178.54:8500/MetaInfo". It was not a
listening to http://192.168.178.54:8500/MetaInfo endpoint present who
could accept the message. This is often caused by an incorrect
address or SOAP action
I tried almost everything I found at the internet but nothing worked.
Switching to IIS or using an other Protocol should be a plan B, i want to keep it self hosted with http.
Please can somebody help me I'm desperate with this Problem.
your operation contract is decorated with [WebGet] attribute, which means you're trying to expose your service as a REST. But your service is using basicHttpBinding as means of building the communication channel which isn't supported because the content type for this binding is soap+xml. You'll need to use WebHttpBinding in this case which is the only binding that supports restful implementation of WCF Services and supports both Xml and Json data types.

Credentials passed from client to WCF do not make it there

Im trying to pass windows credentials into WCF service that requires windows authentication but it seems like my credentials are not making it into the service. My service does not throw any errors but when I check either of the 2 below they are empty.
var user = WindowsIdentity.GetCurrent().User;
var callerUserName = ServiceSecurityContext.Current.WindowsIdentity.User;
Here is my client side code
ServiceReference1.DispatchServiceClient service = new DispatchServiceClient();
service.ClientCredentials.Windows.ClientCredential = ServiceCredentialsManager.GetNetworkCredentials();
service.ClientCredentials.UserName.UserName= ServiceCredentialsManager.GetNetworkCredentials().UserName;
service.ClientCredentials.UserName.Password = ServiceCredentialsManager.GetNetworkCredentials().Password;
Client config -
<basicHttpBinding>
<binding name="BasicHttpsBinding_IDispatchService">
<security mode="Transport">
<transport clientCredentialType="Windows" />
</security>
</binding>
</basicHttpBinding>
<basicHttpsBinding>
<binding name="basicHttpsBindingMax" maxBufferSize="999999999"
maxReceivedMessageSize="999999999">
<security mode="Transport">
<transport clientCredentialType="Windows" />
</security>
</binding>
</basicHttpsBinding>
</bindings>
Service config -
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="basicHttpsBinding">
<security mode="Transport">
<transport clientCredentialType="Windows" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior>
<!-- To avoid disclosing metadata information, set the values below to false before deployment -->
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="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="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<protocolMapping>
<add binding="basicHttpsBinding" scheme="https" />
</protocolMapping>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
Please note that in order to use Windows Authentication both service and the client application has to be run in the same Windows domain.
Please also make sure that that in the client the values You assign are not empty. Usually, the password isn't accessible from code when Windows authentication is used.
If the service client is authenticated using Windows Authentication, You probably shouldn't manually pass the credentials to the service. The authentication process should be handled automatically by the WCF and doesn't rely simply on sending the credentials, but for example it can use Kerberos ticket instead.
Please take a look here for some description and code samples for client and service:
https://msdn.microsoft.com/en-us/library/ms734673%28v=vs.110%29.aspx
https://msdn.microsoft.com/en-us/library/ms733089%28v=vs.110%29.aspx
Update
After some research I've found several sources suggesting that setting credentials appropriately in the client code may enable WCF to authenticate from outside the domain:
https://devdump.wordpress.com/2009/04/29/wcf-windows-authentication-and-external-users/
http://subbusspace.blogspot.com/2009/10/accessing-wshttp-wcf-service-from.html
The code samples suggested in those articles are similar, but slightly different to the one You've posted in the question. I haven't tested those methods and they may not work in all scenarios.

EndpointNotFoundException on call to operation of running RESTful WCF service

I have a really strange problem with one of my WCF services. I'm pretty sure that most people who have experimented with WCF services have had an EndpointNotFoundException thrown when an endpoint had not been set up correctly in one of their configuration files. From the EndpointNotFoundException class page on MSDN:
The exception that is thrown when a remote endpoint could not be found or reached.
Further on, it continues:
The endpoint may not be found or reachable because the remote endpoint is down, the remote endpoint is unreachable, or because the remote network is unreachable.
This does not reflect my situation. So it seems that receiving an EndpointNotFoundException when working with WCF is not unusual, but this Exception is not thrown when first trying to access the service... instead, it is thrown only when trying to call one of the operations of the service:
using (ExportConfirmationServiceClient client = new ExportConfirmationServiceClient(
"WebHttpBinding_IExportConfirmationService")) // <-- Exception is NOT thrown here
{
...
component releaseConfirmation = DeserializeTestXmlFile(filePath);
client.AddExportConfirmation("5051275066302", releaseConfirmation);
// Exception is thrown on call to service operation on line above
...
}
Interestingly, the Exception message also includes the name of the operation in the mentioned file path:
There was no endpoint listening at http://domain/Folder/ServiceName.svc/OperationName that could accept the message. This is often caused by an incorrect address or SOAP action. See InnerException, if present, for more details.
The inner Exception has the following message:
The remote server returned an error: (404) Not Found.
This is particularly confusing for me as I can successfully browse to the service URL and see the default You have created a service page:
Also, if I navigate to the path in the Exception message, I see an Endpoint not found message on the page:
However, if I navigate to any operation page of one of my other, working WCF services, I get a standard 400 Bad Request error from the browser, even though the operation works fine. So it would seem to me as if this original EndpointNotFoundException could be a red herring... I'm really not sure though, as I've not spent much time working with WCF.
I'll show my web.config (server side) here just in case anyone needs to see it:
<?xml version="1.0"?>
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="Midas.WebConfirmations.ExportConfirmationServiceBehaviour">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="webHttp">
<webHttp />
</behavior>
</endpointBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="false" />
<services>
<service name="Midas.WebConfirmations.ExportConfirmationService" behaviorConfiguration="Midas.WebConfirmations.ExportConfirmationServiceBehaviour">
<endpoint address="" binding="webHttpBinding" contract="Midas.WebConfirmations.IExportConfirmationService" behaviorConfiguration="webHttp" />
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</service>
</services>
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
</configuration>
This is the client App.config (bear in mind that this references two WCF services):
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_IDataService" closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00" allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard" maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536" messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered" useDefaultWebProxy="true">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384" maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<security mode="None">
<transport clientCredentialType="None" proxyCredentialType="None" realm="" />
<message clientCredentialType="UserName" algorithmSuite="Default" />
</security>
</binding>
</basicHttpBinding>
<webHttpBinding>
<binding name="WebHttpBinding_IExportConfirmationService" allowCookies="true" maxReceivedMessageSize="20000000" maxBufferSize="20000000" maxBufferPoolSize="20000000">
<readerQuotas maxDepth="32" maxArrayLength="200000000" maxStringContentLength="200000000"/>
</binding>
</webHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="Midas.WebConfirmations.ExportConfirmationServiceBehaviour">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="webEndpointBehavior">
<webHttp defaultBodyStyle="Wrapped" defaultOutgoingResponseFormat="Xml" helpEnabled="true"/>
</behavior>
</endpointBehaviors>
</behaviors>
<client>
<endpoint address="http://devbucket.ministryofsound.mos.local/MidasWebServices/DataService.svc" binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IDataService" contract="Midas.WebServiceClients.IDataService" name="BasicHttpBinding_IDataService" />
<endpoint address="http://devbucket.ministryofsound.mos.local/MidasWebConfirmations/ExportConfirmationService.svc" binding="webHttpBinding" bindingConfiguration="WebHttpBinding_IExportConfirmationService" behaviorConfiguration="webEndpointBehavior" contract="IExportConfirmationService" name="WebHttpBinding_IExportConfirmationService" />
</client>
</system.serviceModel>
</configuration>
So if any of the great minds that frequent Stack Overflow could shed some light on this problem for me, I'd greatly appreciate it.
UPDATE >>>
In response to the first few comments, I suspected that the problem could be caused by an Exception being thrown from the server side code, so I simplified the operation code dramatically... now all it does is this, but I still get the same error:
public void AddExportConfirmation(string upc, component ingestionFeedback)
{
WebOperationContext.Current.OutgoingResponse.StatusCode = HttpStatusCode.OK;
}
Also, I did set up tracing, but it only worked on the client side, so it only told me what I already knew. I will have a look at the link you provided #BigDaddy, in case it shows how to set up tracing on the server side.
In response to Tewr, I generated the service client using svcutil.exe, but I also tried adding a service reference and letting Visual Studio create the reference for me... both methods resulted in the same error. Also, I have been updating the service references all day, as I've been making changes. The includeExceptionDetailInFaults="true" setting didn't make any difference, but I'll try adding a dummy operation to the service and try to view it in the browser.
UPDATE 2 >>>
Ok, so I added a simple getter method to the service and updated the references all round like #Tewr suggested. This has just made me more confused... the method:
[XmlSerializerFormat()]
[OperationContract]
[WebGet()]
string GetString();
The implementation just returns a string and I see that value when I access the service in a web browser:
However, I still get the same error from code, even when calling this same new operation... what does that mean?
UPDATE 3 >>>
After taking the advice from the comments, I set up a Service Trace on the service again... I still couldn't get the one working on the server, but on the client, it did output a trace file. In that file, I see an InvalidOperationException with the following message:
Envelope Version 'EnvelopeNone (http://schemas.microsoft.com/ws/2005/05/envelope/none)' does not support adding Message Headers.
I'm just researching this now, so if you know what this error is about, please let me know.
The problem with WCF is that it is so complex, the Exceptions cover so many different errors each and the Exception messages are so vague. From my limited experience, it seems like an error message will say one thing, but it will often be wholly, or partly irrelevant to your actual problem. So I basically kept fixing errors, which unlocked new Exceptions (and I still haven't come to the end of them yet!), but for the purpose of this question, there is an answer.
So it turned out that the original EndpointNotFoundException was actually thrown because there was an unhandled Exception in the AddExportConfirmation service method implementation. Once I had simplified the code (as in the first question update), that particular Exception went away and was replaced with the next one.

WCF response time, throttling

My WCF service configuration:
<system.net>
<connectionManagement>
<add address ="*" maxconnection="500"/>
</connectionManagement>
</system.net>
<bindings>
<basicHttpBinding>
<binding name="customBasicHttpBinding"
maxBufferSize="2147483647" maxReceivedMessageSize="2147483647"
transferMode="StreamedResponse">
<readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647"
maxArrayLength="2147483647" maxBytesPerRead="2147483647"
maxNameTableCharCount="2147483647"/>
<security mode="None"/>
</binding>
</basicHttpBinding>
<webHttpBinding>
<binding name="customWebBinding" maxBufferSize="2147483647"
maxReceivedMessageSize="2147483647">
<readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647"
maxArrayLength="2147483647" maxBytesPerRead="2147483647"
maxNameTableCharCount="2147483647"/>
<security mode="None">
</security>
</binding>
</webHttpBinding>
</bindings>
<serviceBehaviors>
<behavior name="soapBehavior">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
<dataContractSerializer maxItemsInObjectGraph="6553600"/>
<serviceDebug includeExceptionDetailInFaults="false"/>
<serviceThrottling maxConcurrentCalls="100"
maxConcurrentInstances="100" maxConcurrentSessions="100" />
</behavior>
</serviceBehaviors>
<services>
<service behaviorConfiguration="soapBehavior" name="Service.Service">
<endpoint name="soap"
address=""
binding="basicHttpBinding" bindingConfiguration="customBasicHttpBinding"
contract="ServiceModel.IService"/>
<endpoint
address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
As you can see I set up throttling parameter to handle 100 concurrent instances.
For a test purpose I created dummy method on my interface that looks something like this
[OperationContract]
string Test(){
return "test response time";
}
When I'm trying to call this method, it uses 100 parallel request ats once response time is very bad:
Now running 100 parallel requests...
ResponseTimes: 0,45205P, 10,047P, 0,43304P, 0,86609P, 1,33913P, 0,91409P, 1,34713P, 1,75718P, 1,37414P, 1,80718P, 1,80618P, 2,22622P, 2,64426P, 2,22822P, 2,62626P, 2,68127P, 3,0453P, 3,10731P, 3,47635P, 3,51035P, 3,91039P, 3,94039P, 3,9544P, 4,36844P, 4,34943P, 4,78748P, 4,37144P, 4,82248P, 4,79048P, 5,25052P, 4,81948P, 5,67657P, 5,25253P, 5,71657P, 5,67357P, 6,13761P, 5,70257P, 6,56566P, 6,12361P, 7,0117P, 6,53065P, 7,43674P, 6,9517P, 7,86679P, 7,36974P, 7,81778P, 8,29483P, 8,75988P, 8,71587P, 8,24182P, 8,70187P, 9,16392P, 9,12991P, 9,19492P, 9,57596P, 9,65797P, 10,08201P, 10,45205P, 10,52505P, 10,48905P, 10,9521P, 10,89709P, 11,37714P, 11,81118P, 11,32413P, 11,76418P, 11,83918P, 12,18222P, 12,31723P, 12,60526P, 12,75128P, 13,0423P, 13,17132P, 13,48935P, 13,64836P, 13,91039P, 14,07141P, 14,32843P, 14,48945P, 14,78548P, 14,91149P, 15,20652P, 15,33153P, 15,62856P, 15,75558P, 16,0516P, 16,19262P, 16,48265P, 16,61866P, 16,91169P, 17,05471P, 17,33773P, 17,48375P, 17,74677P, 17,92079P, 18,15782P, 18,34183P, 18,58086P, 18,77388P, 19,0069P,
0 request(s) failed.
Average response time:9,20126
Why are results so bad, I tried to change AppPool Worker Process count but no luck, can anyone tell what I'm missing, what is setting limits?
I'm using WCF 4.0, IIS7.5 on a Windows Server 2008R2 machine.
Thank you
It is difficult to provide much insight regarding communication performance issues without detailed information about the service, configuration and environment. At the least, you may way to provide the service binding, the ServiceBehaviorAttribute and information about the client configuration.
From years of conducting WCF performance testing and optimization, we have seen “similar” issues as you described … despite having 100 concurrent connections, the service does not seem to “respond” efficiently, even though the server resources do not seem busy. In our case, the “delay” was associated with a slow, “cold” startup and the time taken by the .NET thread pool to allocate threads.
The following article discusses our issue:
http://blogs.msdn.com/b/dmetzgar/archive/2011/05/04/wcf-scales-up-slowly-with-bursts-of-work.aspx
Good luck.
I just finished a big, industrial scale WCF project that employed throttling and found that throttling doesn't always yield the results you expect. We set up our WCF web servce on a production-grade virtual server, then we created a test harness that emulated 1000+ virtual clients on a multi-threaded program. Once we were ready, we ran, and re-ran, tests over and over using a bunch of different throttling settings from 1 - 1000, but were surprised by the results.
For instance, you'd think that running your web service with 200 max concurrent connections would be twice as fast as 100 max connections, but that's not what we found for settings for things like:
-max concurrent sessions
-max concurrent calls
-max concurrent instances
In reality, there wasn't much of a performance (callsProcessed/second) difference between MaxConcurrentSessions=10 and MaxConcurrentSessions=1000. The calls processed per second was about the same, only the memory usage was different. Same thing with other throttle settings.
The fastest setting we found for throttling? No setting at all; basically, let the System.ServiceModel library handle everything. That's the fastest that we found after days of testing.
As far as your performance is concerned, what I would do is try and figure out where the bottle necks are. For instance, if your WCF service is using SQL to retrieve data, try eliminating SQL and just return a static dataset and see if your time dramatically improves. If it does, then maybe you need to work on the database side of things. If it doesn't, maybe there's a problem processing your SOAP messages.

Categories