c# - 当请求需要很长时间时,net core 控制台应用程序 C# HttpClient 挂起
问题描述
控制台 App Net Core 3.0
我正在向 Dynamic CRM Api 发送批处理请求,基本上我读取了一个文件夹来查找由另一个进程(Nodejs)生成的文本文件,这些文件具有请求内容,然后我遍历这些文件,将文本内容作为字符串和发送。问题是当任何这些文件的内容更大(500kb +)时问题是当请求需要更长的时间(5分钟或更长时间)然后HttpClient.SendAsync
开始但从未完成时,系统挂在那里,我知道发送是成功的原因我签入 api 并应用更改,但自动化过程在那里停止,我必须终止应用程序。如果内容不是那么大,那么一切都会顺利进行。
最令人沮丧的是没有任何错误或反馈导致我找到任何解决方案或解决方法。
重要细节:
我认为这不应该是死锁,因为链中的每个异步调用都在等待,sendasync 也设置为 ConfigureAwait(false)。没有 .Result,没有 Wait() 或任何其他阻塞操作被调用。
我不会通过为每个请求创建一个 HttpClient 实例来耗尽网络套接字,我正在使用IHttpClientFactory
将 httpClient 实例作为 Singleton 分派。问题发生在它遇到的第一个长内容请求中。
更新 我意识到问题与有效负载大小无关,但随着请求完成所需的时间,我注意到 200kb 或更少的文件挂起,因为服务器需要超过 8 分钟才能完成。
编码:
HttpRequestMessage GetRequest(string batchId, string requestBody)
{
var request = new HttpRequestMessage(HttpMethod.Post,"$batch");
request.Headers.Add("OData-MaxVersion", "4.0");
request.Headers.Add("OData-Version", "4.0");
request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
request.Content = GetContent(batchId, requestBody);
return request;
}
StringContent GetContent(string batchId, string requestBody)
{
var content = new StringContent(requestBody);
content.Headers.Remove("Content-Type");
content.Headers.Add("Content-Type", $"multipart/mixed;boundary=batch_{batchId}");
return content;
}
string GetRequestBody(string file)
{
var requestBody = "";
using (var sr = new StreamReader(file))
{
requestBody = sr.ReadToEnd();
}
return requestBody;
}
private async Task<HttpResponseMessage> SendRequest(string batchId, string file)
{
// this call is awaited since the access token may expire then is necessary to request a new one
var httpClient = await _httpClientBuilder.BuildHttpClient().ConfigureAwait(false);
var requestBody = GetRequestBody(file); // Here I read the text from the file
using(var request = GetRequest(batchId, requestBody)){
using(var response = await httpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead).ConfigureAwait(false)){ // after this call nothing is executed
if (response.IsSuccessStatusCode)
{
CustomConsole.Success("({0})Successfully Sent batch: {1}", response.StatusCode, batchId);
File.Delete(file);
}
else
{
CustomConsole.Error("({0}) Error sending batch: {1}", response.StatusCode, batchId);
var responseBody = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
CustomConsole.Info("Response Body:");
CustomConsole.Info("{0}",responseBody);
}
return response;
}
}
}
解决方案
推荐阅读
- asp.net - 如何运行已发布的 Asp.Net 核心 Web 应用程序
- python - 我希望我的 python 工具具有一种机制,就像任何人运行该工具时都会弹出一个弹出窗口,因为新版本可用,请使用最新版本
- python - 合并包含字典的数据框的两列并将其存储到数据框中的其他列中
- mysql - 如何让我返回零而不是 null?
- time - 是否有库可以将特定年份的天数转换为月份和日期?
- parsing - 在pdf解析中混淆字形是什么
- kubernetes - 如何在 helm chart 的 values.yaml 中将证书作为变量传递
- amazon-web-services - AWS 文档滚动速度很慢
- android - cloud.speech.v1.StreamingRecognizeResponse - 错误:枚举 switch case 标签必须是枚举常量的非限定名称
- caching - 自 1 月 1 日起随机发生奇怪的 umbraco 媒体缓存错误