问题描述
public override async Task<TResponse> UnaryServerHandler<TRequest,TResponse>(
TRequest request,ServerCallContext context,UnaryServerMethod<TRequest,TResponse> continuation)
{
try
{
return await continuation(request,context);
}
catch (Exception ex)
{
LogAndRethrowException(ex);
return null; // keep compiler happy
}
}
LogAndRethrowException 的相关部分如下所示:
s_log.Debug("Unhandled Exception processing gRPC request",ex);
throw new RpcException(new Status(
StatusCode.UnkNown,"Intercepted Unhandled: " + ex.Message));
这工作正常。我在客户端收到异常,并且可以执行我需要在那里执行的必要处理,而且我正在将其记录在服务器上。
我现在需要修改它以使服务器应用程序崩溃,因为这是我工作的政策。但是我仍然需要在客户端获取异常。
在 gRPC 处理 RpcException 并将响应通过线路发送到客户端之后,现有的 gRPC 库中是否有任何方法可以立即挂钩(或获取某种回调)该点?
我确实可以访问服务器端使用的同步上下文,并且可以向其发送 Post 以使其抛出异常。但是,这可能不可靠,因为此时在拦截器中我实际上不在此同步上下文中,因此服务器可能会过早崩溃。 (另一方面,理想情况下,我希望它在将异常响应返回给客户端后立即崩溃,并且同步上下文可能有其他内容排队......)
我一直在寻找 ServerCallContext 中的钩子,或者尝试创造性地使用延续的方法,但我找不到任何好的解决方案。
我确实查看了实际处理异常并发送状态的代码,看看那里是否有任何提示。
在 ServerCallHandler.cs 中,HandleCall 方法如下所示:
public async Task HandleCall(ServerRpcNew newRpc,CompletionQueueSafeHandle cq)
{
var asyncCall = new AsyncCallServer<TRequest,TResponse>(
method.ResponseMarshaller.ContextualSerializer,method.RequestMarshaller.ContextualDeserializer,newRpc.Server);
asyncCall.Initialize(newRpc.Call,cq);
var finishedTask = asyncCall.ServerSideCallAsync();
var requestStream = new ServerRequestStream<TRequest,TResponse>(asyncCall);
var responseStream = new ServerResponseStream<TRequest,TResponse>(asyncCall);
Status status;
AsyncCallServer<TRequest,TResponse>.ResponseWithFlags? responseWithFlags = null;
var context = HandlerUtils.NewContext(newRpc,responseStream,asyncCall.CancellationToken);
try
{
GrpcPreconditions.CheckArgument(await requestStream.MoveNext().ConfigureAwait(false));
var request = requestStream.Current;
var response = await handler(request,context).ConfigureAwait(false);
status = context.Status;
responseWithFlags = new AsyncCallServer<TRequest,TResponse>.ResponseWithFlags(response,HandlerUtils.GetWriteFlags(context.WriteOptions));
}
catch (Exception e)
{
if (!(e is RpcException))
{
Logger.Warning(e,"Exception occurred in the handler or an interceptor.");
}
status = HandlerUtils.GetStatusFromExceptionAndMergeTrailers(e,context.ResponseTrailers);
}
try
{
await asyncCall.SendStatusFromServerAsync(status,context.ResponseTrailers,responseWithFlags).ConfigureAwait(false);
}
catch (Exception)
{
asyncCall.Cancel();
throw;
}
await finishedTask.ConfigureAwait(false);
}
finishedTask
(在开始时设置为 asyncCall.ServerSideCallAsync()
)看起来很有希望。我没有正确地研究它,但正如它在最后等待的那样,这能以某种方式提供一种方法吗?
(而且,有点远……但看起来,使用 java gRPC,您可以通过调用 responSEObserver.onError
将异常“发送”回客户端 - C# 中是否有类似的东西我可以以某种方式使用 gRPC 作为仅抛出 RpcException
以获得适当响应的替代方法?)
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)