Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

What are the considerations for the use of HttpClient in C #

2025-02-24 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/01 Report--

Editor to share with you what to pay attention to the use of HttpClient in C#, I believe that most people do not know much about it, so share this article for your reference, I hope you can learn a lot after reading this article, let's go to know it!

Recently, we are testing a third-party API, ready to integrate into our website application. The call to API uses HttpClient in .NET. Because this API will be used in critical business, it has strict requirements on the overall response speed of calling API, so it pays special attention to HttpClient.

At the beginning of the test, only a http post request was sent with PostAsync on the client side through HttpClient. During the test, it was found that the total time from creating the HttpClient instance to issuing the request to reading the response data to the server was about 2s, and this was true for many tests. Of course, the response speed of 2s is unacceptable, and we want to at least keep it within 100ms. So he began to trace the cause of the problem.

The time spent on the server side of the request is included in the returned data of the API, which is within the 20ms, and the problem has nothing to do with the server API. So the skeptical point is put on the network delay, but the response time of the ping server is around 10ms, and the possibility of network delay is not great.

When we were about to test in a different network environment, it suddenly occurred to us that there was something wrong with our testing method. We only sent a PostAsync request through HttpClient. If there is some kind of warm-up mechanism when HttpClient is called for the first time (such as in EF), most of the total 2s time now may be spent on HttpClient warm-up.

So modify the test code, change the call from 1 to 100, and then suddenly realize that only the first time is 2s, and the next 99 times are all within 100ms. Sure enough, some kind of warm-up mechanism of HttpClient is doing something wrong!

Now that we know the reason for the HttpClient warm-up mechanism, we can help HttpClient warm up and reduce the time spent on the first request. We have tried a warm-up method by sending a http post request before sending a http head request, as follows:

_ httpClient.SendAsync (new HttpRequestMessage {Method = new HttpMethod ("HEAD"), RequestUri = new Uri (BASE_ADDRESS + "/")}) .Result.EnsureSuccessStatusCode ()

After testing, through this warm-up method, the time of the first request can be reduced from about 2s to less than 1s (the test result is more than 700ms).

After knowing the truth that the first HttpClient request took 2 seconds, we turned to the remaining 99 requests that took less than 100ms, and found that most of the requests were above 50ms. Is it possible to bring it below 50ms? Moreover, there has always been a struggle: does it have to be Dispose () on HttpClient for each call? Do you want to make HttpClient singleton or static (declared as a static variable)? Take this opportunity to study together.

Behind HttpClient, there is something that can't be ignored about the speed of response to requests-- TCP connections. A HttpClient instance will associate a TCP connection, and when Dispose the HttpClient, the TCP connection will be closed (this is also verified by using Wireshark for network packet capture).

In the previous test, every time we sent a request with HttpClient, we created a new HttpClient instance and Dispose it as follows:

Using (var httpClient = new HttpClient () {BaseAddress = new Uri (BASE_ADDRESS)}) {httpClient.PostAsync ("/", new FormUrlEncodedContent (parameters));}

Therefore, each request needs to go through a new TCP connection-> send data-> close a connection (commonly known as a short connection), and to make matters worse, the request uses https. Establishing a TCP connection requires a key exchange process based on public and private key encryption and decryption: Client Hello-> Server Hello-> Certificate-> Client Key Exchange-> New Session Ticket.

If we want to reduce the request response time below 50ms, we have to start from this place-- reuse TCP connections (commonly known as long connections). To achieve a persistent connection, the first thing we need is not to close the TCP connection after the first request of HttpClient (without calling the Dispose method); for subsequent requests to continue to use this unclosed TCP connection, we have to use the same HttpClient instance; and to use the same HttpClient instance, we have to implement the singleton or static of HttpClient. Of the previous three problems, the latter two have no choice because of the need to solve the first one.

To achieve a persistent connection, we change the calling code for HttpClient to look like this:

Then test the request response time:

Elapsed:750ms

Elapsed:31ms

Elapsed:30ms

Elapsed:43ms

Elapsed:27ms

Elapsed:29ms

Elapsed:28ms

Elapsed:35ms

Elapsed:36ms

Elapsed:31ms

....

Except for the first request, the vast majority of the next 99 requests are within 50ms. The effect of TCP long connection is necessary!

The effect of persistent connection is also verified by grabbing packets through Wireshak:

Wireshak grabs the bag

At this time, you

Public class HttpClientTest {private static readonly HttpClient _ httpClient; static HttpClientTest () {_ httpClient = new HttpClient () {BaseAddress = new Uri (BASE_ADDRESS)}; / / warm up HttpClient _ httpClient.SendAsync (new HttpRequestMessage {Method = new HttpMethod ("HEAD"), RequestUri = new Uri (BASE_ADDRESS + "/")}) .Result.EnsureSuccessStatusCode () } public async Task PostAsync () {var response = await _ httpClient.PostAsync ("/", new FormUrlEncodedContent (parameters)); return await response.Content.ReadAsStringAsync ();}}

The question may arise: is there a thread safety problem when HttpClient is declared as a static variable? We had the same question at the time, and later found the answer on stackoverflow:

As per the comments below (thanks @ ischell), the following instance methods are thread safe (all async):

CancelPendingRequests

DeleteAsync

GetAsync

GetByteArrayAsync

GetStreamAsync

GetStringAsync

PostAsync

PutAsync

SendAsync

All of HttpClient's asynchronous methods are thread-safe and are safe to use.

At this point, is the question of HttpClient coming to a perfect end?. Wait a minute, there's one more question.

Although the client maintains a TCP connection, but the TCP connection is a matter for the couple, what about the server side? If you don't tell the server, how does the server know that you want to keep the TCP connection all the time? For clients, maintaining a TCP connection is not expensive, but for a server, it is completely different. If you keep an TCP connection by default, you have to keep thousands of clients connected. Therefore, the general Web server will decide whether to maintain the TCP connection according to the client's request, which is the reason for the existence of keep-alive.

So, we also need to add a request header for Connection:keep-alive to HttpClient as follows:

_ httpClient.DefaultRequestHeaders.Connection.Add ("keep-alive")

Now it's finally over. But it is definitely not perfect, sharing is just the process of solving the problem.

The above is all the contents of the article "what are the precautions for using HttpClient in C#". Thank you for reading! I believe we all have a certain understanding, hope to share the content to help you, if you want to learn more knowledge, welcome to follow the industry information channel!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report