使用命名管道承載gRPC

最近GRPC很火,感受整RPC不用GRPC都快跟不上時髦了。git

gRPC設計

gRPC是一種與語言無關的高性能遠程過程調用 (RPC) 框架。恰好須要使用一個的RPC應用系統,天然而然就盯上了它,可是它真可以解決全部問題嗎?不見得,先看看他的優勢:github

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就好,最好性能高一些(數據量大),程序小一點,可是我也不想直接處理二進制數據流(最好能有封裝的框架)。c#

考慮進程通訊經常使用的:瀏覽器

  • 信號/信號量:簡單,可以承載的消息內容較少。
  • 消息隊列:支持消息,功能較爲強大。
  • 共享內存:性能最強,但只限於單機。
  • 管道:性能較強,可是隻支持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程序,添加上面的項目引用,輸入如下代碼:socket

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應用,仍是更推薦使用標準實現。

參考

相關文章
相關標籤/搜索