容器化后无法执行断路器
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));
}
我有一个 .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));
}