.NET Core微服務開發服務間調用篇-GRPC
- 2020 年 7 月 16 日
- 筆記
- .Net Core 3.X, 微服務
在單體應用中,相互調用都是在一個進程內部調用,也就是說調用發生在本機內部,因此也被叫做本地方法調用;在微服務中,服務之間調用就變得比較複雜,需要跨網路調用,他們之間的調用相對於與本地方法調用,可稱為遠程過程調用,簡稱RPC(Remote procedure call)。
看過上篇API網關篇,知道案例中包含商品、訂單兩個微服務,本文將會演示如何採用開源的,高性能rpc框架(grpc),通過訂單微服務調用產品微服務內的介面。沒有看過上篇文章不影響,我先提供下項目程式碼結構圖,方便你閱讀。下面將會一步一步分享如何使用Grpc進行服務之間調用。
步驟1:首先定義服務鍥約-proto文件
1.創建類庫(.NET Standard),作為服務契約項目,命名為-AAStore.ProductCatalog.DataContracts如圖:
2.安裝三個nuget包
Google.Protobuf
Grpc
Grpc.Tools
3.開始定義proto文件:product.api.proto
syntax = "proto3"; option csharp_namespace = "AAStore.ProductCatalog.Api.V1"; package AAStore; service ProductApi{ rpc GetProduct(GetProductRequest) returns (GetProductResponse); } //請求消息體 message GetProductRequest{ int32 Id=1; } //返回消息體 message GetProductResponse{ string productName=1; }
Grpc協議使用Protobuf簡稱proto文件來定義介面名、調用參數以及返回值類型。比如product.api.proto文件,定義一個介面GetProduct方法,它的請求結構體是GetProductRequest,包含一個int類型的id屬性,它的返回結構體GetProductResponse包含一個輸出string類型的產品名稱屬性。
4.添加product.api.proto文件到項目中,雙擊項目或者右鍵-》編輯項目文件,添加一下程式碼
<ItemGroup> <ProjectReference Include="..\AAStore.ProductCatalog\AAStore.ProductCatalog.csproj" /> </ItemGroup>
然後build項目,此時gprc程式碼已經生成了,在obj文件項目,如圖
步驟2:Grpc服務端實現
選擇項目AAStore.ProductCatalog(詳情見項目程式碼結構圖)安裝包Grpc.AspNetCore,同時添加引用項目AAStore.ProductCatalog.DataContracts
<ItemGroup> <PackageReference Include="Grpc.AspNetCore" Version="2.29.0" /> </ItemGroup> <ItemGroup> <ProjectReference Include="..\AAStore.ProductCatalog.DataContracts\AAStore.ProductCatalog.DataContracts.csproj" /> </ItemGroup>
然後定義獲取產品方法的邏輯和實現,供產品api站點項目調用
public class GrpcProductServices { public Task<GetProductResponse> GetProduct(GetProductRequest request, ServerCallContext context) { return Task.FromResult(new GetProductResponse { //todo 具體的邏輯 下面程式碼僅為顯示 ProductName = "測試商品grpc" }) ; } }
選擇AAStore.ProductCatalog.Api產品api項目添加引用項目AAStore.ProductCatalog
<ItemGroup> <ProjectReference Include="..\AAStore.ProductCatalog\AAStore.ProductCatalog.csproj" /> </ItemGroup>
新增ProductServices.cs並繼承ProductApiBase類,實現grpc服務
public class ProductServices : ProductApi.ProductApiBase { public override Task<GetProductResponse> GetProduct(GetProductRequest request, ServerCallContext context) { return new GrpcProductServices().GetProduct(request, context); } }
由於AAStore.ProductCatalog.Api項目不是通過grpc模板項目創建的,所以在Startup類中手工添加gprc服務和中間件程式碼:
public void ConfigureServices(IServiceCollection services) { services.AddControllers(); services.AddGrpc(); } app.UseEndpoints(endpoints => { endpoints.MapGrpcService<ProductServices>(); endpoints.MapControllers(); });
最後在Program文件配置站點啟動監聽8081埠,我們並運行它
webBuilder.ConfigureKestrel(options => { // Setup a HTTP/2 endpoint without TLS. options.ListenLocalhost(8081, o => o.Protocols = HttpProtocols.Http2); });
步驟3:Grpc客戶端實現-調用Grpc服務
選擇AAStore.Orde項目(具體見項目程式碼結構圖),安裝Grpc.AspNetCore包,並且添加項目引用AAStore.ProductCatalog.DataContracts
<ItemGroup>
<ProjectReference Include=”..\AAStore.ProductCatalog.DataContracts\AAStore.ProductCatalog.DataContracts.csproj” />
</ItemGroup>
新建ProductGateway.cs,封裝產品微服務公開grpc服務的調用
public class ProductGateway { private readonly ProductApiClient _client; public ProductGateway() { AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true); _client = new ProductApiClient(GrpcChannel.ForAddress("//localhost:8081"));//TODO 根據動態配置 } public async Task<GetProductResponse> GetProduct(GetProductRequest request) { return await _client.GetProductAsync(request); } }
新建OrderService.cs,添加GetOrder方法,在其方法內調用產品微服務GetProduct方法
public async Task<string> GetOrder() { var productModel = await _productGateway.GetProduct(new GetProductRequest() { Id = 1 }); return $"Order Service=>從產品微服務獲取產品資訊:{productModel.ProductName}"; }
然後在訂單控制器中調用
[Route("api/[controller]")] [ApiController] public class OrderController : ControllerBase { private readonly RestOrderService _restOrderService; public OrderController() { _restOrderService = new RestOrderService(); } [HttpGet(template:"Get")] public async Task<string> GetOrder() { return await _restOrderService.GetOrder(); } }
至此,客戶端程式碼已經完成,我們運行來看看
通過網關訪問訂單服務,查看調用結果
我們發現結果也是一樣的,以上演示了如何使用grpc進行服務間的調用,最後使用一張圖作結。