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. k8s daemonset

    DaemonSet控制器会在每个节点上运行单一的副本,他非常适合部署那些节点本身提供服务或者执行维护的 Pod 例如 : 存储相关,每个节点上运行glusterd, ceph 日志收集相关,每个节点上 ...

  2. 粗浅聊聊Python装饰器

    浅析装饰器 通常情况下,给一个对象添加新功能有三种方式: 直接给对象所属的类添加方法: 使用组合:(在新类中创建原有类的对象,重复利用已有类的功能) 使用继承:(可以使用现有类的,无需重复编写原有类进 ...

  3. Blog总结(前三次作业总结)

    前三次作业总结 1.前言 (1)第一次题目集共有8道题目,难度较为简单,知识点为JAVA的一些编程基础知识点,如输入输出,选择,循环,一维数组等. (2)第二次题目集共有5道题目,难度较第一次题目集有 ...

  4. 【Nginx(一)】Centos下 Nginx环境搭建

    Nginx环境搭建 系统环境: 腾讯云 Linux Centos7 1.下载nginx压缩包 ,上传到腾讯云服务器 http://nginx.org/en/download.html 或者使用dock ...

  5. hdu4561 连续最大积

    题意: 连续最大积 Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others) Total ...

  6. Sqli 注入点解析

    目录 Less-1: 字符型注入 Less-2: 数字型注入 Less-3: 单引号字符型+括号 Less-4: 双引号字符型+括号 Less-5: 单引号字符型+固定输出信息 (floor报错注入& ...

  7. 无线网络的加密方式:WEP、WPA和WPA2

    目录 有线等效加密( WEP ) Wi-Fi 访问保护( WPA ) Wi-Fi 访问保护 II( WPA2 ) WPA-PSK/WPA2-PSK 无线网标准 有线等效加密( WEP ) 有线等效保密 ...

  8. Access denied for user '电脑用户名'@'localhost'

    之前没有碰到这个问题,但是这次从gitee上面拉取代码运行,发现存在bug 错误描述 java.sql.SQLException: Access denied for user '10134'@'lo ...

  9. GUI基础知识点

    简介 GUI的核心技术:AWT(是Swing 的前身) Swing 不流行的原因 界面不美观 运行需要jre环境(可能一个项目的大小比jre还要大) 为什么我们需要学习 了解MVC架构和监听 AWT ...

  10. 二、postman断言及正则表达式取值

    postman老式断言与新式断言总结:本文以微信开发者文档为例 断言处如图所示 一.老式断言 老式断言总结:var variables相当于代码中定义的变量,test['']=true;相当于pyth ...