ASP.NET Core gRPC 使用 Consul 服務註冊發現
一. 前言
gRPC 在當前最常見的應用就是在微服務場景中,所以不可避免的會有服務註冊與發現問題,我們使用gRPC實現的服務可以使用 Consul 或者 etcd 作為服務註冊與發現中心,本文主要介紹Consul。
二. Consul 介紹
Consul是一種服務網路解決方案,可跨任何執行平臺以及公共或私有云來連線和保護服務。它可以讓你發現服務並保護網路流量。它可以在Kubernetes中使用,實現服務發現和服務網格功能(k8s預設etcd)。 提供安全服務通訊,保護和觀察服務之間的通訊,而無需修改其程式碼。 提供動態負載平衡, 使用Consul和HAProxy,Nginx或F5自動執行負載均衡器配置。 Consul 可以用於服務發現和服務網格。
翻譯自官網
三. Consul 安裝配置
安裝
Consul 下載地址: https://www.consul.io/downloads.html
根據自己的系統來選擇,我這裡選擇的是 Windows 版本的,直接解壓即可執行。
啟動
consul agent -dev -ui
本文不詳細介紹Consul使用,如需請自行檢視相關資料
四. .NET Core Consul 客戶端的選擇
Consul 提供了 HTTP API 的方式來進行通訊,我們可以直接呼叫API或者是使用第三方封裝好的客戶端元件,通過Nuget搜尋可以發現許多。
這裡面我沒有一一測試,但是目前使用量最多的 Consul
所以我 Fork 了這個倉庫,然後添加了 GRPC 的支援,本文也將使用這個庫,歡迎大家使用:
Nuget: https://www.nuget.org/packages/NConsul/
Github:https://github.com/stulzq/NConsul
求個star
五. 註冊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 | 異常,不能提供服務 |
最後別忘了註冊服務:
4.測試執行
啟動 GRPC 服務
然後訪問 http://localhost:8500/ui
訪問 Consul 控制檯
可以看到服務成功註冊,並且健康檢查也是通過了的。通過控制檯日誌,還可以看到健康檢查的請求:
六. 客戶端使用服務發現
客戶端專案安裝 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();
}
通過服務名稱獲取服務地址,然後來進行訪問。
執行測試:
可以看到,成功的從Consul獲取了我們的服務地址,然後呼叫。
六. 參考資料
gRPC in Asp.Net Core :官方文件
GPRC Health Check Doc:點我
本文 Demo:點我
本系列文章目錄:點我
NConsul:https://github.com/stulzq/NConsul
.NET Core微服務之基於Consul實現服務治理 by Edison Zhou