You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

生产环境调用Bing地图API随机出现连接超时异常求助

Bing地图API并发调用随机连接超时问题

背景

应用已部署到生产服务器,通过并发调用Bing地图API(地址:https://dev.virtualearth.net/REST/v1/Locations)批量获取位置数据,运行基本正常,但会随机出现连接超时异常,影响稳定性。

调用代码

private async Task<BingResponse> GetBingResponse(string argUri)
{
    try
    {
        WebRequest request = HttpWebRequest.Create(new Uri(argUri));
        var response = await request.GetResponseAsync();

        if (((HttpWebResponse)response).StatusCode == HttpStatusCode.OK)
        {
            using (Stream resStream = (response.GetResponseStream()))
            {
                DataContractJsonSerializer jsonData = new DataContractJsonSerializer(typeof(BingResponse));
                return jsonData.ReadObject(resStream) as BingResponse;
            }
        }
        else
            return null;
    }
    catch (Exception ex)
    {
        XLLogger.Write("Exception with BingResponse URL");
        return null;
    }
}

异常详情(含中文翻译)

原始异常信息

{
    "ClassName": "System.Net.WebException",
    "Message": "A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond. (dev.virtualearth.net:443)",
    "Data": null,
    "InnerException": {
        "StatusCode": null,
        "Message": "A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond. (dev.virtualearth.net:443)",
        "Data": {},
        "InnerException": {
            "ClassName": "System.Net.Sockets.SocketException",
            "Message": "A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond.",
            "Data": null,
            "InnerException": null,
            "HelpURL": null,
            "StackTraceString": "   at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.System.Threading.Tasks.Sources.IValueTaskSource.GetResult(Int16 token)\r\n   at System.Net.Sockets.Socket.<ConnectAsync>g__WaitForConnectWithCancellation|277_0(AwaitableSocketAsyncEventArgs saea, ValueTask connectTask, CancellationToken cancellationToken)\r\n   at System.Net.HttpWebRequest.<>c__DisplayClass216_0.<CreateHttpClient>b__1>d.MoveNext()\r\n--- End of stack trace from previous location ---\r\n   at System.Net.Http.HttpConnectionPool.ConnectToTcpHostAsync(String host, Int32 port, HttpRequestMessage initialRequest, Boolean async, CancellationToken cancellationToken)",
            "RemoteStackTraceString": null,
            "RemoteStackIndex": 0,
            "ExceptionMethod": null,
            "HResult": -2147467259,
            "Source": "System.Net.Sockets",
            "WatsonBuckets": null,
            "NativeErrorCode": 10060
        },
        "HelpLink": null,
        "Source": "System.Net.Http",
        "HResult": -2147467259,
        "StackTrace": "   at System.Net.Http.HttpConnectionPool.ConnectToTcpHostAsync(String host, Int32 port, HttpRequestMessage initialRequest, Boolean async, CancellationToken cancellationToken)\r\n   at System.Net.Http.HttpConnectionPool.ConnectAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)\r\n   at System.Net.Http.HttpConnectionPool.CreateHttp11ConnectionAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)\r\n   at System.Net.Http.HttpConnectionPool.AddHttp11ConnectionAsync(HttpRequestMessage request)\r\n   at System.Threading.Tasks.TaskCompletionSourceWithCancellation`1.WaitWithCancellationAsync(CancellationToken cancellationToken)\r\n   at System.Net.Http.HttpConnectionPool.GetHttp11ConnectionAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)\r\n   at System.Net.Http.HttpConnectionPool.SendWithVersionDetectionAndRetryAsync(HttpRequestMessage request, Boolean async, Boolean doRequestAuth, CancellationToken cancellationToken)\r\n   at System.Net.Http.DiagnosticsHandler.SendAsyncCore(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)\r\n   at System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)\r\n   at System.Net.Http.HttpClient.<SendAsync>g__Core|83_0(HttpRequestMessage request, HttpCompletionOption completionOption, CancellationTokenSource cts, Boolean disposeCts, CancellationTokenSource pendingRequestsCts, CancellationToken originalCancellationToken)\r\n   at System.Net.HttpWebRequest.SendRequest(Boolean async)\r\n   at System.Net.HttpWebRequest.EndGetResponse(IAsyncResult asyncResult)"
    },
    "HelpURL": null,
    "StackTraceString": "   at System.Net.HttpWebRequest.EndGetResponse(IAsyncResult asyncResult)\r\n   at System.Threading.Tasks.TaskFactory`1.FromAsyncCoreLogic(IAsyncResult iar, Func`2 endFunction, Action`1 endAction, Task`1 promise, Boolean requiresSynchronization)\r\n--- End of stack trace from previous location ---\r\n",
    "RemoteStackTraceString": null,
    "RemoteStackIndex": 0,
    "ExceptionMethod": null,
    "HResult": -2147467259,
    "Source": "System.Net.Requests",
    "WatsonBuckets": null
}

中文翻译

  • 顶层异常:System.Net.WebException:连接尝试失败,因为连接方在一段时间后未正确响应,或已建立的连接因目标主机未响应而失败。(dev.virtualearth.net:443)
  • 内层Socket异常:System.Net.Sockets.SocketException(错误码10060):连接尝试失败,因为连接方在一段时间后未正确响应,或已建立的连接因目标主机未响应而失败。

解决方案

  • 添加超时控制:给HttpWebRequest设置合理的超时时间,避免无限制等待。比如在创建请求后加:
    ((HttpWebRequest)request).Timeout = 10000; // 10秒超时
    ((HttpWebRequest)request).ReadWriteTimeout = 15000; // 读写超时15秒
    
  • 实现重试策略:针对连接超时这类临时异常,用指数退避法重试,最多3次,间隔依次为1秒、2秒、4秒,避免单次失败直接返回。
  • 替换为HttpClient:HttpWebRequest是旧API,HttpClient自带连接池,更适合并发场景,能减少连接资源浪费。示例:
    private static readonly HttpClient _httpClient = new HttpClient();
    private async Task<BingResponse> GetBingResponse(string argUri)
    {
        try
        {
            var response = await _httpClient.GetAsync(argUri);
            if (response.IsSuccessStatusCode)
            {
                var json = await response.Content.ReadAsStringAsync();
                // 用JsonSerializer反序列化,替换DataContractJsonSerializer
                return JsonSerializer.Deserialize<BingResponse>(json);
            }
            return null;
        }
        catch (Exception ex)
        {
            XLLogger.Write($"Exception with BingResponse URL: {ex.Message}");
            return null;
        }
    }
    
  • 限制并发量:Bing API有调用配额,并发太高可能被限流或导致自身连接池耗尽。用SemaphoreSlim控制并发数,比如限制同时发送10个请求:
    private static readonly SemaphoreSlim _semaphore = new SemaphoreSlim(10);
    // 在调用GetBingResponse前:
    await _semaphore.WaitAsync();
    try
    {
        var result = await GetBingResponse(uri);
        // 处理结果
    }
    finally
    {
        _semaphore.Release();
    }
    
  • 排查网络问题:确认生产服务器到dev.virtualearth.net的网络是否稳定,有无防火墙、代理拦截,可通过ping、telnet测试连通性。

内容的提问来源于stack exchange,提问作者Vignesh Kumar A

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 07:12:33