gRPC 是一种与语言无关的高性能远程过程调用 (RPC) 框架。

gRPC 的主要优点是:

  • 现代高性能轻量级 RPC 框架。
  • 协定优先 API 开发,默认使用协议缓冲区,允许与语言无关的实现。
  • 可用于多种语言的工具,以生成强类型服务器和客户端。
  • 支持客户端、服务器和双向流式处理调用。
  • 使用 Protobuf 二进制序列化减少对网络的使用。

这些优点使 gRPC 适用于:

  • 效率至关重要的轻量级微服务。
  • 需要多种语言用于开发的 Polyglot 系统。
  • 需要处理流式处理请求或响应的点对点实时服务。

https://github.com/grpc/grpc 提供了.Net的支持库。

.Net Core 创建gRPC服务

新建项目选择"gRPC 服务"

vs需要Visual Studio 2019 16.4 或更高版本。

或者在终端中通过命令行创建 dotnet new grpc -o XXX

相比普通的.Net 项目回多出Protos和Services两个文件夹。Protos文件夹放置.proto文件,Services文件夹放置根据proto文件生成的Service。

 
Startup类 ConfigureServices方法中会添加services.AddGrpc();代码增加Grpc支持。 Configure方法内gRPC服务添加到了终结点路由中。
public void ConfigureServices(IServiceCollection services)
{
services.AddGrpc();
} // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
} app.UseRouting(); app.UseEndpoints(endpoints =>
{
endpoints.MapGrpcService<GreeterService>(); endpoints.MapGet("/", async context =>
{
await context.Response.WriteAsync("Communication with gRPC endpoints must be made through a gRPC client. To learn how to create a client, visit: https://go.microsoft.com/fwlink/?linkid=2086909");
});
});
}

.Net Core 创建gRPC客户端

1.新建.Net Core项目

示例新建控制台应用(.NET Core),并通过Nuget添加如下包:

2.创建 Protos 文件夹

客户端项目创建Protos 文件夹,并将服务项目中的 Protos\greet.proto 文件复制到该文件夹

3.修改客户端proto 文件的命名空间

option csharp_namespace = "GrpcClient";

4.编辑项目文件(GrpcClient.csproj)

添加关于proto元素的项组

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

5.构建客户端项目生成proto文件对应的类

6.添加客户端调用服务代码

static async Task Main(string[] args)
{
  // The port number(5001) must match the port of the gRPC server.
  using var channel = GrpcChannel.ForAddress("https://localhost:5001");
  var client = new Greeter.GreeterClient(channel);
  var reply = await client.SayHelloAsync(
  new HelloRequest { Name = "GreeterClient" });
  Console.WriteLine("Greeting: " + reply.Message);
  Console.WriteLine("Press any key to exit...");
  Console.ReadKey();
}

启动gRPC服务和客户端连接

Demo中gRPC服务和Client在一个项目中,可以解决方案右键属性设置多个项目启动或这通过dotnet命令启动

看到如下输出说明gRPC服务和Client正常

开启gRPC日志

gRPC服务开启日志

在Program文件中增加如下代码

gRPC客户端开始日志

在创建客户端通道时设置 GrpcChannelOptions.LoggerFactory 属性。对于ASP.NET Core项目可以通过依赖注入的方式注入ILoggerFactory类型,本例中为Client为控制台应用,通过使用 LoggerFactory.Create 创建新的 ILoggerFactory 实例的方式。

添加Microsoft.Extensions.Logging包和Microsoft.Extensions.Logging.Console包

再次启动项目会有如下输出

Streaming RPC(流式传输)

上面介绍得示例为Simple RPC,当接收和处理大量数据时会造成阻塞。为了处理大数据适应实时场景,则需要使用Streaming RPC。

Streaming RPC分三种形式:

  • Server-side streaming RPC:服务器端流式 RPC
  • Client-side streaming RPC:客户端流式 RPC
  • Bidirectional streaming RPC:双向流式 RPC

服务器流式处理方法

单向流,服务端为Stream,客户端为普通得RPC请求。服务器流式处理方法以参数的形式获取请求消息。方法返回时,服务器流式处理调用完成。

服务器流式处理方法启动后,客户端无法发送其他消息或数据。 对于连续流式处理方法,客户端可以主动将其取消,客户端将信号发送到服务器,并引发 ServerCallContext.CancellationToken

服务器上通过异步方法使用 CancellationToken 标记,以实现以下目的:

  • 所有异步工作都与流式处理调用一起取消。
  • 该方法快速退出。

服务器流处理方法定义方式在返回值前添加stream关键字

rpc StreamingServer (HelloRequest) returns (stream HelloReply);

在service类里实现对应方法

public override async Task StreamingServer(HelloRequest request, IServerStreamWriter<HelloReply> responseStream, ServerCallContext context)
{
while (!context.CancellationToken.IsCancellationRequested)
{
await responseStream.WriteAsync(new HelloReply() { Message= "Hello From "+ request.Name });
await Task.Delay(TimeSpan.FromSeconds(1), context.CancellationToken);
}
}

服务器流式处理方法,客户端在不再调用时需要主动将其取消。 客户端将信号发送到服务器,并引发 ServerCallContext.CancellationToken,从而取消服务。

客户端简单调用示例

var token = new CancellationTokenSource(TimeSpan.FromSeconds(5));
using var replyStreamServer = client.StreamingServer(
new HelloRequest { Name = "StreamingServer" },
cancellationToken: token.Token);
try
{
await foreach (var item in replyStreamServer.ResponseStream.ReadAllAsync(token.Token))
{
Console.WriteLine(item.Message);
}
}
catch (RpcException exc)
{
Console.WriteLine(exc.Message);
}

客户端流式处理方法

单向流,客户端通过流式发起多次 RPC 请求给服务端,服务端发起一次响应给客户端。返回响应消息时,客户端流式处理调用完成。

客户端流处理方法定义在参数前增加stream关键字

rpc StreamingClient (stream HelloRequest) returns (HelloReply);

service里实现该方法

public override async Task<HelloReply> StreamingClient(IAsyncStreamReader<HelloRequest> requestStream, ServerCallContext context)
{
var replay = new HelloReply();
while (await requestStream.MoveNext())
{
replay.Count++;
replay.Message = "Hello From " + requestStream.Current.Name;
}
return replay;
}

通过requestStream.MoveNext()从客户端发送的流数据中读取消息。使用 C# 8 或更高版本,则可使用 await foreach 语法来读取消息。

await foreach (var message in requestStream.ReadAllAsync())
{
// ...
}

Client流形式发送数据示例代码

using var replyStreamClient = client.StreamingClient();

            foreach (var name in new[] { "Stacking", "Client", "Stream" })
{
await replyStreamClient.RequestStream.WriteAsync(new HelloRequest
{
Name = name
});
} await replyStreamClient.RequestStream.CompleteAsync();
var response = await replyStreamClient.ResponseAsync;

双向流式处理方法

双向流,客户端以流式的方式发起请求,服务端同样以流式的方式响应请求。

双向流定义在参数和返回值前都加上stream

rpc StreamingWays (stream HelloRequest) returns (stream HelloReply);

Service类实现方法

public override async Task StreamingWays(IAsyncStreamReader<HelloRequest> requestStream, IServerStreamWriter<HelloReply> responseStream, ServerCallContext context)
{ while (await requestStream.MoveNext())
{
Console.WriteLine($"Begin read request");
Console.WriteLine(requestStream.Current.Name);
await responseStream.WriteAsync(new HelloReply() {
Message=DateTimeOffset.Now.ToString("HH:mm:ss")
});
} }

客户端调用代码

using var replyStreamWays = client.StreamingWays();
for (int i = 0; i < 5; i++)
{
await replyStreamWays.RequestStream.WriteAsync(new HelloRequest
{
Name = "StreamWaysName " + i,
});
} while (await replyStreamWays.ResponseStream.MoveNext())
{
try
{
Console.WriteLine($"Response Return:{replyStreamWays.ResponseStream.Current.Message}");
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
       await replyStreamWays.RequestStream.CompleteAsync();

参考资料:

.Net Core gRPC 实战(一)的更多相关文章

  1. .Net Core gRPC 实战(二)

    概述 gRPC 客户端必须使用与服务相同的连接级别安全性.  如调用服务时通道和服务的连接级别安全性不一致,gRPC 客户端就会抛出错误. gRPC 配置使用HTTP gRPC 客户端传输层安全性 ( ...

  2. ASP.NET Core gRPC 入门全家桶

    一. 说明 本全家桶现在只包含了入门级别的资料,实战资料更新中. 二.官方文档 gRPC in Asp.Net Core :官方文档 gRPC 官网:点我跳转 三.入门全家桶 正片: ASP.NET ...

  3. java版gRPC实战之二:服务发布和调用

    欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...

  4. Asp.Net Core 项目实战之权限管理系统(4) 依赖注入、仓储、服务的多项目分层实现

    0 Asp.Net Core 项目实战之权限管理系统(0) 无中生有 1 Asp.Net Core 项目实战之权限管理系统(1) 使用AdminLTE搭建前端 2 Asp.Net Core 项目实战之 ...

  5. Asp.Net Core 项目实战之权限管理系统(0) 无中生有

    0 Asp.Net Core 项目实战之权限管理系统(0) 无中生有 1 Asp.Net Core 项目实战之权限管理系统(1) 使用AdminLTE搭建前端 2 Asp.Net Core 项目实战之 ...

  6. Asp.Net Core 项目实战之权限管理系统(1) 使用AdminLTE搭建前端

    0 Asp.Net Core 项目实战之权限管理系统(0) 无中生有 1 Asp.Net Core 项目实战之权限管理系统(1) 使用AdminLTE搭建前端 2 Asp.Net Core 项目实战之 ...

  7. Asp.Net Core 项目实战之权限管理系统(2) 功能及实体设计

    0 Asp.Net Core 项目实战之权限管理系统(0) 无中生有 1 Asp.Net Core 项目实战之权限管理系统(1) 使用AdminLTE搭建前端 2 Asp.Net Core 项目实战之 ...

  8. Asp.Net Core 项目实战之权限管理系统(3) 通过EntityFramework Core使用PostgreSQL

    0 Asp.Net Core 项目实战之权限管理系统(0) 无中生有 1 Asp.Net Core 项目实战之权限管理系统(1) 使用AdminLTE搭建前端 2 Asp.Net Core 项目实战之 ...

  9. Asp.Net Core 项目实战之权限管理系统(5) 用户登录

    0 Asp.Net Core 项目实战之权限管理系统(0) 无中生有 1 Asp.Net Core 项目实战之权限管理系统(1) 使用AdminLTE搭建前端 2 Asp.Net Core 项目实战之 ...

随机推荐

  1. H5小技巧之——巧用<a>标签锚链接(#锚点链接 #页面特定位置 #DOM定位 #hash路由中使用锚链接)

    #作者:矩阵鱼--代码中游泳的咸鱼 前端开发中,常遇到定位到页面某特定位置的需求,JavaScript提供的el.scrollIntoView() 和 el.scrollIntoViewIfNeede ...

  2. 033- while循环语句

    语法 初始化语句; while(boolean表达式) { 循环体语句; 控制条件语句; } 执行过程: 只要boolean表达式里面的结果是true,就会执行while大括号里面的语句,直到bool ...

  3. 转载:Windows使用tail -f 监控文件

    https://www.cnblogs.com/my-bambi/p/11793770.html

  4. flex 的 三个参数 flex:1 0 auto

    flex :flex-group  flex-shirk  flex-basis ①.flex-group 剩余空间索取 默认值为0,不索取 eg:父元素400,子元素A为100px,B为200px. ...

  5. HBASE-使用问题-split region

    问题描述: HBASE表的管理以REGION分区为核心,通常面临如下几个问题: 1) 数据如何存储到指定的region分区,即rowkey设计,region splitkey设计 2)设计的split ...

  6. 【maven】Failed to execute goal org.apache.maven.plugins:maven-site-plugin:3.3:site (default-site)

    问题描述 site一点击就报错,如下 Failed to execute goal org.apache.maven.plugins:maven-site-plugin:3.3:site (defau ...

  7. 【opencv】Java+eclipse+opencv 环境搭建 helloword入门demo

    文章为博主原创,纯属个人理解,如有错误欢迎指出. 如需转载,请注明出处. 引入jar包 引入配置文件 到此环境配置完成!!! 可能会出现的问题: 1. jdk版本不一致导致发生异常.如图 build ...

  8. Postman中如何实现接口之间的关联?

    Postman中如何实现接口之间的关联? 不单单说Postman中,我为什么拿Postman举例,因为它比较简单一点. 那如果我只问你如何实现接口之间的关联,那肯定有很多的方式,Postman只是其中 ...

  9. 序列化-JDK自带Serializable

    如下代码示例:实现了Serializable接口(强制)的类,可以通过ObjectOutputStream的writeObject()方法转为字节流. 字节流通过ObjectInputStream的r ...

  10. 死磕Spring之AOP篇 - Spring 事务详解

    该系列文章是本人在学习 Spring 的过程中总结下来的,里面涉及到相关源码,可能对读者不太友好,请结合我的源码注释 Spring 源码分析 GitHub 地址 进行阅读. Spring 版本:5.1 ...