2

我在多个多线程消费者中使用 .net HTTPClient,每秒一次向本地服务发出 GetAsync Web 请求,速度为 127.0.0.1。

Web 请求在 99.9% 的时间内完成,但偶尔有一些请求(超过 3-4 小时)会卡在 GetAsyc 中并且不会完成或超时。在同一时间段内对同一服务 url/端口的请求将正常工作,新请求将正常完成。

GetAsync 以“即发即忘”模式触发,其中在完成时调用回调以处理生成的解析数据(因为它与一些不使用异步的旧代码集成。)

public void Execute(Action<IAsyncCommand> onCompletion)
{
    this.onAsyncCompletion = onCompletion;
    try
    {
       // do not await as this is fire and forget
       this.HandlRequestAysnc(this.Target, new StringContent(this.CommandPayload));
        return;
    }
    catch(Exception e)
    {
      //log exception
    }
 }
private async Task HandlRequestAysnc(Uri uri, StringContent stringContent)
{
    try
    {
        ConfiguredTaskAwaitable<HttpResponseMessage> request = stringContent != null ? webClient.PostAsync(uri, stringContent).ConfigureAwait(false) : webClient.GetAsync(uri).ConfigureAwait(false);
        //this will never return or timeout 1 in 10000 times
        using (HttpResponseMessage response = await request) 
        {
            if (response.IsSuccessStatusCode)
            {
                using (HttpContent content = response.Content)
                {
                    string result = await content.ReadAsStringAsync(); 
                    //handle result
                }
            }
            else
            {
             //handle failure
            }
        }
    }
    catch (Exception ex)
    {
         //log exception
    }
    if (this.onAsyncCompletion != null)
    {
        this.onAsyncCompletion(this);
    }
}
4

1 回答 1

0

GetAync 的问题之一是,一旦会话开始,TCP 堆栈就会受到控制。最近的一项实验室实验证明,启动 10,000 个 get 请求(用于调查我们在 prod 环境中出现内存问题的原因)需要 5 分钟(在应用程序结束后)让 TCP 堆栈清理所有内容。

如果您发现套接字状态具有 Fin-Wait 1 或 2、Time-Wait 或其他半生不熟的会话,这只是一个更大问题的症状,即两个系统之一(或两者)无法以该速率处理流量. 一旦这种情况开始发生,事情就会迅速失控,因为双方都在努力维持会议,但都在失去足够快的资源来做到这一点。

此类问题的解决方案是寻找另一种提高吞吐量的方法。

于 2015-09-09T10:07:41.250 回答