gRPC之.Net6中的初步使用說明

Qubernet發表於2023-03-13

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專案模板,然後點選下一步,如下圖所示:

image

輸入專案名稱“Quber.Grpc.Service”,然後點選下一步,如下圖所示:

image

選中.Net6,最後點選建立按鈕,如下圖所示:

image

預設專案檔案結構,如下圖所示:

image

2.2、?檔案說明

  • appsettings.json
    我們開啟appsettings.json檔案,其中有一個Protocols屬性,代表基於Http2進行通訊。

    image

  • Protos
    在建立的專案中,我們會看到有一個名稱為Protos的資料夾,該資料夾用於存放proto協議檔案,其中的greet.proto是專案預設給我們建立的一個示例檔案,它會根據協議自動生成需要的類檔案。該協議檔案中的具體說明如下圖所示:

    image

  • Services
    在建立的專案中,我們會看到有一個名稱Services的資料夾,該資料夾用於存放具體的業務實現類(即:服務類),其中的GreeterService.cs是專案預設給我們建立的一個示例檔案,具體說明如下圖所示:

    image

    上述圖中的Greeter.GreeterBase來自greet.proto檔案生成的類檔案,具體位置如下圖所示:

    image

  • 註冊服務

    最後我們開啟Program.cs檔案,需要新增gRPC服務,同時需要將所有的業務服務進行註冊,如下圖所示:

    image

2.3、?建立自定義服務

接下來我們就以獲取使用者資訊為例建立一個名稱為user.proto的協議檔案進行講解。

  • 建立user.proto協議檔案

    新建user.proto協議檔案,如下圖所示:

    image

    image

    該協議檔案的內容如下所示:

    //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節點中增加如下配置:

    image

    <ItemGroup>
    	<Protobuf Include="Protos\user.proto" GrpcServices="Server" />
    </ItemGroup>
    

    接下來我們生成一下專案,就會發現在\obj\Debug\net6.0\Protos目錄下多了2個user.proto協議檔案對應的類檔案了,如下圖所示:

    image

  • 實現定義的服務

    建立UserService.cs類檔案,具體程式碼如下所示:

    image

    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服務在啟動檔案中進行註冊,如下所示:

    image

  • 啟動服務

    到此,gRPC服務端就新建配置完成了,此時我們就可以啟動該專案讓其執行起來,如下圖所示:

    image

    在上圖中,我們發現有2個地址http://localhost:5201https://localhost:7288,這2個地址是我們在建立專案的時候,在launchSettings.json配置中自動給我們配置的,後面gRPC客戶端會使用到這2個地址,目的是給客戶端請求提供監聽的地址。

    image


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協議檔案複製過來,如下圖所示:

image

3.3、?編輯客戶端配置

我們雙擊專案Quber.Grpc.Client開啟專案的編輯檔案,在ItemGroup節點中增加如下配置:

image

<ItemGroup>
	<Protobuf Include="Protos\user.proto" GrpcServices="Client" />
</ItemGroup>

此時我們生成一下客戶端專案,會發現在obj\Debug\net6.0\Protos目錄下也生成了user.proto協議檔案對應的2個類檔案,如下圖所示:

image

3.4、?gRPC服務的https呼叫

在gRPC服務端專案中,給我們提供了2個地址的呼叫,一個是https的https://localhost:7288,另一個是http的http://localhost:5201,此處我們演示呼叫https。

在客戶端專案中我們新建類檔案UserTest.cs,具體程式碼如下所示:

image

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

然後我們在啟動檔案中進行呼叫並執行該客戶端專案,如下圖所示:

image

到此,呼叫gRPC服務端提供的https地址就成功了。

3.5、?gRPC服務的http呼叫

相比https的呼叫,我們只需要在呼叫前加上如下程式碼即可:

AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true);

UserTest.cs中的具體程式碼如下所示:

image

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

執行效果如下:

image

3.6、?依賴注入方式呼叫gRPC

我們在客戶端專案中新建UserTestIoc.cs類檔案,具體程式碼如下所示:

image

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中進行相應的依賴注入配置並呼叫,具體程式碼如下所示:

image

#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

最後我們執行客戶端,效果如下所示:

image


4、?WebApi中使用gRPC

通常情況下,我們會使用WebApi對外提供資料介面服務,如果我們想在WebApi中使用gRPC該怎麼做呢?

4.1、?新建ASP.NET Core Web 應用

這裡我們新建一個名稱為Quber.Grpc.Web的專案(該專案型別為ASP.NET Core Web 應用,方便測試),如下圖所示:

image

image

image

4.2、?新增Grpc.AspNetCore包

新增Grpc.AspNetCore依賴包,如下圖所示:

image

4.3、?新增Proto檔案

此時我們可以直接將Quber.Grpc.Service專案中的檔案複製過來即可,如下圖所示:

image

需要注意的是:複製過來後,需要在Web專案的配置中新增如下節點配置,如果已經有了請忽略:

image

<ItemGroup>
	<Protobuf Include="Protos\user.proto" GrpcServices="Server" />
</ItemGroup>

此時我們同樣可以生成下Quber.Grpc.Web專案,會發現在obj\Debug\net6.0\Protos目錄下也生成了user.proto協議檔案對應的2個類檔案,如下圖所示:

image

4.4、?新增Services服務

同理,我們可以直接將Quber.Grpc.Service專案中的檔案複製過來即可,如下圖所示:

image

4.5、?註冊gRPC服務

在啟動檔案中,我們需要註冊gRPC服務和UserService服務,如下圖所示:

image

到此,在Web專案中新增gRPC就完成了。

4.6、?驗證服務

在此,我們啟動Quber.Grpc.Web專案,如下圖所示就代表啟動正常:

image

此時,我們就可以使用客戶端Quber.Grpc.Client專案進行驗證,啟動Quber.Grpc.Client專案前,我們需要先修改gRPC的連線地址(因為我們新建的Web專案提供的地址和埠號不一樣)

image

這樣,我們就成功的使用Web專案對外提供WebApi資料介面服務,同時又對內提供了gRPC服務

相關文章