HttpClient在响应流完全读取之前被释放,导致连接关闭异常
Posted
技术标签:
【中文标题】HttpClient在响应流完全读取之前被释放,导致连接关闭异常【英文标题】:HttpClient disposed before response stream fully read, leads to connection closed exception 【发布时间】:2021-07-14 09:53:51 【问题描述】:我正在尝试将请求的响应流式传输到响应。所以基本上通过管道将请求发送到另一个 url。这是我拥有的代码,它说明了我正在尝试做的事情。
public async Task<IActionResult> GetArticleImage(string userId, string articleId)
var imageUrl = "https://image-url"; // This url is retrieved from the database
var imageResult = await this.httpClient.GetAsync(imageUrl);
var stream = await imageResult.Content.ReadAsStreamAsync();
return new FileStreamResult(stream, imageResult.Content.Headers.GetValues("Content-Type").First());
在这种情况下会发生ConnectionResetException
被抛出,消息为The client has disconnected
。
我相信这是因为请求范围在流被完全读取之前被释放,这也释放了HttpClient
。
当使用var scope = IServiceScopeFactory.CreateScope()
(伪代码,实际上是通过构造函数注入IServiceScopeFactory serviceScopeFactory
)创建自定义作用域时,HttpClient
通过那个解析,而不是处置(既不是作用域也不是客户端),它可以正常工作。
值得一提的是,GetArticleImage
方法是在单独的服务类中实现的,不是在控制器中。
以前它是在控制器类中实现的,代码可以完美运行。
这使我假设作用域处置机制的工作方式略有不同,但我不知道如何。
HttpClient
被注册为单例,这应该确保它不会被丢弃。
问题是:如何将请求通过管道传输/流式传输到另一个 url?
调用此方法的端点可以经常被调用,同时有许多请求,所以我想避免将响应缓存在内存中只是为了传递它。
【问题讨论】:
在拨打ReadAsStreamAsync
之前,您是否厌倦了拨打LoadIntoBufferAsync
? Reference
你是如何注册你的HttpClient的?这样? services.AddSingleton当外部服务与 .Net async/await 一起工作时,有时会发生这种情况
我找到了解决方法(这不是最佳做法)但它对我有用。
public Task<IActionResult> GetArticleImage(string userId, string articleId)
var imageUrl = "https://image-url"; // This url is retrieved from the database
var imageResult = this.httpClient.GetAsync(imageUrl).GetAwaiter().GetResult();
var stream = imageResult.Content.ReadAsStreamAsync().GetAwaiter().GetResult();
return new FileStreamResult(stream, imageResult.Content.Headers.GetValues("Content-Type").First());
【讨论】:
以上是关于HttpClient在响应流完全读取之前被释放,导致连接关闭异常的主要内容,如果未能解决你的问题,请参考以下文章
释放 HttpClient 4.1.x 的连接以使用一个 HttpClient 实例顺序执行
对象在 PostAsync 与 HttpClient 之后被释放
在内容 100% 完成之前从 HttpResponseMessage 读取标头