在单体应用中,相互调用都是在一个进程内部调用,也就是说调用发生在本机内部,因此也被叫做本地方法调用;在微服务中,服务之间调用就变得比较复杂,需要跨网络调用,他们之间的调用相对于与本地方法调用,可称为远程过程调用,简称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=;
}
//返回消息体
message GetProductResponse{
string productName=;
}

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(, 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("http://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 = });
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进行服务间的调用,最后使用一张图作结。

.NET Core微服务开发服务间调用篇-GRPC的更多相关文章

  1. Prism+MaterialDesign+EntityFramework Core+Postgresql WPF开发总结 之 基础篇

    本着每天记录一点成长一点的原则,打算将目前完成的一个WPF项目相关的技术分享出来,供团队学习与总结. 总共分三个部分: 基础篇主要争对C#初学者,巩固C#常用知识点: 中级篇主要争对WPF布局与美化, ...

  2. Prism+MaterialDesign+EntityFramework Core+Postgresql WPF开发总结 之 中级篇

    本着每天记录一点成长一点的原则,打算将目前完成的一个WPF项目相关的技术分享出来,供团队学习与总结. 总共分三个部分: 基础篇主要争对C#初学者,巩固C#常用知识点: 中级篇主要争对WPF布局与Mat ...

  3. .net core——Docker化开发和部署

    原文:.net core--Docker化开发和部署 本篇文章是使用Vs2017生成的Dockerfile进行部署的. 目录 VS2017生成Docker部署项目 Dockerfile内容 在开发服务 ...

  4. .NET Core微服务之服务间的调用方式(REST and RPC)

    Tip: 此篇已加入.NET Core微服务基础系列文章索引 一.REST or RPC ? 1.1 REST & RPC 微服务之间的接口调用通常包含两个部分,序列化和通信协议.常见的序列化 ...

  5. 【新书推荐】《ASP.NET Core微服务实战:在云环境中开发、测试和部署跨平台服务》 带你走近微服务开发

    <ASP.NET Core 微服务实战>译者序:https://blog.jijiechen.com/post/aspnetcore-microservices-preface-by-tr ...

  6. 使用 ASP.NET Core 3.1 的微服务开发指南

    使用 ASP.NET Core 3.1 的微服务 – 终极详细指南 https://procodeguide.com/programming/microservices-asp-net-core/ A ...

  7. Asp.Net Core使用SignalR进行服务间调用

    网上查询过很多关于ASP.NET core使用SignalR的简单例子,但是大部分都是简易聊天功能,今天心血来潮就搞了个使用SignalR进行服务间调用的简单DEMO. 至于SignalR是什么我就不 ...

  8. net core 微服务框架 Viper 调用链路追踪

    1.Viper是什么? Viper 是.NET平台下的Anno微服务框架的一个示例项目.入门简单.安全.稳定.高可用.全平台可监控.底层通讯可以随意切换thrift grpc. 自带服务发现.调用链追 ...

  9. 基于gin的golang web开发:服务间调用

    微服务开发中服务间调用的主流方式有两种HTTP.RPC,HTTP相对来说比较简单.本文将使用 Resty 包来实现基于HTTP的微服务调用. Resty简介 Resty 是一个简单的HTTP和REST ...

随机推荐

  1. 电脑中找不到.ssh文件的解决办法

    打开GIT bash写上命令:1.git config --global user.name “XXX”xxx代表你的用户名 2.git config --global user.email &quo ...

  2. Centos7.X 搭建Grafana+Jmeter+Influxdb 性能实时监控平台(不使用docker)

    工具介绍 [centos7安装influxDB] Influxdata官网下载路径:https://portal.influxdata.com/downloads/ 1.直接执行以下命令安装 2.安装 ...

  3. 本地yum源及更新

    创建本地yumrepo源 概述 在生产环境中,由于网络环境隔离,很多内网机器,无法直接通过网络下载安装相关软件包,所以这个时候就需要在内网搭建一个yum源,然后通过下载将需要的软件包rpm下载下来,然 ...

  4. Typescript的interface、class和abstract class

    interface,class,和abstract class这3个概念,既有联系,又有区别,本文尝试着结合官方文档来阐述这三者之间的关系. 1. Declaration Merging Declar ...

  5. 关于数据库客户端navicat创建新连接失败的问题

    如图是navicat创建新连接的截图: 我就有一个疑问了,主机填localhost或者127.0.0.1都是本机,自然是可以连接成功的,那如果填本机的IP地址会怎样呢? 如下图,出现了报错: 说我的访 ...

  6. SQL循环遍历,删除表里某一列是重复的数据,只保留一条。

    DECLARE @tempId NVARCHAR(Max), @tempIDD uniqueidentifier WHILE EXISTS ( SELECT UserId FROM Users Gro ...

  7. P2882 Face The Right Way G 题解

    题目 Farmer John has arranged his N \((1 ≤ N ≤ 5,000)\) cows in a row and many of them are facing forw ...

  8. 5.scrapy过滤器

    scrapy过滤器 1. 过滤器 当我们在爬取网页的时候可能会遇到一个调转连接会在不同页面出现,这个时候如果我们的爬虫程序不能识别出 该链接是已经爬取过的话,就会造成一种重复不必要的爬取.所以我们要对 ...

  9. unity 自实现协程总结

    unity本人自实现了一个协程调用. 只是moveNext()的简单协程调用和封装,这个没什么好说的, 网上例子一大堆. 但使用的过程中遇到了几个问题. 1. 自己写的moveNext() 协程不能等 ...

  10. git clone远程仓库的指定分支

    正常clone方式 git clone <远程仓库地址> 默认clone的是远程仓库的master分支 clone指定分支 git clone -b <分支名> <远程仓 ...