zoukankan      html  css  js  c++  java
  • .NET Core微服务开发服务间调用篇-GRPC

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

    Grpc协议使用Protobuf简称proto文件来定义接口名、调用参数以及返回值类型。比如product.api.proto文件,定义一个接口GetProduct方法,它的请求结构体是GetProductRequest,包含一个int类型的id属性,它的返回结构体GetProductResponse包含一个输出string类型的产品名称属性。

    4.添加product.api.proto文件到项目中,双击项目或者右键-》编辑项目文件,添加一下代码

    <ItemGroup>
    <ProjectReference Include="..AAStore.ProductCatalogAAStore.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.DataContractsAAStore.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.ProductCatalogAAStore.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(8081, o => o.Protocols =
    HttpProtocols.Http2);
    });

    步骤3:Grpc客户端实现-调用Grpc服务

    选择AAStore.Orde项目(具体见项目代码结构图),安装Grpc.AspNetCore包,并且添加项目引用AAStore.ProductCatalog.DataContracts

    <ItemGroup>
    <ProjectReference Include="..AAStore.ProductCatalog.DataContractsAAStore.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 = 1 });
                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进行服务间的调,最后使用一张图作结。

  • 相关阅读:
    博客模仿
    实体零售的数据分析与信息化之路
    巡店系统如何应用于连锁加盟店管理
    Dynamics CRM 常用的JS
    公众号被动消息回复原理
    form分辨率
    打开新网页 浏览图片
    网页浏览文件
    Model赋值返回json
    装载 反射
  • 原文地址:https://www.cnblogs.com/chengtian/p/13320864.html
Copyright © 2011-2022 走看看