Abp vnext 微服务架构下集成 gRpc
作者:互联网
Abp vNext 集成 gRpc
gRpc 服务端 : 微服务 IotHub
创建微服务
创建微服务 IotHub
abp new Artisan.IotHub -u none -d ef -dbms SqlServer --separate-identity-server --version 5.2.1
引用 gRpc 包
项目【Artisan.IotHub.Application】引用 gRpc 服务端需要的包
<ItemGroup>
<PackageReference Include="Google.Protobuf" Version="3.20.1" />
<PackageReference Include="Grpc.Core" Version="2.46.1" />
<PackageReference Include="Grpc.Tools" Version="2.46.1">
<ItemGroup>
添加 *.proto 文件
在项目【Artisan.IotHub.Application】新建文件夹 Protos
, 然后在该文件夹下添加一个 product.proto
文件,内容如下:
代码清单: Artisan.IotHub.Application/Protos/product.proto
syntax = "proto3";
option csharp_namespace = "Artisan.IotHub.Grpc";
package IotHubApi;
service ProductPublic {
rpc GetById(ProductRequest) returns (ProductResponse);
}
message ProductRequest {
string id = 1;
}
message ProductResponse {
string id = 1;
string name = 2;
}
修改项目文件
右键项目【Artisan.IotHub.Application】的工程文件,在弹出的菜单中选择【编译项目文件】,添加如下内容:
<ItemGroup>
<Protobuf Include="Protos\product.proto" GrpcServices="Server"/>
<Content Include="@(Protobuf)" />
<None Remove="@(Protobuf)" />
</ItemGroup>
其中,
-
节点:
<Protobuf Include="Protos\product.proto" GrpcServices="Server"/>
是设置 gRpc 的服务文件,以便 grpc.tools 该文件自动生成服务端代码
-
节点:
<Content Include="@(Protobuf)" /> <None Remove="@(Protobuf)" />
将
*.proto
文件的属性设置为:【内容】、【不复制】
新建 gRpc 服务
在项目【Artisan.IotHub.Application】下新建文件夹 Grpc
, 在该文件夹下新建类PublicProductGrpcService
代码清单:Artisan.IotHub.Application/Grpc/PublicProductGrpcService.cs
using Grpc.Core;
using System.Threading.Tasks;
namespace Artisan.IotHub.Grpc
{
public class PublicProductGrpcService : ProductPublic.ProductPublicBase
{
public PublicProductGrpcService()
{
}
public override async Task<ProductResponse> GetById(
ProductRequest request,
ServerCallContext context)
{
return new ProductResponse
{
Id = request.Id,
Name = "TestProduct"
};
}
}
}
其中,
类 ProductPublic.ProductPublicBase 是由 grpc.tools 根据 product.proto 文件自动生成的。
如果没有自动生成,尝试编译项目【Artisan.IotHub.Application】
ApsNet Core 集成 gRpc
引用包
项目【Artisan.IotHub.HttpApi.Host】引入如下包:
<PackageReference Include="Grpc.AspNetCore.Server" Version="2.46.0" />
添加服务
代码清单:代码清单:Artisan.IotHub.HttpApi.Host/IotHubHttpApiHostModule.cs
public class IotHubHttpApiHostModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
//......
ConfigureGrpc(context, configuration);
}
/// <summary>
/// 将 gRPC 服务添加到 ASP.NET Core 应用
/// https://docs.microsoft.com/zh-cn/aspnet/core/grpc/aspnetcore?view=aspnetcore-6.0&tabs=visual-studio
/// </summary>
/// <param name="context"></param>
/// <param name="configuration"></param>
private void ConfigureGrpc(ServiceConfigurationContext context, IConfiguration configuration)
{
context.Services.AddGrpc(options =>
{
options.EnableDetailedErrors = true;
});
}
}
添加 gRpc 服务 Endpoints
代码清单:代码清单:Artisan.IotHub.HttpApi.Host/IotHubHttpApiHostModule.cs
using Artisan.IotHub.Grpc;
public class IotHubHttpApiHostModule : AbpModule
{
public override void OnApplicationInitialization(ApplicationInitializationContext context)
{
//......
app.UseConfiguredEndpoints(endpoints =>
{
endpoints.MapGrpcService<PublicProductGrpcService>();
});
}
}
设置 gRpc 的端口
在配置文件 appsettings.json
中添加微服务IotHub的端口:
{
"Kestrel": {
"Endpoints": {
"Http": {
"Url": "http://localhost:7059",
"Protocols": "Http1AndHttp2" //有些中间件走的还是http1.0,故要兼容
},
"Https": {
"Url": "https://localhost:44359",
"Protocols": "Http1AndHttp2" // 有些中间件走的还是http1.0,故要兼容
},
"gRPC": {
"Url": "http://localhost:81",
"Protocols": "Http2" // gRPC是基于Http2的,必须设置为Http2
}
}
},
// ......
}
特别注意:
gRPC 是基于 Http2的,而项目中的Http 和 Https ,有些功能还是基于 Http1.0的,
故需要通过配置节点:Protocols来分别设置它们的协议。
gRpc客户端:微服务 IotEdge
创建微服务
创建微服务 IotEdge
abp new Artisan.IotEdge -u none -d ef -dbms SqlServer --separate-identity-server --version 5.2.1
引用包
项目【Artisan.IotEdge.Application】引入如下包:
<PackageReference Include="Google.Protobuf" Version="3.20.1" />
<PackageReference Include="Grpc.Core" Version="2.46.1" />
<PackageReference Include="Grpc.Tools" Version="2.46.1">
*.proto 文件
拷贝式
可以将项目【 Artisan.IotHub.Application】下的 Artisan.IotHub.Application/Protos/product.proto
文件拷贝到项目【Artisan.IotEdge.Application】中,然后在项目【Artisan.IotEdge.Application】文件中添加:
<ItemGroup>
<Protobuf Include="Protos\product.proto" GrpcServices="Client"/>
</ItemGroup>
注意:GrpcServices="Client" 是 Client,而不是:Server
但是这样做有点麻烦,当项目【 Artisan.IotHub.Application】的 Artisan.IotHub.Application/Protos/product.proto
文件修改了,还得拷贝一次,比较麻烦而且容易因为遗忘而出错。比较稳妥的做法是直接引用,而不是拷贝。
引用式
通过引用的方式,添加 *.proto 文件
在项目【Artisan.IotEdge.Application】文件中添加:
<ItemGroup>
<Protobuf Include="..\..\..\iot-hub\src\Artisan.IotHub.Application\Protos\product.proto" GrpcServices="Client" />
</ItemGroup>
这样就不用拷贝项目【 Artisan.IotHub.Application】下的 Artisan.IotHub.Application/Protos/product.proto
文件了
编写调用 gRpc 服务
服务接口
在项目【Artisan.IotEdge.Application.Contracts】中添加如下服务接口,
代码清单:Artisan.IotEdge.Application.Contracts/Products/IProductService
public interface IProductService
{
Task<ProductDto> GetAsync(Guid productId);
}
添加DTO:
public class ProductDto : AuditedEntityDto<Guid>
{
public string Name { get; set; }
}
添加AutoMapper
代码清单:Artisan.IotEdge.Application.Contracts/IotEdgeApplicationAutoMapperProfile
public class IotEdgeApplicationAutoMapperProfile : Profile
{
public IotEdgeApplicationAutoMapperProfile()
{
CreateMap<ProductResponse, ProductDto>();
}
}
服务实现
在项目【Artisan.IotEdge.Application.Contracts】中添加如下服务实现,
代码清单:Artisan.IotEdge.Application/Products/ProductService
public class ProductService : ApplicationService, IProductService
{
private readonly ILogger<ProductService> _logger;
private readonly IObjectMapper _mapper;
private readonly ProductPublic.ProductPublicClient _productPublicGrpcClient;
public ProductService(
ILogger<ProductService> logger,
IObjectMapper mapper,
ProductPublic.ProductPublicClient productPublicGrpcClient)
{
_logger = logger;
_mapper = mapper;
_productPublicGrpcClient = productPublicGrpcClient;
}
public async Task<ProductDto> GetAsync(Guid productId)
{
var request = new ProductRequest { Id = productId.ToString() };
_logger.LogInformation("=== GRPC request {@request}", request);
var response = await _productPublicGrpcClient.GetByIdAsync(request);
_logger.LogInformation("=== GRPC response {@response}", response);
return _mapper.Map<ProductResponse, ProductDto>(response) ??
throw new UserFriendlyException(IotEdgeDomainErrorCodes.ProductNotFound);
}
}
其中:
var response = await _productPublicGrpcClient.GetByIdAsync(request);
就是调用微服务:IotHub 的 gRpc 的服务
ApsNet Core 集成 gRpc
引用包
在项目【Artisan.IotEdge.HttpApi.Host】中引用如下包:
<PackageReference Include="Grpc.Net.ClientFactory" Version="2.46.0" />
添加 gRpc 客户端
代码清单:Artisan.IotEdge.HttpApi.Host/IotEdgeHttpApiHostModule.cs
public class IotEdgeHttpApiHostModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
// ......
ConfigureGrpc(context, configuration);
}
private void ConfigureGrpc(ServiceConfigurationContext context, IConfiguration configuration)
{
context.Services.AddGrpcClient<ProductPublic.ProductPublicClient>((services, options) =>
{
var iothubGrpcUrl = configuration["RemoteServices:IotHub:GrpcUrl"];
options.Address = new Uri(iothubGrpcUrl);
});
}
}
在配置文件 appsettings.json
中添加微服务IotHub的配置:
"RemoteServices": {
"IotHub": {
"BaseUrl": "https://localhost:44359",
"GrpcUrl": "http://localhost:81"
}
},
测试
启动微服务:IotHub
启动微服务:IotEdge
在 IotEdge 的Swagger 中调用 微服务:IotEdge 的
微服务IotEdge 调用 微服务IotHub 的示意图如下所示:
返回结果:
{
"name": "TestProduct",
"lastModificationTime": null,
"lastModifierId": null,
"creationTime": "0001-01-01T00:00:00",
"creatorId": null,
"id": "9af7f46a-ea52-4aa3-b8c3-9fd484c2af12"
}
标签:vnext,gRpc,IotHub,Abp,Application,Artisan,IotEdge,public 来源: https://www.cnblogs.com/easy5weikai/p/16288182.html