创建一个gRPC服务项目(grpc服务端)和一个 webapi项目(客户端),测试项目结构如下:

公共模型

测试接口相关类,放在公共类库中,方便服务端和客户端引用相同模型

public class RoleInfo
{
public int Id { get; set; }
public string Name { get; set; }
} public class UserInfo
{
public int Id { get; set; }
public string Name { get; set; }
public int Age { get; set; } public List<RoleInfo> Roles { get; set; } public UserInfo(int id, string name, int age)
{
Id = id;
Name = name;
Age = age;
}
}

gRPC服务端

1.解决方案文件中新增节点

  <ItemGroup>
<!--Server指定为grpc服务端,Client指定为grpc客户端。在文件保存时候就会生成对应的c#代码,可以调用-->
<Protobuf Include="Protos\user.proto" GrpcServices="Server" />
</ItemGroup>

2. grpc接口协议文件 user.proto

syntax = "proto3";

option csharp_namespace = "KmGrpcService";

package guser;

service GUserService {
rpc GetUser (GetUserRequest) returns (GetUserReply);//获取用户信息接口
rpc AddUser(AddUserRequest) returns (AddUserReply);//新增用户接口
} //获取用户信息-入参
message GetUserRequest {
int32 id = 1;
} //获取用户信息-出参
message GetUserReply {
string user = 1;
} //新增用户-入参
message AddUserRequest{
int32 id= 1 ;
string name = 2 ;
int32 age = 3;
repeated RoleRequest roles=4;//repeated 指定为多条,类似数组。用户角色信息集合
} //角色信息入参
message RoleRequest{
int32 id=1;
string name=2;
} //新增用户-出参
message AddUserReply{
bool success=1;
string msg=2;
}

3. grpc服务实现

using Grpc.Core;
using GrpcCommon.Models;
using Newtonsoft.Json; namespace KmGrpcService.Services
{
//每次修改.proto接口协议文件,保存一下 都会自动更新。
//GUserService和GUserServiceBase 都是根据.proto文件自动生成的C#代码
public class UserService : GUserService.GUserServiceBase
{
private readonly ILogger<UserService> _logger;
public UserService(ILogger<UserService> logger)
{
_logger = logger;
} public static List<UserInfo> Users = new List<UserInfo>()
{
new UserInfo(1,"qwer",20),
new UserInfo(2,"asdf",22),
new UserInfo(3,"zxcv",23),
}; public override Task<GetUserReply> GetUser(GetUserRequest request, ServerCallContext context)
{
UserInfo? user = Users.FirstOrDefault(x => x.Id == request.Id);
string? result = user == null ? null : JsonConvert.SerializeObject(user);
GetUserReply reply = new GetUserReply() { User = result };
return Task.FromResult(reply);
} public override Task<AddUserReply> AddUser(AddUserRequest request, ServerCallContext context)
{
AddUserReply reply = new AddUserReply();
try
{
var user = new UserInfo(request.Id, request.Name, request.Age);
user.Roles = request.Roles.Select(x => new RoleInfo { Id = x.Id, Name = x.Name }).ToList();
Users.Add(user);
reply.Success = true;
}
catch (Exception ex)
{
reply.Success = false;
reply.Msg = ex.Message;
throw;
}
return Task.FromResult(reply);
}
}
}

4.Program中

using KmGrpcService.Services;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddGrpc();

/*
builder.Services.AddGrpc(opt =>//设置全局grpc参数
{ }).AddServiceOptions<UserService>(opt =>//设置某个grpc服务的参数
{ });
*/ var app = builder.Build(); app.MapGrpcService<UserService>(); app.Run();

客户端

1. 客户端需要引入3个nuget包

  • Google.Protobuf
  • Grpc.Net.Client
  • Grpc.Tools

    或直接引入 Grpc.AspNetCore 。包含以上三个,如果要使用依赖注入的方式将服务注入,就引入这个包

2. 客户端的解决方案文件中新增节点

<ItemGroup>
<!--Server指定为grpc服务端,Client指定为grpc客户端。在文件保存时候就会生成对应的c#代码,可以调用-->
<Protobuf Include="Protos\user.proto" GrpcServices="Client" />
</ItemGroup>

3. UserClient 调用grpc服务

using Grpc.Core;
using Grpc.Net.Client;
using GrpcCommon.Models;
using KmGrpcService;
using Newtonsoft.Json; namespace KmWebApi.GrpcClients
{
public static class UserClient
{
const string ServerAddress = "http://localhost:5079";//grpc服务端地址
static GrpcChannel? UserGrpcChannel = null;//grpc通道,创建成本高,尽量复用。
public static async Task<UserInfo?> GetUser(int id)
{
if (UserGrpcChannel == null)
{
UserGrpcChannel = GrpcChannel.ForAddress(ServerAddress);
}
var client = new GUserService.GUserServiceClient(UserGrpcChannel);
GetUserRequest request = new GetUserRequest() { Id = id };
try
{
GetUserReply result = await client.GetUserAsync(request, deadline: DateTime.UtcNow.AddSeconds(5));
UserInfo? user = JsonConvert.DeserializeObject<UserInfo>(result.User);
return user;
}
catch (RpcException ex) when (ex.StatusCode == StatusCode.DeadlineExceeded)
{
throw new Exception("grpc调用超时");
} } public static async Task AddUser(int id, string name, int age, List<RoleInfo> roles)
{
if (UserGrpcChannel == null)
{
UserGrpcChannel = GrpcChannel.ForAddress(ServerAddress);
}
var client = new GUserService.GUserServiceClient(UserGrpcChannel);
AddUserRequest request = new AddUserRequest()
{
Id = id,
Name = name,
Age = age
};
foreach (RoleInfo role in roles ?? new List<RoleInfo>())
{
request.Roles.Add(new RoleRequest { Id = role.Id, Name = role.Name });
}
try
{
AddUserReply result = await client.AddUserAsync(request);
}
catch (RpcException ex) when (ex.StatusCode == StatusCode.DeadlineExceeded)
{
throw new Exception("grpc调用超时");
}
catch (Exception ex)
{ }
}
}
}

4. UserController

using GrpcCommon.Models;
using KmWebApi.GrpcClients;
using KmWebApi.Models;
using Microsoft.AspNetCore.Mvc;
using System.ComponentModel.DataAnnotations; namespace KmWebApi.Controllers
{
[Route("[controller]/[action]")]
[ApiController]
public class UserController : ControllerBase
{ public UserController()
{ } [HttpGet]
public Task<UserInfo?> GetUser(int id)
{
return UserClient.GetUser(id);
} [HttpPost]
public Task AddUser([FromBody][Required] AddUserInput input)
{
return UserClient.AddUser(input.Id, input.Name, input.Age, input.roles);
}
}
} public class AddUserInput
{
public int Id { get; set; }
public string Name { get; set; }
public int Age { get; set; }
public List<RoleInfo> roles { get; set; }
}

客户端通过依赖注入的方式调用grpc服务

builder.Services.AddGrpcClient<GrpcUser.GrpcUserClient>((serviceProvider, options) =>
{
options.Address = new Uri("http://localhost:5079");
var loggerFactory = serviceProvider.GetRequiredService<ILoggerFactory>();
options.Interceptors.Add(new TestInterceptor(loggerFactory));//过滤器
options.Interceptors.Add(new ErrorHandlerInterceptor());
}).ConfigureChannel(opt =>
{
opt.UnsafeUseInsecureChannelCallCredentials = true;
}).AddCallCredentials(async(context, metadata, serviceProvider) =>
{
IHttpContextAccessor httpContextAccessor = serviceProvider.GetRequiredService<IHttpContextAccessor>();
string? token = httpContextAccessor.HttpContext?.Request.Headers["Authorization"].FirstOrDefault();
metadata.Add("Authorization", token);
}); //过滤器
public class TestInterceptor : Interceptor
{
private readonly ILogger<TestInterceptor> _logger;
public TestInterceptor(ILoggerFactory loggerFactory)
{
_logger = loggerFactory.CreateLogger<TestInterceptor>();
} public override AsyncUnaryCall<TResponse> AsyncUnaryCall<TRequest, TResponse>(TRequest request, ClientInterceptorContext<TRequest, TResponse> context, AsyncUnaryCallContinuation<TRequest, TResponse> continuation)
{
Console.WriteLine("TestInterceptor 开始...");
_logger.LogInformation($"AsyncUnaryCall.Type/Method :{context.Method.Type}/{context.Method.Name}");
return continuation(request, context);
}
}

官方说明 https://learn.microsoft.com/zh-cn/aspnet/core/grpc/performance?view=aspnetcore-7.0

调试

右键解决方案-设置启动项目-多个 将服务端和客户端都勾选

请求客户端的接口->客户端通过grpc调用服务端服务

.net6 使用gRPC示例的更多相关文章

  1. .NET Core(.NET6)中gRPC使用

    一.简介 简单解析一下gRPC,gRPC 是一个由Google开源的,跨语言的,高性能的远程过程调用(RPC)框架. 特点: 跨语言 内容protobuf格式(比json体积小),网络传输快 使用HT ...

  2. 【.NET6】gRPC服务端和客户端开发案例,以及minimal API服务、gRPC服务和传统webapi服务的访问效率大对决

    前言:随着.Net6的发布,Minimal API成了当下受人追捧的角儿.而这之前,程序之间通信效率的王者也许可以算得上是gRPC了.那么以下咱们先通过开发一个gRPC服务的教程,然后顺势而为,再接着 ...

  3. .Net Core(.Net6)创建grpc

    1.环境要求 .Net6,Visual Studio 2019 以上 官方文档: https://learn.microsoft.com/zh-cn/aspnet/core/tutorials/grp ...

  4. Golang gRPC 示例

    1.安装gRPC runtime go get google.golang.org/grpc 为了自动生成Golang的gRPC代码,需要安装protocal buffers compiler以及对应 ...

  5. python的gRPC示例

    参考URL: https://segmentfault.com/a/1190000015220713?utm_source=channel-hottest gRPC 是一个高性能.开源和通用的 RPC ...

  6. .NET Core(.NET6)中gRPC注册到Consul

    一.简介 上一篇文章介绍了.NET Core 中使用gRPC,在微服务中,我们通常要把服务做成服务注册,服务发现的方式,那么这里来说一下gRPC是如何注册到Consul中的. Consul的安装这里就 ...

  7. 【Networking】gRPC golang 相关资料

    参考资料: Golang gRPC 示例:  http://www.cnblogs.com/YaoDD/p/5504881.html grpc golang学习心得(1)----安装与测试:   ht ...

  8. grpc 入门(一)--hello world

    一,从rpc接口的定义说起,下面给一个最简单的grpc示例--hello world 在这个rpc横行的世界里,实现一个rpc很重要的一件事就是定义一个好接口,一个好的接口定义会让你省去很多麻烦.熟悉 ...

  9. window下golang使用gRPC入门案例&net core客户端

    gRPC是google开源高性能分布式RPC框架,支持http/2 双向数据流传输及Protobuff,可以在任何环境下运行. 它可以有效地将数据中心内和跨数据中心的服务与可插拔支持进行负载均衡,跟踪 ...

  10. gRPC入坑记

    概要 由于gRPC主要是谷歌开发的,由于一些已知的原因,gRPC跑demo还是不那么顺利的.单独写这一篇,主要是gRPC安装过程中的坑太多了,记录下来让大家少走弯路. 主要的坑: 如果使用PHP.Py ...

随机推荐

  1. Known框架实战演练——进销存数据结构

    系统主要包含商品信息.商业伙伴(客户.供应商)信息.业务单表头信息.业务单表体信息.对账单表头信息.对账单表体信息. 1. 商品信息(JxGoods) 该表用于存储公司商品信息. 名称 代码 类型 长 ...

  2. iframe嵌入svg图片动态更改文本样式并进行缩放等功能实现拓扑图

    好久没更了,近期开发遇到的需求,抽空梳理一下~ 需求:实现一个复杂的拓扑图,图中元素的个数,以及各个参数内容是动态展示的. 于是让ui提供了对应的svg图片. 解决思路:使用iframe嵌入svg图片 ...

  3. 关于异步编程中的bind(this)

    异步编程中的.bind(this)方法解决了异步执行后this指针指向全局函数的问题,主要可以通过以下两个场景加以说明:(本文所用例子基于React场景:为简便起见,仅在第一个例子中展示完整HTML代 ...

  4. 【ElasticSearch】突破深度分页限制的分页方案

    一.场景需求 最近在忙一个新的项目,数据源是ES,但是功能就是对文档进行翻页查询 ES提供了分页查询,就是from + size深度查找,但是使用有限制,只能在1万条内 我和同事的意见是1万条之后的数 ...

  5. MindSpore计算框架如何发布训练好的模型到官方模型仓库MindSpore_Hub上

    相关官方资料: https://www.mindspore.cn/tutorial/training/zh-CN/r1.2/use/publish_model.html 参考地址: https://g ...

  6. 经典视频分享:Machine Learning: A New ICE (Identification, Control, Estimation) Age ? —— 自动控制和人工智能的结合前景

    机器学习作为近几年兴起的学科,虽然他诞生的时间已经而久远了,但是真正走进人们视野也就是这几年的事情. 机器学习领域本身只有强化学习这个分支和控制类是天然关联的,因此近几年国内的知名高校的强化学习研究者 ...

  7. 高校教编程是否应该将Python作为主语言

    偶读一文:https://www.cnblogs.com/qing-gee/p/12941219.html 想到了这样的一个老问题,个人搞计算机软件开发.人工智能的时间已经十余年,虽然个人能力有限但是 ...

  8. 【转载】AI的剥削:肯尼亚工人训练ChatGPT,看大量有害内容心理受伤——AI新时代下剥削

    原文地址: https://mbd.baidu.com/newspage/data/landingsuper?context=%7B%22nid%22%3A%22news_90623597686514 ...

  9. Singleton bean creation not allowed while singletons of this factory are in destruction

    1.背景 一直都是正常运行的程序,检查日志发现有一条报错如下: org.springframework.beans.factory.BeanCreationNotAllowedException: E ...

  10. SMU Summer 2023 Contest Round 10(ICPC — International Collegiate Programming Contest Asia Regional Contest, Yokohama,2018)

    SMU Summer 2023 Contest Round 10(ICPC - International Collegiate Programming Contest Asia Regional C ...