确定订阅的哪个 GRPC 服务已关闭 .NET 7

Identify which GRPC service subscribed is down .NET 7

提问人:Yago Oliveira 提问时间:8/23/2023 最后编辑:Yago Oliveira 更新时间:8/24/2023 访问量:92

问:

我有这个用于订阅 GRPC 流服务的实现,但是,我必须确定其中一个服务何时关闭并调用事件以通知 UI。

public async Task Subscribe()
{
     await Policy
          .Handle<RpcException>(e => e.Status.StatusCode == StatusCode.Unavailable)
          .WaitAndRetryAsync(
                    10,
                    attempt => TimeSpan.FromSeconds(Math.Pow(2, attempt)),
                    onRetry: (e, ts) => {
                        logger.Warning("Subscription connection lost. Trying to reconnect in {Seconds}s!", ts.Seconds);

                    })
          .ExecuteAsync(() => {
               IAsyncEnumerable<Notification> stream = await subscribe.Subscribe(currentUser)
               await foreach (Notification? ev in stream)
               {
                    switch (reply.ActionCase)
                    {
                        case Notification.ActionOneofCase.Service1:
                            logger.Warning("Incoming reply 'Service1'");
                            break;

                        case Notification.ActionOneofCase.Service2:
                            //TODO:
                            break;
                    }
            }
     });
}

我尝试使用polly,但我不知道如何在一个特定服务关闭时获取。我需要确定其中一个服务何时关闭以通知 UI。识别哪个服务关闭的最佳方法是什么?

编辑:

这就是每个服务的注入方式:

private static void AddGrpcService<T>(IServiceCollection services,
                                        Config config) where T : class
{
    SocketsHttpHandler socketsHandler = new SocketsHttpHandler()
    {
        PooledConnectionIdleTimeout = Timeout.InfiniteTimeSpan,
        KeepAlivePingDelay = TimeSpan.FromSeconds(60),
        KeepAlivePingTimeout = TimeSpan.FromSeconds(30),
        EnableMultipleHttp2Connections = true
    };

    MethodConfig defaultMethodConfig = new MethodConfig
    {
        Names = { MethodName.Default },
        RetryPolicy = new RetryPolicy
        {
            MaxAttempts = 5,
            InitialBackoff = TimeSpan.FromSeconds(1),
            MaxBackoff = TimeSpan.FromSeconds(5),
            BackoffMultiplier = 1.5,
            RetryableStatusCodes = { StatusCode.Unavailable }
        }
    };

    ServiceConfig serviceConfig = new() { MethodConfigs = { defaultMethodConfig } };
    services.AddGrpcClient<T>(o => {
        o.Address = new Uri(config.GrpcUrl);
    })
            .ConfigureChannel(o => {
                o.Credentials = GetGrpcClientCredentials(config);
                o.ServiceConfig = serviceConfig;
            })
            .ConfigurePrimaryHttpMessageHandler(() => socketsHandler);
}
c# .net-7.0 波莉 重试逻辑 GRPC-C型#

评论

0赞 Peter Csala 8/23/2023
你能澄清一下你卡在哪里吗?在确定下游服务是否已关闭时遇到问题?您想知道应该在何处以及如何触发通知吗?还是别的什么?

答:

1赞 Peter Csala 8/23/2023 #1

在确定下游服务是否已关闭时遇到问题?

在 和 Polly 集成的情况下,有一个称为 HandleTransientHttpError 的静态方法。每当状态代码为 408 或 5xx 时,就会触发此操作。这也会在 .HttpClientHttpRequestException

请记住,它不会触发 429(请求过多)等状态代码,这也可能表明下游服务已过载。

最初,我会建议拍摄一些类似的状态代码。但是由于我不熟悉 GRPC,所以我最好根据文档和这个特使问题在这里猜测。

readonly StatusCode[] RetriableStatusCodes = new[] 
{ 
  StatusCode.Cancelled, 
  StatusCode.DeadlineExceeded, 
  StatusCode.ResourceExhausted
};

...
await Policy
      .Handle<RpcException>(e => RetriableStatusCodes.Contains(e.Status.StatusCode))
      ...

您想知道应该在何处以及如何触发通知吗?

或可能是触发通知的最佳位置。onRetryonRetryAsync

如果策略将触发并在睡眠之前调用这些用户委托。

换句话说,如果初始尝试失败并且谓词被计算为 ,那么它将调用委托。委托完成后,它将在第一次重试尝试之前进入睡眠状态。HandletrueonRetry(Async)

不会被调用onRetry(Async)

  • 如果谓词的计算结果为Handlefalse
  • 如果超过最大重试次数,则无论Handle