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

Consul的安装这里就不介绍了,在之前的篇文章中已经写过:Consul+Ocelot+Polly在.NetCore中使用(.NET5)-Consul服务注册,服务发现

这里Consul已经安装好。

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

1.扩展gRPC注册到Consul封装类

这里沿用上一篇的gRPC的代码,如果服务带api和gRPC的话用http的方式或gRPC的方式注册到可以,http的方式上面文章中的Consul注册和发现中已经有,这里介绍单gRPC的服务的注册。

先在appsettings.json中加入Consul信息代码

{"Logging": {"LogLevel": {"Default":"Information","Microsoft.AspNetCore":"Warning"     }   },"AllowedHosts":"*","Kestrel": {"EndpointDefaults": {"Protocols":"Http2"     }   },"Consul": {     "consulAddress": "http://127.0.0.1:8500",     "serviceName": "api_gRPC",     "currentIp": "127.0.0.1",     "currentPort": "5246"   } }

然后新建ConsulRegister.cs封装注册到Consul的类

///<summary>/// Consul注册///</summary>publicstaticclass ConsulRegister     {//服务注册publicstatic IApplicationBuilder UseConsul(this IApplicationBuilder app, IConfiguration configuration)         {// 获取主机生命周期管理接口var lifetime = app.ApplicationServices.GetRequiredService<IHostApplicationLifetime>();              ConsulClient client=new ConsulClient(c =>             {                 c.Address=new Uri(configuration["Consul:consulAddress"]);                 c.Datacenter="dc1";             });string ip = configuration["ip"];//优先接收变量的值string port = configuration["port"];//优先接收变量的值string currentIp = configuration["Consul:currentIP"];string currentPort = configuration["Consul:currentPort"];              ip=string.IsNullOrEmpty(ip) ? currentIp : ip;//当前程序的IP             port =string.IsNullOrEmpty(port) ? currentPort : port;//当前程序的端口string serviceId = $"service:{ip}:{port}";//服务ID,一个服务是唯一的//服务注册             client.Agent.ServiceRegister(new AgentServiceRegistration()             {                 ID= serviceId,//唯一的                 Name = configuration["Consul:serviceName"],//组名称-Group                 Address = ip,//ip地址                 Port =int.Parse(port),//端口                 Tags =newstring[] {"api站点" },                 Check=new AgentServiceCheck()                 {                     Interval= TimeSpan.FromSeconds(10),//多久检查一次心跳                     GRPC = $"{ip}:{port}",//gRPC注册特有                     GRPCUseTLS=false,//支持http                     Timeout = TimeSpan.FromSeconds(5),//超时时间                     DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(5)//服务停止多久后注销服务                }              }).Wait();//应用程序终止时,注销服务             lifetime.ApplicationStopping.Register(() =>             {                 client.Agent.ServiceDeregister(serviceId).Wait();             });return app;         }     }

Program.cs增加使用这个扩展类

using GrpcDemo.Service.Services;using GrpcDemo.Service.Utils;var builder = WebApplication.CreateBuilder(args);// Additional configuration is required to successfully run gRPC on macOS.// For instructions on how to configure Kestrel and gRPC clients on macOS, visithttps://go.microsoft.com/fwlink/?linkid=2099682// Add services to the container.builder.Services.AddGrpc();var app = builder.Build(); IConfiguration _configuration= builder.Configuration;// Configure the HTTP request pipeline. app.MapGrpcService<GreeterService>(); app.MapGrpcService<OrderService>(); app.MapGrpcService<HealthCheckService>(); app.MapGet("/", () =>"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");app.UseConsul(_configuration); app.Run();

2.创建健康检查gRPC服务

1.新建健康检查proto文件HealthCheck.proto

syntax ="proto3";  package grpc.health.v1;  message HealthCheckRequest {string service =1; }  message HealthCheckResponse {enum ServingStatus {         UNKNOWN=0;         SERVING=1;         NOT_SERVING=2;     }     ServingStatus status=1; }  service Health {     rpc Check(HealthCheckRequest) returns (HealthCheckResponse);      rpc Watch(HealthCheckRequest) returns (stream HealthCheckResponse); }

2.新建健康检查服务实现上面proto协议HealthCheckService.cs

publicclass HealthCheckService : Health.HealthBase     {publicoverride Task<HealthCheckResponse> Check(HealthCheckRequest request, ServerCallContext context)         {             Console.WriteLine($"This is {nameof(HealthCheckService)} Check");//TODO:检查逻辑return Task.FromResult(new HealthCheckResponse() { Status = HealthCheckResponse.Types.ServingStatus.Serving });         }publicoverrideasync Task Watch(HealthCheckRequest request, IServerStreamWriter<HealthCheckResponse> responseStream, ServerCallContext context)         {//TODO:检查逻辑await responseStream.WriteAsync(new HealthCheckResponse()             { Status= HealthCheckResponse.Types.ServingStatus.Serving });         }     }

3.在Program.cs中把服务注册到gRPC管道

using GrpcDemo.Service.Services;using GrpcDemo.Service.Utils;var builder = WebApplication.CreateBuilder(args);// Additional configuration is required to successfully run gRPC on macOS.// For instructions on how to configure Kestrel and gRPC clients on macOS, visithttps://go.microsoft.com/fwlink/?linkid=2099682// Add services to the container.builder.Services.AddGrpc();//配置获取var app = builder.Build(); IConfiguration _configuration= builder.Configuration;// Configure the HTTP request pipeline. app.MapGrpcService<GreeterService>(); app.MapGrpcService<OrderService>();app.MapGrpcService<HealthCheckService>(); app.MapGet("/", () =>"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");  app.UseConsul(_configuration); app.Run();

到这里服务注册就完成了,服务发现和上面简介的链接文章中一模一样,启动项目查看效果。

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

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