ASP.NET Core 6 gRPC客户端调用GetDiscount时遇RpcException错误排查
gRPC通信异常排查:Basket.Api调用Discount.gRPC的GetDiscount方法报错
Grpc.Core.RpcException: Status(StatusCode="Unknown", Detail="Exception was thrown by handler.")
堆栈跟踪
at Basket.Api.Services.DiscountGrpc.DiscountClientService.GetDiscount(String productName) in E:\Microservices\run-aspnetcore-microservices\EcommerceMicro\Basket.Api\Services\DiscountGrpc\DiscountClientService.cs:line 17 at Basket.Api.Controllers.BasketController.UpdateBasket(ShoppingCart basket) in E:\Microservices\run-aspnetcore-microservices\EcommerceMicro\Basket.Api\Controllers\BasketController.cs:line 39 at lambda_method23(Closure , Object ) at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.AwaitableObjectResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeActionMethodAsync>g__Awaited|12_0(ControllerActionInvoker invoker, ValueTask`1 actionResultValueTask) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeNextActionFilterAsync>g__Awaited|10_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeInnerFilterAsync>g__Awaited|13_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeFilterPipelineAsync>g__Awaited|20_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope) at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger) at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context) at Swashbuckle.AspNetCore.SwaggerUI.SwaggerUIMiddleware.Invoke(HttpContext httpContext) at Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext httpContext, ISwaggerProvider swaggerProvider) at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
相关代码片段
Proto文件定义
option csharp_namespace = "Discount.gRPC.Protos"; service DiscountProtoService { rpc GetDiscount(GetDiscountRequest) returns (CouponModel); } message GetDiscountRequest { string productName = 1; } message CouponModel { int32 id = 1; string productId=2; string productName = 3; string description = 4; int32 amount = 5; }
Basket.Api客户端GetDiscount实现
private readonly DiscountProtoService.DiscountProtoServiceClient discountClientService; public DiscountClientService(DiscountProtoService.DiscountProtoServiceClient discountClientService) { this.discountClientService = discountClientService; } public async Task<CouponModel> GetDiscount(string productName) { var discountRequest = new GetDiscountRequest { ProductName = productName }; return await discountClientService.GetDiscountAsync(discountRequest); }
Basket.Api服务注册(Program.cs)
var builder = WebApplication.CreateBuilder(args); builder.Services.AddScoped<IGreeterClientService, GreeterClientService>(); builder.Services.AddScoped<IDiscountClientService, DiscountClientService>(); builder.Services.AddGrpcClient<Greeter.GreeterClient>(c => c.Address = new Uri(builder.Configuration["GrpcSettings:DiscountUrl"])); builder.Services.AddGrpcClient<DiscountProtoService.DiscountProtoServiceClient>(c => c.Address = new Uri(builder.Configuration["GrpcSettings:DiscountUrl"])); var app = builder.Build();
Discount.gRPC服务端GetDiscount实现
public override async Task<CouponModel> GetDiscount(GetDiscountRequest request, ServerCallContext context) { var coupon = await repository.GetDiscount(request.ProductName); if (coupon == null) { throw new RpcException(new Status(StatusCode.NotFound, $"Discount with ProductName = {request.ProductName} not found.")); } var couponModel = mapper.Map<CouponModel>(coupon); logger.LogInformation("Discount is retrieved for ProductName : {productName}, Amount : {amount}", request.ProductName, coupon.Amount); return await Task.FromResult(couponModel); //return await Task.FromResult(new CouponModel()); }
Discount.gRPC服务注册(Program.cs)
using Discount.gRPC.Mapper; using Discount.gRPC.Services; var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.AddGrpc(); builder.Services.AddAutoMapper(typeof(DiscountProfile)); var app = builder.Build(); // Configure the HTTP request pipeline. app.MapGrpcService<GreeterService>(); app.MapGrpcService<DiscountService>(); app.Run();
补充说明
已测试Discount.gRPC中的默认Greeter服务,客户端与服务端通信正常,可提供更多代码片段协助排查问题。
内容的提问来源于stack exchange,提问作者Quốc Phi Nguyễn
相关产品推荐
相关产品推荐

