Spring Cloud Gateway 、Zuul、EdgeService性能對比


關鍵字:網關,Zuul,Gateway,Spring Cloud, ServiceComb,Edge Service性能測試,微服務html


做者 | 李昂java


導讀


本文對幾種流行的 API 網關以關鍵指標 RPS 爲依據,利用 wrk 作出性能測評而且給出結論。本文全部使用的軟件、命令、以及代碼均在文中註明,以便讀者搭建本地環境進行測試。注意性能測試的數據在不一樣的運行環境中差異較大,但整體上來講各項數據會成比例變化,本文的測試過程和結論能夠較準確地反應出各 API 網關之間的性能差別。react


背景知識介紹


API 網關


近些年來,在雲時代的背景下,爲了適應互聯網和大數據的高速發展,隨着微服務架構的持續火熱,對 API 網關的訴求愈來愈強烈,API 網關的產品也層出不窮。除了傳統的 Zuul 和 SpringCloud Gateway, 還誕生了不少優秀的網關,本文選取了Edge Service 做爲比較對象與傳統的網關進行了 API 網關的性能測評。git


到底是久經沙場的老牌網關更經得起考驗,仍是新興的網關性能更優?本文將給出詳細的測評過程和結果。github

 

Netflix Zuul

Zuul 在這三個網關中是最先誕生的,其 github repo 早在 2013 年以前就已經存在,同年開始進入大衆視野,嶄露頭角。雖然 Zuul 誕生較早,也佔據着不小的市場份額,但因爲 Zuul自己是基於阻塞io開發的,在現在的網關市場上,相較其餘的產品,性能上稍顯馬力不足。spring

Spring Cloud Gateway

Gateway 創建在 Spring Framework 5,Project Reactor 和 Spring Boot 2 上,不一樣於 Zuul 的阻塞 IO,Gateway使用的是非阻塞 IO,相較 Zuul 具有更好的內核性能;同時與Spring緊密集成,對於開發者而言,成爲了一個整合方便,使用方便,性能高的產品,有着良好的生態市場做爲依託。
其實,Spring Cloud 最開始是整合 Zuul 做爲網關解決方案,可是隨着時間的推移,BIO 的侷限性不斷暴露,捉襟見肘,Spring 開始考慮另尋他路。自此,Spring Cloud Gateway 網關亮相面世。而這一產品也確實經受住了時間的考驗,成爲了業界最佳的網關選擇之一。apache

ServiceComb EdgeService

EdgeService 來自於 Apache 開源項目 apache/servicecomb-java-chassis,其主項目 Apache ServiceComb 是由華爲公司於2017年捐獻給 Apache孵化,並於次年 10 月 24 日宣佈畢業,也是業界首個在Apache 孵化畢業的頂級開源微服務項目。
在現在的雲原生時代背景下, EdgService 能很好的適應發展變革與鹿場角逐,因爲自帶微服務場景的基因,因此 EdgeService 天生適用於在微服務場景,而且和 ServiceComb-Java-Chassis 完美集成,更好的融入微服務項目,具體信息能夠參考 EdgeService文檔api

性能測試


環境準備:

 

  • 硬件環境:三臺機器,分別運行服務端程序,網關程序和壓測程序
    • CPU: 4vCPU Intel(R) Xeon(R) CPU E5-2680 v4 @ 2.40GHz
    • 內存:8GB
  • 軟件環境:
    • wrk

工程文件:


本文涉及到的全部代碼可從 https://github.com/AngLi2/api-gateway-benchmark 獲取:  架構

其中:app

  • origin:爲本次性能測試的被調用服務文件,測試中在 192.168.0.5:8080 端口啓動
  • zuul: 爲 zuul 網關程序,將請求分發到 origin,測試中在 192.168.0.152:8081 端口啓動
    • odependency依賴的 spring-cloud-starter-zuul 版本爲 1.4.7.RELEASE,對應的 Zuul 版本爲 1.3.1
  • gateway: 爲 gateway 網關程序,將請求分發到 origin,測試中在 192.168.0.152:8082 端口啓動
    • odependency依賴的 spring-cloud-starter-gateway 版本爲 2.1.2.RELEASE
  • edgeservice: 爲 edgeservice 網關程序,將請求分發到 origin,測試中在 192.168.0.152:8083 端口啓動
    • odependency依賴的 org.apache.servicecomb:edge-core 版本爲 1.2.0.B006

關鍵配置:


不一樣的網關使用的是不一樣的配置方法,但最終的效果一致,並不影響網關的使用和性能(並不會對網關的使用和性能形成影響)。


Netflix Zuul:


經過 application.properties 進行配置:

zuul.routes.demo.path=/*
zuul.routes.demo.url=http://192.168.0.5:8080


Spring Cloud Gateway:


經過 Bean 注入的方式進行配置:

@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
    return builder.routes()
            .route(r -> r.path("/checked-out")
                    .uri("http://192.168.0.5:8080/checked-out")
            ).build();
}

ServiceComb EdgeService


因爲 EdgeService 主要是針對微服務,須要先註冊 REST 服務的 endpoint、接口契約等信息,因此這裏的配置稍顯複雜,若是直接使用 ServiceComb 的微服務解決方案(服務中心,配置中心)等,會方便不少,感興趣的同窗能夠參考《21天微服務實踐》中的網關部分實踐一下。


1.根據 REST 接口編寫 Java 接口類

@Path("/checked-out")
@Api(produces = MediaType.TEXT_PLAIN)
public interface Service {
    @GET
    String getCheckedOut();
}


2.根據 endpoint 調用方法而且註冊:

String endpoints="rest://192.168.0.5:8080";
RegistryUtils.getServiceRegistry().registerMicroserviceMappingByEndpoints(
        "thirdPartyService",
        "0.0.1",
        Collections.singletonList(endpoints),
        Service.class
);


3.網關配置文件(這裏的 loadbalance 只是爲了 edgeservice 調用,實際只有一個被調用實例),此處 maxPoolSize 設置成了20,緣由以下:
在沒有進行 maxPoolSize 的設置的時候,使用 netstat -apn | grep 192.168.0.5 | grep ESTA | wc -l 查詢鏈接數,發現只創建了 20 條鏈接。參考 ServiceComb 文檔,能夠看出連接數爲 verticle-count * maxPoolSize,而 maxPoolSize 的默認值只有5,而 verticle-count 的默認值爲:

  • 若是CPU數小於8,則取CPU數
  • 若是CPU數大於等於8,則爲8

由於測試環境的 CPU 讀數爲4,因此總連接數只有 4 * 5 = 20,而 Spring Cloud Gateway 的總連接數測試的時候一直在 90 多,因此這裏爲了保證測評公平有效,將 maxPoolSize 設置成 20。
事實上,即便在 EdgeService 的連接數爲 20 的狀況下,測試時也比 Spring Cloud Gateway 連接數 90 的表現要好一點,讀者們能夠本身嘗試一下。

servicecomb:
  rest:
    address: 127.0.0.1:8083
  client:
    connection:
      maxPoolSize: 20
  http:
    dispatcher:
      edge:
        default:
          withVersion: false
          enabled: true
          prefix: rest
          prefixSegmentCount: 2

 

測試過程:


早期方案使用 Apache Benchmark 進行壓力測試,得出的結論和預期的截然不同,基於 rxNetty 的 Spring Cloud Gateway 比 Zuul 表現還差一大截,並且在進行長鏈接測試的時候 Spring Cloud Gateway 直接卡死。
這個問題在 github 的 spring-cloud-gateway 的 Issues 區早有說起: Throughput problems when compared with Netflix Zuul and Nginx
Issue 被提出是由於有人提出用 Apache Benchmark 對 Spring Cloud Gateway, Netflix Zuul 和 Nginx 進行壓測,發現結果以下:

Experiment     Mean Time Per Request (ms)    Request Per Second
Nginx reverse proxy 32.085 6233.40
Zuul (after warmup) 28.422 7036.90
Spring Cloud Gateway 229.058 873.14

     
經過 Issue 的回覆區的:Add support for HTTP 1.0 關聯問題,咱們能夠找到不少關於 rxNetty 不支持 HTTP1.0 的 Issues,這裏列出來幾個,有興趣的讀者能夠點進去看看:

至此,得出 Apache Benchmark 並不能很好地測試出網關的性能,轉而使用 wrk 進行測試(Spring Cloud Gateway 官方使用的性能測試工具也是這個,後文會有說起)。wrk 默認工做於長鏈接模式,有效地減小了斷連建連的損耗,能夠比較真實地反映出網關的性能。

對原始服務進行測試:


1.運行命令:wrk -t12 -c100 -d300s http://192.168.0.5:8080/checked-out
2.獲得結果以下:

Running 5m test @ http://192.168.0.5:8080/checked-out
  12 threads and 100 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency     2.94ms    1.18ms  56.41ms   81.59%
    Req/Sec     2.76k   228.24     3.76k    72.32%
  9906220 requests in 5.00m, 1.25GB read
Requests/sec:  33014.70
Transfer/sec:      4.26MB


3.根據測試結果,能夠獲得延時服務的 RPS 和平均延時爲:

  • RPS:33014.70 請求/秒
  • Average Latency: 2.94ms

Netflix Zuul


1.運行命令: wrk -t12 -c100 -d300s http://192.168.0.5:8081/checked-out
2.獲得結果以下:

Running 5m test @ http://192.168.0.152:8081/checked-out
  12 threads and 100 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency    12.39ms   21.27ms   1.15s    91.90%
    Req/Sec     1.10k   264.62     2.09k    72.43%
  3953807 requests in 5.00m, 735.99MB read
Requests/sec:  13175.21
Transfer/sec:      2.45MB


3.根據測試結果,能夠獲得 Netflix Zuul 的 RPS 和平均延時爲:

  • RPS:13175.21 請求/秒
  • Average Latency: 12.39ms

4.在性能測試的過程當中使用 top 看一下 CPU 使用狀況,基本滿負載運行: 

 

Spring Cloud Gateway


1.運行命令: wrk -t12 -c100 -d300s http://192.168.0.152:8082/checked-out
2.獲得結果以下:

Running 5m test @ http://192.168.0.152:8082/checked-out
  12 threads and 100 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency     4.95ms    9.96ms 539.29ms   98.96%
    Req/Sec     1.82k   222.74     2.39k    91.81%
  6507221 requests in 5.00m, 850.19MB read
Requests/sec:  21685.14
Transfer/sec:      2.83MB


3.根據測試結果,能夠獲得 Spring Cloud Gateway 的 RPS 和平均延時爲:

  • RPS:21685.14 請求/秒
  • Average Latency: 4.95ms

4.在性能測試的過程當中使用 top 看一下 CPU 使用狀況,基本滿負載運行:

 

 

ServiceComb EdgeService


1.運行命令: wrk -t12 -c100 -d300s http://192.168.0.152:8083/rest/thirdPartyService/checked-out
2.獲得結果以下:

Running 5m test @ http://192.168.0.152:8083/rest/thirdPartyService/checked-out
  12 threads and 100 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency     3.80ms    4.67ms 300.59ms   97.98%
    Req/Sec     2.27k   309.82     3.10k    86.53%
  8144028 requests in 5.00m, 1.03GB read
Requests/sec:  27139.19
Transfer/sec:      3.52MB


3.提取 RPS 數據,能夠獲得 EdgeService 的測試 RPS 爲:27139.19 請求/秒
4.在性能測試的過程當中使用 top 看一下 CPU 使用狀況,基本滿負載運行:

 

 

測試結果:


對測試的數據進行表格分析對比,分別給出平均時延、RPS 和性能損失((原服務的 RPS - 網關的 RPS) / 原服務的 RPS)表格以下圖所示:

服務 平均時延(ms) RPS 性能損失
Origin 2.94 33014.70 0
Netflix Zuul 12.39 13175.21 60.09%
Spring Cloud Gateway 4.95 21685.14 34.32%
ServiceComb EdgeService 4.01 27139.19 17.80%

 
能夠看出,在硬件環境徹底相同,而且 CPU消耗基本一致的狀況下,以 RPS 爲性能指標(以性能損失爲性能指標的話,差別更大,這裏參考業界作法,以 RPS 爲指標),Spring Cloud Gateway 的性能比 Netflix Zuul 好將近一倍,而 Edge Service是 Spring Cloud Gateway 的 1.25 倍多,這仍是在 EdgeService 的連接數劣於 Spring Cloud Gateway 20% 左右的狀況下的數據,若是將 EdgeService 的連接數設置和 Spring Cloud Gateway 一致,性能會相差更大,有興趣的讀者能夠本身嘗試一下。


結論:


Spring Cloud Gateway 的性能比 Zuul 好基本上已是業界公認的了,實際上,Spring Cloud Gateway 官方也發佈過一個性能測試,這裏節選以下數據:

Proxy Avg Latency Avg Req
gateway 6.61ms 3.24k
linkered 7.62ms 2.82k
zuul 12.56ms 2.09k
none 2.09ms 11.77k

*該表格數據來自於 spring-cloud-gateway-bench


由於咱們的測試機器部署在同一個局域網,因此性能損失均要低於 spring-cloud-gateway-bench 官方的測試數據,可是從測試結果看來基本一致。網關的性能和其實現方式也有很大的關係:

  • Netflix Zuul: 測試版本爲 1.x,基於阻塞 io
  • Spring Cloud Gateway: 前面已經提到過,基於 RxNetty,異步非阻塞
  • ServiceComb EdgeService:爲 ServiceComb 的子項目,基於 vert.x,也是異步非阻塞

一樣基於異步非阻塞,EdgeService 的性能明顯優於 Spring Cloud Gateway,能夠看出網關的性能不只和底層實現有關,和內部實現方式和優化也有很大的關係。參考 ServiceComb 的官方文檔,能夠發現 EdgeService 還支持接入 rest 自動變成 highway 轉調,性能更高。這裏由於協議層面不同,就不放出來作對比了,對性能有極致要求的能夠採用這種模式。


在 2018 年終於發佈了 Zuul 2.x 以後,Netflix 給出了一個比較模糊的數據,大體 Zuul2 的性能比 Zuul1 好 20% 左右。然而從測試數據看來即便性能提高一半也徹底比不上 Spring Cloud Gateway 的,更不用說 EdgeService 了。看來 Zuul 2.x 並無把異步非阻塞的性能發揮出來。
競爭是發展的催化劑。在這個網關服務層出不窮的年代,各公司都鉚足力氣打造本身的網關產品,儘可能讓本身的產品成爲用戶的第一選擇。而廣大開發者也在享受這樣的紅利,使用高性能的網關來開發本身的應用。做爲廣大開發者的一員,咱們欣然接受這樣良性競爭的出現,而且也樂於嘗試市面上出現的任何新產品,誰也說不許某一個產品之後就會成爲優選的代名詞。雖然從如今網關的性能差距看來,後發優點明顯,但在可預見的未來,各網關早晚會到達性能瓶頸,在性能差距不大而且產品穩定以後,就會有各類差別化特性出現。而等到網關產品進入百舸爭流的時代以後,用戶就能夠再也不根據性能,而是根據本身的需求選擇適合的網關服務了。


參考資料


https://github.com/spring-cloud/spring-cloud-gateway/issues
https://github.com/reactor/reactor-netty/issues
https://github.com/ReactiveX/RxNetty/issues
https://github.com/spring-projects/spring-framework/issues
https://github.com/spencergibb/spring-cloud-gateway-bench
https://docs.servicecomb.io/java-chassis/zh_CN
http://www.itmuch.com/spring-cloud-sum/performance-zuul-and-gateway-linkerd/
http://www.javashuo.com/article/p-npwoazgf-md.html
https://www.zhihu.com/question/67498050
https://www.jianshu.com/p/52c2fd448f24
https://www.w3xue.com/exp/article/20197/48191.html

相關文章
相關標籤/搜索