1、?介紹
GRPC是一個高效能、通用的開源遠端過程呼叫(RPC)框架,基於底層HTTP/2協議標準
和協議層Protobuf序列化協議
開發,支援眾多的開發語言,由Google開源。
gRPC也是基於以下理念:定義一個服務,指定其能夠被遠端呼叫的方法(包含引數和返回型別)。在服務端實現這個介面,並執行一個 gRPC伺服器來處理客戶端呼叫。在客戶端擁有一個存根能夠像服務端一樣的方法。
特點:
-
跨語言;
-
基於HTTP/2之上的二進位制協議;
-
Protobuf序列化機制,比JSON體積小,網路傳輸快;
-
一個連線上可以多路複用,併發處理多個請求和響應;
-
多種語言的類庫實現;
-
服務定義檔案和自動程式碼生成(.proto 檔案和 Protobuf 編譯工具);
-
適合高效能輕量的微服務,一般對外的介面用Restful API,內部服務的呼叫用gRPC。gRPC是一個分散式服務框架,和以前的WebService,WCF類似;
-
gRPC還提供了很多擴充套件點,用於對框架進行功能定製和擴充套件,例如,透過開放負載均衡介面可以無縫的與第三方元件進行整合對接(Zookeeper、域名解析服務、SLB 服務等)。
2、?建立gRPC服務端
2.1、?建立gRPC服務端專案
開啟VS2022,新建專案,在輸入框中輸入gRPC關鍵字,選中gRPC專案模板,然後點選下一步,如下圖所示:
輸入專案名稱“Quber.Grpc.Service”,然後點選下一步,如下圖所示:
選中.Net6,最後點選建立按鈕,如下圖所示:
預設專案檔案結構,如下圖所示:
2.2、?檔案說明
-
appsettings.json
我們開啟appsettings.json檔案,其中有一個Protocols
屬性,代表基於Http2進行通訊。 -
Protos
在建立的專案中,我們會看到有一個名稱為Protos
的資料夾,該資料夾用於存放proto協議檔案,其中的greet.proto是專案預設給我們建立的一個示例檔案,它會根據協議自動生成需要的類檔案。該協議檔案中的具體說明如下圖所示: -
Services
在建立的專案中,我們會看到有一個名稱Services
的資料夾,該資料夾用於存放具體的業務實現類(即:服務類),其中的GreeterService.cs是專案預設給我們建立的一個示例檔案,具體說明如下圖所示:上述圖中的Greeter.GreeterBase來自greet.proto檔案生成的類檔案,具體位置如下圖所示:
-
註冊服務
最後我們開啟
Program.cs
檔案,需要新增gRPC服務,同時需要將所有的業務服務進行註冊,如下圖所示:
2.3、?建立自定義服務
接下來我們就以獲取使用者資訊為例建立一個名稱為user.proto的協議檔案進行講解。
-
建立user.proto協議檔案
新建user.proto協議檔案,如下圖所示:
該協議檔案的內容如下所示:
//proto版本 syntax = "proto3"; //名稱空間 option csharp_namespace = "Quber.Grpc.Service.Protos"; //包名 package user; //服務名稱 service User{ //方法名稱 rpc GetUserInfo (UserInfoRequest) returns (UserInfoResult); } //請求的引數物件 message UserInfoRequest{ string UserName = 1; int32 UserAge = 2; } //請求響應的物件 message UserInfoResult{ string UserName = 1; int32 UserAge = 2; string Address = 3; }
-
新增user.proto協議檔案的關聯配置
我們雙擊專案Quber.Grpc.Service開啟專案的編輯檔案,在
ItemGroup
節點中增加如下配置:<ItemGroup> <Protobuf Include="Protos\user.proto" GrpcServices="Server" /> </ItemGroup>
接下來我們生成一下專案,就會發現在
\obj\Debug\net6.0\Protos
目錄下多了2個user.proto協議檔案對應的類檔案了,如下圖所示: -
實現定義的服務
建立
UserService.cs
類檔案,具體程式碼如下所示:using Grpc.Core; using Quber.Grpc.Service.Protos; namespace Quber.Grpc.Service.Services { public class UserService : User.UserBase { private readonly ILogger<GreeterService> _logger; public UserService(ILogger<GreeterService> logger) { _logger = logger; } /// <summary> /// 實現了user.proto協議檔案中定義的GetUserInfo方法 /// </summary> /// <param name="request"></param> /// <param name="context"></param> /// <returns></returns> public override Task<UserInfoResult> GetUserInfo(UserInfoRequest request, ServerCallContext context) { //return base.GetUserInfo(request, context); //返回了user.proto協議檔案中GetUserInfo方法定義的響應物件:UserInfoResult return Task.FromResult(new UserInfoResult { UserName = $"姓名:{request.UserName}", UserAge = request.UserAge + 10, Address = "地址:四川省成都市" }); } } }
繼承的
User.UserBase
是user.proto協議檔案生成的類檔案中的。 -
註冊
UserService
服務我們需要將新建的UserService服務在啟動檔案中進行註冊,如下所示:
-
啟動服務
到此,gRPC服務端就新建配置完成了,此時我們就可以啟動該專案讓其執行起來,如下圖所示:
在上圖中,我們發現有2個地址
http://localhost:5201
和https://localhost:7288
,這2個地址是我們在建立專案的時候,在launchSettings.json配置中自動給我們配置的,後面gRPC客戶端會使用到這2個地址,目的是給客戶端請求提供監聽的地址。
3、?建立gRPC客戶端
3.1、?建立gRPC客戶端專案
我們以建立控制檯應用程式為例,新建一個名稱為Quber.Grpc.Client
的控制檯程式,並新增如下引用:
Google.Protobuf
Grpc.Net.Client
Grpc.Tools
Grpc.Net.ClientFactory
3.2、?複製proto協議檔案
將服務端專案Quber.Grpc.Service
中的user.proto協議檔案複製過來,如下圖所示:
3.3、?編輯客戶端配置
我們雙擊專案Quber.Grpc.Client開啟專案的編輯檔案,在ItemGroup
節點中增加如下配置:
<ItemGroup>
<Protobuf Include="Protos\user.proto" GrpcServices="Client" />
</ItemGroup>
此時我們生成一下客戶端專案,會發現在obj\Debug\net6.0\Protos
目錄下也生成了user.proto協議檔案對應的2個類檔案,如下圖所示:
3.4、?gRPC服務的https呼叫
在gRPC服務端專案中,給我們提供了2個地址的呼叫,一個是https的https://localhost:7288,另一個是http的http://localhost:5201,此處我們演示呼叫https。
在客戶端專案中我們新建類檔案UserTest.cs
,具體程式碼如下所示:
using Grpc.Net.Client;
using Quber.Grpc.Service.Protos;
namespace Quber.Grpc.Client
{
public class UserTest
{
public void GetUserInfo()
{
//使用https
const string urlHttps = "https://localhost:7288";
using (var channel = GrpcChannel.ForAddress(urlHttps))
{
var client = new User.UserClient(channel);
var userInfo = client.GetUserInfo(new UserInfoRequest()
{
UserName = "Quber",
UserAge = 32
});
//列印服務方法返回的結果
Console.WriteLine($"{userInfo.UserName},{userInfo.UserAge},{userInfo.Address}");
}
Console.ReadKey();
}
}
}
然後我們在啟動檔案中進行呼叫並執行該客戶端專案,如下圖所示:
到此,呼叫gRPC服務端提供的https地址就成功了。
3.5、?gRPC服務的http呼叫
相比https的呼叫,我們只需要在呼叫前加上如下程式碼即可:
AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true);
UserTest.cs
中的具體程式碼如下所示:
using Grpc.Net.Client;
using Quber.Grpc.Service.Protos;
namespace Quber.Grpc.Client
{
public class UserTest
{
public void GetUserInfo()
{
//使用http
AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true);
const string urlHttp = "http://localhost:5201";
using (var channel = GrpcChannel.ForAddress(urlHttp))
{
var client = new User.UserClient(channel);
var userInfo = client.GetUserInfo(new UserInfoRequest()
{
UserName = "Quber",
UserAge = 32
});
//列印服務方法返回的結果
Console.WriteLine($"{userInfo.UserName},{userInfo.UserAge},{userInfo.Address}");
}
Console.ReadKey();
}
}
}
執行效果如下:
3.6、?依賴注入方式呼叫gRPC
我們在客戶端專案中新建UserTestIoc.cs
類檔案,具體程式碼如下所示:
using Quber.Grpc.Service.Protos;
namespace Quber.Grpc.Client
{
public class UserTestIoc
{
/// <summary>
/// 定義gRPC客戶端服務物件
/// </summary>
private readonly User.UserClient _userClient;
public UserTestIoc(User.UserClient userClient)
{
_userClient = userClient;
}
public void GetUserInfo()
{
var userInfo = _userClient.GetUserInfo(new UserInfoRequest()
{
UserName = "Quber - IOC",
UserAge = 20
});
Console.WriteLine($"{userInfo.UserName},{userInfo.UserAge},{userInfo.Address}");
Console.ReadKey();
}
}
}
然後我們在啟動檔案Program.cs
中進行相應的依賴注入配置並呼叫,具體程式碼如下所示:
#region 使用IOC注入的方式呼叫gRPC
//引入名稱空間
using Microsoft.Extensions.DependencyInjection;
using Quber.Grpc.Client;
using Quber.Grpc.Service.Protos;
IServiceCollection services = new ServiceCollection();
//註冊UserTestIoc服務
services.AddTransient<UserTestIoc>();
#region gRPC Client註冊
//呼叫http時啟用該設定
//AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true);
//新增gRPC客戶端服務
services.AddGrpcClient<User.UserClient>(options =>
{
//設定gRPC的https服務呼叫地址
options.Address = new Uri("https://localhost:7288");
}).ConfigureChannel(grpcOptions =>
{
});
#endregion
//構建容器
IServiceProvider serviceProvider = services.BuildServiceProvider();
//解析UserTestIoc服務
var grpcRequestTest = serviceProvider.GetService<UserTestIoc>();
//呼叫UserTestIoc服務中的GetUserInfo方法
grpcRequestTest.GetUserInfo();
#endregion
最後我們執行客戶端,效果如下所示:
4、?WebApi中使用gRPC
通常情況下,我們會使用WebApi對外提供資料介面服務,如果我們想在WebApi中使用gRPC該怎麼做呢?
4.1、?新建ASP.NET Core Web 應用
這裡我們新建一個名稱為Quber.Grpc.Web
的專案(該專案型別為ASP.NET Core Web 應用,方便測試),如下圖所示:
4.2、?新增Grpc.AspNetCore包
新增Grpc.AspNetCore
依賴包,如下圖所示:
4.3、?新增Proto檔案
此時我們可以直接將Quber.Grpc.Service
專案中的檔案複製過來即可,如下圖所示:
需要注意的是:複製過來後,需要在Web專案的配置中新增如下節點配置,如果已經有了請忽略:
<ItemGroup>
<Protobuf Include="Protos\user.proto" GrpcServices="Server" />
</ItemGroup>
此時我們同樣可以生成下Quber.Grpc.Web
專案,會發現在obj\Debug\net6.0\Protos
目錄下也生成了user.proto協議檔案對應的2個類檔案,如下圖所示:
4.4、?新增Services服務
同理,我們可以直接將Quber.Grpc.Service
專案中的檔案複製過來即可,如下圖所示:
4.5、?註冊gRPC服務
在啟動檔案中,我們需要註冊gRPC服務和UserService服務,如下圖所示:
到此,在Web專案中新增gRPC就完成了。
4.6、?驗證服務
在此,我們啟動Quber.Grpc.Web
專案,如下圖所示就代表啟動正常:
此時,我們就可以使用客戶端Quber.Grpc.Client
專案進行驗證,啟動Quber.Grpc.Client
專案前,我們需要先修改gRPC的連線地址(因為我們新建的Web專案提供的地址和埠號不一樣)
這樣,我們就成功的使用Web專案對外提供WebApi資料介面服務,同時又對內提供了gRPC服務。