I have a self hosted WCF service I'm hosting in a Windows Service. My binding is setup as a basicHttpBinding.
When I am running the service, I run netsh http show servicestate and I see my service is listening; however, I cannot seem to configure the parameters properly.
When hosted under IIS, it performs about 20% slower so I want to self host. How can I configure the parameters of my self hosted WCF service to match IIS? The parameters I'm particularly looking at are timeouts, Max Connections, Timeouts, and Max Requests. I've attempted to put a Service Behavior; however, it doesn't do anything. I've added the MaxConnections in the Registry under HTTP/Parameters without luck either. Any help is appreciated.
Here is the output when hosted under IIS:
Server session ID: F9000000200015DA
Version: 2.0
State: Active
Properties:
Max bandwidth: 4294967295
Timeouts:
Entity body timeout (secs): 120
Drain entity body timeout (secs): 120
Request queue timeout (secs): 65535
Idle connection timeout (secs): 120
Header wait timeout (secs): 120
Minimum send rate (bytes/sec): 240
URL groups:
URL group ID: F600000040001737
State: Active
Request queue name: MyService
Properties:
Max bandwidth: inherited
Max connections: 4294967295
Timeouts:
Entity body timeout (secs): 120
Drain entity body timeout (secs): 120
Request queue timeout (secs): 65535
Idle connection timeout (secs): 120
Header wait timeout (secs): 0
Minimum send rate (bytes/sec): 0
Logging information:
Log directory: C:\inetpub\logs\LogFiles\W3SVC2
Log format: 0
Authentication Configuration:
Authentication schemes enabled:
Number of registered URLs: 1
Registered URLs:
HTTP://*:80/
Request queues:
Request queue name: MyService
Version: 2.0
State: Active
Request queue 503 verbosity level: Basic
Max requests: 3000
Number of active processes attached: 1
Controller process ID: 1400
Process IDs:
Here is the output when I'm self hosting:
Server session ID: FC00000120000229
Version: 2.0
State: Active
Properties:
Max bandwidth: 4294967295
Timeouts:
Entity body timeout (secs): 120
Drain entity body timeout (secs): 120
Request queue timeout (secs): 120
Idle connection timeout (secs): 120
Header wait timeout (secs): 120
Minimum send rate (bytes/sec): 150
URL groups:
URL group ID: FB000001400005DE
State: Active
Request queue name: Request queue is unnamed.
Properties:
Max bandwidth: inherited
Max connections: inherited
Timeouts:
Timeout values inherited
Number of registered URLs: 1
Registered URLs:
HTTP://+:80/MyService/
Request queues:
Request queue name: Request queue is unnamed.
Version: 2.0
State: Active
Request queue 503 verbosity level: Basic
Max requests: 1000
Here is my service config file:
<?xml version="1.0"?> <configuration> <system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="MyThrottle">
<serviceThrottling maxConcurrentCalls="3000" maxConcurrentSessions="3000"
maxConcurrentInstances="12500" />
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<basicHttpBinding>
<binding name="MyConfig" closeTimeout="00:10:00"
openTimeout="00:10:00" receiveTimeout="00:10:00" sendTimeout="00:10:00"
maxReceivedMessageSize="10485760" useDefaultWebProxy="false">
<readerQuotas maxDepth="999999999" maxStringContentLength="999999999"
maxArrayLength="999999999" maxBytesPerRead="999999999" maxNameTableCharCount="999999999" />
<security mode="None">
<transport clientCredentialType="None" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<services>
<service behaviorConfiguration="MyThrottle" name="This.MyService">
<endpoint address="http://localhost:80/MyService" binding="basicHttpBinding"
bindingConfiguration="MyConfig" name="MyService"
contract="This.IMyService" />
</service>
</services> </system.serviceModel> </configuration>
Here is the official response from Microsoft HTTP.SYS team:
The “Max Connections” = HttpServerConnectionsProperty output has a different meaning than “Max Requests” = HttpServerQueueLengthProperty.
HttpListener does not let you set the Max Connections property (HttpServerConnectionsProperty) for the URL group or the Max requests property (HttpServerQueueLengthProperty) for the request queue, so WCF cannot set http.sys settings when self-hosting through code.
Related
I am running a WCF service with a netMsmqBinding on IIS. It is configured to use 'Message' security with the 'Windows' client credential type, which uses kerberos to encrypt and sign the message. The service contract enforces ProtectionLevel.EncryptAndSign. It might be important to note that transactions are being used from client to service.
When the service is operational, the communication works flawlessly. However, to test the durability of delayed messages or when the service is unreachable, I temporarily disabled the application pool of the service in IIS. Then I send a message from the client. It leaves the outgoing queue on the client machine and it is transported to the private queue on the server. The .NET MSMQ Listener picks up the messages and tries to call the WCF service method, but that fails as expected. After about 10 minutes I reenable the application pool. In the service trace log, the following exception is logged:
System.ServiceModel.Security.MessageSecurityException:
"Message security verification failed."
System.IdentityModel.Tokens.SecurityTokenException:
"The AcceptSecurityContext failed."
System.ComponentModel.Win32Exception:
"The clocks on the client and server machines are skewed"
I also tried the same scenario by taking the Message Queuing service offline on the server. The result is the same.
My guess is that the client obtains the kerberos ticket to encrypt the message, but because the message is decrypted (at least) 10 minutes later by the WCF service, it detects a clock skew. Of course I manually verified the clocks on both the client and the server but they are the same.
Client configuration:
<bindings>
...
<netMsmqBinding>
<binding>
<security mode="Message">
<message clientCredentialType="Windows" />
</security>
</binding>
</netMsmqBinding>
</bindings>
<client>
...
<endpoint address="net.msmq://host/private/service/service.svc"
binding="netMsmqBinding"
contract="Namespace.Contract" />
</client>
Server configuration:
<bindings>
...
<netMsmqBinding>
<binding receiveErrorHandling="Reject">
<security mode="Message">
<message clientCredentialType="Windows" />
</security>
</binding>
</netMsmqBinding>
</bindings>
<serviceActivations>
...
<add relativeAddress="service.svc"
service="Namespace.Contract"
factory="Ninject.Extensions.Wcf.NinjectServiceHostFactory"/>
</serviceActivations>
<services>
...
<service name="Namespace.Contract">
<endpoint address="net.msmq://localhost/private/service/service.svc"
binding="netMsmqBinding"
contract="Namespace.IContract" />
</service>
</services>
How is this supposed to work? What am I missing?
Edit:
This page does state the fact that "The problem with using the Kerberos protocol for queued communication is that the tickets that contain client identity that the Key Distribution Center (KDC) distributes are relatively short-lived.", but it does not really elaborate when it can be useful.
The beauty about kerberos message security is that it works nearly out of the box, someone should have considered this situation, right?
Edit 2:
I verified the time on both servers and the skew is about 0.1 second for both the client (DC01 is the domain controller):
C:\>w32tm /stripchart /computer:DC01 /samples:5
Tracking DC01 [10.1.1.2:123].
Collecting 5 samples.
The current time is 04-11-2015 16:49:17.
16:49:17 d:+00.0000000s o:-00.1020864s [ * ]
16:49:19 d:+00.0000000s o:-00.1020897s [ * ]
16:49:21 d:+00.0000000s o:-00.1020896s [ * ]
16:49:23 d:+00.0000000s o:-00.1020952s [ * ]
16:49:25 d:+00.0000000s o:-00.1021011s [ * ]
and the server:
C:\>w32tm /stripchart /computer:DC01 /samples:5
Tracking DC01 [10.1.1.2:123].
Collecting 5 samples.
The current time is 04-11-2015 16:49:17.
16:49:17 d:+00.0000000s o:-00.1171919s [ * ]
16:49:19 d:+00.0000000s o:-00.1360460s [ * ]
16:49:21 d:+00.0000000s o:-00.1237094s [ * ]
16:49:23 d:+00.0000000s o:-00.1269640s [ * ]
16:49:25 d:+00.0000000s o:-00.1302236s [ * ]
Hmmmm... sounds vaguely like something I blogged about. 45 seconds seems to be the maximum delay.
We have a WCF net.tcp service in high traffic site.
http://www.artedelcorpo.com/
It works very well for some time, then it stops and returns a timeout error.
When I restart IIS, it runs again.
Why?
Is there a limit on connections?
There is a default setting of 10 connections for the NetTcp Binding. You can increase this in the <binding> section of your config. The same is true of the timeouts - the default is 1 minute, but you can also adjust the close timeout, open timeout, receive timeout and send timeout.
<system.serviceModel>
<bindings>
<netTcpBinding>
<binding name="MyNetTcpBinding" closeTimeout="00:05:00"
openTimeout="00:05:00" receiveTimeout="00:05:00"
sendTimeout="00:05:00" maxConnections="100" />
<netTcpBinding>
</bindings>
</system.serviceModel>
The above sample will set the timeouts to 5 minutes and the max connections to 100.
See <netTcpBinding> for more detail/information.
Increasing network timeouts buys you time for the request to be processed. This can help you survive a short burst of high traffic, but it doesn't change your system throughput.
If your hardware still has some headroom in terms of memory and CPU when these problems occur, you should look at changing your concurrency throttles. This will allow more requests to be processed in parallel. The default throttle values in .NET 3.5 are actually quite conservative and this might be a quick fix (depending on your service architecture).
Here's some good examples of configuring WCF service throttles.
If your hardware is maxed out and you are still getting timeouts, its probably time to cluster the service and add another node.
I setup a WCF service to work over HTTP and MSMQ. It kind of works. The HTTP protocol works 100%. The problem is with net.msmq. When I check the queue, the messages have gone down by 1 which I assume means it's being processed. But at the same time, the service is no longer available. I receive a 403 service unavailable error from IIS. When I purge the queue and reset the site, the service is available again.
Message queue has full permissions for everyone and the service doesn't do anything (seriously, it's just a stub method) so it isn't a code problem.
The contract is marked as one way and the action is *.
Messages are going into the queue (sending 10 at a time) and at least 1 message is getting pulled (count goes down to 9).
The net.msmq listener service is running.
How can I fix this problem?
I had the same problem, because I forgot to specify the bindingConfiguration. I had the binding setup like
<bindings>
<netMsmqBinding>
<binding name="Msmq" exactlyOnce="true" >
<security mode="None" />
</binding>
</netMsmqBinding>
</bindings>
Once I realized the bindingConfiguration was missing from my endpoint, I added it in, and it started working correctly.
<endpoint address ="net.msmq://localhost/private/MyQueue.svc"
binding="netMsmqBinding"
contract="IService" bindingConfiguration="Msmq">
I have a wcf webHttp endpoint and noticed today that when called httpGet with a long url ~364 total characters (http:// etc counted) IIS throws a 400 bad request error. Throwing a breakpoint in the code never gets reached. If I remove some parameters and have a url that is 354 the web service runs as expected.
I'm not sure where the issue is since urls can be like 2k. I'm not posting any data so I don't think I'm hitting a 4mb limit like from here
What gives?
Here's some wcf xml stuff.
<behaviors>
<endpointBehaviors>
<behavior name="REST">
<webHttp/>
</behavior>
</endpointBehaviors>
</behaviors>
<endpoint address="" behaviorConfiguration="REST" binding="customBinding" bindingConfiguration="jsonpBinding" contract="Interface"/>
<bindings>
<customBinding>
<binding name="jsonpBinding">
<jsonpMessageEncoding/>
<httpTransport manualAddressing="true"/>
</binding>
</customBinding>
</bindings>
<extensions>
<bindingElementExtensions>
<add name="jsonpMessageEncoding" type="Microsoft.Ajax.Samples.JsonpBindingExtension, service, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
</bindingElementExtensions>
</extensions>
I just removed the callback function name which significantly reduced the size of the url and it still threw a 400 error. This makes me think that there is a WCF size limit on the text that can be sent in as a string parameter.
here;'s some Contract stuff
[OperationContract]
[WebGet(UriTemplate = #"{userName}/layer({layerName})returnAttributes({attributeList})where({attributeName})({op})({attributeValue})", ResponseFormat = WebMessageFormat.Json)]
[JSONPBehavior(callback = "callback")]
DojoGrouping GetAttributes(string userName, string layerName, string attributeList, string attributeName, string attributeValue);
the issue is with attributeList which can be comma separated list.
so with a url call like
http://../demo/layer(OfficialsLookup)returnAttributes(USHOUSE,US_Photo,US_Web,US_Name,SENDIST,SEN_Name,SEN_Email,SEN_Party,SEN_Photo,REPDIST,REP_Name,REP_Email,REP_Party,REP_Web,REP_Photo)utmX(430)utmY(4502)
it busts. But if i shorten the return attribute text then it functions properly.
I've added I added the following entry into the registry:
Key Name: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\HTTP\Parameters
Class Name: <NO CLASS>
Last Write Time: 1/25/2011 - 3:34 PM
Value 0
Name: UrlSegmentMaxLength
Type: REG_DWORD
Data: 0x200
I rebooted the machine after adding it and am still receiving the same error. Is this the correct spot to be modifying the HTTP.sys settings that WCF and IIS are using? Is there a way to test that WCF is being affected by this registry value?
Here is a related post with no answer but saying that the httpsys stuff did not fix a 64 bit server which is what we are using.
Related Post
To fix our issue we had to use the .NET 4.0 framework. We moved the web service to run under a .net 4.0 app pool and changed the target framework to 4.0. This caused the site to spit out url is too long error instead of just a bad request. After adding a web config entry in
<system.web>
added
<httpRuntime maxUrlLength="500" />
for max url length, the service is up and running as expected.
WCF uses HTTP.sys to handle HTTP traffic. HTTP.sys has system wide settings to handle various restrictions around URL. You might be hitting one of them.
See the following article to find out those settings:
http://support.microsoft.com/kb/820129
You will need to restart http service and your WCF service. If it is hosted in IIS, restart IIS. UrlSegmentMaxLength seems to be an interesting for your URI template.
I have written a very simple WCF Service that sends and receives messages. I have tested the app through the VS 2008 default web server host and everything works fine. But when I deploy the WCF service to another computer's IIS I receive the following error:
"The request for security token could not be satisfied because authentication failed."
How can I set the authentication type to use my custom username and password in config file?
If it is not possible, please tell me how I can set its windows credentials because the 2 computers that I'm using, don't share the same users.
You need to turn off security for the binding. Otherwise, I believe that, by default, the wsHttpBinding will try to negotiate a Security Context Token (SCT).
So, modify the endpoint definition to point to a binding configuration section. Here's an example:
<endpoint address=""
binding="wsHttpBinding"
contract="HelloWorldService.IService1"
bindingConfiguration="TheBindingConfig">
And then add something like the following binding configuration right after the <services> section in the web.config's <system.serviceModel> section.
<bindings>
<wsHttpBinding>
<binding name="TheBindingConfig">
<security mode="None" />
</binding>
</wsHttpBinding>
</bindings>
Setting security to "None" is the key.
Hope this helped!
The above helped me - but what is not immediately obvious is how to add to the service end (its clear once you've done it what's needed, but not until you've done so). The reason its not entirely obvious is because there isn't a bindings section by default whereas there is liable to be one in the client.
So, just to be very clear - at the service end, add the bindings section (as detailed above) and then to the appropriate endpoint add the bindingConfiguration="TheBindingConfig" attribute. Obvious once you've done it once...
You don't actually need to turn off security and in some cases you shouldn't. Within a bindingConfiguration, you can specify message level security that does not establish a security context as follows:
<security mode="Message">
<transport clientCredentialType="Windows" proxyCredentialType="None"
realm="" />
<message clientCredentialType="Windows" negotiateServiceCredential="true"
algorithmSuite="Default" establishSecurityContext="false" />
</security>
Note the establishSecurityContext attribute. Both the client and service should have a security configuration with establishSecurityContext set to the same value. A value of true also works fine but false is recommended in an environment where the servers are load balanced.
Be sure to set this bindingConfiguration (specifying security mode 'none') on both client and server or else you will get this message - which is quite a red herring as far as debugging the problem.
The message could not be processed.
This is most likely because the action
'http://tempuri.org/IInterfaceName/OperationName'
is incorrect or because the message
contains an invalid or expired
security context token or because
there is a mismatch between bindings.
The security context token would be
invalid if the service aborted the
channel due to inactivity. To prevent
the service from aborting idle
sessions prematurely increase the
Receive timeout on the service
endpoint's binding.
If you are in debug mode then set the debug attribute as
<serviceDebug includeExceptionDetailInFaults="true"/>
by default it sets as false ..so while you go for debugging it throws that exception .
hope it helps .