【问题标题】:C# Slow response times with HttpClient compared to HttpWebRequest与 HttpWebRequest 相比,使用 HttpClient 的 C# 响应时间较慢
【发布时间】:2016-12-05 04:24:31
【问题描述】:

由于某种原因,当使用 HttpClient 和 HttpWebRequest 执行相同的 POST 请求时,HTTPClient 需要 2000+ms 而 HttpWebRequest 需要大约 1000-1400 ms。 这种差异是否正常,我可以做些什么来使 httpclient 与 httpwebrequest 的速度相匹配?

我已经在下面发布了代码,以防我搞砸了。

protected WebRequest CreateWebRequest(Uri uri)
{
    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(new Uri(EndPoint));
    request.Method = "POST";
    request.ContentType = "application/json-rpc";
    request.Headers.Add(HttpRequestHeader.AcceptCharset, "ISO-8859-1,utf-8");
    request.Headers.Add(CustomHeaders);
    request.AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip;
    request.ServicePoint.Expect100Continue = false;
    ServicePointManager.Expect100Continue = false;
    return request;
}

private async Task<string> DoHttpClientPost(string method, IDictionary<string, object> args = null)
{
    {
        HttpClientHandler handler = new HttpClientHandler()
        {
            AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate
        };
        handler.Proxy = null;
        HttpResponseMessage response;
        using (var myHttpClient = new HttpClient(handler))
        {
            myHttpClient.DefaultRequestHeaders.ExpectContinue = false;
            myHttpClient.DefaultRequestHeaders.Add("Accept-Charset", "ISO-8859-1,utf-8");
            myHttpClient.DefaultRequestHeaders.Add(APPKEY_HEADER, CustomHeaders.GetValues(APPKEY_HEADER));
            myHttpClient.DefaultRequestHeaders.Add(SESSION_TOKEN_HEADER, CustomHeaders.GetValues(SESSION_TOKEN_HEADER));
            myHttpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json-rpc"));
            var call = new JsonRequest { Method = method, Id = 1, Params = args };
            var jsonObject = JsonConvert.Serialize<JsonRequest>(call);
            var content = new StringContent(jsonObject.ToString(), Encoding.UTF8, "application/json-rpc");
            response = await myHttpClient.PostAsync(new Uri(EndPoint), content);
        }
        Console.WriteLine("\nCalling: " + method + " With args: " + JsonConvert.Serialize<IDictionary<string, object>>(args));
        string jsonResponse = await response.Content.ReadAsStringAsync();

        return jsonResponse;
    }
}


public async Task<T> Invoke2<T>(string method, IDictionary<string, object> args = null)
{
    if (method == null)
        throw new ArgumentNullException("method");
    if (method.Length == 0)
        throw new ArgumentException(null, "method");
    string jsonString = await DoHttpClientPost(method, args);
    var jsonResult = JsonConvert.Deserialize<JsonResponse<T>>(jsonString);

    return jsonResult.Result;
}



public async Task<T> Invoke<T>(string method, IDictionary<string, object> args = null)
{
    if (method == null)
        throw new ArgumentNullException("method");
    if (method.Length == 0)
        throw new ArgumentException(null, "method");

    var request = CreateWebRequest(new Uri(EndPoint));

    using (Stream stream = request.GetRequestStream())
    using (StreamWriter writer = new StreamWriter(stream, Encoding.UTF8))
    {
        var call = new JsonRequest { Method = method, Id = 1, Params = args };
        JsonConvert.Export(call, writer);
    }
    Console.WriteLine("\nCalling: " + method + " With args: " + JsonConvert.Serialize<IDictionary<string, object>>(args));

    using (WebResponse response = GetWebResponse(request))
    using (Stream stream = response.GetResponseStream())
    using (StreamReader reader = new StreamReader(stream, Encoding.UTF8))
    {
        var jsonResponse = JsonConvert.Import<T>(reader);
        // Console.WriteLine("\nGot Response: " + JsonConvert.Serialize<JsonResponse<T>>(jsonResponse));
        if (jsonResponse.HasError)
        {
            throw ReconstituteException(jsonResponse.Error);
        }
        else
        {
            return jsonResponse.Result;
        }
    }
}

【问题讨论】:

  • 您是否使用 Wireshark 或 Fiddler 等工具查看过网络上发生的情况?
  • 是的,它们具有相同的标题和相同的大小,这非常令人困惑。

标签: c# api httpclient


【解决方案1】:

如果可能的话,HttpClient 应该是reused across requests。您是否尝试过隔离创建 HttpClient 实例并执行实际请求?创建和释放实例持有的资源都需要时间,虽然 1000 毫秒听起来很长。

使用 HttpClient 或 WebRequest 时速度变慢的另一个可能原因是设置 ServicePointManager.DefaultConnectionLimit too low。默认值为 2,因此如果您正在快速连续执行大量并发甚至多个请求,您最终将等待 ServicePointManager 释放连接。

【讨论】:

    猜你喜欢
    • 2019-11-10
    • 1970-01-01
    • 2018-07-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多