Polly 使用不同的请求主体重试请求

2024-03-22

我以前从未使用过 Polly,并且不确定这对 Polly 来说是否是一个好的场景。

我正在调用一个列表为 1000 的端点DTO in the POST身体。现在端点将对每个执行一些验证DTO如果其中任何 DTO 验证失败,则返回 HTTP 400 Bad Request,并且响应还将包含id所有的DTO验证失败。所以,即使一个DTO验证失败,我收到 HTTP 400 响应。

现在我想知道是否可以为通过验证的其余 DTO 优雅地处理这个问题。

因此,每当我从 API 获得 HTTP 400 时,我都想更改请求负载以删除DTO导致验证失败的 s 并使用剩余的重试请求DTOs.

我怎样才能通过 Polly 实现这一目标?

我正在使用打字机HttpClient using HttpClientFactory在 .NET 5 中使我的POST要求。


Polly 的重试策略执行完全相同的操作每当它触发时。因此,默认情况下您无法更改请求。

但你可以在里面修改onRetryAsyncdelegate,在实际重试发生之前触发。


为了演示这一点,我将使用WireMock.NET https://github.com/WireMock-Net/WireMock.Net库来模仿您的下游系统。

因此,首先让我们创建一个网络服务器,它监听40000端口上的localhost at the /api route:

protected const string route = "/api";
protected const int port = 40_000;

protected static readonly WireMockServer server = WireMockServer.Start(port);
protected static readonly IRequestBuilder endpointSetup = Request.Create().WithPath(route).UsingPost();

然后设置一个scenario http://wiremock.org/docs/stateful-behaviour/模拟第一个请求失败,返回 400,第二个请求成功,返回 200。

protected const string scenario = "polly-retry-test";
server.Reset();
server
    .Given(endpointSetup)
    .InScenario(scenario)
    .WillSetStateTo(1)
    .WithTitle("Failed Request")
    .RespondWith(Response.Create().WithStatusCode(HttpStatusCode.BadRequest));

server
    .Given(endpointSetup)
    .InScenario(scenario)
    .WhenStateIs(1)
    .WithTitle("Succeeded Request")
    .RespondWith(Response.Create().WithStatusCode(HttpStatusCode.OK));

我们来测试一下

protected static readonly HttpClient client = new HttpClient();
var result = await client.PostAsync($"http://localhost:{port}{route}", new StringContent(""));
Console.WriteLine(result.StatusCode);

result = await client.PostAsync($"http://localhost:{port}{route}", new StringContent(""));
Console.WriteLine(result.StatusCode);

输出如下:

BadRequest
OK

好的,现在我们有了一个下游模拟器,现在是时候关注重试策略了。为了简单起见,我将序列化List<int>集合将其作为有效负载发布。

我设置了每当收到 400 时重试,然后在其onRetryAsync委托我检查响应并删除不需要的整数。

AsyncRetryPolicy<HttpResponseMessage> retryInCaseOfPartialSuccess = Policy
    .HandleResult<HttpResponseMessage>(r => r.StatusCode == HttpStatusCode.BadRequest)
    .RetryAsync(1, onRetryAsync: (dr, _, __) => {

        //TODO: Process response from: `dr.Result.Content`
        //TODO: Replace the removal logic to appropriate one
        dtoIds.RemoveAt(0);
        return Task.CompletedTask;
    });

让我们使用修饰后的重试策略调用下游 API:

await retryInCaseOfPartialSuccess.ExecuteAsync(async (_) => {
    var payload = JsonSerializer.Serialize(dtoIds);
    Console.WriteLine(payload); //Only for debugging purposes
    return await client.PostAsync($"http://localhost:{port}{route}", new StringContent(payload));
}, CancellationToken.None);

让我们把所有这些放在一起:

protected const string scenario = "polly-retry-test";
protected const string route = "/api";
protected const int port = 40_000;
protected static readonly WireMockServer server = WireMockServer.Start(port);
protected static readonly IRequestBuilder endpointSetup = Request.Create().WithPath(route).UsingPost();
protected static readonly HttpClient client = new HttpClient();

private static async Task Main()
{
    server.Reset();
    server
        .Given(endpointSetup)
        .InScenario(scenario)
        .WillSetStateTo(1)
        .WithTitle("Failed Request")
        .RespondWith(Response.Create().WithStatusCode(HttpStatusCode.BadRequest));

    server
        .Given(endpointSetup)
        .InScenario(scenario)
        .WhenStateIs(1)
        .WithTitle("Succeeded Request")
        .RespondWith(Response.Create().WithStatusCode(HttpStatusCode.OK));

    //var result = await client.PostAsync($"http://localhost:{port}{route}", new StringContent(""));
    //Console.WriteLine(result.StatusCode);

    //result = await client.PostAsync($"http://localhost:{port}{route}", new StringContent(""));
    //Console.WriteLine(result.StatusCode);

    await IssueRequestAgainstDownstream(new List<int> { 1, 2 });
}

private static async Task IssueRequestAgainstDownstream(List<int> dtoIds)
{
    AsyncRetryPolicy<HttpResponseMessage> retryInCaseOfPartialSuccess = Policy
        .HandleResult<HttpResponseMessage>(response => response.StatusCode == HttpStatusCode.BadRequest)
        .RetryAsync(1, onRetryAsync: (dr, _, __) => {
            //TODO: Process response from: `dr.Result.Content`
            //TODO: Replace the removal logic to appropriate one
            dtoIds.RemoveAt(0);
            return Task.CompletedTask;
        });

    await retryInCaseOfPartialSuccess.ExecuteAsync(async (_) => {
        var payload = JsonSerializer.Serialize(dtoIds);
        Console.WriteLine(payload); //Only for debugging purposes
        return await client.PostAsync($"http://localhost:{port}{route}", new StringContent(payload));
    }, CancellationToken.None);
}

那么,我们做了什么?

  • 创建了一个下游模拟来模拟 400 和 200 个后续响应
  • 创建了一个重试策略,如果收到 400,可以修改请求的有效负载
  • 将序列化逻辑和 http 调用放入重试中,以便我们始终可以序列化最新的对象列表
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Polly 使用不同的请求主体重试请求 的相关文章

  • 是否有与 posix_memalign 对应的 C++ 版本?

    当我打电话时posix memalign http man7 org linux man pages man3 posix memalign 3 html为类型的对象分配对齐的内存Foo在我的 C 代码中 我需要做一个reinterpret
  • 当我在组合框中选择一个项目时,如何防止 TextChanged 事件?

    我有一个TextChanged http msdn microsoft com en us library system windows forms control textchanged aspx我的事件ComboBox http msd
  • 使用 lambda 表达式注册类型

    我想知道如何在 UnityContainer 中实现这样的功能 container RegisterType
  • 使用 C# 登录《我的世界》

    我正在尝试为自己和一些朋友创建一个简单的自定义 Minecraft 启动器 我不需要启动 Minecraft 的代码 只需要登录的实际代码行 例如 据我所知 您过去可以使用 string netResponse httpGET https
  • C++ 是否可以在 MacOS 上与 OpenMP 和 boost 兼容?

    我现在已经尝试了很多事情并得出了一些结论 也许 我监督了一些事情 但似乎我无法完成我想要的事情 问题是 是否有可能使用 OpenMP 和 boost 在 MacOS High Sierra 上编译 C 一些发现 如果我错了请纠正我 Open
  • 从同一个类中的另一个构造函数调用构造函数

    我有一个带有两个构造函数的类 C 这是代码片段 public class FooBar public FooBar string s constructor 1 some functionality public FooBar int i
  • C# 数据表更新多行

    我如何使用数据表进行多次更新 我找到了这个更新 1 行 http support microsoft com kb 307587 my code public void ExportCSV string SQLSyntax string L
  • 使用可变参数包类型扩展的 C++ 函数调用者包装器

    我绑定了一些 API 并且绑定了一些函数签名 如下所示 static bool WrapperFunction JSContext cx unsigned argc JS Value vp 我尝试将对象和函数包装在 SpiderMonkey
  • Python 属性和 Swig

    我正在尝试使用 swig 为一些 C 代码创建 python 绑定 我似乎遇到了一个问题 试图从我拥有的一些访问器函数创建 python 属性 方法如下 class Player public void entity Entity enti
  • 在Linux中,找不到框架“.NETFramework,Version=v4.5”的参考程序集

    我已经设置了 Visual studio 来在我的 Ubuntu 机器上编译 C 代码 我将工作区 我的代码加载到 VS 我可以看到以下错误 The reference assemblies for framework NETFramewo
  • 打破 ReadFile() 阻塞 - 命名管道 (Windows API)

    为了简化 这是一种命名管道服务器正在等待命名管道客户端写入管道的情况 使用 WriteFile 阻塞的 Windows API 是 ReadFile 服务器已创建启用阻塞的同步管道 无重叠 I O 客户端已连接 现在服务器正在等待一些数据
  • 在视口中查找 WPF 控件

    Updated 这可能是一个简单或复杂的问题 但在 wpf 中 我有一个列表框 我用一个填充数据模板从列表中 有没有办法找出特定的数据模板项位于视口中 即我已滚动到其位置并且可以查看 目前我连接到了 listbox ScrollChange
  • 为什么我的单选按钮不起作用?

    我正在 Visual C 2005 中开发 MFC 对话框应用程序 我的单选按钮是 m Small m Medium 和 m Large 它们都没有在我的 m Summary 编辑框中显示应有的内容 可能出什么问题了 这是我的代码 Pizz
  • 等待 IAsyncResult 函数直至完成

    我需要创建等待 IAsyncResult 方法完成的机制 我怎样才能做到这一点 IAsyncResult result contactGroupServices BeginDeleteContact contactToRemove Uri
  • WPF DataGridTemplateColumn 组合框更新所有行

    我有这个 XAML 它从 ItemSource 是枚举的组合框中选择一个值 我使用的教程是 http www c sharpcorner com uploadfile dpatra combobox in datagrid in wpf h
  • 打印大型 WPF 用户控件

    我有一个巨大的数据 我想使用 WPF 打印 我发现WPF提供了一个PrintDialog PrintVisual用于打印派生的任何 WPF 控件的方法Visual class PrintVisual只会打印一页 因此我需要缩放控件以适合页面
  • WebBrowser.Print() 等待完成。 。网

    我在 VB NET 中使用 WebBrowser 控件并调用 Print 方法 我正在使用 PDF 打印机进行打印 当调用 Print 时 它不会立即启动 它会等到完成整个子或块的运行代码 我需要确保我正在打印的文件也完整并继续处理该文件
  • C++ new * char 不为空

    我有一个问题 我在 ASIO 中开发服务器 数据包采用尖头字符 当我创建新字符时 例如char buffer new char 128 我必须手动将其清理为空 By for int i 0 i lt 128 i buffer i 0x00
  • OpenGL:仅获取模板缓冲区而没有深度缓冲区?

    我想获取一个模板缓冲区 但如果可能的话 不要承受附加深度缓冲区的开销 因为我不会使用它 我发现的大多数资源表明 虽然模板缓冲区是可选的 例如 排除它以利于获得更高的深度缓冲区精度 但我还没有看到任何请求并成功获取仅 8 位模板缓冲区的代码
  • 实体框架中的“it”是什么

    如果以前有人问过这个问题 请原谅我 但我的任何搜索中都没有出现 它 我有两个数据库表 Person 和 Employee 对每个类型的表进行建模 例如 Employee is a Person 在我的 edmx 设计器中 我定义了一个实体

随机推荐

  • 多索引 pandas 更新

    有两个数据帧 df1 和 df2 import pandas as pd import numpy as np import datetime A list range 3 9 B datetime date 2019 1 1 dateti
  • 单元测试复杂交互的正确方法

    我必须开始使用 QualityTools UnitTestFramework 为我们开发的 Web 服务层编写一些单元测试 而我的方法从一开始似乎就不正确 单元测试似乎应该能够以任何顺序运行 而不依赖于其他测试 我最初的想法是拥有类似于以下
  • 错误:由于表单未连接,表单提交被取消

    关于潜在重复的免责声明 我也遇到过类似的问题 我想我现在已经阅读了几乎所有这些答案 但没有一个为我解决了问题 我有一个应用程序 前端是 React 后端是 Flask 服务器 我有一个重大问题 该代码似乎检查了前端和后端 但是当我单击表单的
  • R - 如何分割文本和标点符号但有例外?

    在 R 中分析 Facebook 评论进行情感分析 表情符号是在 符号之间的文本编码 例子 Jesus te ama
  • 使用 jQuery 的 GridView 向上和向下导航

    我正在尝试使用 jQuery 实现 GridView 向上和向下键盘导航功能 我已经为此编写了代码 但有一个错误 它只能工作一次 重现错误的步骤 将我的示例代码复制到您的 WebForm aspx 和 WebForm aspx cs 后 分
  • 在 C# 中向 DateTime 添加时间

    我有一个日历和一个包含一天中某个时间的文本框 我想创建一个由两者组合而成的日期时间 我知道我可以通过查看小时和分钟然后将它们添加到日历 DateTime 中来做到这一点 但这看起来相当混乱 有没有更好的办法 您可以使用日期时间 添加 htt
  • jquery中如何定义变量

    我想知道如何在 jQuery 中声明变量 我当前使用的代码是 name anirudha alert name 该代码工作正常 但如果我将其写为 name document myForm txtname value alert name 那
  • HttpListener 的使用

    我有以下 HTTP 侦听器方法 深受 MSDN 使用 HttpListener 类的示例的启发 我对编程相当陌生 我不知道从这里到哪里从我的 Main 初始化它 有什么建议么 public static void HttpListener
  • 使用 typegoose 将项目添加到 Ref 数组

    我延长了 2 个课程Typegoose Item and Player In the Player我的班级有一个数组Ref
  • 为 VS2022 构建扩展时出现有关 ProductArchitecture 的错误 VSSDK1311

    我正在构建 VSIX 项目并看到以下错误消息 VSSDK1311 vsixmanifest 必须包含 PackageManifest Installation InstallTarget ProductArchitecture 的值 我需要
  • 传递参数以包含在 Liquid 模板中

    在我的 Jekyll 支持的网站上 我有一个包含函数 可以执行类似功能的操作 但我不知道如何正确传递它的参数 当我使用 include 像这样传递参数 include function liquid foo baz quux 它只是传递文字
  • 从网络驱动器启动时,Structuremap 不加载注册表

    我是 Structuremap 的热心 新 用户 但我在加载注册表时遇到问题 当我从本地驱动器启动应用程序时 应用程序中的所有注册表都用于解析类型 我通过 ObjectFactory WhatDoIHave 验证了这一点 但是 当我从共享启
  • 如何隐藏 VsCode 滚动条?

    VsCode 中似乎曾经有一个隐藏滚动条的设置 editor scrollbar vertical hidden 但是 这似乎已被弃用 现在我收到错误Unknown configuration setting VsCode 中有隐藏滚动条的
  • LibGit2Sharp CheckoutPaths()

    我做了一次提交 49916 现在我想将提交的一个文件检出到工作目录中 该文件名为 NEW txt 如果我输入 Git 签出 49916 NEW txt 进入 Git Bash 后 它会创建 NEW txt 文件 其内容位于我的工作目录中 但
  • 非重叠串行端口挂在 CloseHandle 处

    我编写了一个自己开发的串行端口类 为了简单起见 我使用了阻塞 同步 不重叠 我浏览了所有 MSDN 文档 这对我来说很困难 我在从端口打开 传输或接收字节方面没有任何问题 所有操作都是同步并且不存在线程复杂性 function TSeria
  • Crystal Reports 11 - 添加无用的空白页,仅添加有数据的组标题

    我遇到了一个在使用 Crystal Reports 之前从未见过的奇怪问题 我为一家银行制作了一份复杂的 PDF 月度报告 生成了 200 多页 这些规范花了几个月的时间与客户进行调整 但现在它工作得很好 显示了所有应该显示的数据 所有数据
  • Kubernetes API 服务器日志中的 TLS 握手错误

    我正在研究一个AWS 中 Kubernetes 集群的 terraform 配置 https github com ericandrewlewis kubernetes via terraform 我已经让集群运行起来了 我可以通过 kub
  • 是否有通用方法将约束应用于类型应用程序?

    A comment https stackoverflow com questions 41111715 making a constraint of maybe a where eq a 41111825 noredirect 1 com
  • 不使用循环操作数组

    学习 VBA for Excel 我尝试在不使用循环的情况下完成尽可能多的编码 作为练习 将两个相邻范围的数字相乘 我想出了这个 Sub multiply range Dim a b c As Range Set a Range a1 a5
  • Polly 使用不同的请求主体重试请求

    我以前从未使用过 Polly 并且不确定这对 Polly 来说是否是一个好的场景 我正在调用一个列表为 1000 的端点DTO in the POST身体 现在端点将对每个执行一些验证DTO如果其中任何 DTO 验证失败 则返回 HTTP