容器化后无法执行断路器

Can't execute circuit breaker after containerization

我有一个 .NET 5 应用程序,分为微服务。我使用 Microsoft 库和 Polly 实现了断路器模式。

一切都在本地进行了相应的测试和工作。 但是当我尝试 运行 和 docker 时,如果微服务的 none 出现故障,它会完美运行,所有请求都有响应(预期的)。

相反,当我放下其中一个微服务并尝试测试并查看电路是否打开(获取包含该信息的响应)时,它只是超时,返回一个任务未完成的异常完成(超时)。

我该如何解决这个问题?我正在使用 运行 docker 的 http 端口,我试图禁用 Startup.cs 中的 httpsRedirection 以及使用 http 和 https 发出请求,但是 none 其中后者是成功的。我真的没主意了。下面是一个微服务示例(带有问题的相关代码)和相应的 docker 文件:

OrchAuth.cs:

services.AddControllers();
services.AddHttpClient<ISearchCommunicationServiceWatchables, SearchRESTCommunicationServiceWatchables>("Watchables")
     .SetHandlerLifetime(TimeSpan.FromMinutes(1))
     .AddPolicyHandler(GetRetryPolicy())
     .AddPolicyHandler(GetCircuitBreakerPolicy());
services.AddHttpClient<IUsersCommunicationService, UsersRESTCommunicationService>("Users")
     .SetHandlerLifetime(TimeSpan.FromMinutes(1))
     .AddPolicyHandler(GetRetryPolicy())
     .AddPolicyHandler(GetCircuitBreakerPolicy());
services.AddHttpClient<IUserPreferencesService, UserPreferencesService>("UserPreferences")
     .SetHandlerLifetime(TimeSpan.FromMinutes(1))
     .AddPolicyHandler(GetRetryPolicy())
     .AddPolicyHandler(GetCircuitBreakerPolicy());
services.AddHttpClient<ISearchCommunicationServiceBooks, SearchRESTComunicationServiceBooks>("Books")
     .SetHandlerLifetime(TimeSpan.FromMinutes(1))
     .AddPolicyHandler(GetRetryPolicy())
     .AddPolicyHandler(GetCircuitBreakerPolicy());
...
static IAsyncPolicy<HttpResponseMessage> GetRetryPolicy()
{
    Random jitterer = new ();
    return HttpPolicyExtensions
        .HandleTransientHttpError()
        .WaitAndRetryAsync(2, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt))  // exponential back-off: 2, 4, 8 etc
            + TimeSpan.FromMilliseconds(jitterer.Next(0, 1000))); // plus some jitter: up to 1 second);
}

static IAsyncPolicy<HttpResponseMessage> GetCircuitBreakerPolicy()
{
    return HttpPolicyExtensions
        .HandleTransientHttpError()
        .CircuitBreakerAsync(2, TimeSpan.FromSeconds(10));
}

docker 文件:

FROM mcr.microsoft.com/dotnet/aspnet:5.0 AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443

FROM mcr.microsoft.com/dotnet/sdk:5.0 AS build
WORKDIR /src
COPY ["boomoseries-OrchAuth-api/boomoseries-OrchAuth-api.csproj", "boomoseries-OrchAuth-api/"]
RUN dotnet restore "boomoseries-OrchAuth-api/boomoseries-OrchAuth-api.csproj"
COPY . .
WORKDIR "/src/boomoseries-OrchAuth-api"
RUN dotnet build "boomoseries-OrchAuth-api.csproj" -c Release -o /app/build

FROM build AS publish
RUN dotnet publish "boomoseries-OrchAuth-api.csproj" -c Release -o /app/publish

FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENV USERS_HOST=http://host.docker.internal:5020/Users
ENV PREFS_HOST=http://host.docker.internal:5024/UserPreferences/Favorites
ENV SEARCH_HOST=http://host.docker.internal:5018/api/v1/Search
ENTRYPOINT ["dotnet", "boomoseries-OrchAuth-api.dll"]

问题已解决。问题如下:断路器策略配置为处理 5XX 和 408 类型的 HTTP 错误,我没有收到任何这些作为响应(当 运行 docker 时):我正在“空白的”。这不会在本地发生,因为主机主动拒绝连接,能够触发并打开电路。所以为此,我不得不在 Polly 中配置超时策略,抛出异常并让断路器策略处理它(代码如下)。

 public static IAsyncPolicy<HttpResponseMessage> GetCircuitBreakerPolicy()
    {
        return HttpPolicyExtensions
            .HandleTransientHttpError()
            .Or<TimeoutRejectedException>()
            .CircuitBreakerAsync(2, TimeSpan.FromSeconds(10));
    }

另一个细节是在启动时配置的顺序:断路器策略必须在重试策略(下面的代码)之前实现。

public static IHttpClientBuilder ConfigHttpClient<TInterface, TClass>(this IServiceCollection services, string httpClientName)
        where TInterface : class
        where TClass : class, TInterface
    {

       return services.AddHttpClient<TInterface, TClass>(httpClientName)
           .AddPolicyHandler(Startup.GetCircuitBreakerPolicy())
           .AddPolicyHandler(Startup.GetRetryPolicy())
           .AddPolicyHandler(Policy.TimeoutAsync<HttpResponseMessage>(3));

    }