How to change the connection limit of a HttpWebRequest/Response during program execution - c#

Is there a way to change the the number of connections allowed for a HttpWebResponse/Request during execution? I understand how to initially set this value on program start however changing the defaultConnectionLimit of the Service point manager class doesn't work once the program is executing.
Thanks for any guidance!

Looking over some more material online I was able to come up with a solution that works for me. In order to change the connection limit during execution you cannot use
ServicePointManager.DefaultConnectionLimit = number
This is partially because once the connection first goes through trying to use the previous line to change it will work as the connection with a limit to your host has already been established with a default limit, but after this point will not work as it'll only change new connections that need a new default limit.
You can however use
ServicePoint tmp = ServicePointManager.FindServicePoint(hostUri);
tmp.ConnectionLimit = updatedNumberOfConnections;

Related

Axis2 Client Connection Issue

I have a java(axis2 1.4.1 client) component in Middleware which consumes a web service hosted in another application. I'am facing some issues in it.
Please find the code snippet below
ConfigurationContext configContxt;
MultiThreadedHttpConnectionManager connxMgr = new MultiThreadedHttpConnectionManager();
HttpConnectionManagerParams params = connxMgr.getParams();
params.setDefaultMaxConnectionsPerHost(50);
params.setMaxTotalConnections(50);
connxMgr .setParams(params);
HttpClient client = new HttpClient(connxMgr);
configContxt.setProperty(HTTPConstants.REUSE_HTTP_CLIENT, "True");
Please help to clarify the below queries:
Whenever a new request comes in, a new connection is getting created. This can be confirmed by doing netstat -a|grep <<provider URI>>.
When we were using axis2 1.3v client earlier there was no new connection created, please clarify why this is creating a new connection while using axis2 1.4.1?
To prevent this, I have set REUSE_HTTP_CLIENT property in ConfigurationContext to TRUE. So this will reuse the existing (already established) connection to the server.
I have set the setDefaultMaxConnectionsPerHost and setMaxTotalConnections as 50. When I do the load test from SoapUI by triggering 50 requests, only 3 connections were created. Later I increased to 200 requests, but still the connections count didnt exceed 3.
Am not sure why it is not able to serve with only one connection (since reuse property is used) and also why the number of connections did not gradually increase with the number of requests (3 connx for 50 requests and again same 3 connx for 200 requests)
How will the reuse propery (HTTPConstants.REUSE_HTTP_CLIENT) behave?
How many transactions can be done per connection concurrently while using REUSE_HTTP_CLIENT property in the code?
Another Issue is that I have set the closeIdleConnections with the timeout of 30 secs. httpClient.getHttpConnectionManager().closeIdleConnections(30000);
Even this is not working. The unused connections are closed only after 5 mins. I just want to know If there could be some property set at server side which overriding this 30 seconds which am setting at client side?
Can someone help me on the above?
The code you have posted creates an HttpClient, but doesn't actually use it anywhere. Therefore it is not surprising that none of the settings you apply on the connection manager has any effect.

How does MongoDB C# Driver's serverSelectionTimeout, SocketTimeout, ConnectTimeout Work?

My goal was to reduce the time it takes until the application stops to try connecting to a server.
This is the solution I am now using:
(It works, but I want to understand more in detail how)
MongoClientSettings clientSettings = new MongoClientSettings()
{
Server = new MongoServerAddress(host, port),
ClusterConfigurator = builder =>
{
//The "Normal" Timeout settings are for something different. This one here really is relevant when it is about
//how long it takes until we stop, when we cannot connect to the MongoDB Instance
//https://jira.mongodb.org/browse/CSHARP-1018, https://jira.mongodb.org/browse/CSHARP-1231
builder.ConfigureCluster(settings => settings.With(serverSelectionTimeout: TimeSpan.FromSeconds(2)));
}
};
I do not understand exactly what SocketTimeout and ConnectTimeout is then used for.
If I make those settings e.g. to 3 seconds, it actually would not make sense for the driver to wait longer then, since it is not expected that anything good can happen after the socket had a timeout?
My theory is that Connect and SocketTimeout affect how long it takes until the the connect to a single server waits, while serverSelectionTimeout is the timeout for the overall process? Is this true?
You might see here in ClusterRegistry.cs that ConnectTimeout is passed to TcpStreamSettings.ConnectTimeout, while SocketTimeout is passed to both TcpStreamSettings.ReadTimeout and TcpStreamSettings.WriteTimeout.
Then in TcpStreamFactory.cs you see how those Read and Write timeouts are used: they are used as NetworkStream.ReadTimeout and NetworkStream.WriteTimeout, when creating stream to read\write data from\to TCP connection.
Now, if we go to documentation of NetworkStream.ReadTimeout we see there:
This property affects only synchronous reads performed by calling the Read method. This property does not affect asynchronous reads performed by calling the BeginRead method.
But in Mongo driver, those network streams are read asynchronously, which means those timeouts do nothing. Same story with NetworkStream.WriteTimeout.
So long story short: SocketTimeout seems to have no effect at all and ConnectTimeout on the other hand is used when doing TCP connection. How exactly it happens you can see in TcpStreamFactory.cs.

MySQL Connector Pooling with many async inserts

I was reading about the MySQL: Using Connector/Net with Connection Pooling. It is suggested to not use a global MySqlConnection object and manually open/close it. Further, it's suggested to use the MySqlHelper instead of working with MySqlCommand objects.
So, assuming I have a CONNECTION_STRING setup, I could do something like:
MySqlHelper.ExecuteNonQuery(CONNECTION_STRING,
#"INSERT INTO `table1` (`col3`,`col4`) VALUES (#col3, #col4 );",
(new List<MySqlParameter>() {
new MySqlParameter("#col3", #"another value"),
new MySqlParameter("#col4", #"some value")
}).ToArray()
);
Now, imagine that I make the above call a few thousand times in async parallel tasks (via TPL).
There's some max allowed connections on my MySQL server, and I start to get exceptions thrown claiming the user had exceeded max connections. I thought the connection pooling was suppose to handle this automatically for me? Isn't the driver suppose to pool and queue them automatically for me?
I have 1500 max connections allowed currently, and I added this in my connection string:
Pooling=True;minimumPoolSize=0;maximumpoolsize=100;
Yet, I still get max connections exceeded. I need some advice with how to handle many async inserts without exploding this max connections limit.
In addition to max_connections, the max_user_connections is what is important here. It can be queried for:
show variables like 'max_user_connections';
To avoid exceeding max connections for your MySQL user you'll need to make sure the maximumpoolsize (in the connection string) is set to something lower than max_user_connections and that other apps are not opening connections with that same user account whose total could exceed the cap. So for example, I could set mine to 5 given I have a cap of 15.
Capping this is very common by most hosting services to limit the resources you are using.
Performing a larger batch of queries in a single connection could also be a viable workaround.
In addition, sometimes hosts limit max_queries_per_hour and other such variables.

Trying to run multiple HTTP requests in parallel, but being limited by Windows (registry)

I'm developing an application (winforms C# .NET 4.0) where I access a lookup functionality from a 3rd party through a simple HTTP request. I call an url with a parameter, and in return I get a small string with the result of the lookup. Simple enough.
The challenge is however, that I have to do lots of these lookups (a couple of thousands), and I would like to limit the time needed. Therefore I would like to run requests in parallel (say 10-20). I use a ThreadPool to do this, and the short version of my code looks like this:
public void startAsyncLookup(Action<LookupResult> returnLookupResult)
{
this.returnLookupResult = returnLookupResult;
foreach (string number in numbersToLookup)
{
ThreadPool.QueueUserWorkItem(lookupNumber, number);
}
}
public void lookupNumber(Object threadContext)
{
string numberToLookup = (string)threadContext;
string url = #"http://some.url.com/?number=" + numberToLookup;
WebClient webClient = new WebClient();
Stream responseData = webClient.OpenRead(url);
LookupResult lookupResult = parseLookupResult(responseData);
returnLookupResult(lookupResult);
}
I fill up numbersToLookup (a List<String>) from another place, call startAsyncLookup and provide it with a call-back function returnLookupResult to return each result. This works, but I found that I'm not getting the throughput I want.
Initially I thought it might be the 3rd party having a poor system on their end, but I excluded this by trying to run the same code from two different machines at the same time. Each of the two took as long as one did alone, so I could rule out that one.
A colleague then tipped me that this might be a limitation in Windows. I googled a bit, and found amongst others this post saying that by default Windows limits the number of simultaneous request to the same web server to 4 for HTTP 1.0 and to 2 for HTTP 1.1 (for HTTP 1.1 this is actually according to the specification (RFC2068)).
The same post referred to above also provided a way to increase these limits. By adding two registry values to [HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings] (MaxConnectionsPerServer and MaxConnectionsPer1_0Server), I could control this myself.
So, I tried this (sat both to 20), restarted my computer, and tried to run my program again. Sadly though, it didn't seem to help any. I also kept an eye on the Resource Monitor (see screen shot) while running my batch lookup, and I noticed that my application (the one with the title blacked out) still only was using two TCP connections.
So, the question is, why isn't this working? Is the post I linked to using the wrong registry values? Is this perhaps not possible to "hack" in Windows any longer (I'm on Windows 7)?
Any ideas would be highly appreciated :)
And just in case anyone should wonder, I have also tried with different settings for MaxThreads on ThreadPool (everyting from 10 to 100), and this didn't seem to affect my throughput at all, so the problem shouldn't be there either.
It is matter of ServicePoint. Which provides connection management for HTTP connections.
The default maximum number of concurrent connections allowed by a ServicePoint object is 2.
So if you need to increase it you can use ServicePointManager.DefaultConnectionLimit property. Just check the link in MSDN there you can see a sample. And set the value you need.
For quicker reference for someone. To increase the connection limit per host you can do this in your Main() or anytime before you begin making the HTTP requests.
System.Net.ServicePointManager.DefaultConnectionLimit = 1000; //or some other number > 4
Fire and forget this method from your main method. Icognito user is correct, only 2 threads are allowed to play at the same time.
private static void openServicePoint()
{
ServicePointManager.UseNagleAlgorithm = true;
ServicePointManager.Expect100Continue = true;
ServicePointManager.CheckCertificateRevocationList = true;
ServicePointManager.DefaultConnectionLimit = 10000;
Uri MS = new Uri("http://My awesome web site");
ServicePoint servicePoint = ServicePointManager.FindServicePoint(MS);
}
For Internet Explorer 8:
Run Registry Editor and navigate to following key HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Internet Explorer\MAIN\FeatureControl\FEATURE_MAXCONNECTION SPERSERVER
and
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Internet Explorer\MAIN\FeatureControl\FEATURE_MAXCONNECTION SPER1_0SERVER
If FEATURE_MAXCONNECTIONSPERSERVER and FEATURE_MAXCONNECTIONSPER1_0SERVER are missing then create them. Now create DWORD Value called iexplore.exe for both sub keys (listed above) and set their value to 10 or whatever number desired.

Fastest way to tell if SQL Server is available

I have a winform program that uses Merge Replication to keep a local SQL Express sync'd with a Central SQL Server on our network. Due to the nature of this app the sync process runs automatically on App open and close. The way I am doing it (below) seems quite time consuming. What would be a faster way?
Thinking outside the box it would probably be okay if I just checked for the Server itself though that could present a hole for an edge case where the Server is available but SQL is down. Alternately, maybe just checking if our domain is available though that could leave the same hole I guess.
Thanks!
private static bool IsSqlAvailable()
{
try
{
var conn = new SqlConnection("Data Source=WWCSTAGE;Initial Catalog=Connect;Integrated Security=True");
conn.Open();
conn.Close();
HUD.IsSQLAvailable = true;
return true;
}
catch (Exception)
{
HUD.IsSQLAvailable = false;
return false;
}
}
As an additional note. The above is particularly slow when off network. I even set the Connection Timeout = 1 and it still sits at this point for quite some time.
My usual advice in this kind of scenario, where you're checking for the existence/connectivity of something that is out of your control is: don't.
Your check can pass and an instant later, the result is no longer true. So just try to do whatever it is you want to do, assuming that the SQL server is available, and handle the inevitable errors gracefully.
I would wrap my Connection in a using clause and probably lower the connection timeout in my connection string (generally, if the server is up, it should connect more quickly than the default), but other than that, it's fine.
I think you can just ask the SQL Server TCP port.
But there is a problem if used named instances.
You may be thinking about this too hard. The availability of your SQL server is essentially equivalent to you being able to connect to it, so I would say your method of trying to open a connection is quite valid. My only suggestion would be to assign HUD.IsSQLAvailable once where you call the method since you are already getting a return value, instead of assigning it twice inside IsSqlAvailable().
I just wrote a test connection method today in an app I am writing at work.
I just use a simple try catch method on just a connection.open and connection.close and catch the exception if it fails. You dont have to set a variable if you dont need it. Just return true or false. It will hang for a few seconds if the connection is going to fail.

Resources