eShopOnContainer 中 Grpc 服务定义与实现

服务于前端的后端 (BFF) 模式是 API 网关模式的一种变形,针对外部使用者的不同需求,为每种不同的客户端使用者提供一种后端 API,形成服务统一优雅的服务边界。

边界层封装内部服务的复杂性,为外部调用提供统一的外观表示。不同的外部使用者有着不同的使用需求,所以边界层的封装也会由于外部使用者的多样化,而出现多种形式。

Web.Shopping.HttpAggregator 是对内部服务进行封装之后,提供给 Web 层使用。

而 Mobile.Shopping.HttpAggregator 对内部服务进行封装之后,提供给 SPA 单页应用使用。

在 BFF 与实际的后端服务之间,使用了 Grpc 通讯协议来提高通讯效率。通讯协议的实际定义位于微服务中,在 BFF 中,通过引用 Grpc 协议定义文件来生成访问服务的 Grpc 客户端。而在微服务中,也通过这个通讯协议定义文件来完成实际的服务实现。最终完成 BFF 与微服务之间的通讯实现。

在下面的项目文件中,引入了 Grpc 的定义文件:

  • src\ApiGateways\Web.Bff.Shopping\aggregator\Web.Shopping.HttpAggregator.csproj
  • src\ApiGateways\Mobile.Bff.Shopping\aggregator\Mobile.Shopping.HttpAggregator.csproj
  <ItemGroup>
<Protobuf Include="..\..\..\Services\Basket\Basket.API\Proto\basket.proto" GrpcServices="Client" />
<Protobuf Include="..\..\..\Services\Catalog\Catalog.API\Proto\catalog.proto" GrpcServices="Client" />
<Protobuf Include="..\..\..\Services\Ordering\Ordering.API\Proto\ordering.proto" GrpcServices="Client" />
</ItemGroup>

为了支持 Grpc,项目文件中引用了 Grpc 相关的 NuGet 包:

<PackageReference Include="Google.Protobuf" Version="3.15.0" />
<PackageReference Include="Grpc.AspNetCore.Server.ClientFactory" Version="2.34.0" />
<PackageReference Include="Grpc.Core" Version="2.34.0" />
<PackageReference Include="Grpc.Net.ClientFactory" Version="2.34.0" />
<PackageReference Include="Grpc.Tools" Version="2.34.0" PrivateAssets="All" />

以 src\Services\Basket\Basket.API\Proto\basket.proto 为例,其定义如下:

syntax = "proto3";

option csharp_namespace = "GrpcBasket";

package BasketApi;

service Basket {
rpc GetBasketById(BasketRequest) returns (CustomerBasketResponse) {}
rpc UpdateBasket(CustomerBasketRequest) returns (CustomerBasketResponse) {}
} message BasketRequest {
string id = 1;
} message CustomerBasketRequest {
string buyerid = 1;
repeated BasketItemResponse items = 2;
} message CustomerBasketResponse {
string buyerid = 1;
repeated BasketItemResponse items = 2;
} message BasketItemResponse {
string id = 1;
int32 productid = 2;
string productname = 3;
double unitprice = 4;
double oldunitprice = 5;
int32 quantity = 6;
string pictureurl = 7;
}

在 .NET 中,会忽略 package 语句,而使用 csharp_namespace 中定义的命名空间。

实现 Basket 服务端 Grpc 服务

在 Basket.API 项目中,定义了如下内容:

<ItemGroup>
<Protobuf Include="Proto\basket.proto" GrpcServices="Server" Generator="MSBuild:Compile" />
<Content Include="@(Protobuf)" />
<None Remove="@(Protobuf)" />
</ItemGroup>

其中的 GrpcServices 特性用来限制 C# 代码生成。 有效 GrpcServices 选项如下:

  • 同时生成服务端定义和客户端代码(如果不存在 GrpcServices 属性定义,则为默认值)
  • Server,只生成服务端定义,服务器端抽象接口定义会自动添加 Base 后缀
  • Client,只生成客户端代码,客户端定义会自动添加 Client 后缀
  • None,不生成

由于这里定义了 Server,所以,在服务器端仅仅生成了服务定义的抽象接口 Basket.BasketBase。

在 src\Services\Basket\Basket.API\Grpc\BasketService.cs 中,实现了 Grpc 服务端。

namespace GrpcBasket;

public class BasketService : Basket.BasketBase
{
private readonly IBasketRepository _repository;
private readonly ILogger<BasketService> _logger; public BasketService(IBasketRepository repository, ILogger<BasketService> logger)
{
_repository = repository;
_logger = logger;
} [AllowAnonymous]
public override async Task<CustomerBasketResponse> GetBasketById(BasketRequest request, ServerCallContext context)

服务端作为 ASP.NET Core,配置 Grpc 支持。

public virtual IServiceProvider ConfigureServices(IServiceCollection services)
{
// ...
services.AddGrpc(options =>
{
options.EnableDetailedErrors = true;
});
// ...
} public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory loggerFactory)
{
// ...
app.UseEndpoints(endpoints =>
{
endpoints.MapGrpcService<BasketService>();
// ...
}

使用 Basket 客户端

在 Web.Bff.Shopping/aggregator 项目中,也包含了 Grpc 定义的 protobuf 定义。

<ItemGroup>
<Protobuf Include="..\..\..\Services\Basket\Basket.API\Proto\basket.proto" GrpcServices="Client" />
<Protobuf Include="..\..\..\Services\Catalog\Catalog.API\Proto\catalog.proto" GrpcServices="Client" />
<Protobuf Include="..\..\..\Services\Ordering\Ordering.API\Proto\ordering.proto" GrpcServices="Client" />
</ItemGroup>

这里设置了 GrpcServices 为 Clinet,所以,将会生成名称为 GrpcBasket.Basket.BasketClient 的类型。在 Web.Shopping.HttpAggregator.csproj 和 Mobile.Shopping.HttpAggregator.csproj 两个项目的 Startup.cs 中,可以看到对该类型的使用。

// Basket
public static IServiceCollection AddGrpcServices(this IServiceCollection services)
{
// grpc 的异常处理器
services.AddTransient<GrpcExceptionInterceptor>(); // basket
services.AddScoped<IBasketService, BasketService>();
services.AddGrpcClient<Basket.BasketClient>((services, options) =>
{
var basketApi = services.GetRequiredService<IOptions<UrlsConfig>>().Value.GrpcBasket;
options.Address = new Uri(basketApi);
}).AddInterceptor<GrpcExceptionInterceptor>(); // catalog
services.AddScoped<ICatalogService, CatalogService>();
services.AddGrpcClient<Catalog.CatalogClient>((services, options) =>
{
var catalogApi = services.GetRequiredService<IOptions<UrlsConfig>>().Value.GrpcCatalog;
options.Address = new Uri(catalogApi);
}).AddInterceptor<GrpcExceptionInterceptor>(); // ordering
services.AddScoped<IOrderingService, OrderingService>();
services.AddGrpcClient<OrderingGrpc.OrderingGrpcClient>((services, options) =>
{
var orderingApi = services.GetRequiredService<IOptions<UrlsConfig>>().Value.GrpcOrdering;
options.Address = new Uri(orderingApi);
}).AddInterceptor<GrpcExceptionInterceptor>(); return services;
};

而自定义的 BasketService 则封装了生成的 BasketClient 实现,其中主要完成了客户端数据表示到服务端数据表示的转换工作。

public class BasketService : IBasketService
{
private readonly Basket.BasketClient _basketClient;
private readonly ILogger<BasketService> _logger; public BasketService(Basket.BasketClient basketClient, ILogger<BasketService> logger)
{
_basketClient = basketClient;
_logger = logger;
} public async Task<BasketData> GetByIdAsync(string id)
{
_logger.LogDebug("grpc client created, request = {@id}", id);
var response = await _basketClient.GetBasketByIdAsync(new BasketRequest { Id = id });
_logger.LogDebug("grpc response {@response}", response); return MapToBasketData(response);
}

注:这里似乎可以考虑使用 AutoMapper 来优化数据传输对象的转换。

eShopOnContainer 中 Grpc 服务定义与实现的更多相关文章

  1. 在.NET Core中批量注入Grpc服务

    GRPC 是谷歌发布的一个开源.高性能.通用RPC服务,尽管大部分 RPC 框架都使用 TCP 协议,但其实 UDP 也可以,而 gRPC 干脆就用了 HTTP2.还有就是它具有跨平台.跨语言 等特性 ...

  2. 如何在 Knative 中部署 WebSocket 和 gRPC 服务?

    作者 | 冬岛  阿里云容器平台工程师 导读:虽然说 Knative 默认就支持 WebSocket 和 gRPC,但在使用中会发现,有时想要把自己的 WebSocket 或 gRPC 部署到 Kna ...

  3. 使用Node.JS访问Hyperledger Fabric的gRPC服务

    在即将正式发布的Hyperledger Fabric SDK 1.0中,Hyperledger Fabric通过gRPC提供服务接口以取代现有的REST API.本文介绍了如何使用Node.JS访问H ...

  4. 用Java开发gRPC服务的例子分析

    本文的代码例子来自:https://github.com/grpc/grpc-java  定义服务 这一步与其他语言完全一样,需要定义gRPC的服务.方法.request和response的类型. 完 ...

  5. ASP.NET Core 3.0 上的gRPC服务模板初体验(多图)

    早就听说ASP.NET Core 3.0中引入了gRPC的服务模板,正好趁着家里电脑刚做了新系统,然后装了VS2019的功夫来体验一把.同时记录体验的过程.如果你也想按照本文的步骤体验的话,那你得先安 ...

  6. .NET Core微服务之路:基于gRPC服务发现与服务治理的方案

    重温最少化集群搭建,我相信很多朋友都已经搭建出来,基于Watch机制也实现了出来,相信也有很多朋友有了自己的实现思路,但是,很多朋友有个疑问,我API和服务分离好了,怎么通过服务中心进行发现呢,这个过 ...

  7. gRPC初探——概念介绍以及如何构建一个简单的gRPC服务

    目录 引言 1. gRPC简介 2. 使用Protocol Buffers进行服务定义 2.1 定义消息 2.2 定义服务接口 3.构建简单的gRPC服务 3.1 编写proto文件,定义消息和接口 ...

  8. python与consul 实现gRPC服务注册-发现

    背景 通过对gRPC的介绍我们知道,当正常启动服务后,我们只需要知道ip,port就可以进行gRPC的连接.可以想到,这种方式并不适合用于线上环境,因为这样直连的话就失去了扩展性,当需要多机部署的时候 ...

  9. .NET Core 3.0中用 Code-First 方式创建 gRPC 服务与客户端

    .NET Core love gRPC 千呼万唤的 .NET Core 3.0 终于在 9 月份正式发布,在它的众多新特性中,除了性能得到了大大提高,比较受关注的应该是 ASP.NET Core 3. ...

  10. python golang中grpc 使用示例代码详解

    python 1.使用前准备,安装这三个库 pip install grpcio pip install protobuf pip install grpcio_tools 2.建立一个proto文件 ...

随机推荐

  1. SpringBoot配置多个数据源-详解

    一直在趟坑,从未被超越. 借鉴文章 个人觉得我算是整理的比较详细的了,有些博客老是缺斤少两的.最恶心的是竟然会有人写到,如需下文请关注什么什么公众号. 结构 pom文件 <dependencie ...

  2. 仿函数(Functor)是什么?

    仿函数(Functor) 仿函数是通过重载()运算符的类或结构体的对象.这样一个对象可以像普通函数一样被调用. 仿函数通常用于需要在对象内部保留状态或多次调用时有特定行为的情况. 特点: 仿函数是一个 ...

  3. Android Qcom USB Driver学习(十二)

    keypad 在suspend的过程中导致Android无法进入suspend的问题,导致整体功耗过高,其实是主机都没有进入睡眠,通过以下打log的方式最终定位到问题,pmic vbus输出的时候会有 ...

  4. find命令,查找文件

    find 是 Linux 中强大的搜索命令,不仅可以按照文件名搜索文件,还可以按照权限.大小.时间.inode 号等来搜索文件. [root@localhost ~]#find 搜索路径 [选项] 搜 ...

  5. 使用 Prometheus 在 KubeSphere 上监控 KubeEdge 边缘节点(Jetson) CPU、GPU 状态

    作者:朱亚光,之江实验室工程师,云原生/开源爱好者. KubeSphere 边缘节点的可观测性 在边缘计算场景下,KubeSphere 基于 KubeEdge 实现应用与工作负载在云端与边缘节点的统一 ...

  6. 基于 KubeSphere 的应用容器化在智能网联汽车领域的实践

    公司简介 某国家级智能网联汽车研究中心成立于 2018 年,是担当产业发展咨询与建议.共性技术研发中心.创新成果转化的国家级创新平台,旨在提高我国在智能网联汽车及相关产业在全球价值链中的地位. 目前着 ...

  7. 用故事说透HTTPS

    本文来自素燕公众号,原文地址:用故事说透https 故事中的主演: 小华今年上大一,这是她第一次离开父母,独自一人到北京上学.今天妈妈的生日,想了想要给妈妈一个祝福,便给妈妈发了条消息: 妈妈收到这条 ...

  8. Python实现微博舆情分析的设计与实现

    引言 随着互联网的发展,社交媒体平台如微博已经成为公众表达意见.分享信息的重要渠道.微博舆情分析旨在通过大数据技术和自然语言处理技术,对微博上的海量信息进行情感分析.热点挖掘和趋势预测,为政府.企业和 ...

  9. OpenCV3 图像处理笔记

    此笔记针对 Python 版本的 opencv3,c++ 版本的函数和 python 版本的函数参数几乎一样,只是矩阵格式从 ndarray 类型变成适合 c++ 的 mat 模板类型.注意,因为 p ...

  10. C# 13(.Net 9) 中的新特性 - 半自动属性

    C# 13 即 .Net 9 按照计划会在2024年11月发布,目前一些新特性已经定型,今天让我们来预览其中的一个新特性: 作者注:该特性虽然随着 C# 13 发布,但是仍然是处于 preview 状 ...