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

gRPC设计

刚好需要使用一个的RPC应用系统,自然而然就盯上了它,但是它真能够解决所有问题吗?不见得,先看看他的优点:

gRPC是一种与语言无关的高性能远程过程调用 (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 Library
  2. 添加一个proto文件,可以直接使用微软的简单例子
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

建立Client

新建一个Console程序,添加上面的项目引用,输入以下代码:

var server = new NamedPipeServer("MY_PIPE_NAME");
Greeter.BindService(server.ServiceBinder, new GreeterService());
server.Start();

添加GrpcDotNetNamedPipes的nuget依赖:

Install-Package GrpcDotNetNamedPipes

建立Server

再新建一个Console程序,添加上面的项目引用,也添加那个nuget依赖和一些别的依赖,输入以下代码:

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应用,还是更推荐使用标准实现。

参考

使用命名管道承载gRPC的更多相关文章

  1. Linux环境进程间通信(一):管道及命名管道

    linux下进程间通信的几种主要手段: 管道(Pipe)及有名管道(named pipe):管道可用于具有亲缘关系进程间的通信,有名管道克服了管道没有名字的限制,因此,除具有管道所具有的功能外,它还允 ...

  2. 【windows 操作系统】进程间通信(IPC)简述|无名管道和命名管道 消息队列、信号量、共享存储、Socket、Streams等

    一.进程间通信简述 每个进程各自有不同的用户地址空间,任何一个进程的全局变量在另一个进程中都看不到,所以进程之间要交换数据必须通过内核,在内核中开辟一块缓冲区,进程1把数据从用户空间拷到内核缓冲区,进 ...

  3. 【说解】在shell中通过mkfifo创建命名管道来控制多个进程并发执行

    背景: 工作中有两个异地机房需要传数据,数据全名很规范,在某个目录下命名为统一的前缀加上编号.如/path/from/file.{1..100}.而机房间的专线对单个scp进程的传输速度是有限制的,比 ...

  4. Windows进程间通信—命名管道

    命名管道是通过网络来完成进程间的通信,它屏蔽了底层的网络协议细节.我们在不了解网络协议的情况下,也可以利用命名管道来实现进程间的通信.与Socket网络通信相比,命名管道不再需要编写身份验证的代码.将 ...

  5. Linux学习笔记(13)-进程通信|命名管道

    匿名管道只能在具有亲属关系的进程间通信,那么如果想要在不具有亲戚关系,想在陌生人之间通信,那又该怎么办呢? 别慌,Linux身为世界上*强大的操作系统,当然提供了这种机制,那便是命名管道-- 所谓命名 ...

  6. Linux进程间通信(四):命名管道 mkfifo()、open()、read()、close()

    在前一篇文章—— Linux进程间通信 -- 使用匿名管道 中,我们看到了如何使用匿名管道来在进程之间传递数据,同时也看到了这个方式的一个缺陷,就是这些进程都由一个共同的祖先进程启动,这给我们在不相关 ...

  7. [C++] socket -8 [命名管道]

    ::命名管道不但能实现同一台机器上两个进程通信,还能在网络中不同机器上的两个进程之间的通信机制.与邮槽不同,命名管道是采用基于连接并且可靠的传输方式,所以命名管道传输数据只能一对一进行传输. /* 命 ...

  8. SQL Server 连接问题圣经-命名管道

    SQL Server 连接问题圣经-命名管道 (1) APGC DSD Team 12 Jan 2011 1:24 AM 3 一.前言 在使用SQL Server 的过程中,用户遇到的最多的莫过于连接 ...

  9. [杂]SQL Server 之命名管道连接

    命名管道是通过进程间通信(IPC)机制实现通信.具体来说,命名管道建立在服务器的IPC$共享基础上,通过IPC$共享来进行通信. SQL Server命名管道 SQL Server 首先在服务器上创建 ...

随机推荐

  1. centos7上安装memcached以及PHP安装memcached扩展(一)

    安装memecached 第一步:安装libevent # tar zvxf libevent-2.1.8-stable.tar.gz # cd libevent-2.1.8-stable # ./c ...

  2. 【分区】使用 MBR 分区表分区并格式化

    注意: 本方法仅适用于容量小于 2TB 的硬盘进行分区及格式化.大于 2TB 的硬盘的分区及格式化请使用 GPT方式,可参阅 使用 GPT 分区表分区并格式化. 格式化后,数据盘中的数据将被全部清空. ...

  3. C#数据结构与算法系列(一):介绍

    1.介绍 数据结构:是指相互之间存在一种或多种特定关系的数据元素的集合用计算机存储.组织数据的方式.数据结构分别为逻辑结构.(存储)物理结构和数据的运算三个部分. 数据结构包括:线性结构和非线性结构. ...

  4. Shell编译安装nginx

    环境及规划 [root@nginx-node01 ~]# cat /etc/redhat-release CentOS Linux release 7.6.1810 (Core) ID 主机名 ip ...

  5. (四)Maven项目工程目录约定

    使用maven创建的工程我们称它为maven工程,maven工程具有一定的目录规范,如下: src/main/java 存放项目的.java文件 src/main/resources 存放项目资源文件 ...

  6. CSS sprites的定义及使用

    定义:CSS sprites 其实就是把网页中的一些背景图片整合到一张图片文件中,再利用CSS的“background-image”.“background-repeat”.“background-p ...

  7. Mac App破解之路九 vscode插件破解

    破解对象: luaide 破解目的:学习如何破解vscode插件 破解背景: vsscode用了这么多年,安装了很多插件,其中luaide插件是收费的.  说实话,100块并不贵, 我本来准备买的. ...

  8. #linux vscode 保存总提示“Retry as sudo”

    linux中,对不同路径下的文件,系统默认指定了不同的操作权限(读/写/执行),出现这个问题是由于文件的权限不足造成的.(路径为/opt/lampp/htdocs/LearnPHP_jayce/hel ...

  9. 韩顺刚-tcp报文头协议详细分析第一包数据:序号是0,发送数据的长度是0,因为没有收到对端的数据,所以确认号是0, Syn的标志位设置成1,这里没有发送的数据,只发送TCP的20个字节的头部

    TCP报文段首部格式 大部分TCP报文头部都是20个字节,有的数据包要加上选项. 上面一行代表4个字节,源端口和目的端口都是2个字节. TCP协议是面向字节流的协议 TCP是一段一段分块的发送数据的 ...

  10. android handle详解3 ThreadHandler

    在android handle详解2的基础上,我们来学习ThreadHandler ThreadHandler的本质就是对android handle详解2的实现 HandlerThread其实还是一 ...