• .NET Core(.NET6)中gRPC使用


     


    一、简介

    简单解析一下gRPC,gRPC 是一个由Google开源的,跨语言的,高性能的远程过程调用(RPC)框架。

    特点:

    • 跨语言
    • 内容protobuf格式(比json体积小),网络传输快
    • 使用HTTP/2进行传输

    适合高性能轻量的微服务,一般对外的接口用restful api,内部服务的调用用gRPC。gRPC是一个分布式服务框架,和以前的WebService,WCF类似。

    二、创建gRPC服务端

    1.创建gRPC项目

    新建一个gRPC模板的项目

     

     

     

     

     

     特别的地方就这里4点。

    1.基于http2来通信。

    2.proto协议文件,greet.proto是项目默认给我们的一个hello world的示例。它会根据协议自动生成需要的类。

     

     

    3.服务类,Greeter.GreeterBase来自于2中的proto文件自动生成的类,生成的类在\obj\Debug\net6.0\Protos 目录下。

     

     自动生成的类:

     

     4.Program.cs添加了gRPC服务,和把GreeterService注册到管道中。

    2.编写自己的服务

    怎么样写自己的调用服务呢?

     1.创建proto文件

    参照上面的示例创建自己的Proto文件

     

     

     

     

     代码:

    复制代码
    syntax = "proto3";
    
    option csharp_namespace = "GrpcDemo.Service";
    
    package order;
    
    // 订单服务定义
    service Order {
      // 创建订单
      rpc CreateOrder (CreateRequest) returns (CreateResult);
      //查询订单
      rpc QueryOrder (QueryRequest) returns (QueryResult);
    }
    
    //创建订单请求参数
    message CreateRequest {
      string orderNo = 1;
      string orderName=2;
      double price=3;
    }
    
    //创建订单返回结果
    message CreateResult {
      bool result = 1;
      string message=2;
    }
    
    //查询订单请求参数
    message QueryRequest{
        int id=1;
    }
    //查询订单返回结果
    message QueryResult{
        int id=1;
        string orderNo=2;
        string orderName=3;
        double price=4;
    }
    复制代码

     

    生成一下就能看到对应的类已经生成了。

     

     2.实现定义的服务

     创建OrderService.cs

    复制代码
     public class OrderService:Order.OrderBase
        {
            private readonly ILogger<GreeterService> _logger;
            public OrderService(ILogger<GreeterService> logger)
            {
                _logger = logger;
            }
            /// <summary>
            /// 创建订单
            /// </summary>
            /// <param name="request"></param>
            /// <param name="context"></param>
            /// <returns></returns>
            public override Task<CreateResult> CreateOrder(CreateRequest request, ServerCallContext context)
            {
                //报存数据库 todo
    
                return Task.FromResult(new CreateResult
                {
                    Result=true,
                    Message="订单创建成功"
                });
            }
            /// <summary>
            /// 查询订单
            /// </summary>
            /// <param name="request"></param>
            /// <param name="context"></param>
            /// <returns></returns>
            public override Task<QueryResult> QueryOrder(QueryRequest request, ServerCallContext context)
            {
                //查询数据库 //todo
    
                return Task.FromResult(new QueryResult
                {
                    OrderInfo=new OrderInfo
                    {
                        Id = request.Id,
                        OrderNo = DateTime.Now.ToString("yyyyMMddHHmmss"),
                        OrderName = "冰箱",
                        Price = 1288
                    }
                });
            }
        }
    复制代码

    继承的Order.OrderBase 是上面的proto文件生成的,然后实现了proto里面定义的两个服务。

    然后在program.cs里面把服务注入管道。

     

     到这里服务端就完成了,就可以启动服务端了。

     

     浏览器访问不了,要通过gRPC客户端才能访问,下面就建一个gRPC客户端。

    三、创建gRPC客户端

    1.创建客户端项目

    1.1、这里创建一个控制台程序。

    1.2、然后添加Nuget包

    Google.Protobuf
    Grpc.Net.Client
    Grpc.Tools
    Grpc.Net.clientFactory

    1.3、把服务端的proto文件拷贝过来

     

     1.4、编辑项目文件,把proto里面的内容替换掉,默认是服务端的配置

     

     

      <Protobuf Include="Protos\greet.proto" GrpcServices="Client" />
          <Protobuf Include="Protos\order.proto" GrpcServices="Client" />

    生成的时候,客户端也生成了对应proto的类

     

    2.grPC服务https的调用

    因为服务端提供了http和https的端口,这里先调用https的

    创建GrpcRequestTest.cs类

    复制代码
     /// <summary>
        /// gRPC请求测试
        /// </summary>
        public class GrpcRequestTest
        {
            public void CreateOrder()
            {
                //常规使用,https
                string url = "https://localhost:7246";
                using(var channel=GrpcChannel.ForAddress(url))
                {
                    var client = new Order.OrderClient(channel);
                    var reply = client.CreateOrder(new CreateRequest()
                    {
                        OrderNo = DateTime.Now.ToString("yyyMMddHHmmss"),
                        OrderName = "冰箱22款",
                        Price = 1688
                    });
    
                    Console.WriteLine($"结果:{reply.Result},message:{reply.Message}");
                }
                Console.ReadKey();
            }
        }
    复制代码

    结果:

    3.gRPC内网http调用

    复制代码
          public void CreateOrder()
            {
                 //使用http
                AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true);
                string url = "http://localhost:5246";
    
                using(var channel=GrpcChannel.ForAddress(url))
                {
                    var client = new Order.OrderClient(channel);
                    var reply = client.CreateOrder(new CreateRequest()
                    {
                        OrderNo = DateTime.Now.ToString("yyyMMddHHmmss"),
                        OrderName = "冰箱22款",
                        Price = 1688
                    });
    
                    Console.WriteLine($"结果:{reply.Result},message:{reply.Message}");
                }
                Console.ReadKey();
            }
    复制代码

    比起https,前面多了一行。结果:

     

    4.IOC注入的方式调用gRPC

    4.1、program.cs里面注入gRPCClient

    复制代码
    // See https://aka.ms/new-console-template for more information
    using GrpcDemo.Client;
    using GrpcDemo.Service;
    using Microsoft.Extensions.DependencyInjection;
    
    Console.WriteLine("Hello, World!");
    
    IServiceCollection services = new ServiceCollection();
    services.AddTransient<GrpcRequestTest>();
    
    #region gRPC Client注册
    AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true);
    services.AddGrpcClient<Order.OrderClient>(options =>
    {
        options.Address = new Uri("http://localhost:5246");
    }).ConfigureChannel(grpcOptions =>
    {
        //可以完成各种配置,比如token
    });
    #endregion
    
    //构建容器
    IServiceProvider serviceProvider = services.BuildServiceProvider();
    //解析grpc请求测试
    var grpcRequestTest = serviceProvider.GetService<GrpcRequestTest>();
    //执行
    grpcRequestTest.CreateOrder();
    复制代码

    grpcRequestTest里代码:

    复制代码
    /// <summary>
        /// gRPC请求测试
        /// </summary>
        public class GrpcRequestTest
        {
            private Order.OrderClient _orderClient;
            public GrpcRequestTest(Order.OrderClient orderClient)
            {
                _orderClient = orderClient;
            }
            public void CreateOrder()
            {
                var reply = _orderClient.CreateOrder(new CreateRequest()
                {
                    OrderNo = DateTime.Now.ToString("yyyMMddHHmmss"),
                    OrderName = "冰箱22款",
                    Price = 1688
                });
                Console.WriteLine($"结果:{reply.Result},message:{reply.Message}");
                Console.ReadKey();
            }
        }
    复制代码

    结果:

     

    四、webapi中加入gRPC

    通常我们的服务有对外提供对外接口,又要对内提供gRPC服务,那怎么做呢,下面在webapi中加入gRPC服务

    1.创建asp.net core mvc项目

    2.安装nuget包

    Grpc.AspNetCore

    3.添加protebuf文件

    把上面的proto文件复制过来

     

     

    4.添加Service

     

     

    复制代码
      public class OrderService : Order.OrderBase
        {
            private readonly ILogger<OrderService> _logger;
            public OrderService(ILogger<OrderService> logger)
            {
                _logger = logger;
            }
            /// <summary>
            /// 创建订单
            /// </summary>
            /// <param name="request"></param>
            /// <param name="context"></param>
            /// <returns></returns>
            public override Task<CreateResult> CreateOrder(CreateRequest request, ServerCallContext context)
            {
                //报存数据库 todo
    
                return Task.FromResult(new CreateResult
                {
                    Result = true,
                    Message = "订单创建成功"
                });
            }
            /// <summary>
            /// 查询订单
            /// </summary>
            /// <param name="request"></param>
            /// <param name="context"></param>
            /// <returns></returns>
            public override Task<QueryResult> QueryOrder(QueryRequest request, ServerCallContext context)
            {
                //查询数据库 //todo
    
                return Task.FromResult(new QueryResult
                {
                    OrderInfo = new OrderInfo
                    {
                        Id = request.Id,
                        OrderNo = DateTime.Now.ToString("yyyyMMddHHmmss"),
                        OrderName = "冰箱",
                        Price = 1288
                    }
                });
            }
        }
    复制代码

    5.注册gRPC服务

    在Program.cs文件中

     

    到这里,就把gRPC加入到webapi里面了。 

    6.验证

    启动asp.net core mvc程序

     

     

     

    浏览器能访问,证明 restful api是没问题的。

    然后再用上面的客户端访问一下gRPC的服务。

     

     

     结果:

     

     这样就成功对外提供api接口和对内提供gRPC服务了。

     

    源码地址:https://github.com/weixiaolong325/GrpcDemo.Service

  • 相关阅读:
    Arduino程序设计(八)LCD显示实验
    Minikube 入门基础:基础操作命令
    椭圆的矩阵表示法
    [量化投资-学习笔记006]Python+TDengine从零开始搭建量化分析平台-MACD
    THREE--demo4
    Python递归函数的定义和几个小例子
    中断处理过程的压栈问题
    获得反射对象
    从这两道题重新理解,JS的this、作用域、闭包、对象
    市面上北方水稻居多 国稻种芯:南方盛产水稻去哪里了?
  • 原文地址:https://www.cnblogs.com/wei325/p/16128279.html