閱讀目錄
一、前言
在上一篇分布式系統系列中《分布式系統中的必備良葯 —— 服務治理》中闡述了服務治理的一些概念,那么與服務治理配套的必然會涉及到RPC框架。在當前互聯網的大背景下,RPC的運用應該大家或多或少都有涉及,國內外的RPC框架也是百花齊放。那么各個RPC框架各自有什么特點,另外RPC的核心點又是哪些,我們該如何去選擇是本文需要講述的內容。本文會圍繞.Net技術棧來展開,暫不討論諸如dubbo之類對.Net 不太友好的框架。
二、成熟的解決方案
1.Google.gRpc(https://github.com/grpc/grpc)
大名鼎鼎的Google出品的RPC框架,基於Http2設計,支持雙向流、消息頭壓縮、單 TCP 的多路復用、服務端推送等特性,這些特性使得 gRPC 在移動端設備上更加省電和節省網絡流量。使用的時候需要通過定義proto文件生成客戶端和服務端代碼,可以跨平台(客戶端和服務端生成代碼時使用不同的語言)。如果大家已經被微軟寵慣了,那么是不太習慣以一個純txt方式編輯這個proto文件的,畢竟全部需要手打 ╮(╯_╰)╭
2.Facebook.Thrift(https://github.com/apache/thrift)
同樣是大廠Facebook出品的RPC框架,使用方式和gRpc類似,需要通過定義.thrift文件生成客戶端和服務端代碼,可以跨平台(客戶端和服務端生成代碼時使用不同的語言)。Thrift的缺點是無法生成async,await,Task<T>之類的泛型代碼,這個對於當下大背景來說有一定的局限性(如果有小伙伴知道如何解決此問題,感謝賜教)。Thrift最大的特點是5種適用不同場景的服務模型,一圖勝千言,直接上圖,見圖1:

【圖1】
但是遺憾的是Apache在.Net下提供的實現並不是上面的5種模式,僅僅3種(TSimpleServer、TThreadPoolServer、TThreadedServer),特別是在Java下大規模宣傳的NIO模式沒有提供實現。
3.Orleans(http://dotnet.github.io/orleans/)
這是微軟在2015開源的構建分布式應用的框架。(什么意思?那它是RPC框架么?)我想這是大部分對Orleans不熟悉的同學的疑問,實際上Orleans的層次比RPC框架更高,它不僅僅解決了遠程調用問題,其內部還包含了服務發現、負載均衡、高可用等一些處理機制。一般用Akka(有.net版本 Akka.net)和它對標,都是基於Actor模型設計的分布式框架,順手附上一篇經典的對比文章:https://github.com/akka/akka-meta/blob/master/ComparisonWithOrleans.md 。Orleans最大的特點就是微軟一向的風格,高度封裝,提高生產力。面向OOP的設計,便於使用,大家可以在文末下載Demo感受一下,手感和WCF比較類似。
4.WCF
這應該是.net系下做分布式系統開發中的RPC標配了,隨着.net framework3.5在2007年推出,可謂功能豐富,而且支持的協議相比其它框架也是最多(沒有之一)。
5.WebApi
這是隨着VS2012一起推出的REST化API的一項web服務。近幾年隨着整個大環境的變化,逐漸有代替WCF的趨勢。跨平台(特別是針對移動端有很大優勢)、便於開放共享和測試是他相對WCF的最大優勢。
三、剖析
上面的這些框架說不上孰優孰劣,都有各自適用的場景。那么我們來刨析一下如果要選擇哪個RPC框架更適合的話從何處入手。一個RPC框架核心的概念是下面幾個:
網絡協議:
這是RPC框架的核心,面向什么協議去設計,基本上也已經決定了框架最理想的適用場景了。協議又分為2個大類,分別對應OSI七層模型的應用層(http協議、ftp協議等)和傳輸層(tcp協議、udp協議)。這其中的協議又有各自的特點,這里就不展開說了。當然有些框架將協議這層做成可適配的,比如WCF(不同協議)、thrift(同協議不同實現),那么他們的覆蓋場景肯定就更多,但是相應的框架的實現復雜度肯定也是相應增加,需要考慮是否能接收這帶來的額外成本。
序列化方式:
序列化一般從3個維度去考慮,數據大小、可讀性、傳輸效率(序列化反序列所消耗的時間)。屬於可讀性較好的序列化比如Json;屬於數據壓縮比比較好的序列化比如Protobuf;屬於傳輸效率高的序列化比如MessageShark、MessagePack、Protobuf等。對於對性能十分執着的小伙伴們,這里有一份轉載的基准測試報告,連接附上:https://www.cnblogs.com/shanyou/p/3294201.html 。大部分的框架都會序列化這層做成可適配的,相對網絡協議,對序列化的個性化迫求是更強烈的。
四、性能測試
測試環境如下:
CPU:I5-4300U 1.90GHz 2.50GHz
內存:8G
策略:10000次調用發送封裝world字符串的對象HelloRequest,並等待接收返回封裝Hello world字符串的HelloReply對象。
網絡:數據較小+本地調用,網絡不是問題。想進一步測試局域網和大數據的可以基於文末的Demo項目自行改造。
這里需要提一下,WCF的測試使用了http和tcp2種常見的模式,針對webapi的訪問使用了HttpClient和HttpWebRequest2種方式。另外值得注意的是,由於Thrift和HttpWebRequest不支持多線程復用同一個實例,故在測試中都是使用每次實例化的方式進行(包括線程數1的時候)。
由於數據比較多,直接付上2個動圖,想進一步分析的可以在文末下載excel自行解決~。見圖2,圖3:

【圖2】

【圖3】
五、結語
這個是我網上找到的一篇性能相關的文章,大家可以參考一下:http://blog.csdn.net/jek123456/article/details/53395206。
歸根到底,大家在使用之前還是需要結合自己的實際情況,放到實際的場景去測一把,看看效果。下面奉上替大家邁出第一步的Demo,大家可以進行進一步的深入研究。
本文相關的測試數據excel在此:https://github.com/ZacharyFan/RpcTest/raw/master/PerfTest.xlsx
本文相關的Demo地址在此:https://github.com/ZacharyFan/RpcTest
作者:Zachary
出處:https://zacharyfan.com/archives/269.html
▶關於作者:張帆(Zachary,個人微信號:Zachary-ZF)。堅持用心打磨每一篇高質量原創。歡迎掃描右側的二維碼~。
定期發表原創內容:架構設計丨分布式系統丨產品丨運營丨一些思考。
如果你是初級程序員,想提升但不知道如何下手。又或者做程序員多年,陷入了一些瓶頸想拓寬一下視野。歡迎關注我的公眾號「跨界架構師」,回復「技術」,送你一份我長期收集和整理的思維導圖。
如果你是運營,面對不斷變化的市場束手無策。又或者想了解主流的運營策略,以豐富自己的“倉庫”。歡迎關注我的公眾號「跨界架構師」,回復「運營」,送你一份我長期收集和整理的思維導圖。
