Software Engineering Stack Exchange is a question and answer site for professionals, academics, and students working within the systems development life cycle. It only takes a minute to sign up. As per the blog post, if we dispose the HttpClient after every request it can keep the TCP connections open. This can potentially lead to System. The correct way as per the post is to create a single instance of HttpClient as it helps to reduce waste of sockets.
If we share a single instance of HttpClient then we can reduce the waste of sockets by reusing them:. I have always disposed HttpClient object after using it as I felt this is the best way of using it. But this blog post now makes me feel I was doing it wrong all this long. Should we create a new single instance of HttpClient for all requests?
Are there any pitfalls of using static instance? It seems like a compelling blog post. However, before making a decision, I would first run the same tests that the blog writer ran, but on your own code. I would also try and find out a bit more about HttpClient and its behavior. This post states:. An HttpClient instance is a collection of settings applied to all requests executed by that instance.
In addition, every HttpClient instance uses its own connection pool, isolating its requests from requests executed by other HttpClient instances. So what is probably happening when an HttpClient is shared is that the connections are being reused, which is fine if you don't require persistent connections.
The only way you're going to know for sure whether or not this matters for your situation is to run your own performance tests. If you dig, you'll find several other resources that address this issue including a Microsoft Best Practices articleso it's probably a good idea to implement anyway with some precautions.
I mean, if reusing HttpClient is intended and doing so is importantsuch advocate is better documented in its own API documentation, rather than being hidden in lots of "Advanced Topics", "Performance anti pattern" or other blog posts out there.
How to Find and Check Number of Connections to a Server
Otherwise how is a new learner supposed to know it before it is too late? As of now Maythe first search result when googling "c httpclient" points to this API reference page on MSDNwhich does not mention that intention at all.
Well, lesson 1 here for newbie is, always click the "Other Versions" link right after the MSDN help page headline, you will probably find links to the "current version" there.
In this HttpClient case, it will bring you to the latest document here containing that intention description. I suspect many developers who was new to this topic did not find the correct documentation page either, that's why this knowledge is not widely spread, and people were surprised when they found it out laterpossibly in a hard way.
I believe that comes down to an unspoken mis? By definition, IDisposable is merely a mechanism to allow you to release unmanaged resources. Nothing more. It is therefore your job to properly choose when to trigger the disposal, base on your real object's life cycle requirement. There is nothing stopping you from using an IDisposable in a long-lived way:. In practice, it is not a big deal to leak only one connection open after your entire program ends, and the blog poster still see a performance gain after the fix; but still, it is conceptually incorrect to blame IDisposable and choose to NOT dispose it.
Based on the understanding of the previous section, I think the answer here becomes clear: "not necessarily". It really depends on how you organize your code, as long as you reuse an HttpClient AND ideally dispose it eventually.That requires of HttpClient to be able to mimic mis- behavior of widely used web browsers; support flexible and configurable level of leniency toward non-critical protocol violations especially in those gray areas of the specification subject to different, at times conflicting, interpretations; apply a different set of parameters to individual HTTP methods, hosts, or client instances using common interface.
All major components of the HttpClient toolkit agents, host configurations, methods, connections, connection managers contain a collection of HTTP parameters, which determine the runtime behavior of those components. If a particular parameter value has not been explicitly defined in the collection itself, its value will be drawn from the upper level collection of parameters.
When resolving a parameter HttpClient uses the following algorithm: start parameter lookup from the lowest level at which this parameter applies if the parameter is undefined at the current level, defer its resolution to the next level up in the hierarchy return parameter value from the lowest level in the hierarchy the parameter defined at return null if the parameter is undefined.
This architecture enables the users to define generic parameters at a higher level for instance, at the agent level or host level and selectively override specific parameters at a lower level for instance, at the method level.
Whenever a parameter is not explicitly defined at a given level, the defaults of the upper levels will apply. Defines whether responses with an invalid Transfer-Encoding header should be rejected. Defines whether the content body sent in response to HEAD request should be rejected.
Sets period of time in milliseconds to wait for a content body sent in response to HEAD response from a non-compliant server. If the parameter is not set or set to -1 non-compliant response body check is disabled. Activates 'Expect: Continue' handshake for the entity enclosing methods. The 'Expect: Continue' handshake allows a client that is sending a request message with a request body to determine if the origin server is willing to accept the request based on the request headers before the client sends the request body.
The use of the 'Expect: continue' handshake can result in noticeable performance improvement for entity enclosing requests such as POST and PUT that require the target server's authentication. The charset to be used when encoding credentials. If not defined then the value of the 'http. Defines HttpClient's behavior when a response provides more bytes than expected specified with Content-Length header, for example.
Such surplus data makes the HTTP connection unreliable for keep-alive requests, as malicious response data faked headers etc. If this parameter is set to trueany detection of extra input data will generate a warning in the log. Defines the maximum number of ignorable lines before we expect a HTTP response's status code.
Unfortunately, in some cases, this is not possible after the bad response, but only before the next one. So, HttpClient must be able to skip those surplus lines this way. A timeout value of zero is interpreted as an infinite timeout. The method retry handler used for retrying failed methods.
For details see the Exception handling guide. Date patterns used for parsing. The patterns are stored in a Collection and must be compatible with SimpleDateFormat. The maximum buffered response size in bytes that triggers no warning. Buffered responses exceeding this size will trigger a warning in the log. If not set, the limit is 1 MB. The multipart boundary string to use in conjunction with the MultipartRequestEntity. When not set a random value will be generated for each request.
Whenever a parameter is left undefined no value is explicitly set anywhere in the parameter hierarchy HttpClient will use its best judgment to pick up a value.
This default behavior is likely to provide the best compatibility with widely used HTTP servers. This value is used when no socket timeout is set in the HTTP method parameters. Determines whether Nagle's algorithm is to be used.Applications that use HTTP to connect to data resources can use the. The ServicePoint class provides an application with an endpoint to which the application can connect to access Internet resources.
Each ServicePoint contains information that helps optimize connections with an Internet server by sharing optimization information between connections to improve performance. If the application already has a persistent connection to the server www. ServicePointManager is a static class that manages the creation and destruction of ServicePoint instances. The ServicePointManager creates a ServicePoint when the application requests an Internet resource that is not in the collection of existing ServicePoint instances.
ServicePoint instances are destroyed when they have exceeded their maximum idle time or when the number of existing ServicePoint instances exceeds the maximum number of ServicePoint instances for the application. The number of connections between a client and server can have a dramatic impact on application throughput.
By default, an application using the HttpWebRequest class uses a maximum of two persistent connections to a given server, but you can set the maximum number of connections on a per-application basis. The optimum number of connections depends on the actual conditions in which the application runs. Increasing the number of connections available to the application may not affect application performance.
To determine the impact of more connections, run performance tests while varying the number of connections.HTTP connections
You can change the number of connections that an application uses by changing the static DefaultConnectionLimit property on the ServicePointManager class at application initialization, as shown in the following code sample. Changing the ServicePointManager. DefaultConnectionLimit property does not affect previously initialized ServicePoint instances.
You may also leave feedback directly on GitHub. Skip to main content. Exit focus mode. Is this page helpful? Yes No. Any additional feedback? Skip Submit. Send feedback about This product This page. This page. Submit feedback. There are no open issues. View on GitHub.My site was unstable and my clients furious, with a simple fix performance improved greatly and the instability disapeared.
At the same time I actually improved the performance of the application through more efficient socket usage. Microservices can be a bear to deal with.
As more services are added and monoliths are broken down there tends to be more communication paths between services. There are many options for communicating, but HTTP is an ever popular option. If the microservies are built in C or any. I know I did. The using statement is a C nicity for dealing with disposable objects.
Once the using block is complete then the disposable object, in this case HttpClientgoes out of scope and is disposed. The dispose method is called and whatever resources are in use are cleaned up. This is a very typical pattern in. NET and we use it for everything from database connections to stream writers. Really any object which has external resources that must be clean up uses the IDisposable interface.
In fact, the official docs for using state:. As a rule, when you use an IDisposable object, you should declare and instantiate it in a using statement. Secondly, all code you may have seen since…the inception of HttpClient would have told you to use a using statement block, including recent docs on the ASP.
NET site itself. The internet is generally in agreement as well. But HttpClient is different. Although it implements the IDisposable interface it is actually a shared object. This means that under the covers it is reentrant and thread safe. Instead of creating a new instance of HttpClient for each execution you should share a single instance of HttpClient for the entire lifetime of the application. We just print the status code so we know it is working.
The output is going to be:. All work and everything is right with the world. NET Monsters website. Searching for that in the Googles will give you some terrible advice about decreasing the connection timeout. In fact, decreasing the timeout can lead to other detrimental consequences when applications that properly use HttpClient or similar constructs are run on the server. I really must thank Harald S.
If we share a single instance of HttpClient then we can reduce the waste of sockets by reusing them:. Note here that we have just one instance of HttpClient shared for the entire application. Eveything still works like it use to actually a little faster due to socket reuse. Netstat now just shows:.In one of projects which I'm involved in we had to configure the limit for concurrent requests being processed.
The project is quite specific, processing of a request is quite heavy and requires considerable resources. Because of that, when there was a high number of concurrent requests to process, the server was becoming unresponsive. I went on some research for best practices in this area. The "stress your server and see" seems to be the best advice but number of possible different approaches got me interested.
In order to satisfy my curiosity I've decided to implement couple of them myself.
Subscribe to RSS
Limiting concurrent requests is a server responsibility, there shouldn't be a need for application to handle it. This is one of reasons for suggestion from the ASP.
Despite that here I'm implementing a middleware. This is not that bad, registering such middleware at the beginning of the pipeline should prevent heavy processing early enough. Still I'm doing this just for fun, don't do it in production unless you have an unquestionable reason to do so. For the testing purposes I've decided to set up couple integration tests using XUnit and Microsoft.
The general setup is very well described in documentation.
As I intended to spawn multiple requests I wanted to have some rough timings captured for them, so I've prepared following extension method. This is not perfect the timings have risk of not being accurate but should be good enough. I also wanted to have easy access to status code and timing during debugging so I've introduced another intermediate representation.
The MaxConcurrentRequestsOptions class empty at this point will be used for controlling the behavior of the middleware. The Startup looks like this to simulate long request processing :.
This by providing different configuration and concurrentRequestsCount will allow me to test different approaches I'm going to play with. The first and most important thing which middleware needs to support is a hard limit. The functionality is very simple in theory, if the application is processing maximum number of concurrent request every incoming request should immediately result in Service Unavailable.
The challenge hides in maintaining the count of concurrent requests. It must be incremented and decremented in a thread safe way while affecting performance as little as possible. The Interlocked class with its atomic operations for shared variables seems perfect for the job. I've decided to use the Interlocked. CompareExchange "do-while pattern" for check and increment which should ensure that value will not be exceeded.
After adding the middleware to the pipeline I've set up a test with 30 concurrent requests and 10 as MaxConcurrentRequestsOptions. The result is best observed through responseInformation temporary value.
There are 10 requests which resulted in OK and 20 requests which resulted in Service Unavailable red frames - the desired effect. The hard limit approach gets the job done, but there are more flexible approaches. In general they are based on assumption that the application can cheaply store more requests in memory than it's currently processing and client can wait for the response a little bit longer.This one has been on my list to complete for quite a while.
I want to cover something pretty important which happened in. NET Core 2. NET Core since 2. This supports the use of a single HttpClient instance which reduces the chances of socket exhaustion whilst ensuring connections re-connect periodically to reflect DNS changes.
HttpClient initially started its life as a NuGet package which could optionally be included in. NET Framework 4. This was built on top of the pre-existing HttpWebRequest implementation. Rolling forward. NET Core 1. This first version was limited to a much smaller API surface than was available in. NET Core web applications. An API wich has been available since. HttpClient in. By August it was soon noted that the recommendation to re-use HttpClient instances to prevent socket exhaustion had one quite troublesome side-effect.
In this issue, it was acknowledged that re-using a single HttpClient instance would result in connections remaining open indefinitely and as a result, DNS changes may either cause a request failure or communication with outdated endpoints. NET Standard 2. This sits on top of the HttpClient implementation, the reverse of how this works in. ServicePoint was also added, although much of its API surface is either not implemented throwing a PlatformNotSupportedException or having no implementation, nor effect.
This problematic behaviour led to two pieces of work from team different teams. The ASP. NET team started working on the Microsoft.
Http package, of which the primary feature is IHttpClientFactory. This opinionated factory for HttpClient instances also includes lifetime management of the underlying HttpMessageHandler chains.
If you want to read more about this feature, you can review my series of blog postswhere I cover this extensively. In the same timeframe, the. NET team were working on a solution of their own.In my last postwe implemented the rate limiting for an API endpoint on the server side. On the client sidethe API consumers then should throttle the rate of concurrent HTTP requests in order to comply with the rate limits of the endpoints and moderate the usage of client side resources.
This post will go over how to make concurrent outgoing HTTP requests on the client side. The goal is to let the HTTP Client send concurrent requests at the maximum allowed rate which is set by the server, for example, at a maximum rate of 2 requests per second. We will use a semaphore in C to limit the maximum concurrent tasks.
The demo project is a. NET Core 2. The full project is located in this GitHub repository. For demo purposes, we are going to create a small. NET Core Console app. Two necessary NuGet packages are Microsoft. DependencyInjection and Microsoft.
The first one allows us to take advantage of the DI system, and the second one provides the HttpClient. We modify the Main method as below. Notice that this Main method returns a Task in async mode, which requires us to configure the project to build with a C version of 7.
Lines 3 to 5 register all dependencies and build a service provider. Then we can use the service provider to resolve dependencies for the services we want to use. Line 9 then instructs the ThrottledHttpClient instance to issue requests against an API endpoint with a list of numbers as query parameters.
In the end, lines 10 to 13 print out the results. We now have a bare-bones program to let an HttpClient make requests. We want to throttle concurrent HTTP requests not only because of the rate limit policies enforced by API providers, but also because of resource allocation optimization. A high volume network traffic may obstruct the network bandwidth and deteriorate the computing power.
Therefore, we will need some mechanisms to dispatch asynchronous tasks in order to limit the number of concurrent HTTP requests within any given time period. There are several ways to throttle concurrent tasks. A semaphore in C is often compared to a bouncer in a night club, whose responsibility is to only allow a certain number of people step into the club at a point of time.
By default, a semaphore only takes care of the maximum number of concurrent requests at a point of time. In the case we are discussing here, we need to add a second dimension: the time period.