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. JDBC_06_处理查询结果集

    JDBC处理查询结果集 * ResultSet resultSet=null 结果集对象 * executeQuery(select) 执行SQL查询语句需要的使用executeQuery方法 * i ...

  2. 数据结构之Stack | 让我们一块来学习数据结构

    栈的介绍 栈就是和列表类似的一种数据结构,它可用来解决计算机世界里的很多问题.栈是一种高 效的数据结构,因为数据只能在栈顶添加或删除,所以这样的操作很快,而且容易实现. 栈的使用遍布程序语言实现的方方 ...

  3. UI自动化测试框架:PO模式+数据驱动

    1. PO 设计模式简介 2. 工程结构说明 3. 工程代码实现 page 包 action 包 business_process 包 util 包 conf 包 test_data 目录 log 目 ...

  4. 1025 PAT Ranking

    Programming Ability Test (PAT) is organized by the College of Computer Science and Technology of Zhe ...

  5. 1057 Stack

    Stack is one of the most fundamental data structures, which is based on the principle of Last In Fir ...

  6. shellcode 开发

    0x00 设置堆栈 栈顶指针按位与之后,将栈桢以16字节的大小对齐: push rbp ;store rbp original state mov rbp, rsp ;set stack base p ...

  7. Appium命令行启动,提示找不到命令,本地没有appium.cmd文件

    安装appium时,直接从github上下载的appium-desktop-windows版本,安装后,从打开桌面端Server,能启动服务,appium-doctor也能正常运行. 但奇怪的地方来了 ...

  8. hdu4284 dfs+floyd

    题意:       给你n个城市,m条边,要有h个必须旅游和打工的城市,问你能不能从1把所有必须的h个城市全部旅游并且打工完... 思路:       先一遍floyd跑出全局最短路,然后暴力枚举出打 ...

  9. hdu2438 三分

    题意:       给你个90度的转弯,和一辆标准矩形的车,问你这台车能不能拐过去.. 思路:      求出靠近最里侧的那条边所在的直线(这个图形右下角为坐标原点)       y = x * ta ...

  10. LA3213加密

    题意:       白书上有些题的题意说的太蛋疼了,这个题的意思是说有两种加密方式,一种是交换位置,另一种是一一映射,交换位置是指如ABCD 可以加密成DCBA 也可以加密成ACBD就是把某些字母的位 ...