查看原文
其他

.NET 6 中 gRPC 使用

DotNet 2022-07-19

推荐关注↓

一、简介


简单解析一下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.ToolsGrpc.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

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

转自:包子wxl

链接:cnblogs.com/wei325/p/16128279.html

- EOF -

推荐阅读  点击标题可跳转
.NET Core 利用 AsyncLocal 实现共享变量C# 利用.NET 升级助手将.NET Framework项目升级为.NET 6一款倍受欢迎的 .NET 开源UI库 


看完本文有收获?请转发分享给更多人

推荐关注「DotNet」,提升.Net技能 

点赞和在看就是最大的支持❤️

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存