使用命名管道承载gRPC,以及适用场景

摘要:
使用Protobuf二进制序列化来减少网络的使用。GRPC对于对效率至关重要的轻量级微服务非常有用。gRPC服务可以实时推送消息而无需轮询。gRPC消息始终小于等效的JSON消息。SignalR是适用于该方案的框架。根据采取的想法,我在github上找到了一个grpc dotnet namedpipes,它支持在命名管道上实现grpc。它相当于在流上封装一个层,而不是直接处理二进制数据流。因此,对于一般的gRPC应用程序,更建议使用标准实现。

最近GRPC很火,感觉整RPC不用GRPC都快跟不上时髦了。

gRPC设计

gRPC是一种与语言无关的高性能远程过程调用 (RPC) 框架。刚好需要使用一个的RPC应用系统,自然而然就盯上了它,但是它真能够解决所有问题吗?不见得,先看看他的优点:

gRPC的主要优点:#

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

对应的适用场景:#

  • 微服务:gRPC 设计用于低延迟和高吞吐量通信。 gRPC 对于效率至关重要的轻量级微服务非常有用。
  • 点对点实时通信:gRPC 对双向流式传输提供出色的支持。 gRPC 服务可以实时推送消息而无需轮询。
  • 多语言环境:gRPC 工具支持所有常用的开发语言,因此,gRPC 是多语言环境的理想选择。
  • 网络受限环境:gRPC 消息使用 Protobuf(一种轻量级消息格式)进行序列化。 gRPC 消息始终小于等效的 JSON 消息。

gRPC还是有缺点的:#

  • 浏览器支持受限:绝大数浏览器不支持HTTP/2
  • 非人工可读取:proto文件规定的格式在通讯中会序列化成二进制数据,人工解析较为困难。

不适用的场景与替代:#

  • 浏览器可访问的API:gRPC 在浏览器中未受到完全支持。 gRPC-Web 可以提供浏览器支持,但它具有局限性并引入了服务器代理。
  • 广播实时通信:gRPC 支持通过流式传输进行实时通信,但不存在将消息广播到注册连接的概念。 例如,在聊天室方案中,应将新的聊天消息发送到聊天室中的所有客户端,这要求每个 gRPC 调用将新的聊天消息单独流式传输到客户端。 SignalR 是适用于此方案的框架。 SignalR 具有持久性连接的概念,并内置对广播消息的支持。
  • 进程间通信:进程必须托管 HTTP/2 服务器才能接受传入的 gRPC 调用。 对于 Windows,进程间通信管道是一种快速、轻便的通信方法。
目标分析

我需要有一个能够实现远程调用的好办法,系统支持Windows就好,最好性能高一些(数据量大),程序小一点,但是我也不想直接处理二进制数据流(最好能有封装的框架)。

考虑进程通信常用的:

  • 信号/信号量:简单,能够承载的消息内容较少。
  • 消息队列:支持消息,功能较为强大。
  • 共享内存:性能最强,但只限于单机。
  • 管道:性能较强,但是只支持stream。
  • Socket:最灵活,但是需要有网卡。

首先排除信号/信号量,处理的信息量太小了;然后共享内存也排除,只能单机不符合我的要求;剩下的三个似乎都可以满足要求,可以在这个基础上建立RPC,而gRPC就是建立在socket(HTTP/2)上的,就像上面讲的,要自己集成一个HTTP/2服务器(比如Kestrel)才行,不够轻量化;剩下的两个Windows都有內建支持,可以考虑一下。

本着拿来主义的思想,我在github上找到一个grpc-dotnet-namedpipes,支持在命名管道上实现gRPC,相当于在stream上封装了一层,不用直接处理二进制数据流了。

用作者自己的话来说,这么做相较于普通的gRPC有几个优点:

  • 更优秀的访问控制;
  • 纯.NET库,不需要带ASP.NET Core或者超过3MB的非托管库依赖;
  • 启动时间更快
  • 2-3倍的数据吞吐量
  • 没有防火墙警告
  • 不需要网卡
实现

建立一个proto#

  1. 创建一个.NET Framework Library
  2. 添加一个proto文件,可以直接使用微软的简单例子
Copy
syntax = "proto3";

service Greeter {
  rpc SayHello (HelloRequest) returns (HelloReply);
}

message HelloRequest {
  string name = 1;
}

message HelloReply {
  string message = 1;
}
  1. 添加nuget包:Google.Protobuf,Grpc.Core,Grpc.Tools
  2. 单击proto文件,在属性对话框,选择生成操作为Protobuf  Compiler (如果没有这个选项,请检查您的csproj文件是否有如下,重启你的VS试试)
  <ItemGroup>
    <Protobuf Include="ProtosHello.proto" GrpcServices="Server" />
  </ItemGroup>

建立Server端#

新建一个Console程序,添加GrpcDotNetNamedPipes的nuget依赖:

Copy
Install-Package GrpcDotNetNamedPipes

添加上面的类库项目引用,输入以下代码:

Copy
var server = new NamedPipeServer("MY_PIPE_NAME");
Greeter.BindService(server.ServiceBinder, new GreeterService());
server.Start();
再创建一个GreeterService.cs文件,输入以下代码:

    public class GreeterService: Greeter.GreeterBase
    {
        // 实现SayHello方法
        public override Task<HelloReply> SayHello(HelloRequest request, ServerCallContext context)
        {
            return Task.FromResult(new HelloReply { Message = "Hello " + request.Name });
        }
    }
 

建立Client端#

新建一个Console程序,添加GrpcDotNetNamedPipes的nuget依赖:

Copy
Install-Package GrpcDotNetNamedPipes

添加上面的类库项目引用,输入以下代码:

Copy
var channel = new NamedPipeChannel(".", "MY_PIPE_NAME");
var client = new Greeter.GreeterClient(channel);

var response = await client.SayHelloAsync(
	new HelloRequest { Name = "World" });

Console.WriteLine(response.Message);

然后在命令行中运行就能看见熟悉的Hello World了,用起来和gRPC的标准实现没太大区别。

总结

完整代码见gRPC_Demo

这种方式也有它的局限性,首先是Windows的命名管道与Linux上面的实现是不同的,所以并不能实现直接跨平台通讯;然后就是这个对于其他语言的开发的gRPC也不是完全兼容的,需要其他语言开发的程序也做命名管道的适配才行,换言之,它不是通用标准。所以,对于一般的gRPC应用,还是更推荐使用标准实现。

参考

出处:https://www.cnblogs.com/podolski/p/13282975.html

免责声明:文章转载自《使用命名管道承载gRPC,以及适用场景》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇视频监控系统中的流媒体服务器、直写和全切换三种取流架构方案最高优先级下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

QT多线程及通过事件进行通信(通过自定义事件,然后QApplication::postEvent给主界面,我之前用的是信号槽)

可以通过QThread实现跨平台的多线程开发,Qt库负责在特定平台上的特定多线程实现。要采用QThread进行多线程开发,首先需要包含头文件: #include <QThread> 然后需要从QThread继承一个自己的线程类,暂作MyThread,关键是要实现QThread内的一个虚函数run。在run函数内部,最后一般都调用exec(),使...

(六)Android中Service通信

一、启动Service并传递参数 传递参数时只需在startService启动的Intent中传入数据便可,接收参数时可在onStartCommand函数中通过读取第一个参数Intent的内容来实现 1.MainActivity.java package com.example.shiyanshi.serviceconnected;import andro...

移远通信LC29D

转自:http://www.elecfans.com/d/1238490.html LC29D图片来源于移远通信推出多模双频高精度GNSS定位模组LC29D 关键点:1.博通47758芯片 2.自带惯导 移远通信宣布正式推出采用博通BCM47758芯片研发的多模双频高精度GNSS定位模组LC29D。该模组利用双频段GNSS原始观测量数据和IMU原始数据,...

iframe中子父页面跨域通讯

目录 #跨域发送信息#window.postMessage()语法 #跨域接收信息 #示例Demo 在非跨域的情况下,iframe中的子父页面可以很方便的通讯,但是在跨域的情况下,只能通过window.postMessage()方法来向其他页面发送信息,其他页面要通过window.addEventListener()监听事件来接收信息; #跨...

Host是如何与EC通信的

第一种方式:遵循ACPI规范完成通信,通过LPC的62h、64h偏移/端口。 此种方式适合host对EC进行读写操作。 EC提供256字节的可被系统读写的RAM空间,EC的资源在该RAM空间映射,通过访问对应偏移(0x00~0xFF),即可操作对应的资源。实际上就是外部RAM的前256字节。EC会将键盘、触摸板、电池、温度传感器等一些设备的状态信息保存在此...

VMware虚拟机宿主机与虚拟机通讯慢解决方法

在公司,为了充分利用服务器性能,我在服务器上装了一个VMware Server2.0 ,真是方便,又免费,又稳定,经过一系列调优,速度挺好(具体调优过程,查询我以前发的博文吧),一台计算机变了好多台服务器(就是硬盘IO受限,回来申请加硬盘)。 近期调测系统时发现,宿主机与虚拟机通讯慢,奇慢无比,只有2K-5K;但是其他通讯都是非常正常的,和内网其他计算机一...