我创建了一个 .Net Framework 4.7.2 控制台应用程序,该应用程序在 AWS 托管的 API 中同时发出许多请求。我的问题是请求花费的时间太长。
根据 AWS 控制台中的 taget 组监控,API 的响应时间通常为 100ms-400ms,但在我的应用程序中,每个请求所花费的时间从 1 秒开始,一直增加到 11 秒。
我已经意识到 HttpClient 无法正确关闭连接,因此我们不应该使用
using
,而应始终为每个应用程序使用一个实例。
我已经找到了一个类似的问题,但答案没有解决它。
当我将 MaxDegreeOfParallelism 设置为 1 时,应用程序中的响应时间与应用程序类似。这似乎是在多线程中的 HttpClient 中发生的问题。
这就是我提出请求的方式:
public static class RequestMaker
{
private static readonly string _urlHttp = "http://apidomain.com/api/apiname";
private static readonly HttpClient _httpClient = new HttpClient();
public static async Task<string> PostAsync(string postData)
{
bool IsSuccessStatusCode = false;
int maxRetries = 5;
int count = 0;
do
{
try
{
Stopwatch watcher = Stopwatch.StartNew();
using (HttpContent content = new StringContent(postData, Encoding.UTF8, "application/json"))
using (HttpResponseMessage result = await _httpClient.PostAsync(_urlHttp, content).ConfigureAwait(false))
{
watcher.Stop();
Console.WriteLine("Elapsed = " + watcher.ElapsedMilliseconds.ToString("N0"));
IsSuccessStatusCode = result.IsSuccessStatusCode;
if (IsSuccessStatusCode)
return await result.Content.ReadAsStringAsync().ConfigureAwait(false);
count++;
if (count > maxRetries)
return "";
Console.WriteLine($"Retrying request because of request status code {result.StatusCode}");
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
count++;
if (count > maxRetries)
return "";
}
} while (!IsSuccessStatusCode);
return "";
}
}
这是我同时调用请求的函数:
static void RunBatchMany(List<string> list)
{
var getCustomerBlock = new TransformBlock<string, long>(
async lstRec =>
{
ApiInputObject apiInput = new ApiInputObject();
// PrepareInputObject
string postData = JsonConvert.SerializeObject(apiInput);
Stopwatch watcher = Stopwatch.StartNew();
string json = await RequestMaker.PostAsync(postData);
ApiResponseObject res = JsonConvert.DeserializeObject<ApiResponseObject>(json);
watcher.Stop();
return watcher.ElapsedMilliseconds;
}, new ExecutionDataflowBlockOptions
{
MaxDegreeOfParallelism = 8
});
foreach (var id in list)
getCustomerBlock.Post(id);
getCustomerBlock.Complete();
getCustomerBlock.Completion.Wait();
}
您可以尝试使用此扩展禁用查找 ipv6
public static void DisableIpV6(this SocketsHttpHandler socketsHttpHandler)
{
socketsHttpHandler.ConnectCallback = async (context, cancellationToken) =>
{
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
await socket.ConnectAsync(context.DnsEndPoint.Host, context.DnsEndPoint.Port);
return new NetworkStream(socket, true);
};
}
using SocketsHttpHandler handler = new();
handler.DisableIpV6();
using Httpclient httpclient = new(handler,false);