ASP.NET Core gRPC 使用 Consul 服務註冊發現

一. 前言

gRPC 在當前最多見的應用就是在微服務場景中,因此不可避免的會有服務註冊與發現問題,咱們使用gRPC實現的服務可使用 Consul 或者 etcd 做爲服務註冊與發現中心,本文主要介紹Consul。html

二. Consul 介紹

Consul是一種服務網絡解決方案,可跨任何運行平臺以及公共或私有云來鏈接和保護服務。它可讓你發現服務並保護網絡流量。它能夠在Kubernetes中使用,實現服務發現和服務網格功能(k8s默認etcd)。 提供安全服務通信,保護和觀察服務之間的通訊,而無需修改其代碼。 提供動態負載平衡, 使用Consul和HAProxy,Nginx或F5自動執行負載均衡器配置。 Consul 能夠用於服務發現和服務網格。git

翻譯自官網github

三. Consul 安裝配置

安裝

Consul 下載地址: https://www.consul.io/downloads.htmlshell

根據本身的系統來選擇,我這裏選擇的是 Windows 版本的,直接解壓便可運行。安全

image-20191122160153106

啓動

consul agent -dev -ui

image-20191127133742306

本文不詳細介紹Consul使用,如需請自行查看相關資料網絡

四. .NET Core Consul 客戶端的選擇

Consul 提供了 HTTP API 的方式來進行通信,咱們能夠直接調用API或者是使用第三方封裝好的客戶端組件,經過Nuget搜索能夠發現許多。負載均衡

image-20191127134428569

這裏面我沒有一一測試,可是目前使用量最多的 Consul 組件是不支持設置 GRPC 健康檢查的,並且 github 也中止了更新。async

image-20191127134541731

因此我 Fork 了這個倉庫,而後添加了 GRPC 的健康檢查支持,本文也將使用這個庫,歡迎你們使用:ide

由於原倉庫已經 Archived 了,因此我才 Fork 了本身改一下,改動很小,不影響原來的穩定性。微服務

Nuget: https://www.nuget.org/packages/NConsul/

Github:https://github.com/stulzq/NConsul

求個star img

關於支持 GPRC 健康檢查的好處:

偷個懶,不翻譯了,摘自GRPC官方文檔

五. 註冊GRPC服務與健康檢查

基於前文(ASP.NET Core 使用gRPC)的Demo

1.爲服務端項目安裝 NConsul.AspNetCore ( https://www.nuget.org/packages/NConsul.AspNetCore )

這裏面對 AspNetCore 作了適配,使用簡單。

2.在 Startup 的 ConfigureServices方法內進行配置

public void ConfigureServices(IServiceCollection services)
{
    services.AddGrpc();

    services.AddConsul("http://localhost:8500")
        .AddGRPCHealthCheck("localhost:5000")
        .RegisterService("grpctest","localhost",5000,new []{"xc/grpc/test"});
}

AddConsul 添加 Consul Server 地址。

AddGRPCHealthCheck 添加 GRPC 健康檢查,即健康檢查走的是 GRPC 協議,該值爲 GRPC 服務的地址,不須要path不須要提供 http/https

RegisterService 註冊服務

到這步,還不能啓動運行,若是運行健康檢查是會失敗的。

3.編寫 Health Check 服務 **

對於 GRPC 的健康檢查,官方有標準的定義,新建一個 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);
}

這裏面的內容不得更改,是官方標準,資料見後文

這裏編譯一下項目,以便自動生成代碼。

而後,添加一個服務的實現類 HealthCheckService

public class HealthCheckService:Health.HealthBase
{
    public override Task<HealthCheckResponse> Check(HealthCheckRequest request, ServerCallContext context)
    {
        //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種狀況:

結果類型 說明
Unknown 未知狀態
Serving 正常
NotServing 異常,不能提供服務

最後別忘了註冊服務:

image-20191127151059008

4.測試運行

啓動 GRPC 服務

而後訪問 http://localhost:8500/ui 訪問 Consul 控制檯

image-20191127151652840

能夠看到服務成功註冊,而且健康檢查也是經過了的。經過控制檯日誌,還能夠看到健康檢查的請求:

image-20191127151727397

六. 客戶端使用服務發現

客戶端項目安裝 Consul 組件,而後改造下代碼:

static async Task Main(string[] args)
{
    var serviceName = "grpctest";
    var consulClient = new ConsulClient(c => c.Address = new Uri("http://localhost:8500"));
    var services = await consulClient.Catalog.Service(serviceName);
    if (services.Response.Length == 0)
    {
        throw new Exception($"未發現服務 {serviceName}");
    }

    var service = services.Response[0];
    var address = $"http://{service.ServiceAddress}:{service.ServicePort}";

    Console.WriteLine($"獲取服務地址成功:{address}");

    //啓用經過http使用http2.0
    AppContext.SetSwitch(
        "System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true);
    var channel = GrpcChannel.ForAddress(address);
    var catClient = new LuCat.LuCatClient(channel);
    var catReply = await catClient.SuckingCatAsync(new Empty());
    Console.WriteLine("調用擼貓服務:"+ catReply.Message);
    Console.ReadKey();
}

經過服務名稱獲取服務地址,而後來進行訪問。

運行測試:

image-20191127152941168

能夠看到,成功的從Consul獲取了咱們的服務地址,而後調用。

六. 參考資料

相關文章
相關標籤/搜索