How to control number of inbound connections on webHttpBinding service? - c#

I have a standard Web Service that processes JSON requests via an webHttpBinding. I am trying to find out whether there is a limit on how many concurrent connections it can handle and how to control it. Can't find anything. I am missing something simple or some setting?
Here is a skeleton of my service:
[ServiceContract]
public interface IMyService {...}
[ServiceErrorBehavior(typeof(ErrorHandler))]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class MyService : IMyService {...}

I have some suggestion for this, but this will not be direct config related change. Hold on and read this.
In WCF, there is InstanceContextMode and ConcurrencyMode properties defined for ServiceBehavior. These parameters are configurable only within the service code, and not in XML configuration, because they relate to the runtime behavior of the service and the service developer should be aware of their values. The InstanceContextMode parameter determines how many instances of the service have to be created by the WCF runtime. The possible values are:
PerCall: a new InstanceContext object is created for each call.
PerSession: a new InstanceContext object is created for each session. If the channel does not create a session this value behaves as if it were PerCall.This is the default value.
Single: only one InstanceContext object is used for all incoming calls and is not recycled subsequent to the calls. If a service object does not exist, one is created.
More helpful Blog

Use WCF Service Throttling to control the service.
<behaviors>
<serviceBehaviors>
<behavior name="Throttled">
<serviceThrottling
maxConcurrentCalls="1"
maxConcurrentSessions="1"
maxConcurrentInstances="1"
/>
</behavior>
</serviceBehaviors>
</behaviors>
Always remember that service behaviors do not override limits defined in the host (or binding). For example when using webHttpBinding the default IIS Maximum Concurrent Connections would likely need to be changed for large concurrency values.

Turns out it has more to do with threading than anything else. The default ASP.NET settings are pretty conservative, so you have to hike them up. Once I did that, the concurrent connections bottleneck completely disappeared.
Make sure you have the following in the appropriate machine.config (not web.config):
<configuration>
<system.net>
<connectionManagement>
<add address="*" maxconnection="100" />
</connectionManagement>
</system.net>
<system.web>
<processModel
autoConfig="true"
maxWorkerThreads = "100"
maxIoThreads = "100"
minWorkerThreads = "50"
minIoThreads = "50"
/>
<httpRuntime
minFreeThreads="176"
minLocalRequestFreeThreads="152"
/>
</system.web>
</configuration>
I took all this info from Tuning IIS article by Stuart Brierley. The only thing I changed significantly from his recommendations is maxConnection value.

Related

IIS ServicePoint ConnectionLimit always set to Int32.MaxValue

I have a local web application running on IIS which contacts a service deployed on AWS.
While I was testing the throughput against the AWS service I realised that my local web application didn't respect the ConnectionLimit value set in the web.config through the following code:
<system.net>
<connectionManagement>
<add address="*" maxconnection="48" />
</connectionManagement>
</system.net>
Instead the following code always return int.MaxValue
#(ServicePointManager.FindServicePoint(new Uri("https://myawsservice/")).ConnectionLimit)
This seems to contradict what I have read here: http://msdn.microsoft.com/en-us/library/ms998583.aspx#scalenetchapt17_topic14
Increasing maxconnection enables more calls to be executed concurrently to a remote Web service. This attribute does not affect local Web service calls. An increase in the number of concurrent calls causes an increase in the utilization of threads that are used to make the remote calls.
I would expect Int32.MaxValue to only be applicable to local web services. I don't consider my AWS service to be local.
Did I miss something? Did I misunderstood the definition of local web service?
Thanks in advance for your help.
Nico.
Found the issue.
If the processModel autoConfig attribute is set to "true" inside your machine.config then you can't override the ConnectionLimit using the web.config
<system.web>
<processModel autoConfig="true" />
...
</system.web>
Set it to "false" if you want to control the ConnectionLimit but in that case you'll probably want to review the other values set when autoConfig is on.

Can you mimic an existing service in WCF?

We have a 3rd party vendor service and an in-house service to communicate with it. Everything works perfectly with our in-house service, but I've been asked to write a fall back clone of our vendor's service. The intention is to be able to run up our clone, swap-out the client end-point and allow our in-house service to continue testing against the clone.
Is it possible to recreate/mimic a service such that an existing client can communicate with it (without modification) as if it were the original service?
So far I’ve tried 3 things and none of them work.
1st approach
Create a simple service, reference the 3rd party service to gain access to the custom types and mimic the [operation Contract]’s.
When I try to communicate with this service I get the following error.
A first chance exception of type 'System.ServiceModel.ActionNotSupportedException' occurred in System.ServiceModel.dll
Additional information: The message with Action '' cannot be processed at the receiver, due to a ContractFilter mismatch at the EndpointDispatcher. This may be because of either a contract mismatch (mismatched Actions between sender and receiver) or a binding/security mismatch between the sender and the receiver. Check that sender and receiver have the same contract and the same binding (including security requirements, e.g. Message, Transport, None).
There is no security requirements as we are using basic http (no ssl). The service model portion of the config file and the service behaviour class attributes are below:
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="SimpleBinding" />
</basicHttpBinding>
</bindings>
<services>
<service behaviorConfiguration="cloneBehavior" name="MyClone">
<endpoint address="" binding="basicHttpBinding" bindingConfiguration="SimpleBinding"
contract="MyService.IMyService" />
<host>
<baseAddresses>
<add baseAddress="http://localhost/clone/" />
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="cloneBehavior">
<serviceMetadata httpGetEnabled="True" httpGetUrl="http://localhost/clone/mex" />
<serviceDebug includeExceptionDetailInFaults="False" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
and the service behaviour
[ServiceBehavior(Name = "CloneService",
ConfigurationName = "MyClone",
InstanceContextMode = InstanceContextMode.PerCall,
AddressFilterMode = AddressFilterMode.Any)]
public class MyService : IMyService
{
Everything looks good and I have come to my first dead end.
2nd approach
Get rid of my interface/service contract and inherit directly from the interface generated in the reference.cs file.
When I run this service up, I get the following error
System.InvalidOperationException: The operations myMethodA and myMethodB have the same action (). Every operation must have a unique action value.
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ActionDemuxer.Add(String action, DispatchOperationRuntime operation)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime..ctor(DispatchRuntime dispatch)
at System.ServiceModel.Dispatcher.DispatchRuntime.GetRuntimeCore()
at System.ServiceModel.Dispatcher.ChannelDispatcher.OnOpened()
at System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout)
at System.ServiceModel.ServiceHostBase.OnOpen(TimeSpan timeout)
at System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout)
at Microsoft.Tools.SvcHost.ServiceHostHelper.OpenService(ServiceInfo info)
Taking a look at the generated interface for this method, they are all decorated with the following attribute:
[System.ServiceModel.OperationContractAttribute(Action="", ReplyAction="*")]
My understanding from msdn is that WCF defaults to adding a unique action of the pattern <namespace>/<service>/<operation>[Response].
If I try setting the action to * then I can hit the service (as expected with the catch all / unmatched message handler), but I can't hit a specific method.
Nevertheless, manually making all the actions unique (and conforming to the above pattern), give this error:
The contract ‘IMyService’ in client configuration does not match the name in service contract, or there is no valid method in this contract.
…
I have clearly defined methods in the service contract and have come to a second dead end.
3rd approach
Using the wsdl.exe tool to generate a service from the wsdl. I followed the instructions from this SO post to generate an interface and inherit from it.
I’ve also tried generating the service itself by using the clientWsdl.wsdl /l:CS /server command and following the instructions in this post.
After tidying up the generated code and running it up, I’m back to my original error:
A first chance exception of type 'System.ServiceModel.ActionNotSupportedException' occurred in System.ServiceModel.dll
Additional information: The message with Action '' cannot be processed at the receiver, due to a ContractFilter mismatch at the EndpointDispatcher. This may be because of either a contract mismatch (mismatched Actions between sender and receiver) or a binding/security mismatch between the sender and the receiver. Check that sender and receiver have the same contract and the same binding (including security requirements, e.g. Message, Transport, None).
At each attempt I have double checked all the config settings and updated the contract at each stage.
At this stage I'm wondering if it's even possible.
Were you ever able to mimic the service using WCF? I find myself in a similar situation where I've been tasked to write some integration tests where our method makes a call to a vendor's web service. I would have preferred to leverage Moq to write proper unit tests, but I'm constrained by 1) not being allowed to change the signature of the method that I'm testing, and 2) not really knowing anything about the web service itself except for what we send to the service and its expected response.
#jparram's suggestion was my next approach.
Note: I would have preferred to have posted this as a comment seeing that I'm not really answering your question.
If I understand your scenario, I would create wrapper service that decides which service to call. It sounds like that's what you want to do with Scenario 1. So, your client would always be calling your wrapper service, and your wrapper service would map the inputs to the required inputs of your 3rd party service or your back up service.
The error you received sounds like an issue in the generation of the proxy client where the "Action" is not getting mapped. Take a look at the generated proxy code from a known working configuration and compare it to what is in your scenario 1.
Edit
Compare the generated proxy client of your service and the 'real' service. The complaint about the Action = "" is probably due to the:
[System.ServiceModel.OperationContractAttribute(Action="", ReplyAction="")]
On your client not getting mapped to the corresponding operation.

Max Outbound connections

I have an application written in c# on .NET 4.0 which needs to make multiple web service requests. The web service requests vary in nature but are mostly requesting information.
The Types involved is a derivative of System.ServiceModel.ClientBase
The connection is setup in code and uses types such as BasicHttpBinding, EndpointAddress, and CustomBinding to name a few.
How can I determine the max number of concurrent requests that can be made on the derivative of the ClientBase?
I've not been able to find any property that pertains to MaxConnections but I do come across things like NetTcpBinding.MaxConnections and ConnectionManagementElement.MaxConnection but neither of these seem compatible with my leveraged APIs. Either I'm missing how to use them, this isn't available or I don't know where to look.
WCF is an abstraction on core networking concepts. For HTTP bindings, it falls under the ServicePoint configuration which determines things like your HTTP concurrent connection limits.
You want ServicePointManager.DefaultConnectionLimit for HTTP:
http://msdn.microsoft.com/en-us/library/system.net.servicepointmanager.defaultconnectionlimit.aspx
You can also do this via your config file:
http://msdn.microsoft.com/en-us/library/fb6y0fyc.aspx
This would be in the binding configuration section of the service host's .config file. Depending on the binding being used, you can set things like maxConcurrentCalls and maxConcurrentSessions, there are usually default limits for them imposed by WCF.
Real life example:
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="ServiceBehaviorBasicHttp">
<serviceThrottling maxConcurrentCalls="1000" maxConcurrentSessions="1000" maxConcurrentInstances="1000"/>
<serviceMetadata />
</behavior>
</system.serviceModel>
Or in code behind, something like this:
ServiceHost host = new ServiceHost(typeof(MyService));
ServiceThrottlingBehavior throttleBehavior = new ServiceThrottlingBehavior
{
MaxConcurrentCalls = 40,
MaxConcurrentInstances = 20,
MaxConcurrentSessions = 20,
};
host.Description.Behaviors.Add(throttleBehavior);
host.Open();
Taken from here: WCF: How do I add a ServiceThrottlingBehavior to a WCF Service?

WCF call that references Windows Service

I have a long-running service that gets data from one source, manipulates it, stores it in a database, etc.
I'd like to expose some methods on that service to other applications. Currently we do this via .NET Remoting but I'd like to move to WCF.
Unfortunately, I the endpoint I connect to is never the one I exposed via my long-running service. Below is a simple example:
[ServiceContract]
public interface ITestWcfService
{
[OperationContract]
CounterResult GetCurrentValue();
}
public class TestWcfService : ITestWcfService
{
private ITestWindowsService _service;
public TestWcfService() { /*NOTE: For discoverability*/ }
public TestWcfService(ITestWindowsService service)
{
_service = service;
}
public CounterResult GetCurrentValue()
{
return _service.GetCurrentValue();
}
}
public interface ITestWindowsService
{
CounterResult GetCurrentValue();
}
Then I have my actual Windows Service, which self-hosts the WCF service via the ServiceHost class.
public partial class TestWindowsService : ServiceBase, ITestWindowsService
{
private static ServiceHost _wcfService;
public TestWindowsService()
{
InitializeComponent();
}
public void OnStart(string[] args)
{
//Create instance of WCF, passing in reference to this service instance
TestWcfService wcf = new TestWcfService(this);
_wcfService = new ServiceHost(wcf);
}
public CounterResult GetCurrentValue()
{
//Note: Some logic here
}
}
Now, this more-or-less works except that each time I make a call to the TestWcfServiceClient(), it uses the default constructor and creates a new instance of the Wcf Service and does not use the instance created by the windows service. This means that when I call GetCurrentValue() I get a null reference because the _service member hasn't been set.
I've looked around for solutions and found some citing ServiceHostFactory and ServiceHost and IInstanceProvider but each has seemed to be very, very complicated.
Any thoughts you could provide would be most appreciated.
EDIT: Here's my ServiceModel info
<system.serviceModel>
<services>
<service name="WcfService.TestWcfService">
<host>
<baseAddresses>
<add baseAddress = "http://localhost:8733/Design_Time_Addresses/WcfService/TestWcfService/" />
</baseAddresses>
</host>
<!-- Service Endpoints -->
<!-- Unless fully qualified, address is relative to base address supplied above -->
<endpoint address="" binding="basicHttpBinding" contract="WcfService.ITestWcfService">
<!--
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>
<!-- Metadata Endpoints -->
<!-- The Metadata Exchange endpoint is used by the service to describe itself to clients. -->
<!-- This endpoint does not use a secure binding and should be secured or removed before deployment -->
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
<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="False" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
WCF is VERY extensible, but in order to provide such extensibility it is also very complicated. In my opinion, more than it should be so if you want to use this implementation that's the way to go. YOu have to create a behavior that changes the service factory so you can use the custom constructor instead of the empty one.
However, I think there might be another alternative. Since both the service and the WCF share the same app domain they can share values through static objects.
I would move the logic that carries the value you want to expose to un underlying assembly (if you didn't already) and both the service and WCF service would see the same instance therefore you don't need to change all the WCF plumbing.
You are trying to put a square peg in a round hole.
WCF is explicitly designed to enable calling business logic independent of how it is hosted. You are trying to maintain the old remoting design that has your business logic in the host layer (in this case a Window's service). As a result you are asking to pass information back up to the host in a way that is possible in WCF but ugly and is generally avoided for many good reasons.
If you want a clean WCF design you will need to create abstraction layers and move your business logic out of the existing TestWindowsService class. Then the windows service creates the WCF service host, the WCF host creates the WCF service, and the WCF service is not dependent on the classes that host it.
Having said all that...
To actually answer your question:
Conceptually the code that you have written should work. Passing an object instance into the ServiceHost constructor is by far the easiest way to avoid the complexity of writing a custom IInstanceProvider. A couple of things to check:
When you pass a service instance into the ServiceHost constructor it needs to be marked as a singleton.
[ServiceBehavior(InstanceContextMode=InstanceContextMode.Single)]
Make sure that initialization is really working the way you think it is:
Put a guard on your TestService(ITestWindowsService) constructor that throws if service is null.
You have a comment on the default constructor for TestWcfService() that says "for discoverability". I would remove that constructor (at least while you are troubleshooting). A piece of code might be using that constructor to host a service instance you don't want. This is likely to cause your app to start throwing exceptions or compile errors that point out your real problem.
If you are still having problems: What does the Service Model section of your app.config look like?

Read Global Application property from WCF Service

I'm using in my Global.asax class the object Application to store data.
Application.Set("data", "test");
Now, in my WCF Service, I want to be abble to read this property. How can I do that?
Application["data"];
In debug, I can see my global.asax is called (Begin_Request), but in my webservice's method, how can I access to this Application?
var yourData=HttpContext.Current.Application["data"];
bear in mind anyway thay if you will deploy the Service on a Server Farm you could have issues as the Application is inProc and each server will have its own Application variable
in order to get the HttpContext.Current working with wcf you gotta turn on compatibility:
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
</system.serviceModel>
then you can get access as Massimiliano Peluso suggests:
// in the wcf service
var yourData=HttpContext.Current.Application["data"];

Categories

Resources