5.NET中GRPC服务端快速入门,服务端与客户端
gRPC是一个现代的开源高性能远程过程调用(RPC)框架,可以在任何环境中运行。它可以有效地连接数据中心内和跨数据中心的服务,支持负载均衡、跟踪、健康检查和身份验证。它也适用于分布式计算,将设备、移动应用程序和浏览器连接到后端服务
1.创建一个空项目GrpcServer
安装包:Grpc.AspNetCore
添加GRPC服务,Program.cs里面
builder.Services.AddGrpc();
设置GRPC为http2.0,Program.cs里面
builder.WebHost.UseKestrel(p => { p.ConfigureEndpointDefaults(opt => { opt.Protocols = HttpProtocols.Http2; }); });
也可以在配置文件内去设置,appsettings文件里
"Kestrel": { "EndpointDefaults": { "Protocols": "Http2" } }
2.创建一个文件夹Apis里面存放服务
接口:IUserService
public interface IUserService { List<UserInfo> GetUsers(); }
实现:UserServiceImpl
public class UserServiceImpl:IUserService { public List<UserInfo> GetUsers() { return new() { new(){Id = 1,NickName = "张三"}, new(){Id = 2,NickName = "李四"}, new(){Id = 3,NickName = "王五"}, new(){Id = 4,NickName = "赵交"} }; } }
3.创建Protos文件夹,里面中定义服务和消息
创建一个文件:user.proto
syntax="proto3"; //声明语法为proto3 option csharp_namespace = "GrpcServer";//声明命名空间,一般为项目的名称 package user;//定义包 //请求参数,1,2,....表示参数的下标。nick_name编译后NickName message UserDtoGrpc{ int32 id=1; // Id string nick_name=2; // NickName } // 入参对象,请求参数,没有可以不写,如果有参数和上面写法一样。 message UserReuqest{ } // 出参对象,返回对象,为list集合,repeated表示一个集合。 message UserResponse{ repeated UserDtoGrpc user_list=1; } //里面定义方法 service UserService{ // 声明了需要暴露的Grpc方法 rpc GetUsers(UserReuqest) returns (UserResponse); }
编辑GrpcServer.csproj文件,将user.proto暴露出来生成C#的资产。
<ItemGroup> <PackageReference Include="Grpc.AspNetCore" Version="2.56.0" /> <ProtoBuf Include="Protos/user.proto" GrpcService="Server" /> </ItemGroup>
最后重新生成项目
4.创建一个文件夹Services,来存放GRPC的服务。
在Program.cs里面注册
builder.Services.AddTransient<IUserService, UserServiceImpl>();
添加一个类UserServiceGrpc继承的UserService其实就是user.proto文件里面的UserService。
重写的GetUsers方法其实就是UserServiceBase的GetUsers方法。
public class UserServiceGrpc:UserService.UserServiceBase { private readonly IUserService _userService; public UserServiceGrpc(IUserService userService) { _userService = userService; } public override Task<UserResponse> GetUsers(UserReuqest request, ServerCallContext context) { UserResponse response = new(); var userInfos = _userService.GetUsers(); foreach (var userInfo in userInfos) { response.UserList.Add(new UserDtoGrpc() { Id = userInfo.Id, NickName = userInfo.NickName }); } return Task.FromResult(response); } }
添加到管道里面去
app.MapGrpcService<UserServiceGrpc>();
5.创建一个客户端空项目GrpcClient
安装包:
Swashbuckle.AspNetCore
Grpc.Net.Client
Grpc.Tools
Google.Protobuf
Program.cs里面配置
builder.Services.AddControllers();
builder.Services.AddSwaggerGen();
app.UseSwagger();
app.UseSwaggerUI();
app.UseRouting();
app.MapControllers();
launchSettings.json里面配置Swagger页面。
"http": { "commandName": "Project", "dotnetRunMessages": true, "launchBrowser": true, "launchUrl": "swagger", "applicationUrl": "http://localhost:5290", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } }
创建一个文件夹Protos,添加user.proto文件
syntax="proto3"; option csharp_namespace = "GrpcClient"; package user; message UserDtoGrpc{ int32 id=1; // Id string nick_name=2; // NickName } // 入参对象 message UserReuqest{ } // 出参对象 message UserResponse{ repeated UserDtoGrpc user_list=1; } service UserService{ // 声明了需要暴露的Grpc方法 rpc GetUsers(UserReuqest) returns (UserResponse); }
生成后注意GrpcClient.csproj文件内是否有生成
<Protobuf Include="Protos\user.proto"> <GrpcServices>Client</GrpcServices> <Access>Public</Access> <ProtoCompile>True</ProtoCompile> <CompileOutputs>True</CompileOutputs> <OutputDir>obj\Debug\net7.0\</OutputDir> <Generator>MSBuild:Compile</Generator> </Protobuf>
添加控制器文件夹Controllers
[ApiController] [Route("[controller]/[action]")] public class UserController : ControllerBase { private readonly UserService.UserServiceClient _userServiceClient; public UserController(UserService.UserServiceClient userServiceClient) { _userServiceClient = userServiceClient; } [HttpGet] public IActionResult Get() { // 创建通信频道 var channel = GrpcChannel.ForAddress("http://localhost:5023"); // 创建客户端 var userServiceClient = new UserService.UserServiceClient(channel); var userResponse = _userServiceClient.GetUsers(new UserReuqest()); return Ok(userResponse.UserList); } }