搜索错误关键字“Cannot assign requested address”,"返回" JSON 内容,返回的引号是因为其实并不是远程接口返回的,而是 IdentityModel 返回的,毕竟直译后从字面意思理解“无法分配请求的地址”,也可以理解为不能正确发起请求,所以就是在发起请求的过程中产生的错误。
在和运维一起排查后得知被调用服务出现很多 close wait,导致连接数不能及时释放,连接数耗尽,所以就不能再建立新请求了。知道了原因接下来就好办了。顺藤摸瓜,找到发起请求的地方,将能 Close Dispose 的都处理了。
错误返回的完整内容如下:
{
"AccessToken": null,
"IdentityToken": null,
"TokenType": null,
"RefreshToken": null,
"ErrorDescription": null,
"ExpiresIn": 0,
"Raw": null,
"Json": null,
"Exception": {
"Message": "Cannot assign requested address",
"Data": {},
"InnerException": {
"ClassName": "System.Net.Sockets.SocketException",
"Message": "Cannot assign requested address",
"Data": null,
"InnerException": null,
"HelpURL": null,
"StackTraceString": "at System.Net.Http.ConnectHelper.ConnectAsync(String host, Int32 port, CancellationToken cancellationToken)",
"RemoteStackTraceString": null,
"RemoteStackIndex": 0,
"ExceptionMethod": null,
"HResult": -2147467259,
"Source": "System.Private.CoreLib",
"WatsonBuckets": null,
"NativeErrorCode": 99
},
"StackTrace": "at System.Net.Http.ConnectHelper.ConnectAsync(String host, Int32 port, CancellationToken cancellationToken)\n at System.Threading.Tasks.ValueTask`1.get_Result()\n at System.Net.Http.HttpConnectionPool.CreateConnectionAsync(HttpRequestMessage request, CancellationToken cancellationToken)\n at System.Threading.Tasks.ValueTask`1.get_Result()\n at System.Net.Http.HttpConnectionPool.WaitForCreatedConnectionAsync(ValueTask`1 creationTask)\n at System.Threading.Tasks.ValueTask`1.get_Result()\n at System.Net.Http.HttpConnectionPool.SendWithRetryAsync(HttpRequestMessage request, Boolean doRequestAuth, CancellationToken cancellationToken)\n at System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)\n at System.Net.Http.HttpClient.FinishSendAsyncBuffered(Task`1 sendTask, HttpRequestMessage request, CancellationTokenSource cts, Boolean disposeCts)\n at IdentityModel.Client.TokenClient.RequestAsync(IDictionary`2 form, CancellationToken cancellationToken)",
"HelpLink": null,
"Source": "System.Net.Http",
"HResult": -2147467259
},
"IsError": true,
"ErrorType": 3,
"HttpStatusCode": 0,
"HttpErrorReason": null,
"Error": "Cannot assign requested address"
}
/// <summary>
/// 统一获取 SpiderBIM token的通用方法
/// </summary>
/// <param name="config">配置信息</param>
/// <returns></returns>
public static TokenResponse GetAuthorizeAsync(SpiderBIMConfigOptions config)
{
var tokenClient = new TokenClient(config.TokenUrl, config.ClientId, config.ClientSecret);
var tokenResponse = tokenClient.RequestResourceOwnerPasswordAsync(config.Username, config.Password, config.Scope).GetAwaiter().GetResult();
if (tokenResponse.IsError)
{
Console.WriteLine($"DEBUG {DateTime.Now:yyyy-MM-dd HH:mm:ss,fff} - ---------------------------- 获取 SPDToken 失败 ----------------------------{tokenResponse.ToJsonString()}");
return null;
}
return tokenResponse;
}
/// <summary>
/// 统一获取 SpiderBIM token的通用方法
/// </summary>
/// <param name="config">配置信息</param>
/// <returns></returns>
public static TokenResponse GetAuthorizeAsync(SpiderBIMConfigOptions config)
{
using (var tokenClient = new TokenClient(config.TokenUrl, config.ClientId, config.ClientSecret))
{
var tokenResponse = tokenClient.RequestResourceOwnerPasswordAsync(config.Username, config.Password, config.Scope).GetAwaiter().GetResult();
if (tokenResponse.IsError)
{
Console.WriteLine($"DEBUG {DateTime.Now:yyyy-MM-dd HH:mm:ss,fff} - ---------------------------- 获取 SPDToken 失败 ----------------------------{tokenResponse.ToJsonString()}");
return null;
}
return tokenResponse;
}
}
修改后的代码加上了 using 是的 tokenClient 在使用后及时被释放,避免被调用服务出现太多的 close wait。从而导致连接数被占用完。
所以就是因为没有注意到 tokenClient 是可以被 Dispose 的类,并且因为业务关系发起了频繁的请求,所以才导致问题的产生。
cs