HttpClient optimization combat under high concurrency scenarios

Use HttpClient in the project may be very common, especially in the current situation the micro-fire service, if the service is http call between and ultimately, find http dealings with clients. Depending on the size of the project and the different user scenarios, may not need a lot of time special treatment too. However, we must do some optimization in some high concurrency scenarios.

The project is the company's express courier trajectory query item, the current average level of ten million calls per hour amount. Trajectory inquiries to Oracle as the main data source, Mongodb to spare, when Oracle is not available, the data source is switched to Mongodb. This year rookie team to join, migrate to the primary data aliyun to Hbase main storage. Hbase wherein the data provided by the data query service to resolve the group Http manner. Mongodb original abandoned, the cloud becomes the primary data source data source, Oracle as a backup when data after source switching, the main invocation will become a http ways. the first ran in early October 11 first round of the double pressure test, qps non-compliance. of course, this is a good position, because the track between eleven fake domain groups has been in the test run, then check that the oracle. November holiday to come back, only significant change at this, it is easy to locate problems on the call, but specifically on the cloud Hbase slow, or network transmission problems ( Hbase service on Ali cloud, trajectory query project deployed in IDC room) by cloud services, analytical group and network operation and maintenance of cooperation, identify problems arise in the application. log in to play at Http call service Records and found the following problems:

img

Can be seen from time to time, there will be a lot of time-consuming requests to be significantly higher than the other.

This may cause may be repeated to create HttpClient destruction caused due to the pin, the first rule of thumb may be on HttpClient operation performed Dispose (Using (HttpClient client = new HttpClient) {...})

If you install some third-party plug-ins, when you write HttpClient not Using surrounded reconstruction will give suggestions, recommendations or manually add Using dispose. In practice, however whether or not to dispose even as the case may be, for the average project it feels may be without no big problem, but also added a still ok. but the actual project, is generally not recommended to re-create the object repeatedly about whether HttpClient need Dispose see here

In answer to this question, the questioner pointed out some examples of Microsoft is no use using the following answers indicate a relatively hot HttpClient life cycle of the application life cycle and should be consistent, as long as the application requires Http request, do not apply to Dispose it off. the following is still a relatively hot responded by noting that in general, the object with the Dispose method should be dispose off, but HttpClient is an exception.

While these are combined with his experience gives everyone a suggestion for a possible puzzling question, in fact, for the average project, with or without Dispose will not cause a big problem. The problem with the above-mentioned article also HttpClient It does not matter, because Http client program used is based on HttpWebRequestthe package.

Troubleshooting and Optimization

Queries related information through experience sharing and peer ( This article gives great inspiration)

View Code, request.KeepAlive = true; query Microsoft related documents , this property is actually set up a 'Keep-alive' request header, then colleagues Http client package scene scene is not known, but for scenarios mentioned in this article, because the every request is the same interface, thus maintaining a constant connection can obviously reduce the overhead of repeatedly create tcp connection, so comment out this line re-release test, these problems will not re-appeared!

Of course, in practice we do more than just optimize it, if only such a word can be finished, that we will have to remember to do so on the Ok. Actually reference a lot of people in the actual project experience or pit below the whole HttpClient code stickers, and then the following key will be described.

 public static string Request(string requestUrl, string requestData, out bool isSuccess, string contentType = "application/x-www-form-urlencoded;charset=utf8")
    {
        string apiResult = "";
        isSuccess = false;
        if (string.IsNullOrEmpty(requestData))
        {
            return apiResult;
        }
        HttpWebRequest request = null;
        HttpWebResponse response = null;
        try
        {
            byte[] buffer = Encoding.UTF8.GetBytes(requestData);
            request = WebRequest.Create($"{requestUrl}") as HttpWebRequest;
            request.ContentType = "application/json";
            request.Method = "POST";
            request.ContentLength = buffer.Length;
            request.Timeout =200;
            request.ReadWriteTimeout =  Const.HttpClientReadWriteTimeout
            request.ServicePoint.Expect100Continue = false;
            request.ServicePoint.UseNagleAlgorithm = false;
            request.ServicePoint.ConnectionLimit = 2000
            request.AllowWriteStreamBuffering = false;
            request.Proxy = null;

            using (var stream = request.GetRequestStream())
            {
                stream.Write(buffer, 0, buffer.Length);
            }
            using (response = (HttpWebResponse)request.GetResponse())
            {
                string encoding = response.ContentEncoding;
                using (var stream = response.GetResponseStream())
                {
                    if (string.IsNullOrEmpty(encoding) || encoding.Length < 1)
                    {
                        encoding = "UTF-8"; //默认编码
                    }

                    if (stream != null)
                    {
                        using (StreamReader reader = new StreamReader(stream, Encoding.GetEncoding(encoding)))
                        {
                            apiResult = reader.ReadToEnd();
                            //byte[] bty = stream.ReadBytes();
                            //apiResult = Encoding.UTF8.GetString(bty);
                        }
                    }
                    else
                    {
                        throw new Exception("响应流为null!");
                    }
                }
            }
            isSuccess = true;
        }
        catch (Exception err)
        {
            isSuccess = false;
            LogUtilities.WriteException(err);
        }
        finally
        {
            response?.Close();
            request?.Abort();
        }

        return apiResult;
    }
  • The first is the TimeOutproblem, not just at high concurrency scenarios, regardless of the actual project is proposed to be set up in any setting its value in HttpWebRequest object, its default value is 100000milliseconds, which is 100 seconds. If the server problems The default settings will cause serious obstruction to the general project will seriously affect the user experience. return failure retry also allows users to experience long waits better than this.

  • ReadWriteTimeout many of my friends may not have contact with this property, especially with friends .net 4.5 in HttpClient object. Had Socket programming experience friends may know, socket connection timeout connection and transmission timeout here ReadWriteTimeoutis similar to Socket Programming in the transmission timeout. literally speaking, reading and writing timeout is to prevent excessive data or network problems spread into a very long time can not be completed. of course, in the general scenario we can completely ignore it, if for network timeout causes the reader is also likely to result in connection timeouts. the reason here to set this value is due to the actual business scenarios decisions. you may have seen, for the above code ReadWriteTimeoutsetting is not as Timeoutthe same is set to a fixed value, Const is placed a class, it is actually reading a configuration, the size dynamically determined according to the configuration values. in practice such a scenario is, since the pressure measurement environment can not completely simulate the real user access scenario. sensed pressure all the time using a single number for a single query track, but the actual service allows the user to request the query Up to as many as several hundred single number. A number of single track records are generally tens of KB size, number, order number if the requested amount excessive number will greatly increase long query time and transmission time will be greatly increased, in order to ensure that the majority of users during the 11 double normal visit, will put this little time setting if necessary (default is 3000 milliseconds), allowing users to query a single big to fail fast.

More than just an alternative, we have to admit, since a query system allows multiple single number, so the user does not reach the upper limit before all the requests are legitimate, it should be supported, so the above practice is in fact detrimental user experience, but the system resources are limited, only when necessary to sacrifice the interests of specific users, to ensure that the interests of the vast majority of users.'ve spent 11 double, 11 twin practice has not changed the value of the above configuration, but the increase in risk prevention as dynamic configuration is necessary.

Here more about the poor mouth, is about the ContentLengthvalue of it is not set, the program will automatically calculate the time is not set, but the time must be set to set the length of the byte array, rather than the length of the string, because that contains Chinese the different coding rules, Chinese characters may occupy two bytes or more bytes in length.

  • About request.ServicePoint.Expect100Continue = false; request.ServicePoint.UseNagleAlgorithm = false;two author is not particularly clear, read the relevant documents are not particularly clear, please understand friends pointing, we learn together and progress.

  • request.ServicePoint.ConnectionLimit = 2000Is set the maximum number of connections, many of my friends to this value is set to 65536, in fact, a single server web concurrent connections is far too less than this value. Here the actual situation of the project, set to 2000. capability to prevent undertreatment request queue is too long.

  • request.AllowWriteStreamBuffering = false;According to [Microsoft document ( https://docs.microsoft.com/zh-cn/dotnet/api/system.net.httpwebrequest.allowwritestreambuffering?redirectedfrom=MSDN&view=netframework-4.8#System_Net_HttpWebRequest_AllowWriteStreamBuffering )] This option is set to true, data the buffer memory, so that data can be resend request redirection or identity verification.

Most importantly, the document said, 将 AllowWriteStreamBuffering 设置为 true 可能会在上传大型数据集时导致性能问题,因为数据缓冲区可能会使用所有可用内存。because the request is sent only a single number, the amount of data is small, and there is little demand for a single user number repeated queries. Plus there may be side effects. Here is set to false.

  • request.Proxy = null;Here is a reference to a netizen's article, which referred to the default timeout Proxy lead to bizarre behavior. Since the settlement of the problem in October, according to this writing has been for some time, so they could not find it again when looking for the articles are interested friends can search for their own look.

Many people may be concerned about, the above configuration in the end there is no problem. After the configuration has been in practice more than 11 experienced a double peak qps over a million tests are given time of this writing request time-consuming to monitor the following

img

We can see, the overall request time-consuming relatively stable.

May read this chart, some friends still have questions, you can see from the above screenshot logs, in addition to consuming more than 100ms at the request of the ordinary took in forty or fifty milliseconds, there are still many, but the following screenshot there are floating in the range of 10 to 20, the highest it 30ms. this is actually due to the pressure during the test, it was found Hbase itself has instability (most of the time-consuming request response is very smooth, but occasionally there will be Lou individual request of a thousand or tens of milliseconds (expressed as a very unexpected lines on the control chart, the general practice is called glitches), which is under high concurrency scenarios are unacceptable, Ali cloud feedback for future issues Hbase optimized, after consuming optimization also declined.)

Guess you like

Origin www.cnblogs.com/tylerzhou/p/11922473.html