自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

云原生時(shí)代,Java還是Go?

開發(fā) 后端 云原生
Java曾經(jīng)著名的座右銘:"一次編寫,到處運(yùn)行",已經(jīng)很過(guò)時(shí)了,因?yàn)楝F(xiàn)在我們只想在容器里運(yùn)行代碼。在容器里,一個(gè) "Just in time "的編譯器意義不大。

Java曾經(jīng)著名的座右銘:"一次編寫,到處運(yùn)行",已經(jīng)很過(guò)時(shí)了,因?yàn)楝F(xiàn)在我們只想在容器里運(yùn)行代碼。在容器里,一個(gè) "Just in time "的編譯器意義不大。

出于這個(gè)原因,可能為了更好地適應(yīng)云計(jì)算,Java生態(tài)系統(tǒng)正處于轉(zhuǎn)型之中。Oracle 的GraalVm允許將字節(jié)碼編譯成Linux可執(zhí)行文件(ELF),而Rad Heat的Quarkus以及其他框架,則立志讓響應(yīng)式服務(wù)這件事變得更簡(jiǎn)單。Quarkus以Netty和Vertx.x為核心,可以用來(lái)構(gòu)建非常高效的響應(yīng)式Web服務(wù)。

 

Java編譯成可執(zhí)行二進(jìn)制文件,以毫秒級(jí)的速度啟動(dòng),內(nèi)存占用很小。這樣就可以利用Java生態(tài)系統(tǒng),甚至可以用其他JVM語(yǔ)言(如Scala和Kotlin)編寫。你可以用online項(xiàng)目生成器玩玩Quarkus,或者用maven插件在本地生成一個(gè)項(xiàng)目。

而Golang則是為云而生的,在容器中運(yùn)行時(shí),沒有遺留負(fù)擔(dān)。它被認(rèn)為是云端的編程語(yǔ)言。生成的二進(jìn)制可執(zhí)行文件很小,快速啟動(dòng),內(nèi)存占用也很小,而且這是從Go誕生之初就具備的特性。Golang的流行對(duì) Java 世界形成了嚴(yán)峻的挑戰(zhàn)。

Java有機(jī)會(huì)嗎,也許只有時(shí)間才會(huì)告訴我們最終答案。然而,出于好奇,我想從性能和開發(fā)體驗(yàn)方面比較一下 Java 和 Golang 的云原生服務(wù)。

在這篇文章中,我將使用兩種語(yǔ)言來(lái)寫同樣的服務(wù)。比較它們的CPU使用率、RAM、延遲和運(yùn)行速度。這些服務(wù)將在容器中啟動(dòng),資源分配相同,使用ab來(lái)測(cè)試。

對(duì)于我的案例來(lái)說(shuō),這是一個(gè) "足夠好 "的基準(zhǔn),因?yàn)槲也患僭O(shè)找到最好/最差的基準(zhǔn)結(jié)果,而是在同一環(huán)境下執(zhí)行運(yùn)行兩個(gè)基準(zhǔn)測(cè)試進(jìn)行比較。

場(chǎng)景

這兩個(gè)服務(wù)將連接到在另一個(gè)容器中運(yùn)行的MySQL數(shù)據(jù)庫(kù),有一個(gè)表和三行數(shù)據(jù)。

 

每一個(gè)服務(wù)都會(huì)獲取所有記錄,將它們轉(zhuǎn)化為對(duì)象,然后輸出JSON數(shù)組。

ab將發(fā)出10K請(qǐng)求,并發(fā)級(jí)別為100,quarkus JVM版本運(yùn)行兩次(用于測(cè)試 "冷"/"暖 "JVM)。

 

Go語(yǔ)言版本

Go語(yǔ)言版本使用gin框架。

  1. # the service 
  2. package main 
  3.  
  4. import ( 
  5.     "database/sql" 
  6.     "fmt" 
  7.     "github.com/gin-gonic/gin" 
  8.     _ "github.com/go-sql-driver/mysql" 
  9.     "net/http" 
  10.  
  11. type Fruit struct { 
  12.     Id  int `json:"id"
  13.     Name string `json:"name"
  14.  
  15. var con *sql.DB 
  16.  
  17. func init(){ 
  18.   //opening a mysql connection pool with another container 
  19.    db, err := sql.Open("mysql""root:password@tcp(host.docker.internal:3306)/payments"
  20.    if err != nil { 
  21.        panic("failed to open a mysql connection"
  22.    } 
  23.    con = db 
  24.  
  25. func main() { 
  26.     r := gin.Default() 
  27.     r.GET("/fruits", fruits) 
  28.     r.Run() //server up on 8080 
  29.  
  30. // THE REQUEST HANDLER 
  31. func fruits(c *gin.Context) { 
  32.     fruits := getFruits() 
  33.     c.JSON(http.StatusOK, fruits) 
  34.  
  35. func getFruits() []Fruit { 
  36.     rows, _ := con.Query("SELECT * FROM fruits"
  37.     fruits := []Fruit{} 
  38.     for rows.Next() { 
  39.         var r Fruit 
  40.         rows.Scan(&r.Id, &r.Name
  41.         fruits = append(fruits, r) 
  42.     } 
  43.     return fruits 

Golang的MySQL驅(qū)動(dòng)的使用go-sql-driver。golang的代碼風(fēng)格是非常明確的。一種一切都在眼前態(tài)度。主函數(shù)啟動(dòng)服務(wù)器,配置請(qǐng)求處理程序,打開DB連接。

編譯本地可執(zhí)行文件

 

Kotlin版本

  1. package org.acme 
  2. import io.vertx.core.json.JsonArray 
  3. import io.vertx.core.json.JsonObject 
  4. import io.vertx.mutiny.mysqlclient.MySQLPool 
  5. import io.vertx.mutiny.sqlclient.Row 
  6. import io.vertx.mutiny.sqlclient.RowSet 
  7. import java.util.concurrent.CompletionStage 
  8. import javax.inject.Inject 
  9. import javax.ws.rs.GET 
  10. import javax.ws.rs.Path 
  11. import javax.ws.rs.Produces 
  12. import javax.ws.rs.core.MediaType 
  13.  
  14. @Path("/fruits"
  15. class FruitResource { 
  16.     @field:Inject 
  17.     lateinit var client: MySQLPool 
  18.  
  19.  
  20.     @GET 
  21.     @Produces(MediaType.APPLICATION_JSON) 
  22.     fun listFruits(): CompletionStage<JsonArray> { 
  23.         return client.query("SELECT * FROM fruits").execute() 
  24.                 .map { rows: RowSet<Row> -> 
  25.                     rows.fold(JsonArray()) { array, row -> 
  26.                         array.add(JsonObject() 
  27.                                 .put("id", row.getLong("id")) 
  28.                                 .put("name", row.getString("name"))) 
  29.                     } 
  30.                 }.subscribeAsCompletionStage() 
  31.     } 

數(shù)據(jù)庫(kù)連接使用Quarkus React Mysql 擴(kuò)展。

 

與Go版本相比,代碼有很大不同,比如CDI依賴注入,使用javax注釋的聲明式路由,自動(dòng)配置解析,以及數(shù)據(jù)源/連接創(chuàng)建/服務(wù)器引導(dǎo)。這是使用框架的代價(jià),它為你完成了繁重的工作,并決定了做事方式。不過(guò),它比go版本代碼要簡(jiǎn)短很多。

這里使用Netty響應(yīng)式web服務(wù)器,由Vert.x多事件循環(huán)包裝,還有一個(gè)Vert.x響應(yīng)式MySQL驅(qū)動(dòng),這樣可以用一個(gè)線程處理多個(gè)DB連接。

另外,我可以使用Kotlin的集合庫(kù)的fold函數(shù),這種函數(shù)還沒有通用的Go版本。

編譯Java版本的可執(zhí)行文件

 

我已經(jīng)弄清楚構(gòu)建過(guò)程中發(fā)生了什么,其核心是SubstrateVM。它被設(shè)計(jì)在AOT過(guò)程中的可嵌入虛擬機(jī),它會(huì)鏈接到我們的代碼,并作為一個(gè)單元進(jìn)行編譯。然而根據(jù)Oracle的說(shuō)法,SubstrateVM的優(yōu)化比HotSpot Vm少,垃圾收集器也比較簡(jiǎn)單。

該AOT編譯器被稱為 "Graal",它是語(yǔ)言不相關(guān)的。java字節(jié)碼需要被翻譯成一種中間表示法(Truffle語(yǔ)言)。這在這篇文章【1】中可以找到關(guān)于Graal和Truffle的相關(guān)論述。

構(gòu)建一個(gè) Java 本地可執(zhí)行文件看起來(lái)更復(fù)雜,編譯得更慢,它產(chǎn)生的二進(jìn)制文件幾乎是Go版本兩倍大小。然而一個(gè)35M的可執(zhí)行二進(jìn)制文件和Java FatJar相比,還是小D多了。35MB甚至可以讓你使用aws lambda運(yùn)行。

壓力測(cè)試

我在本機(jī)運(yùn)行所有測(cè)試,設(shè)置如下。

  • MacBook Pro(15英寸,2017年
  • 2.9 GHz英特爾酷睿i7(8個(gè)核心)。
  • 16 GB 2133 MHz LPDDR3

使用cAdvisor的工具來(lái)監(jiān)控容器的統(tǒng)計(jì)數(shù)據(jù)。

場(chǎng)景

  • Quarkus JVM hotspot
  • Quarkus Java native
  • Golang

上述的每種情況都在以下三種配置上測(cè)試

  • 100MB / 0.5 CPU | 200MB / 1 CPU | 300MB / 2 CPU

我主要關(guān)注:

  • cpu/ram利用率(多核的利用率)
  • cpu/ram峰值
  • cpu/ram空余
  • 啟動(dòng)時(shí)間
  • 響應(yīng)延遲avg/max
  • 吞吐量(每秒請(qǐng)求數(shù))

測(cè)試結(jié)果

 

看起來(lái)Quarkus已經(jīng)為生產(chǎn)環(huán)境做好準(zhǔn)備了,它允許簡(jiǎn)單的JVM/原生發(fā)布/開發(fā) 模式,并允許在本地運(yùn)行原生測(cè)試。只要你不使用反射或JNI,根據(jù)GraalVM的配置就是可行的。否則,你將不得不自己配置graal編譯器,然而現(xiàn)在也有解決方案。

延遲和吞吐量

Golang 和原生 Java 的測(cè)試結(jié)果比較接近,雖然平均來(lái)說(shuō) Golang 版本的測(cè)試結(jié)果略好一些。不過(guò),Java Native版本的測(cè)試結(jié)果更穩(wěn)定。Golang服務(wù)有時(shí)在1.25μs內(nèi)完成響應(yīng),也有一部分需要7s才能完成。

"預(yù)熱 "后的JVM版本結(jié)果也不差,但比Native或Go版本稍遜一籌。

CPU利用率

使用0.5核的時(shí)候,Go和native-java在負(fù)載下似乎都表現(xiàn)不佳,而用2核啟動(dòng)時(shí),也沒有明顯改善。這可能是因?yàn)楣ぷ髫?fù)載的瓶頸是IO?;蛘呤且?yàn)間in/Netty的默認(rèn)配置沒有考慮到多核的問(wèn)題。

而JVM版本則利用了所有給定的核心,并在各個(gè)維度上提升了性能。

內(nèi)存使用率

在壓力下,Java native 使用40MB,Golang 使用24MB。兩種情況下都還不錯(cuò),雖然Golang版本使用的內(nèi)存幾乎少了一倍。

JVM使用了140MB。和Quarkus官方的統(tǒng)計(jì)完全一樣。對(duì)于JVM來(lái)說(shuō)還不錯(cuò),但比Golang版本多了近6倍。

啟動(dòng)時(shí)間

Golang和cloud-native java都能立即啟動(dòng),然而JVM版本需要幾秒鐘(取決于分配的CPU),并且在啟動(dòng)時(shí)產(chǎn)生CPU峰值。如果配置不當(dāng),會(huì)導(dǎo)致k8s HPA發(fā)飆,并增加pods。

開發(fā)體驗(yàn)

這與其說(shuō)是一個(gè)實(shí)際問(wèn)題,不如說(shuō)是一個(gè)宗教問(wèn)題。Quarkus 使用了在 Java 世界中很常見的抽象(比如基于注解的DI)。它為你啟動(dòng)服務(wù)并創(chuàng)建連接池。它可以使用豐富的集合標(biāo)準(zhǔn)庫(kù)和generics。然而,這可能感覺有點(diǎn)像黑魔法,一旦有些組件不工作,你會(huì)感覺很無(wú)助。此外,將 Java 代碼編譯成原生二進(jìn)制并不是那么簡(jiǎn)單,有一些限制和注意事項(xiàng)是你必須知道的,并非每個(gè)Java庫(kù)都能兼容原生編譯。一旦使用一個(gè)不兼容的庫(kù)(比如Guice),你就需要自己配置Graal VM。

Quarkus 和 Graal VM "相對(duì) "較新。所以可能會(huì)有一些問(wèn)題。但由于雙模式(JVM或原生)。在原生版本的某些組件停止工作的情況下,總是有一個(gè)后備方案,這對(duì)任何新問(wèn)題來(lái)說(shuō)都是很好的變通方法。

另一方面,Golang 在成立10年后才承認(rèn)它需要generics。而且它肯定不喜歡框架使用很多魔法操作。這在很多方面既是好事也是壞事。此外,盡管 Go 社區(qū)做的非常好,然而可用的工具和庫(kù)還是相對(duì)較少。然而它的編譯和構(gòu)建過(guò)程更快/更簡(jiǎn)單。而且兼容每個(gè)Golang的包,沒有java-native平臺(tái)帶來(lái)的限制。

結(jié)論

Java已經(jīng)為云原生做好了準(zhǔn)備,Golang并沒有大幅度領(lǐng)先。相信未來(lái)Cloud Native Java會(huì)被大規(guī)模使用。

 

原文地址:https://medium.com/swlh/cloud-native-java-vs-golang-2a72c0531b05

本文轉(zhuǎn)載自微信公眾號(hào)「高可用架構(gòu)」,可以通過(guò)以下二維碼關(guān)注。轉(zhuǎn)載本文請(qǐng)聯(lián)系Igor Domrev 公眾號(hào)。 

 

責(zé)任編輯:武曉燕 來(lái)源: 高可用架構(gòu)
相關(guān)推薦

2019-09-20 13:37:50

Java云原生Docker

2021-08-09 11:43:02

容器云原生安全

2020-08-28 08:29:40

云原生微服務(wù)編程

2023-08-28 16:08:12

2022-06-22 09:24:30

云原生Go 語(yǔ)言

2019-07-04 17:28:04

騰訊云云原生開源

2020-10-21 10:04:56

云原生應(yīng)用架構(gòu)

2020-12-01 17:44:15

華為云Go語(yǔ)言云原生

2021-03-23 11:09:36

云計(jì)算

2022-05-26 11:50:15

云原生云安全

2021-08-23 13:50:46

云原生PaaS

2022-01-14 07:17:39

阿里云云原生經(jīng)濟(jì)

2022-11-30 18:38:50

2022-10-27 18:03:04

GogRPC云原生

2021-12-08 12:03:09

金融科技云原生

2023-11-30 16:42:21

2012-09-26 10:59:52

大數(shù)據(jù)云計(jì)算云服務(wù)

2024-01-03 15:09:21

云原生Go語(yǔ)言

2023-10-04 00:18:00

云原生Go語(yǔ)言
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)