其他分享
首页 > 其他分享> > Abp vnext 微服务架构下集成 gRpc

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>

其中,

  1. 节点:

    <Protobuf Include="Protos\product.proto" GrpcServices="Server"/>
    

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

  2. 节点:

        <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