GRpc异常处理Filter

全局错误处理服务端

微软已经实施了Interceptors,它们类似于Filter或Middlewares在ASP.NET MVC的核心或的WebAPI,它们可以用于全局异常处理,日志记录,验证等。
这是服务器端Interceptor自己的实现,Continuation是必须等待的Task,然后,如果引发了任何异常,则可以根据所获得的异常来控制RpcException和关联的StatusCode

using Grpc.Core; using Grpc.Core.Interceptors; using Microsoft.Extensions.Logging; using System; using System.Data.SqlClient; using System.Threading.Tasks; namespace DemoGrpc.Web.Logging { public class LoggerInterceptor : Interceptor { private readonly ILogger<LoggerInterceptor> _logger; public LoggerInterceptor(ILogger<LoggerInterceptor> logger) { _logger = logger; } public async override Task<TResponse> UnaryServerHandler<TRequest, TResponse>( TRequest request, ServerCallContext context, UnaryServerMethod<TRequest, TResponse> continuation) { LogCall(context); try { return await continuation(request, context); } catch (SqlException e) { _logger.LogError(e, $"An SQL error occured when calling {context.Method}"); Status status; if (e.Number == -2) { status = new Status(StatusCode.DeadlineExceeded, "SQL timeout"); } else { status = new Status(StatusCode.Internal, "SQL error"); } throw new RpcException(status); } catch (Exception e) { _logger.LogError(e, $"An error occured when calling {context.Method}"); throw new RpcException(Status.DefaultCancelled, e.Message); } } private void LogCall(ServerCallContext context) { var httpContext = context.GetHttpContext(); _logger.LogDebug($"Starting call. Request: {httpContext.Request.Path}"); } } }

注册方式如下

using DemoGrpc.Web.Logging; using DemoGrpc.Web.Services; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; namespace DemoGrpc.Web { public class Startup { public Startup(IConfiguration configuration) { Configuration = configuration; } public IConfiguration Configuration { get; } public void ConfigureServices(IServiceCollection services) { //注册GRpc全局异常捕获 services.AddGrpc(options => { options.Interceptors.Add<LoggerInterceptor>(); }); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } else { app.UseHsts(); } app.UseHttpsRedirection(); app.UseRouting(); app.UseEndpoints(endpoints => { endpoints.MapGrpcService<CountryGrpcService>(); endpoints.MapGet("http://www.likecs.com/", async context => { await context.Response.WriteAsync("Communication with gRPC endpoints must be made through a gRPC client. To learn how to create a client, visit: https://go.microsoft.com/fwlink/?linkid=2086909"); }); }); } } }

第二种方法也可以捕获到GRpc异常,但是写法比较粗糙。不推荐使用

using AutoMapper; using DemoGrpc.Domain.Entities; using DemoGrpc.Protobufs; using DempGrpc.Services.Interfaces; using Grpc.Core; using System; using System.Threading.Tasks; public class CountryGrpcService : CountryService.CountryServiceBase { private readonly ICountryService _countryService; private readonly IMapper _mapper; public CountryGrpcService(ICountryService countryService, IMapper mapper) { _countryService = countryService; _mapper = mapper; } public override async Task<CountriesReply> GetAll(EmptyRequest request, ServerCallContext context) { try { var countries = await _countryService.GetAsync(); return _mapper.Map<CountriesReply>(countries); } catch (Exception e) { throw new RpcException(Status.DefaultCancelled, e.Message); } } }

Rpc异常信息介绍如下

一个普通标题 一个普通标题
Aborted   操作被中止,通常是由于并发性问题,如顺序器检查失败、事务中止等。  
AlreadyExists   试图创建的一些实体(例如,文件或目录)已经存在。  
Cancelled   该操作被取消(通常由调用者取消)。  
DataLoss   不可恢复的数据丢失或损坏。  
DeadlineExceeded   操作完成前截止日期已过期。对于改变系统状态的操作,即使操作已经成功完成,也会返回此错误。例如,来自服务器的成功响应可能会延迟到截止日期过期。  
FailedPrecondition   操作被拒绝,因为系统没有处于执行操作所需的状态。例如,要删除的目录可能是非空的,一个rmdir操作被应用到一个非目录,等等。  
Internal   内部错误。表示底层系统期望的某些不变量被打破。  
InvalidArgument   客户端指定了无效的参数。注意,这与FAILED_PRECONDITION不同。INVALID_ARGUMENT表示与系统状态无关的参数(例如格式不正确的文件名)。  
NotFound   一些被请求的实体(例如,文件或目录)没有找到。  
OK   成功返回  
OutOfRange   操作尝试超过有效范围。例如,查找或读取文件的前端。  
PermissionDenied   调用者没有权限执行指定的操作。PERMISSION_DENIED不能用于由于耗尽某些资源而导致的拒绝(对于那些错误,应该使用RESOURCE_EXHAUSTED)。如果无法识别调用者,则不能使用PERMISSION_DENIED(对于那些错误,则使用UNAUTHENTICATED)。  
ResourceExhausted   某些资源已经耗尽,可能是每个用户的配额,或者可能是整个文件系统空间不足。  
Unauthenticated   未认证/授权  
Unavailable   该服务目前不可用。这很可能是一种暂时的情况,可以通过后退重新尝试来纠正。注意,重试非幂等操作并不总是安全的。  
Unimplemented   此服务中未实现或不支持/启用操作。  
Unknown   未知的错误。可能返回此错误的一个示例是,如果从另一个地址空间接收到的状态值属于此地址空间中未知的错误空间。如果api没有返回足够的错误信息,则可能会将其转换为此错误。  

具体地址:https://grpc.github.io/grpc/csharp/api/Grpc.Core.StatusCode.html

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zygywd.html