Polly 使用不同的 url 重试

2023-12-11

我正在尝试使用 polly 创建一个解决方案,其中我请求其他 api。
我有同一服务的多个实例的 URL 列表。
我希望当第一个请求失败时,另一个请求应该自动从我的列表中的下一个网址开始。

这是一个示例,我使用两个静态地址尝试此行为
此解决方案的问题是,在我开始下一个请求之前,网址不会更改。 我希望每次重试时网址都会改变

 public static void ConfigureUserServiceClient(this IServiceCollection services)
    {

        _userServiceUri = new Uri("https://localhost:5001");

        services.AddHttpClient("someService", client =>
        {
            client.BaseAddress = _userServiceUri;
            client.DefaultRequestHeaders.Add("Accept", "application/json");
        }).AddPolicyHandler(retryPolicy());
    }

    private static IAsyncPolicy<HttpResponseMessage> retryPolicy()
    {
        return Policy.HandleResult<HttpResponseMessage>(r => r.StatusCode == HttpStatusCode.RequestTimeout)
            .WaitAndRetryAsync(3, retryAttempt => TimeSpan.FromSeconds(retryAttempt),
            onRetry: (result, span, ctx) =>
            {
                _userServiceUri = new Uri("https://localhost:5002");
            });
    }

您应该考虑使用Fallback政策代替。

像这样:

private static HttpClient client = new HttpClient();
static async Task Main(string[] args)
{
    var addressIterator = GetUrls().GetEnumerator();

    var retryLikePolicy = Policy<string>
        .Handle<HttpRequestException>()
        .FallbackAsync(fallbackAction: async (ct) =>
        {
            if (addressIterator.MoveNext())
               return await GetData(addressIterator.Current);
            return null;
        });

    addressIterator.MoveNext();
    var data = await retryLikePolicy.ExecuteAsync(
       async () => await GetData(addressIterator.Current));

    Console.WriteLine("End");
}

static async Task<string> GetData(string uri)
{
    Console.WriteLine(uri);
    var response = await client.GetAsync(uri);
    return await response.Content.ReadAsStringAsync();
}

static IEnumerable<string> GetUrls()
{
    yield return "http://localhost:5500/index.html";
    yield return "http://localhost:5600/index.html";
    yield return "http://localhost:5700/index.html";
}

请注意,此代码仅用于演示。


更新#1: 多重后备

如果您有多个后备网址,那么您可以像这样更改上述代码:

private static HttpClient client = new HttpClient();
static async Task Main(string[] args)
{
    var retryInCaseOfHRE = Policy
        .Handle<HttpRequestException>()
        .WaitAndRetryForeverAsync(_ => TimeSpan.FromSeconds(1));

    var response = await retryInCaseOfHRE.ExecuteAsync(
         async () => await GetNewAddressAndPerformRequest());
    
    if (response == null)
    {
        Console.WriteLine("All requests failed");
        Environment.Exit(1);
    }

    Console.WriteLine("End");
}

static IEnumerable<string> GetAddresses()
{
    yield return "http://localhost:5500/index.html";
    yield return "http://localhost:5600/index.html";
    yield return "http://localhost:5700/index.html";
    yield return "http://localhost:5800/index.html";
}

static readonly IEnumerator<string> AddressIterator = GetAddresses().GetEnumerator();

static async Task<string> GetNewAddressAndPerformRequest()
    => AddressIterator.MoveNext() ? await GetData(AddressIterator.Current) : null;

static async Task<string> GetData(string uri)
{
    Console.WriteLine(uri);
    var response = await client.GetAsync(uri);
    return await response.Content.ReadAsStringAsync();
}
  • The trick: the retry policy wraps a method which is responsible to retrieve the next url and then call the GetData
    • 换句话说,我们需要将迭代过程移至要包装的方法中(GetNewAddressAndPerformRequest)
  • 我已经更换了Fallback政策Retry因为我们需要(可能)执行超过 1 个后备操作
  • 我用过null表明我们已经用完了后备网址,但为此使用自定义异常可能是更好的解决方案
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Polly 使用不同的 url 重试 的相关文章

随机推荐

  • 分割十六进制的最佳方法?

    一般来说 我对十六进制还很陌生 并且我有一个应用程序需要我分割十六进制数 例如 给定数字 0x607F 我需要返回高 0x60 或低 0x7F 字节 这是可能的实现 但感觉有点麻烦 在 python 中是否有更标准的方法来做到这一点 def
  • 使用 jq 将对象的嵌套 JSON 转换为数组到 bash 数组

    我正在做一些根本错误的事情 但只是看不出是什么 有人可以指出我在 jq 或 JSON 方面的错误吗 我在数组中包含以下子对象 entries profile name TesterRun1 download entries ENTRY A
  • 使用 SIMD,如何有条件地仅移动 alpha 通道值为 255 的像素?

    我目前正在向量化一些代码以使用 AVX2 内在函数存储 32 位像素数据 由于 AVX2 寄存器是 256 位 因此我可以同时操作 8 个像素 我目前的代码可以从一个缓冲区加载 8 个像素 然后将它们存储到另一个缓冲区 Load 256 b
  • 实体框架级联删除

    首先 如果我在这里遗漏了一些基本的东西 我深表歉意 但我是 EF 的新手 并且仍然首先考虑设置数据库代码 我遇到了与此类似的问题引入 FOREIGN KEY 约束可能会导致循环或多条级联路径但似乎无法从那里的评论中找出我需要对我的特定模型做
  • 如何在awk中将驼峰式字符串拆分为数组?

    如何使用 split 函数将驼峰式字符串拆分为 awk 中的数组 Input STRING camelCasedExample 期望的结果 WORDS 1 camel WORDS 2 Cased WORDS 3 Example 糟糕的尝试
  • 实体框架代码优先迁移认为存在不应该存在的更改

    我有一个网站和一个 Windows 服务 它们都引用同一个项目来获取实体框架数据上下文 每次启动 Windows 服务时 实体框架都会运行自动迁移 将数据库列之一从 NOT NULL 更改为 NULL 不进行其他更改 该列的属性被标记为 R
  • 如何使用R中的函数替换数据框中的字符值

    我有一个数据框 max1 max2 max3 max4 max5 max6 max7 max8 max9 max10 x9 x8 x7 x6 x10 x5 x4 x2 x1 x3 x5 x3 x4 x6 x10 x1 x7 x2 x8 x9
  • Pandas:混合数据类型的列;如何找到异常情况

    我有一个很大的数据框 当阅读它时 它给了我这样的消息 DtypeWarning 列 0 8 具有混合类型 导入时指定 dtype 或设置 low memory False 它应该是一列浮标 但我怀疑里面藏着几根绳子 我想识别它们 并可能删除
  • 当CPU处于内核模式时,它可以读写任何寄存器吗?

    当CPU处于内核模式时 它可以读写任何寄存器吗 或者是否有一些寄存器即使在内核模式下也无法访问 在 x86 上 没有分组寄存器 因此所有寄存器在架构上同时可见 是的 在内核模式 环 0 下 x86 可以写入任何寄存器 只要内核运行在64位模
  • 无重叠的圆检测

    我想在以下条件下进行圆检测 重叠圆将计为 1 个圆 Particularly when I do circle detection and put the letter P to every circle actually they are
  • 如何从 Azure DB 表获取数据到 Android 应用程序?

    我是 Azure 新手 我不知道如何连接到我在 Azure 数据库上创建的表 我想获取表数据 SELECT 并将它们填充到 android 的 GridView 中 我知道使用适配器的 填充 部分 我想知道的是如何连接并接收表中的数据 我试
  • 编译器如何处理编译时分支?

    EDIT 我以 if else 情况为例 有时可以在编译时解决 例如 当涉及静态值时 参见
  • SQL - 在分组依据中使用别名

    只是对 SQL 语法感到好奇 所以如果我有 SELECT itemName as ItemName substring itemName 1 1 as FirstLetter Count itemName FROM table1 GROUP
  • JQuery ajax 文件上传到 ASP.NET 并包含所有表单数据

    我正在构建一个网站 该网站有一个职业页面 其中包含用于简历上传的输入文件 HTML 控件 使用 JQuery 将表单值 POST 到 ASPX 页面时 除了文件上传之外 一切正常 如何使用 JQuery 发布一个 AJAX 请求中的每个字段
  • ChartJS 3+ x 轴仅显示完整的时刻对象而不是仅显示月份

    我试图使用 momentjs 在图表的 x 轴上仅显示月份和年份 但它只是将看起来完整的时刻日期放在 x 轴上 我一直在看很多人这样做的例子 但他们似乎都不能在最新版本的 Chartjs 中工作 我知道我已经包含了与 momentjs 一起
  • 未定义的属性测试 Lit typescript Web 组件

    我最近将一个lit web组件转换为Typescript 似乎无法弄清楚为什么我的测试现在失败了 在转换之前一切都工作正常 这些是我的测试依赖项 open wc testing 3 1 2 web dev server esbuild 0
  • 如何通过打开文件来打开用户界面

    我在用 Private Sub start Click UserForm1 Show End Sub 通过按开始按钮打开我的用户界面 但是 我希望当我刚刚打开 Excel 文件时 我的用户界面能够自动打开 有谁知道我该怎么做 在工作簿代码窗
  • 如何将“使用”数据库传递给 django 连接对象

    要查询 django 中的特定数据库 我可以这样做 Item objects using specific db all 有没有办法使用 django 连接来做同样的事情 例如 gt gt gt from django db import
  • 实现更改事件以检查文本框值的更改并启用“应用”按钮

    我需要你的帮助 Excel VBA 是否可以为所有文本框和组合框的指定用户窗体应用某种全局更改事件处理程序 我知道可以一对一地完成它们 但是如果您有大约 20 个文本框 那么为每个用户窗体控件编写代码 change 就太过分了 不是吗 我本
  • Polly 使用不同的 url 重试

    我正在尝试使用 polly 创建一个解决方案 其中我请求其他 api 我有同一服务的多个实例的 URL 列表 我希望当第一个请求失败时 另一个请求应该自动从我的列表中的下一个网址开始 这是一个示例 我使用两个静态地址尝试此行为此解决方案的问