首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Polly回退策略导致"ObjectDisposedException:无法访问封闭流“--第二次回退在ASP.NET核心3.1上激活

Polly回退策略导致"ObjectDisposedException:无法访问封闭流“--第二次回退在ASP.NET核心3.1上激活
EN

Stack Overflow用户
提问于 2020-05-09 21:04:17
回答 1查看 604关注 0票数 1

我正在编写一个REST,它使用Polly弹性策略调用另一个REST。我第一次得到了可以正常工作的后备策略,但是第二次触发它会抛出一个错误:

代码语言:javascript
复制
System.IO.StreamHelpers.ValidateCopyToArgs(Stream source, Stream destination, int bufferSize)
System.IO.MemoryStream.CopyToAsync(Stream destination, int bufferSize, CancellationToken cancellationToken)
System.IO.Stream.CopyToAsync(Stream destination)
ProxyBase.HttpResponseMessageResult.ExecuteResultAsync(ActionContext context) in HttpResponseMessageResult.cs
+                await stream.CopyToAsync(context.HttpContext.Response.Body);
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResultFilterAsync>g__Awaited|29_0<TFilter, TFilterAsync>(ResourceInvoker invoker, Task lastTask, State next, Scope scope, object state, bool isCompleted)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResultExecutedContextSealed context)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.ResultNext<TFilter, TFilterAsync>(ref State next, ref Scope scope, ref object state, ref bool isCompleted)

HttpResponseMessageResult类是客户端在回退处理程序中返回的HttpResponseMessage到控制器方法所期望的IActionResult的自定义转换器。下面是抛出异常的方法的代码:

代码语言:javascript
复制
        context.HttpContext.Response.StatusCode = (int)_responseMessage.StatusCode;

        using (var stream = await _responseMessage.Content.ReadAsStreamAsync())
        {
            await stream.CopyToAsync(context.HttpContext.Response.Body);
            await context.HttpContext.Response.Body.FlushAsync();
        }

我的政策是:

代码语言:javascript
复制
                var fallbackPolicy = Policy<HttpResponseMessage>.Handle<Exception>()
                .OrResult(r => r.StatusCode == System.Net.HttpStatusCode.RequestTimeout)
                .FallbackAsync(
                    GetFailoverResponse(fallbackUrl),
                    (ct,cx) => {
                            HttpClient client = new HttpClient();
                              return client.GetAsync(fallbackUrl + ct.Result.RequestMessage.RequestUri.AbsolutePath);
                        });
                clientBuilder.AddPolicyHandler(fallbackPolicy);

我第二次检查返回的HttpResponseMessage是否新鲜--它是唯一的,当我添加一个随机参数时,我可以看到queryString是不同的。

我还尝试将实际的失败调用直接替换为回退调用(即将Polly从等式中提取出来)--就像这样,它工作得很好,因此,出于某种原因,polly用一个封闭的流来传递HttpResponseMessage。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-05-12 10:40:19

这个问题似乎与(Ab)使用FallbackAsync方法的第二个参数有关:它的目的是在返回回退结果之前运行,而不是生成结果本身,这就是我在上面代码的坏版本中所做的。

该方法具有不同的过载,但它们大多支持两个参数,并且精确数据类型不同: fallbackResult和onFallbackAsync。在这个中断的示例中,我返回一个静态fallbackResult作为备份,即使我的onFallbackAsync委托返回任务。我(错误的)理解是,这将是将由策略返回的HTTP响应。显然,在引擎盖下,它实际上是返回静态响应,在第二次使用时,它的流已经被读取了。

解决方案是使用第一个参数的另一个重载,该重载不会返回静态HttpResponseMessage,而是将HTTP上下文传递给可以执行回退HTTP请求的lambda,如下所示:

代码语言:javascript
复制
    var fallbackPolicy = Policy<HttpResponseMessage>.Handle<Exception>()
    .OrResult(r => r.StatusCode == System.Net.HttpStatusCode.RequestTimeout)
    .FallbackAsync(
        (res, cx, ct) => {
            HttpClient client = new HttpClient();
            return client.GetAsync(fallbackUrl + res.Result.RequestMessage.RequestUri.AbsolutePath);
        },
        (ct, cx) =>
        {
            return Task.CompletedTask;
        });
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61703707

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档