RPC框架性能基本比較測試
21 March 2015
gRPC是Google最近公布的開源軟件,基于最新的HTTP2.0協議,并支持常見的眾多編程語言。 我們知道HTTP2.0是基于二進制的HTTP協議升級版本,目前各大瀏覽器都在快馬加鞭的加以支持。 我們可以設想一下,未來瀏覽器支持HTTP2.0,并通過現有開源序列化庫比如protobuf等,可以直接和各種語言的服務進行高效交互,這將是多么“美好”的場景!
gPRC的Java實現底層網絡庫是Netty,而且是用到最新的Netty5.0.0.Alpha3的開發版本,因為最新版本針對HTTP/2做了很多改進。 為了跨語言,gPRC也和其他方案一樣,采用了類似古老IDL的接口描述語言,利用自家的Protobuf項目帶的protoc編譯器來生成框架代碼。這和目前最流行的Facebook開源的,現為Apache頂級項目的Thrift原理一致。
我比較好奇,這個新出世的框架的性能怎么樣,和現有的RPC開源方案比較如何。就花了一些時間進行簡單比較。 我選擇了以下五種開源項目進行測試:gRPC, Thrift, Wildfly, Dubbo, JBoss EAP。 為了簡化,測試范例都使用項目自帶的demo或者sample等進行簡單修改,使得跨進程網絡調用次數一致。
gRPC https://github.com/grpc/grpc
從Github master主干上獲得最新版本,按照說明文件進行編譯。如上所述,網絡框架是Netty5,基于最新的HTTP/2.
測試例子為 RouteGuideClient
IDL為 route_guide.proto
選擇其中getFeature方法,去除不用的語句和屏幕輸出,進行10,000次同步調用。
TestClientSync client = new TestClientSync("localhost", 8980);try { final long startTime = System.nanoTime(); for (int i = 0; i < 10000; i++) client.getFeature(409146138, -746188906); final long endTime = System.nanoTime(); info("method 1 : " + (endTime - startTime));}
public void getFeature(int lat, int lon) { try { Point request = Point.newBuilder().setLatitude(lat).setLongitude(lon).build(); Feature feature = blockingStub.getFeature(request); } catch (RuntimeException e) { logger.log(Level.WARNING, "RPC failed", e); throw e; }}
多次執行,記錄需要的時間。
gRPC還有一種非阻塞的調用方法,不過因為時間有限,為了簡化測試,我只用標準的server啟動的方式,asyncStub在大并發訪問時出錯,用時也較長,故這次測試沒有這種方法的結果數據。
Thrift http://thrift.apache.org
從Apache網站獲得最新的0.9.2版本,本機編譯獲得C的編譯器和Java運行環境。
測試例子為 JavaClient.java
IDL tutorial.thrift
int diff;final long startTime = System.nanoTime();try { for (int i = 0; i < 10000; i++) diff = client.calculate(1, work);} catch (InvalidOperation io) { System.out.println("Invalid operation: " + io.why);}final long endTime = System.nanoTime();System.out.println("method 1 : " + (endTime - startTime));
Thrift采用經典的基于網絡端口的RPC,效率最高,在最后的總結數據可以看到。
Wildfly 8.2.0 http://www.wildfly.org
Wildfly是JBossAS改名后的JBoss應用服務器,實現了完整的JavaEE規范。我們知道JavaEE中遠程RPC調用是在EJB規范中定義的。我們這里就是要測試Wildlfy中的遠程EJB調用能力,
選用的Wildfly8.2是目前發布的最新穩定版本。這個版本也支持端口多路服用,也就是EJB遠程調用是通過HTTP端口復用來進行的,利用HTTP的Upgrade機制做到二進制運行時刻協商升級。盡管不是純粹的HTTP/2,但也運行機理也相差無幾。
測試例子選用jboss-eap-quickstarts項目中的遠程ejb調用例子 RemoteEJBClient.java
純Java的RPC方案好處是不需要再有IDL文件定義和編譯生成代碼的過程,只要商議好接口就可以了
public interface RemoteCalculator { int add(int a, int b);}
int sum=0;final long startTime = System.nanoTime();for (int i = 0; i < 10000; i++) { sum = statelessRemoteCalculator.add(a, b);}final long endTime = System.nanoTime();System.out.println("method 1 : " + (endTime - startTime));
調用無狀態的SessionBean方法10,000次,對應的遠程EJB服務是部署在Wildfly應用服務器中的EJB。
Dubbo 2.5.4-SNAPSHOT https://github.com/alibaba/dubbo
Dubbo是阿里集團開源的一個極為成員的RPC框架,在很多互聯網公司和企業應用中廣泛使用。協議和序列化框架都可以插拔是及其鮮明的特色。同樣的遠程接口是基于Java Interface,并且依托于spring框架方便開發。可以方便的打包成單一文件,獨立進程運行,和現在的微服務概念一致。
采用github中master主干,目前版本是 2.5.4-SNAPSHOT
測試例子選用其中的demo進行修改 DemoAction.java
public interface DemoService { String sayHello(String name);}
final long startTime = System.nanoTime();for (int i = 0; i < 10000; i ++) { try { String hello = demoService.sayHello("world" + i); } catch (Exception e) { e.printStackTrace(); }}final long endTime = System.nanoTime();System.out.println("method 1 : " + (endTime - startTime));
調用完畢后查看輸入log文件獲得運行時間。
Redhat JBoss EAP 6.3.2 Link
EAP是JBossAS的商業版本,實現了完整的JavaEE規范。
EAP6基于AS7.2以后的版本構建,紅帽提供商業支持。
AS7在7.2以后,社區版沒有再發布,具備能力的企業可以從源碼進行編譯使用,EAP6.3基于AS7.4分支構建,很快發布的EAP6.4基于AS7.5分支構建,不出意外這個會是最后一個EAP6的minor版本。
AS7還沒有像Wildfly完全采用端口復用的方式,短程EJB調用通過獨立端口完成,基于JBossRemoting3的網絡連接管理能力。
測試例子依然選用jboss-eap-quickstarts項目中的遠程ejb調用例子
public interface RemoteCalculator { int add(int a, int b);}
記錄一萬次調用后的時長。
數據結果。
最終經過4輪測試,不間斷運行10,000次遠程RPC調用后的結果如下:
我們可以看到Thrift的效率最高,大概領先一個數量級。而其他三個項目的性能數據在同數量級中,由高到低分別為JBossEAP, dubbo, wildfly和gRPC。
需要說明的有以下幾點:
為了簡化測試,我并沒有選擇同樣的調用接口,而是順手用了項目自帶的,方便修改的示例程序。其中gRPC和Thrift的接口有對象傳遞,稍微復雜一些。
不是嚴格的性能測試流程,比如沒有做預熱過程,以及測試都運行在我的桌面用機上,沒有完全恢復成“干凈”的狀態。
都是簡單的服務器單一進程實例,標準示范例子,沒有做特別優化和設置多個線程池之類的。而客戶端調用也是最簡單的阻塞式多次調用壓力測試。應該是用多個機器多連接,多個線程,以及異步非阻塞的調用多種環境進行測試更為客觀,有機會再繼續完善。
之前沒有看到過基于HTTP/2的RPC調用性能比較,理論上是應該低于經典的基于端口的RPC方案的。這個測試結果可以簡單印證這個猜想。Thrift的數據遙遙領先.gRPC還在開發之中,基于的Netty還是alpha版本,而且非阻塞的方式還沒有最后的數據。我想耐心一些,給gRPC一些時間,它會讓我們驚艷的。
Wildfly表現良好,要知道它的服務端可是完整的JavaEE服務器啊。不過有時間的化,我試試看經典RMI連接的效率如何,要是能和thrift一個數量級就更好了。
dubbo性能也很出色,而且協議層可以更換的話,應該還能有更大提升。
我的測試在一臺過時的筆記本上,受條件限制,沒有先進的G級網絡和多臺服務器進行標準化性能測試。如果哪位在互聯網或者企業工作的朋友有條件,也愿意充分完成這個測試,請和我聯系,我會完整介紹我的測試搭建環境,共享代碼,并幫助完成。我想那個結果會更有意義。
補記
最初四個測試時間為2015-03-11,03-21加入EAP6.3.2的測試,為基于JBossRemoting的EJB遠程調用測試,性能良好。和thrift進入一個數量級,EJB功能可是很豐富的,帶有事務,安全等高級企業級組件特性。
Wildfly8經過配置后使用和EAP類似的遠程調用選項,效率和EAP應該是一致的。
轉載地址:http://www.useopen.net/blog/2015/rpc-performance.html