Azure Concurrency Boost? - wcf

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.

Related

How to set up Redis in custom namespace as cache and MQ on ServiceStack web application using Structuremap

I want to set up my application to use Redis as Cache for sessions etc as well as run my Message Queues.
My application is a ASP.net MVC website along with ServiceStack based Json service provider. What is the optimal way to configure?
I want to be able to pass an IMessageQueueClient into my service classes and controllers so that I can add tasks to the queue.
I'm getting somewhat lost over what scope to make what. My code is as follows:
//Redis Client Manager
var pooledClientManager = new PooledRedisClientManager(ConfigurationManager.AppSettings.Get("RedisServer"));
pooledClientManager.NamespacePrefix = "myApp-";
For<IRedisClientsManager>().Singleton().Use(x => pooledClientManager);
//Cache
For<ICacheClient>().Use(c => c.GetInstance<IRedisClientsManager>().GetCacheClient());
//MQ
MyApplication.MqService = new RedisMqServer(pooledClientManager);
For<IMessageQueueClient>().Singleton(). Use(
x => MyApplication.MqService.CreateMessageQueueClient());
For<IMessageService>().Singleton().Use(x=>MyApplication.MqService);
I then later on call MyApplication.MqService.RegisterHandler(etc etc);
This works but I'm not convinced I've got my scoping correct.
The Namespace prefix doesn't work, and I need this feature.
Thanks for your help with this!
The NamespacePrefix is only for internal data-structures maintained by the RedisClients and doesn't affect user-specified keys.

Can WCF connection throttling be changed at runtime?

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.

WCF Comet Implementation

I have a requirement that needs a real-time updates on the Web client (ASP.NET MVC). The only way I can turn around on it is that to implement the COMET technique (ServerPush/Reverse-AJAX) technique.
The scenario is that:
User A save a message in different website client. Then, User B will automatically get the updates made by User "A" in different browser.
I actually finish the solution by this Architecture:
ASP.NET MVC - did a jquery ajax (post) request (long-pooled) on the WCF.
WCF - do some polling on the database (SQL Server) with the interval of 1 second. If new data has been added to the database, the polling is break with the data being returned on the client.
WCF COMET Method Pseudo Code:
private Message[] GetMessages(System.Guid userID)
{
var messages = new List<Message>();
var found = false;
/* declare connection, command */
while (!found )
{
try
{
/* open connection - connection.Open(); */
/* do some database access here */
/* close connection - connection.Close(); */
/* if returned record > 0 then process the Message and save to messages variable */
/* sleep thread : System.Threading.Thread.Sleep(1000); */
found = true;
}
finally
{
/* for sure, incase of exception */
/* close connection - connection.Close(); */
}
}
return messages.ToArray();
}
My concern and question is: Is it the best approach to do the polling technique in WCF (with 1 second interval)?
Reason: I maximized the use of database connection pooling and I am expecting that there is no issue on that technique.
Note: This is a multi-threaded implementation with the use of WCF given attributes below.
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall), ConcurrencyMode = ConcurrencyMode.Multiple, UseSynchronizationContext = true)]
I'd recommend using a dedicated realtime server (i.e. don't host the WCF service in IIS) or using a hosted service for realtime updates. As Anders says, IIS isn't all that great at handling multiple long-running concurrent requests.
I'd also suggest you look at using a solution which uses WebSockets with support for fallback solutions such as Flash, HTTP streaming, HTTP long-polling and then possibly polling. WebSockets are the first standardised method of full duplex bi-directional communication between a client and a server and will ultimately deliver a better solution to any such problems.
For the moment implementing your own Comet/WebSockets realtime solution is definitely going to be a time consuming task (as you may have already found), especially when building a public facing app where it could be accessed by users with a multitude of different browsers.
With this in mind the XSockets project looks very interesting as does the SuperWebSocket project.
.NET Comet solutions I know of are from FrozenMountain have a WebSync server for IIS. There is also PokeIn.
I've compiled a list of realtime web technologies that may also be useful.
nstead of polling the database cant you have an event sent when updating instead? Thats the way I've implemented Pub/Sub scenarios anyway and it works great.

How to Improve WCF Data Services Performance

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)

How can I change EndPoint address in WCF?

I have a client app and a server app.
The client calls a wcf service and passes machine information
to server , based on the machine name the server calls back a wcf service on client side.
So to achieve this , I am just changing the EndPointAddress but then it's throwing
NoEndPointFoundException , how can i fix it , below is the code :
public void RegisterTasks(MachineConfig machineInfo)
{
string add = exeProxy.Endpoint.Address.Uri.Scheme + "://" + machineInfo.MachineName.Trim()+"/"
+ exeProxy.Endpoint.Address.Uri.Segments[1];
Uri uri = new Uri(add);
EndpointAddress eadd = new EndpointAddress(add);
WSHttpBinding whttpBinding = new WSHttpBinding(SecurityMode.None);
//ServiceReference1.ExecuteTaskClient newProxy = new ExecuteTaskClient(whttpBinding , eadd);
//EndpointAddress endPointAddress = ;
exeProxy.Endpoint.Address = eadd;
//exeProxy.Endpoint.Binding = new System.ServiceModel.BasicHttpBinding("httpBinding");
// we just execute the task by
// calling the wcf service on client side
foreach (Task task in machineInfo.Tasks)
{
exeProxy.ExecuteTask(task.TaskID);
// newProxy.ExecuteTask(task.TaskID);
}
}
I am assuming that you are getting EndpointNotFoundException not NoEndPointFoundException. I could not find a reference to NoEndPointFoundException.
http://msdn.microsoft.com/en-us/library/system.servicemodel.endpointnotfoundexception.aspx
What this is saying is that the client cannot find the server. In your case the server is trying to call back to the client, so the roles are reversed.
There are two things that could be wrong:
the url that you have in the variable "add" is incorrect (try logging the value)
the wcf service on the client side is not listening on the correct url (try putting the url in a browser)
Hope this helps
Shiraz
My first impression is that your design should be reconsidered. Any time I see an ingenious (read: bizarre) solution I see a whole heap of head banging in the making.
So firstly, write out what it is that you are trying to acheive in baby speak: "I want client to be contacted when server has new data." and then think about how it can be acheived using more conventional techniques.
Check out the duplex bindings - and polling a stateful singleton is not always a bad idea if you're not scaling into thousands of clients -- in fact, I bet it'd scale better than your current design.
But, to solve your current design issue, I'd setup the client (which will become the server) with the MEX endpoint (mexHttpBinding) and then set it off so its listening, then use VS (an empty project or from the server project) to try and connect to the client(server) by way of Add Service Reference and supplying the local machine name etc. This alone might turn up your problem. Then once added, you can use the autogen app.config to know what settings you need.
Also, have you considered how the server will be able to call the client if the server doesn't have the proxy classes setup?
It does sound like you're making a rod for your own back.