集装箱化后不能执行断路器

llew8vvj  于 2022-10-04  发布在  Docker
关注(0)|答案(1)|浏览(110)

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

所有东西都经过了测试,并相应地在本地运行。但当我尝试使用docker运行时,如果没有一个微服务关闭,它就会完美地工作,所有请求都有响应(预期的请求)。

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

我怎么才能解决这个问题?我正在使用http端口运行docker,我尝试禁用Startup.cs中的httpsRedirection,并使用http和https发出请求,但后者均未成功。我在这里真的没有主意了。下面是一个微服务的示例(带有问题的相关代码)和相应的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"]
ivqmmu1c

ivqmmu1c1#

问题已经解决了。问题如下:断路器策略被配置为处理类型为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));

    }

相关问题