I have a WCF web service that has ServiceThrottlingBehavior configured at startup, the code for which looks something like this:
'config service throttling
If objWSParams.bUseServiceThrottling Then
Dim stb As New ServiceThrottlingBehavior
stb.MaxConcurrentSessions = 100 '1-1000
stb.MaxConcurrentCalls = 100 '1-1000
stb.MaxConcurrentInstances = 100 '1-1000
ServiceHost.Description.Behaviors.Add(stb)
End If
My architects and I are talking about making our web service more "load dynamic" so that performance settings can be adjusted based on load.
Does anyone know if ServiceThrottlingBehavior can be reset at runtime, or does the service have to be restarted before changes kick in?
The answer is, unfortunately, No. According to MS, the ServiceThrottlingBehavior can only be set on startup and cannot be changed during runtime. This, of course, means that dynamically managing the web service as conditions change on the server is impossible unless you want to take your web service offline on a regular basis.
Disappointing.
Related
We have a WCF service called service1 hosted in IIS.
We are creating another WCF service, say, service2, which will always be running in the background and will monitor if a file, say, X, is having enough data that has to be consumed by Service1.
If the file X is not having enough data then service2 will call another component which will load the data to the file.
So please suggest a hosting technique for service2 which fulfils all the above requirements and should be independent, i.e if the service2 is down, it should not impact service1 or vice versa. Both these services are a part of the same app-domain.
We have one scenario where we hosted the same as a window service. Now we are looking to try something else.
Please provide your valuable suggestions.
You're looking for the right kind of screwdriver to hammer a nail. 8-)
WCF services run on demand, based on network activity (a request comes in, the service runs and handles the request). However after a defined period with no activity the service shuts down and the resources are released, and the server waits for the next request, however the existence of a file containing the data you want does not create this type of request.
What you need is a Windows Service (the things that you see in the Services Control Panel). These run continuously and are appropriate for tasks that don't produce network requests, like monitoring to see if you have the data you need.
We have one scenario where we hosted the same as a window service. Now we are looking to try something else.
There really isn't anything else suitable for unattended operation. Windows Services are designed exactly for this type of task, while WCF Services aren't.
Apart from your hosting requirement you should also consider using a FileSystemWatcher if you haven't done so already. You would obviously have to add your own logic to meet your requirements.
Basic example:
protected override void OnStart(string[] args)
{
FileSystemWatcher Watcher = new FileSystemWatcher("some file path");
Watcher.EnableRaisingEvents = true;
Watcher.Changed += new FileSystemEventHandler(Watcher_Changed);
}
// This event is raised when a file is changed
private void Watcher_Changed(object sender, FileSystemEventArgs e)
{
// your code here
}
More complete example:
http://www.rhyous.com/2012/11/27/c-creating-a-service-to-monitor-a-directory/
I am trying to create a simple OWIN/Katana - hosted web service, resident in an Azure Worker Role. I expect high concurrency situations to arise,and am trying to figure out how to increase things like the HTTP.Sys queue limit and make other configuration changes that boost concurrency (like max concurrent instances in WCF).
All ideas appreciated.
Thanks.
I believe you are looking for throttling the selfhost katana. For katana selfhost you can throttle the underlying HttpListener by using the following way:
public class Startup
{
public void Configuration(IAppBuilder app)
{
var owinHttpListener = (OwinHttpListener)app.Properties["Microsoft.Owin.Host.HttpListener.OwinHttpListener"];
//Default for maxAccepts = 5 * ProcCount
//Default for maxRequests = Int32.MaxValue;
owinHttpListener.SetRequestProcessingLimits(x, y);
//Your OWIN pipeline here...
}
}
Configuration changes to the machine level config values, IIS values and what not can be accomplished for both Web and Worker roles by using start up tasks. Specifically you should be able to use appcmd.xe to set the change for the HTTP.sys queue limit (Note, I've not tried it personally, but if you use a start up command with elevated rights I don't see why it wouldn't work).
Example (for 2008, 2012 should be similar I'd think):
appcmd.exe set config /section:serverRuntime /appConcurrentRequestLimit:<#of users * 1.5>.
Docs for appcmd.exe command line: Modifying the ASP.NET queue length limit
Note that this can be tricky depending on what you are trying to accomplish, so check out this other MS documentation on the subject.
I have a WCF service which need to initialize some expensive resources used for all incoming calls. Firstly I used a static variable to record its status, but the variable was reset on every call. Then I used a static service constuctor to init, but it got called on every incoming call. I tried to set InstanceContextMode to Single and PerSession, but neither of them worked.
Any ideas?
Setting your InstanceContextMode to Single is definitely the way to go if you need access to these resources across ALL calls to the service. What probably happened (just a guess) is your worker process is getting recycled, resulting in your initialization code have to run again when a new worker process is started. If that is what is happening, then take a look at this document to configure your application pool to use auto-start.
http://msdn.microsoft.com/en-us/library/ee677260.aspx
If this doesn't help then some additional details on how/where your initialization code is implemented would be helpful.
I’ve a WCF service which is used to get some data from my database. Size of database is very large approximately 2 GB. So I cache this data. I want when service host this data should be cached so I firstly used
InstanceContextMode = InstanceContextMode.Single
This Service Behviors allows me that I can simply write caching code in service constructor, as constructor will only be invoked when servicehost.open (); method call. Whenever client will call this service through proxy constructor will not invoked. This works very fine. Later I realized that this InstanceContextMode has performance issue when 1000 users call this service at a time, because only single instance of this service serves the all requests. To get maximum performance I changed my settings to
InstanceContextMode = InstanceContextMode.PerCall
with
ConcurrencyMode = ConcurrencyMode.Multiple
Now I want to get the same caching feature that is when service host data would be cached. Please help me to solve this problem.
Please do let me know either through CustomBehaviors I can achieve this?
Regards,
Rizwan
Combination of InstanceContextMode.PerCall with ConcurrencyMode.Multiple doesn't make sense. PerCall instancing creates new service instance for each request. Multiple concurrency mode allow service instance to handle multiple parallel requests. How can service instance which is created only to handle single request (PerCall) be used to handle parallel requests (Multiple)?
I think the problem which occured by calling your singleton service (I believe that you also used ConcurrencyMode.Multiple) with 1000 concurrent users is simply based on the fact that server doesn't have performance to deal with so many concurrent users or the service code / caching is not optimized. This will not be solved by using PerCall instancing.
Anyway if you want to share some cache among multiple PerCall instances of the service you have to create some well known object representing your cache - use singleton pattern or service locator. This object will handle caching and concurrent access from service instances.
I'm new to WCF Data Services so I've been playing. After some initial tests I am disappointed by the performance of my test data service.
I realize that because a WCF DS is HTTP-based there is overhead inherent in the protocol but my tests are still way slower than I would expect:
Environment:
All on one box: Quad core 64-bit laptop with 4GB RAM running W7. Decent machine.
Small SQL database (SQLExpress 2008 R2) with 16 tables... the table under test has 243 rows.
Hosted my test service in IIS with all defaults.
Code:
I've created a Entity Framework model (DataContext) for this database (stock codegen by VS2010).
I've created a data-service based on this model.
I've created a client which has a direct service reference (ObjectContext) for this service (stock codegen by VS2010)
In the client I am also able to call the EF model directly and also use Native SQL (ADO.NET SqlConnection)
Test Plan:
Each iteration connects to the database (there is an option to reuse connections), queries for all rows in the target table ("EVENTS") and then counts them (thus forcing any deferred fetches to be performaed).
Run for 25 iterations each for Native SQL (SqlConnection/SqlCommand), Entity Framework (DataContext) and WCF Data Services (ObjectContext).
Results:
25 iterations of Native SQL: 436ms
25 iterations of Entity Framework: 656ms
25 iterations of WCF Data Services: 12110ms
Ouch. That's about 20x slower than EF.
Since WCF Data Services is HTTP, there's no opportunity for HTTP connection reuse, so the client is forced to reconnect to the web server for each iteration. But surely there's more going on here than that.
EF itself is fairly fast and it's the same EF code/model is reused for both the service and the direct-to-EF client tests. There's going to be some overhead for Xml serialization and deserialization in the data-service, but that much!?! I've had good performance with Xml serialization in the past.
I'm going to run some tests with JSON and Protocol-Buffer encodings to see if I can get better performance, but I'm curious if the community has any advice for speeding this up.
I'm not strong with IIS, so perhaps there are some IIS tweaks (caches, connection pools, etc) that can be set to improves this?
Consider deploying as a windows service instead? IIS may have ASAPI filters, rewrite rules, etc that it runs through. even if none of these are active, the IIS pipeline is so long, something may slow you down marginally.
a service should give you a good baseline of how long it takes the request to run, be packed, etc, without the IIS slowdowns
The link below has video that has some interesting WCF benchmarks and comparisons between WCF data services and Entity Framework.
http://www.relationalis.com/articles/2011/4/10/wcf-data-services-overhead-performance.html
I increased performance of our WCF Data Service API by 41% simply by enabling compression. It was really easy to do do. Follow this link that explains what to do on your IIs server: Enabling dynamic compression (gzip, deflate) for WCF Data Feeds, OData and other custom services in IIS7
Don't forget to iisReset after your change!
On the client-side:
// This is your context basically, you should have this code throughout your app.
var context = new YourEntities("YourServiceURL");
context.SendingRequest2 += SendingRequest2;
// Add the following method somewhere in a static utility library
public static void SendingRequest2(object sender, SendingRequest2EventArgs e)
{
var request = ((HttpWebRequestMessage)e.RequestMessage).HttpWebRequest;
request.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
}
Try setting security to "none" in the binding section in the configuration. This should make big improvement.
In order to eliminate most of the connection overhead you can try to batch all operations to the WCF DS to to see if that makes a significant difference.
NorthwindEntities context = new NorthwindEntities(svcUri);
var batchRequests =
new DataServiceRequest[]{someCustomerQuery, someProductsQuery};
var batchResponse = context.ExecuteBatch(batchRequests);
For more info see here.
WCF DataServices are for providing your disparate clients with OpenData protocol; so as you don't have to write/refactor multiple web service methods for each change request. I never advise it to be used if the entire system is microsoft technology stack based. It's meant for remote clients.
How do you pass those 25 iterations for WCF?
var WCFobj = new ...Service();
foreach(var calling in CallList)
WCFobj.Call(...)
If you call like that it means you call WCF 25 times, which consumes too many resources.
For me, I used to build up everything into a DataTable and user table name to stored procedure I'm calling; DataRow is params. When calling, just pass the DataTable in encrypted form by using
var table = new DataTable("PROC_CALLING")...
...
StringBuilder sb = new StringBuilder();
var xml = System.Xml.XmlWriter.Create(sb);
table.WriteXml(xml);
var bytes = System.Text.Encoding.UTF8.GetBytes(sb.ToString());
[optional]use GZip to bytes
WCFobj.Call(bytes);
The thing is you pass all 25 calls at once, that can save performance significantly. If the return object is same structure, just pass it as DataTable in bytes form and convert it back to DataTable.
I used to implement this methods with GZip for import/export data modules. Passing large amount of bytes is going make WCF unhappy. Its depends whatever you want to consume; computing resources or networking resources.
things to try:
1) results encoding: use binary encoding of your WCF channel if possible, see http://msdn.microsoft.com/en-us/magazine/ee294456.aspx -- alternately use compression: http://programmerpayback.com/2009/02/18/speed-up-your-app-by-compressing-wcf-service-responses/
2) change your service instance behavior, see http://msdn.microsoft.com/en-us/magazine/cc163590.aspx#S6 -- try InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode=ConcurrencyMode.Multiple - if you can verify that your service is built in a thread safe way.
Regarding your benchmark, I think you should simulate more realistic load (including concurrent users) and ignore outliers, the first request to IIS will be really slow (it has to load all the DLLs)