怎樣對 RPC 進行有效的性能測試

在 RPC Benchmark Round 1 中 turbo 的成績一騎絕塵,實力碾壓衆 rpc 框架。對此,不少人表示不服氣,認爲做者既是運動員又是裁判員有失公平。因此我認爲有必要解釋一下 rpc-benchmark 的公正性,以及爲何 turbo 可以如此強悍。html

參考對象

rpc-benchmark 靈感源自 techempower-benchmarks,爲了可以評測衆多服務器框架,techempower-benchmarks 提供了6個測試用例:java

  1. JSON serialization
    This test exercises the framework fundamentals including keep-alive support, request routing, request header parsing, object instantiation, JSON serialization, response header generation, and request count throughput.git

  2. Single database query
    This test exercises the framework's object-relational mapper (ORM), random number generator, database driver, and database connection pool.github

  3. Multiple database queries
    This test is a variation of Test #2 and also uses the World table. Multiple rows are fetched to more dramatically punish the database driver and connection pool. At the highest queries-per-request tested (20), this test demonstrates all frameworks' convergence toward zero requests-per-second as database activity increases.spring

  4. Fortunes
    This test exercises the ORM, database connectivity, dynamic-size collections, sorting, server-side templates, XSS countermeasures, and character encoding.json

  5. Database updates
    This test is a variation of Test #3 that exercises the ORM's persistence of objects and the database driver's performance at running UPDATE statements or similar. The spirit of this test is to exercise a variable number of read-then-write style database operations.springboot

  6. Plaintext
    This test is an exercise of the request-routing fundamentals only, designed to demonstrate the capacity of high-performance platforms in particular. Requests will be sent using HTTP pipelining. The response payload is still small, meaning good performance is still necessary in order to saturate the gigabit Ethernet of the test environment.服務器

techempower-benchmarks 規則都是公開的,代碼都是開放的。任何人以爲xx框架寫得很差,配置有問題,均可以來提交本身的 Pull Request 。一句話,不服氣的話就來提交代碼。app

測試用例

不過 techempower-benchmarks 對比的都是服務器框架,並不能用來測試 rpc 的性能,做爲學習模仿者,我建立了 rpc-benchmark 這個項目。 rpc-benchmark 提供了4個測試用例:框架

  1. boolean existUser(String email), 判斷某個 email 是否存在
    輸入是很短的字符串,輸出是 bool 值,這個測試用例用於衡量小 Request 小 Response 的性能。

  2. boolean createUser(User user), 添加一個 用戶
    輸入是一個 User 的對象,輸出是 bool 值,這個測試用例用於衡量大 Request 小 Response 的性能。

  3. User getUser(long id), 根據 id 獲取一個用戶
    輸入是一個 long 類型的值,輸出是 User 對象,這個測試用例用於衡量小 Request 大 Response 的性能。

  4. Page<User> listUser(int pageNo), 獲取用戶列表
    輸入是 int 類型的值,輸出是一個包含15個 User 的列表,這個測試用例用於衡量小 Request 超大 Response 的性能。

這4個測試用例構成了一個基本的業務邏輯: 用戶註冊管理。很是具備表明性,而且沒有脫離現實使用場景。有些測試用例可能會注重衡量字符串的傳輸速度,從4字節 64字節 ... 64k字節 依次測起,這樣的測試用例就過於脫離現實,沒有太多的實際意義。畢竟做爲 rpc 框架,除了傳輸速度,序列化速度其實也是很是重要的。而僅僅用字符串來測試僅能測試出框架的傳輸速度,並不能有效衡量序列化的性能,也不能衡量總體的 rpc 性能。

測試工具

由於每一個 rpc 框架都有本身的 序列化協議 傳輸協議,因此 rpc-benchmark 不能像 techempower-benchmarks 同樣直接使用 wrk 做爲測試工具,只能每一個框架都編寫測試用的 客戶端實現。

客戶端實現 使用的工具是JMH,這個工具 Java 開發團隊本身也在使用。正確的性能測試在以前並非一件簡單的事情,JMH 的出現讓性能測試真正的 標準化 簡單化。更多關於 JMH 的介紹能夠參考下面的連接。

測試方法

測試的過程是先進行10次預熱,而後纔開始真正的3次測試(JMH的「每次」執行其實是執行不少次,更好的翻譯其實應該是「每輪」)。剛開始使用的是5次預熱,可是後來發現 http 傳輸協議的 undertow grpc 等框架都比較慢熱,須要更多的預熱次數。完整的測試要跑起來依然有點費勁,須要配置不少環境。不過若是你只是想研究下某個框架的代碼實現的話,徹底能夠更簡單一些。拉下代碼來直接導入到 Eclipse/IDEA ,配置好hosts,啓動 Server,而後啓動相應的 Client 就行了。

爲何把 undertow springboot netty 也做爲了測試對象

按照 wiki 的定義,這3個確實不能認爲是 rpc ,不過簡單封裝以後他們均可以做爲 rpc 使用。加入這幾個更多的是爲給 rpc 框架的實現者提供一個參考,做爲基礎的協議層性能是怎麼樣的?做爲springcloud 的底層實現,springboot 其實表明了springcloud 的性能。undertow 證實了 http+json 並不比 tcp+binary 慢太多,其速度甚至比 dubbo motan 還要快很多。同時也是爲了告訴噴子們,並非說你用了高性能的 netty+protopuff 就能比 turbo 快,turbo 能碾壓衆框架並不僅是靠簡單的拼積木就能作到的。

不足之處

僅1個客戶端32個線程實際上是很是不嚴謹的,正確的作法應該是從1個線程一直到32k個線程逐步增長,從1臺客戶端機器到1000臺客戶端機器逐步增長(客戶端數量 線程數量 應該是一個笛卡爾積)。不過每輪測試實在都太耗費時間了,並且阿里雲的服務器也不便宜,因此只能做罷。後續若是有云服務器廠商贊助的話,能夠考慮把這塊給作起來。

turbo爲何如此強悍

篇幅有限寫不開了,下篇再說吧。

相關文章
相關標籤/搜索