.NET Core(.NET6)中gRPC註冊到Consul

包子wxl發表於2022-04-18

一、簡介

上一篇文章介紹了.NET Core 中使用gRPC,在微服務中,我們通常要把服務做成服務註冊,服務發現的方式,那麼這裡來說一下gRPC是如何註冊到Consul中的。

Consul的安裝這裡就不介紹了,在之前的篇文章中已經寫過:Consul+Ocelot+Polly在.NetCore中使用(.NET5)-Consul服務註冊,服務發現

這裡Consul已經安裝好。

 

 

 二、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>
    public static class ConsulRegister
    {
        //服務註冊
        public static 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 = 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<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

public class HealthCheckService : Health.HealthBase
    {
        public override 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 });
        }

        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<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();

到這裡服務註冊就完成了,服務發現和上面簡介的連結文章中一模一樣,啟動專案檢視效果。

 

 

 

相關文章