【问题标题】:httpclient PostAsJsonAsync errors after (n) messages (port exhaustion?)(n) 条消息后的 httpclient PostAsJsonAsync 错误(端口耗尽?)
【发布时间】:2016-09-01 11:18:43
【问题描述】:

我有一个在 Azure 中运行的控制台应用程序(webjob),它调用也在 azure 中运行的 API。控制台应用程序从 csv 文件发布消息。 当我从我的本地(windows 10)机器(api 在 azure 中运行)运行控制台应用程序时,它按预期工作(没有错误)。 当我在 Azure 中运行控制台应用程序(api 在 azure 中运行)时,它会处理大约 980 条消息,然后开始报告错误

错误:

  • “发送请求时出错”
  • “无法连接到远程服务器”

我相信由于某种原因,当控制台应用程序在 Azure 中运行时,它会耗尽端口,但我不知道如何解决这个问题。 我的文件有 50,000 行,但如前所述,在问题出现之前只能达到大约 980 行。 在另一端,api 将收到的消息发布到 sql 数据库和 azure 事件中心。 PostAsJsonAsync 完成后,如何强制应用程序释放端口? 如何检查端口是否已释放或如何检查端口是否可用? 如果您知道我可能会收到这些错误的任何其他原因,请提供帮助。

这是我的代码:

public async Task<string> PostMessageToAPI(string aMsg)
{
    HttpResponseMessage response = null;
    string strResponse = "";    
    try
    {
        using (var client = new HttpClient())
        {
            client.SetBearerToken("access token here");
            client.BaseAddress = new Uri("MyBaseUrl.com");
            client.DefaultRequestHeaders.Accept.Clear();
            client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
            using (response =  await client.PostAsJsonAsync("my/url/goes/here", anEvent.ToLower()))
            {
                if (response != null)
                {
                    if (response.StatusCode != HttpStatusCode.OK)
                    {
                        throw new HttpRequestException(response.ReasonPhrase);
                    }
                    else
                    {
                        return await response.Content.ReadAsStringAsync();
                    }
                }
            }
        }
    }
    catch (HttpRequestException ex)
    {       
        //  exception message states: "An error occurred while sending the request"
    }   
    return strResponse;           
}
  • Visual Studio 2015 更新 3
  • .net 4.5.1
  • Azure 控制台应用计划:基本 1 小
  • Azure API 应用计划:基本 1 小

【问题讨论】:

  • 是从多线程环境调用PostMessageToAPI 吗?
  • 它是从 Azure WebJob 调用的,因此可以调用多个实例,但这由 Azure 管理。然而,我只测试一个实例。
  • 谁/什么在远程服务器上?有没有可能是那一端的连接没有正确断开?
  • 您的网络作业中使用了什么样的触发器? - 时间/队列/斑点?原因是如果排队,您可以灵活地设置可以/需要处理的消息数量,以及租用和释放锁的能力

标签: c# azure runtime-error httpclient azure-webjobs


【解决方案1】:

请不要使用包裹在using 中的HttpClient。使用静态实例并共享它。

public class MyClass()
{
private HttpClient client = null;
public MyClass(){
    client = new HttpClient();
    client.SetBearerToken("access token here");
    client.BaseAddress = new Uri("MyBaseUrl.com");
    client.DefaultRequestHeaders.Accept.Clear();
    client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

}
public async Task<string> PostMessageToAPI(string aMsg)
{
    HttpResponseMessage response = null;
    string strResponse = "";    
    try
    {
        using (var response =  await client.PostAsync("my/url/goes/here", new StringContent(aMsg, Encoding.UTF8, "application/json")))
        {
            if (response != null)
            {
                if (response.StatusCode != HttpStatusCode.OK)
                {
                    throw new HttpRequestException(response.ReasonPhrase);
                }
                else
                {
                    return await response.Content.ReadAsStringAsync();
                }
            }
        }

    }
    catch (HttpRequestException ex)
    {       
        //  exception message states: "An error occurred while sending the request"
    }   
    return strResponse;           
}
}

你甚至可以共享同一个类的实例,关键是每次都重新创建和重新打开套接字并不是最佳的,它最终会导致套接字耗尽,具体取决于你的调用吞吐量。

Source

【讨论】:

  • 注:只有9个方法that are actually thread safeCancelPendingRequests,DeleteAsync,GetAsync,GetByteArrayAsync,GetStreamAsync,GetStringAsync,PostAsync,@9876543和SendAsync。没有一个属性保证是线程安全的。确保您的 PostAsJsonAsync 扩展方法不使用不在该列表中的任何方法,也不使用任何属性。
  • 好收获!我只是移植了静态使用的代码,这就是端口耗尽的原因。
  • 嗨,Matias,问题是我为每次调用都重新创建了 httpclient。我现在为所有调用重用相同的 httpclient,问题得到解决。这基本上就是您在代码中描述的内容,所以谢谢。我已将您的答案标记为解决方案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-25
相关资源
最近更新 更多