.NET Core(.NET6)中gRPC注册到Consul
阅读原文时间:2022年04月19日阅读:1

一、简介

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

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

这里Consul已经安装好。

二、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的类

   ///

/// Consul注册 ///
public static class ConsulRegister
{
//服务注册
public static IApplicationBuilder UseConsul(this IApplicationBuilder app, IConfiguration configuration)
{
// 获取主机生命周期管理接口
var lifetime = app.ApplicationServices.GetRequiredService();

        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 = new string\[\] { "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, visit https://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();
app.MapGrpcService();
app.MapGrpcService();
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();

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

public class HealthCheckService : Health.HealthBase
{
public override Task Check(HealthCheckRequest request, ServerCallContext context)
{
Console.WriteLine($"This is {nameof(HealthCheckService)} Check ");
//TODO:检查逻辑
return Task.FromResult(new HealthCheckResponse() { Status = HealthCheckResponse.Types.ServingStatus.Serving });
}

    public override async 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, visit https://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();
app.MapGrpcService();
app.MapGrpcService();
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();

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