.Net Core 微服务实战 - gRPC 管理内部服务间通讯

源码及系列文章目录

Git 源码https://github.com/tangsong1995/TS.Microservices
CSDN 资源https://download.csdn.net/download/qq_33649351/34675095

系列文章目录https://blog.csdn.net/qq_33649351/article/details/120998558

gRPC

gRPC 是一个远程过程调用框架,由 Google 公司发起并开源。它可以让我们像在调用本地的类一样调用远程的服务。

gRPC 的特点

  • 提供几乎所有主流语言的实现,打破语言隔阂
  • 基于 HTTP/2 ,开放协议,受到广泛的支持,易于实现和集成
  • 默认使用 Protocol Buffers 序列化,性能相较于 RESTful Json 好很多
  • 工具链成熟,代码生成便捷,开箱即用
  • 支持双向流式的请求和响应,对批量处理、低延时场景友好

.NET 生态对 gRPC 的支持

.NET 对 gRPC 进行了很好的支持,具体如下:

  • 提供基于 HttpClient 的原生框架实现
  • 提供原生的 ASP.NET Core 集成库
  • 提供完整的代码生成工具
  • Visual Studio 和 Visual Stuido Code 提供 proto 文件的智能提示

gRPC 服务端核心包:

  • Grpc.AspNetCore

gRPC 客户端核心包:

  • Google.Protobuf
  • Grpc.Net.Client
  • Grpc.Net.ClientFactory
  • Grpc.Tools

使用 gRPC

.proto 文件

定义 order.proto 文件,内容如下:

syntax = "proto3";

option csharp_namespace = "GrpcServices";

package GrpcServices;

service OrderGrpc {
	rpc CreateOrder(CreateOrderCommand) returns (CreateOrderResult);
}

message CreateOrderCommand {
	string buyerId = 1;
    int32 productId = 2;
    double unitPrice = 3;
    double discount = 4;
    int32 units = 5;
}

message CreateOrderResult {
    int32 orderId = 1;
}

syntax 指定版本为 proto3 。
option csharp_namespace 指定命名空间为 GrpcServices 。
package 指定包为 GrpcServices 。
service 定义服务,定义方法。
message 定义消息,如上使用 message 定义了 CreateOrder 方法的入参及出参。需要注意定义参数的顺序,因为 gRPC 使用 Protocol Buffers 序列化,参数定义的顺序就决定了序列化时的顺序。

服务端使用 gRPC

引用包:Grpc.AspNetCore
编辑 .csproj 项目文件:

<ItemGroup>
	<Protobuf Include="Proto\order.proto" GrpcServices="Server" />
</ItemGroup>

在生成项目时,会生成相应的类,并且会将相关代码编译到 dll 内:
在这里插入图片描述
代码反编译

添加 OrderService 继承 OrderGrpc.OrderGrpcBase 实现业务逻辑:

public class OrderService : OrderGrpc.OrderGrpcBase
{
    public override Task<CreateOrderResult> CreateOrder(CreateOrderCommand request, ServerCallContext context)
    {
        // do sth. save order
        return Task.FromResult(new CreateOrderResult { OrderId = 1 });
    }
}

在 Startup 中进行注册:

public void ConfigureServices(IServiceCollection services)
{
    services.AddGrpc(options =>
    {
        options.EnableDetailedErrors = true; // 开启错误详细信息,生成环境不应该启用
    });
}

定义 OrderService 的 Endpoints :

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
	...
    app.UseEndpoints(endpoints =>
    {
        endpoints.MapGrpcService<OrderService>();
        endpoints.MapControllers();
    });
}

客户端使用 gRPC

引用包:Grpc.AspNetCore 。
将服务端的 .proto 文件文件引入到客户端:

<ItemGroup>
	<Protobuf Include="..\GrpcServer\Proto\order.proto" Link="Protos\order.proto" />
</ItemGroup>

在 Startup 中进行注册,并指定服务端的请求地址:

public void ConfigureServices(IServiceCollection services)
{
    services.AddGrpcClient<OrderGrpc.OrderGrpcClient>(options =>
    {
        options.Address = new Uri("https://localhost:5001");
    });
}

调用服务端:

public class TestController : ControllerBase
{
    private readonly OrderGrpcClient _orderGrpcClient;

    public TestController(OrderGrpcClient orderGrpcClient)
    {
        _orderGrpcClient = orderGrpcClient;
    }

    [HttpGet]
    public async Task<CreateOrderResult> Test()
    {
        var result = await _orderGrpcClient.CreateOrderAsync(new GrpcServices.CreateOrderCommand() { BuyerId = "test" });
        return result;
    }
}

使用非加密的 HTTP2

服务端增加对 HTTP2 的监听端口:

"Kestrel": {
  "Endpoints": {
    "Http": {
      "Url": "http://+:5000"
    },
    "Https": {
      "Url": "https://+:5001"
    },
    "Http2": {
      "Url": "http://+:5002",
      "Protocols": "Http2"
    }
  }
}

客户端允许使用不加密的HTTP/2协议:

public void ConfigureServices(IServiceCollection services)
{
    AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true); //允许使用不加密的HTTP/2协议
}

使用 AddGrpcClient 注册时,注册对应监听了 Http2 的请求地址:

public void ConfigureServices(IServiceCollection services)
{
    services.AddGrpcClient<OrderGrpc.OrderGrpcClient>(options =>
    {
        options.Address = new Uri("http://localhost:5002");
    });
}

控制台可以看到调用成功结果:
在这里插入图片描述

使用异常拦截器

创建异常拦截器类继承 Interceptor :

public class ExceptionInterceptor : Interceptor
{
    public override async Task<TResponse> UnaryServerHandler<TRequest, TResponse>(TRequest request, ServerCallContext context, UnaryServerMethod<TRequest, TResponse> continuation)
    {
        try
        {
            return await base.UnaryServerHandler(request, context, continuation);
        }
        catch (Exception ex)
        {
            var data = new Metadata();
            data.Add("message", ex.Message);
            throw new RpcException(new Status(StatusCode.Unknown, "Unknon"), data);
        }
    }
}

注册 gRPC 时添加此异常拦截器 :

services.AddGrpc(options =>
{
    options.EnableDetailedErrors = true; // 开启错误详细信息,生成环境不应该启用
    options.Interceptors.Add<ExceptionInterceptor>();
});

使用代码生成工具

打开 cmd 输入以下命令安装 dotnet-grpc :

dotnet tool install dotnet-grpc -g

安装后需要重启VS。

将目录定位到工作目录:
在这里插入图片描述
dotnet-grpc 的命令主要有以下四个:

  • dotnet grpc add-file :通过目录添加文件
  • dotnet grpc add-url :通过 url 添加文件
  • dotnet grpc remove :移除文件
  • dotnet grpc refresh :更新文件

使用 dotnet grpc add-file 添加:

dotnet grpc add-file ..\GrpcServer\Proto\order.proto

在这里插入图片描述

使用 dotnet grpc add-url 添加服务器文件:

dotnet grpc add-url https://raw.githubusercontent.com/grpc/grpc/master/examples/protos/helloworld.proto -o Protos\helloworld.proto

在这里插入图片描述

使用 dotnet grpc remove 移除文件:

dotnet grpc remove https://raw.githubusercontent.com/grpc/grpc/master/examples/protos/helloworld.proto 
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值