电脑疑难杂症、电脑操作问题教程就来系统教程网

Abp vnext 微服务架构下集成 gRpc

2022-12-29 11:25 投稿人:网络编辑

目录
  • Abp vNext 集成 gRpc
    • gRpc 服务端 : 微服务 IotHub
      • 创建微服务
      • 引用 gRpc 包
      • 添加 *.proto 文件
      • 修改项目文件
      • 新建 gRpc 服务
      • ApsNet Core 集成 gRpc
        • 引用包
        • 添加服务
        • 添加 gRpc 服务 Endpoints
        • 设置 gRpc 的端口
    • gRpc客户端:微服务 IotEdge
      • 创建微服务
      • 引用包
      • *.proto 文件
        • 拷贝式
        • 引用式
      • 编写调用 gRpc 服务
      • 服务接口
      • 服务实现
      • ApsNet Core 集成 gRpc
        • 引用包
        • 添加 gRpc 客户端
    • 测试

Abp vNext 集成 gRpc

为了演示,这里将创建两个微服务:

  1. Artisan.IotHub
  2. Artisan.IotEdge

项目层级目录

src
├── applications
├── modules
├── ...
├── services # 主目录
│   ├── iot-edge # iot-edge 微服务
│   │   ├── src # 代码
│   │   │   ├── Artisan.IotEdge.Application # 项目
│   │   │   └── ...
│   │   ├── Artisan.IotEdge.sln # 解决方案
│   │   └── ...
│   ├── iot-hub # iot-hub 微服务
│   │   ├── src # 代码
│   │   │   ├── Artisan.IotHub.Application # 项目
│   │   │   └── ...
│   │   ├── Artisan.IotHub.sln # 解决方案
│   │   └── ...
└── ...

re>

gRpc 服务端 : 微服务 IotHub

创建微服务

创建微服务 IotHub

abp new Artisan.IotHub -u none -d ef -dbms SqlServer --separate-identity-server --version 5.2.1

re>

引用 gRpc 包

项目【Artisan.IotHub.Application】引用 gRpc 服务端需要的包

  
    
    
    
   

re>

添加 *.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;
}

re>

修改项目文件

右键项目【Artisan.IotHub.Application】的工程文件,在弹出的菜单中选择【编译项目文件】,添加如下内容:

  
    
    
    
  

re>

其中,

  1. 节点:

    
    

    re>

    是设置 gRpc 的服务文件,以便 grpc.tools 该文件自动生成服务端代码

  2. 节点:

        
        
    

    re>

    *.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 GetById(
               ProductRequest request, 
               ServerCallContext context)
           {
               return new ProductResponse
               {
                   Id = request.Id,
                   Name = "TestProduct"
               };
           }
       }
   }
   

re>

其中,

类 ProductPublic.ProductPublicBase 是由 grpc.tools 根据 product.proto 文件自动生成的。

如果没有自动生成,尝试编译项目【Artisan.IotHub.Application】

ApsNet Core 集成 gRpc

引用包

项目【Artisan.IotHub.HttpApi.Host】引入如下包:

    

re>

添加服务

代码清单:代码清单:Artisan.IotHub.HttpApi.Host/IotHubHttpApiHostModule.cs

public class IotHubHttpApiHostModule : AbpModule
{
    public override void ConfigureServices(ServiceConfigurationContext context)
    {
        //......
        ConfigureGrpc(context, configuration);
    }
    
    /// 
    /// 将 gRPC 服务添加到 ASP.NET Core 应用
    /// https://docs.microsoft.com/zh-cn/aspnet/core/grpc/aspnetcore?view=aspnetcore-6.0&tabs=visual-studio
    /// 
    /// 

aram> ///

aram> private void ConfigureGrpc(ServiceConfigurationContext context, IConfiguration configuration) { context.Services.AddGrpc(options => { options.EnableDetailedErrors = true; }); } }

re>

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

re>

设置 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
      }
    }
  },
  // ......
}

re>

特别注意:

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

re>

引用包

项目【Artisan.IotEdge.Application】引入如下包:

    
    
    

re>

*.proto 文件

拷贝式

可以将项目【 Artisan.IotHub.Application】下的 Artisan.IotHub.Application/Protos/product.proto 文件拷贝到项目【Artisan.IotEdge.Application】中,然后在项目【Artisan.IotEdge.Application】文件中添加:

  
    
  

re>

注意:GrpcServices="Client" 是 Client,而不是:Server

但是这样做有点麻烦,当项目【 Artisan.IotHub.Application】的 Artisan.IotHub.Application/Protos/product.proto 文件修改了,还得拷贝一次,比较麻烦而且容易因为遗忘而出错。比较稳妥的做法是直接引用,而不是拷贝。

引用式

通过引用的方式,添加 *.proto 文件

在项目【Artisan.IotEdge.Application】文件中添加:

  
    
  

re>

这样就不用拷贝项目【 Artisan.IotHub.Application】下的 Artisan.IotHub.Application/Protos/product.proto 文件了

项目层级目录

src
├── applications
├── modules
├── ...
├── services # 主目录
│   ├── iot-edge # iot-edge 微服务
│   │   ├── src # 代码
│   │   │   ├── Artisan.IotEdge.Application # 项目
│   │   │   └── ...
│   │   ├── Artisan.IotEdge.sln # 解决方案
│   │   └── ...
│   ├── iot-hub # iot-hub 微服务
│   │   ├── src # 代码
│   │   │   ├── Artisan.IotHub.Application # 项目
│   │   │   │   ├── Protos
│   │   │   │   │   ├── product.proto
│   │   │   └── ...
│   │   ├── Artisan.IotHub.sln # 解决方案
│   │   └── ...
└── ...

re>

编写调用 gRpc 服务

服务接口

在项目【Artisan.IotEdge.Application.Contracts】中添加如下服务接口,
代码清单:Artisan.IotEdge.Application.Contracts/Products/IProductService

    public interface IProductService
    {
        Task GetAsync(Guid productId);
    }

re>

添加DTO:

    public class ProductDto : AuditedEntityDto
    {
        public string Name { get; set; }
    }

re>

添加AutoMapper
代码清单:Artisan.IotEdge.Application.Contracts/IotEdgeApplicationAutoMapperProfile

public class IotEdgeApplicationAutoMapperProfile : Profile
{
    public IotEdgeApplicationAutoMapperProfile()
    {
        CreateMap();
    }
}

re>

服务实现

在项目【Artisan.IotEdge.Application.Contracts】中添加如下服务实现,

代码清单:Artisan.IotEdge.Application/Products/ProductService

    public class ProductService : ApplicationService, IProductService
    {
        private readonly ILogger _logger;
        private readonly IObjectMapper _mapper;
        private readonly ProductPublic.ProductPublicClient _productPublicGrpcClient;

        public ProductService(
            ILogger logger,
            IObjectMapper mapper,
             ProductPublic.ProductPublicClient productPublicGrpcClient)
        {
            _logger = logger;
            _mapper = mapper;
            _productPublicGrpcClient = productPublicGrpcClient;
        }

        public async Task 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(response) ??
                   throw new UserFriendlyException(IotEdgeDomainErrorCodes.ProductNotFound);
        }
    }

re>

其中:

  var response = await _productPublicGrpcClient.GetByIdAsync(request);

re>

就是调用微服务:IotHub 的 gRpc 的服务

ApsNet Core 集成 gRpc

引用包

在项目【Artisan.IotEdge.HttpApi.Host】中引用如下包:

    

re>

添加 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((services, options) =>
        {
            var iothubGrpcUrl = configuration["RemoteServices:IotHub:GrpcUrl"];
            options.Address = new Uri(iothubGrpcUrl);
        });
    }
}

re>

在配置文件 appsettings.json中添加微服务IotHub的配置:

  "RemoteServices": {
    "IotHub": {
      "BaseUrl": "https://localhost:44359",
      "GrpcUrl": "http://localhost:81"
    }
  },

re>

测试

启动微服务:IotHub

启动微服务:IotEdge

在微服务IotEdge的Swagger 中调用微服务IotHub的 PublicProductGrpcServiceGetById()方法:

微服务IotEdge 调用 微服务IotHub 的示意图如下所示:

返回结果:

{
  "name": "TestProduct",
  "lastModificationTime": null,
  "lastModifierId": null,
  "creationTime": "0001-01-01T00:00:00",
  "creatorId": null,
  "id": "9af7f46a-ea52-4aa3-b8c3-9fd484c2af12"
}

re>

相关文章