容器化后无法执行断路器



我有一个。net 5应用程序,分为多个微服务。我使用Microsoft库和Polly实现了Circuit Breaker模式。

一切都经过测试,并相应地在本地工作。但是当我尝试用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"]

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

最新更新