クラウドネイティブ時代は Java か Go か?

クラウドネイティブ時代は Java か Go か?

Java のかつての有名なモットー、「一度書けばどこでも実行できる」は、今ではコンテナ内でコードを実行するだけなので、時代遅れになっています。コンテナでは、「ジャストインタイム」コンパイラはあまり意味がありません。

このため、そしておそらくクラウド コンピューティングへの適応性を高めるために、Java エコシステムは変革の真っ只中にあります。 Oracle の GraalVm を使用すると、バイトコードを Linux 実行可能ファイル (ELF) にコンパイルできます。一方、Rad Heat の Quarkus やその他のフレームワークは、応答性の高いサービスを容易にすることを目的としています。 Quarkus は Netty と Vertx.x に基づいており、非常に効率的で応答性の高い Web サービスを構築するために使用できます。

Java は実行可能なバイナリ ファイルにコンパイルされ、数ミリ秒で起動し、メモリをほとんど使用しません。これにより、Java エコシステムを活用し、Scala や Kotlin などの他の JVM 言語で記述することもできます。オンライン プロジェクト ジェネレーターを使用して Quarkus を試したり、Maven プラグインを使用してローカルでプロジェクトを生成したりできます。

一方、Golang はクラウド用に生まれたため、コンテナ内で実行してもレガシーな問題はありません。クラウドのプログラミング言語として考えられています。生成されたバイナリ実行ファイルは小さく、起動が速く、メモリをほとんど消費しません。これは、Go が誕生して以来備わっている機能です。 Golang の人気は Java の世界に深刻な課題をもたらしました。

Javaにチャンスはあるでしょうか?おそらく、最終的な答えは時間だけが教えてくれるでしょう。しかし、好奇心から、Java と Golang のクラウドネイティブ サービスをパフォーマンスと開発体験の観点から比較したいと思いました。

この記事では、同じサービスを2つの言語で記述します。 CPU 使用率、RAM、レイテンシ、動作速度を比較します。これらのサービスは、同じリソース割り当てを持つコンテナで起動され、ab を使用してテストされます。

これは私のケースでは「十分に良い」ベンチマークです。これは、最良/最悪のベンチマーク結果を見つけることを想定しているのではなく、比較のために同じ環境で両方のベンチマークを実行することを想定しているからです。

シナリオ

これら 2 つのサービスは、1 つのテーブルと 3 行のデータを持つ、別のコンテナーで実行されている MySQL データベースに接続します。

各サービスはすべてのレコードを取得し、オブジェクトに変換して、JSON 配列を出力します。

ab は同時実行レベル 100 で 10K のリクエストを発行し、quarkus JVM バージョンは 2 回実行されます (「コールド」/「ウォーム」JVM をテストするため)。

Go言語バージョン

Go 言語バージョンでは、gin フレームワークを使用します。

  1. # サービス
  2. パッケージメイン
  3.  
  4. 輸入 (
  5. 「データベース/SQL」  
  6. 「fmt」  
  7. 「github.com/gin-gonic/gin」  
  8. _ "github.com/go-sql-driver/mysql"  
  9. 「ネット/http」  
  10.  
  11. フルーツ構造体型{
  12. ID int `json: "id" `
  13. 名前文字列 `json: "name" `
  14. }
  15.  
  16. var con *sql.DB
  17.  
  18. 関数init(){
  19. //別のコンテナとのmysql接続プールを開く
  20. db、エラー:= sql。開く( "mysql" "root:password@tcp(host.docker.internal:3306)/payments" )
  21. err != nil の場合 {
  22. panic( "mysql接続を開けませんでした" )
  23. }
  24. コン = デシベル
  25. }
  26.  
  27. 関数main() {
  28. r := gin.Default ()です。
  29. r.GET( "/果物" , 果物)
  30. r.Run() // 8080サーバーを起動
  31. }
  32.  
  33. // リクエストハンドラ
  34. func fruit(c *gin.Context) {
  35. 果物:= getFruits()
  36. c.JSON(http.StatusOK、果物)
  37. }
  38.  
  39. getFruits()関数 []フルーツ{
  40. 、_ := con.Query( "SELECT * FROM 果物" )
  41. フルーツ := []果物{}
  42. のために 行.次へ( ) {
  43. var r フルーツ
  44. .Scan(&r.Id, & r.Name )
  45. 果物 = append(果物, r)
  46. }
  47. 果物を返す
  48. }

Golang の MySQL ドライバーは go-sql-driver を使用します。 Golang のコーディングスタイルは非常に明確です。すべてが見えるという姿勢。メイン関数はサーバーを起動し、リクエスト ハンドラーを構成し、DB 接続を開きます。

ローカル実行ファイルをコンパイルする

Kotlin バージョン

  1. パッケージ org.acme
  2. io.vertx.core.json.JsonArray をインポートします。
  3. io.vertx.core.json.JsonObject をインポートします。
  4. io.vertx.mutiny.mysqlclient.MySQLPool をインポートします。
  5. io.vertx.mutiny.sqlclient.Row をインポートします。
  6. io.vertx.mutiny.sqlclient.RowSet をインポートします。
  7. java.util.concurrent.CompletionStage をインポートします。
  8. javax.inject.Inject をインポートする
  9. javax.ws.rs.GET をインポートする
  10. javax.ws.rs.Path をインポートする
  11. javax.ws.rs.Produces をインポートする
  12. javax.ws.rs.core.MediaType をインポートします。
  13.  
  14. @Path( "/果物" )
  15. クラス FruitResource {
  16. @フィールド:挿入
  17. lateinit var client: MySQLPool
  18.  
  19.  
  20. @得る
  21. @Produces(メディアタイプ.APPLICATION_JSON)
  22. 楽しいリストフルーツ(): 完了ステージ<JsonArray> {
  23. client.query( "SELECT * FROM fruit" )を返します実行する()
  24. .map {: RowSet<行> ->
  25. .fold(JsonArray()) { 配列、行 ->
  26. 配列.add (JsonObject()
  27. .put( "id" 、row.getLong( "id" )) は、
  28. .put( "名前" , row.getString( "名前" )))
  29. }
  30. }.subscribeAsCompletionStage()
  31. }
  32. }

データベース接続には、Quarkus React Mysql 拡張機能が使用されます。

CDI 依存性注入、javax アノテーションを使用した宣言型ルーティング、自動構成解決、データソース/接続作成/サーバー ブートストラップなど、コードは Go バージョンとはかなり異なります。これはフレームワークを使用する際の代償であり、フレームワークがあなたに代わって面倒な作業を実行し、物事の実行方法を決定します。ただし、go バージョンのコードよりもはるかに短くなります。

ここでは、Vert.x マルチイベント ループでラップされた Netty リアクティブ Web サーバーと、Vert.x リアクティブ MySQL ドライバーを使用して、1 つのスレッドで複数の DB 接続を処理できるようにします。

あるいは、Kotlin のコレクション ライブラリの fold 関数を使用することもできますが、これにはまだ一般的な Go バージョンがありません。

実行ファイルのJavaバージョンをコンパイルする

ビルド プロセスで何が起こっているのかがわかりましたが、その中心にあるのは SubstrateVM です。これは、AOT プロセスに埋め込み可能な仮想マシンとして設計されており、コードにリンクされ、ユニットとしてコンパイルされます。しかし、Oracle によれば、SubstrateVM は HotSpot VM よりも最適化が少なく、ガベージ コレクターもシンプルです。

この AOT コンパイラは「Graal」と呼ばれ、言語に依存しません。 Java バイトコードは中間表現 (Truffle 言語) に変換する必要があります。これについては、GraalとTruffleに関するこの記事[1]で確認できます。

Java ネイティブ実行可能ファイルの構築はより複雑で、コンパイルが遅く、Go バージョンのほぼ 2 倍の大きさのバイナリが生成されます。ただし、35 MB の実行可能バイナリ ファイルは、Java FatJar よりはるかに小さいです。 35MB あれば、AWS Lambda を使用して実行することもできます。

ストレステスト

次の設定で、ローカル マシン上ですべてのテストを実行します。

  • MacBook Pro (15インチ、2017)
  • 2.9GHz Intel Core i7(8コア)。
  • 16 GB 2133 MHz LPDDR3

cAdvisor のツールを使用してコンテナの統計を監視します。

シナリオ

  • Quarkus JVM ホットスポット
  • Quarkus Javaネイティブ
  • Go言語

上記の各ケースは、次の 3 つの構成でテストされました。

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

私が主に関心を持っているのは以下の点です。

  • CPU/RAM 使用率 (マルチコア使用率)
  • CPU/RAM ピーク
  • CPU/RAM空き容量
  • 起動時間
  • 応答遅延の平均/最大
  • スループット(1秒あたりのリクエスト数)

テスト結果

Quarkus は実稼働環境に対応しており、JVM/ネイティブ リリース/開発モードが簡単に使用でき、ネイティブ テストをローカルで実行できるようになっているようです。リフレクションや JNI を使用しない限り、GraalVM の構成に応じてこれが可能です。それ以外の場合は、Graal コンパイラを自分で構成する必要がありますが、これにも解決策があります。

レイテンシとスループット

Golang とネイティブ Java のテスト結果は非常に近いですが、平均すると Golang バージョンの方がわずかにパフォーマンスが優れています。ただし、Java ネイティブ バージョンのテスト結果はより安定しています。 Golang サービスは 1.25μs 以内に応答することもあります。しかし、完了するまでに 7 秒かかることもあります。

「ウォームアップ」された JVM バージョンの結果も悪くはありませんが、ネイティブ バージョンや Go バージョンに比べるとわずかに劣ります。

CPU使用率

Go と native-java はどちらも、0.5 コアを使用すると負荷がかかったときのパフォーマンスが低下するようで、2 コアで開始しても大きな改善は見られません。これは、ワークロードが IO によってボトルネックになっていることが原因である可能性があります。あるいは、gin/Netty のデフォルト設定ではマルチコアの問題が考慮されていないことが原因である可能性があります。

一方、JVM バージョンでは、与えられたすべてのコアを活用し、あらゆる面でパフォーマンスが向上します。

メモリ使用量

ストレス下では、Java ネイティブは 40MB を使用し、Golang は 24MB を使用します。どちらの場合も悪くありませんが、Golang バージョンではほぼ 2 倍のメモリを使用します。

JVM は 140MB を使用しました。 Quarkus の公式統計と全く同じです。 JVM としては悪くないですが、Golang バージョンと比べると 6 倍近くになります。

起動時間

Golang とクラウドネイティブ Java はどちらも即座に起動しますが、JVM バージョンでは数秒かかり (割り当てられた CPU によって異なります)、起動時に CPU スパイクが発生します。適切に構成されていない場合、k8s HPA が爆発的に増加し、ポッドの数が増加します。

開発経験

これは実用的な問題というよりも宗教的な問題です。 Quarkus は、Java の世界で一般的な抽象化 (アノテーションベースの DI など) を使用します。サーバーを起動し、接続プールを作成します。コレクションとジェネリックの豊富な標準ライブラリを使用できます。しかし、これは少し黒魔術のように感じられることもあり、何かが機能しなくなると無力感を感じることがあります。さらに、Java コードをネイティブ バイナリにコンパイルするのはそれほど簡単ではありません。注意しなければならない制限と考慮事項がいくつかあり、すべての Java ライブラリがネイティブ コンパイルと互換性があるわけではありません。互換性のないライブラリ (Guice など) を使用するとすぐに、Graal VM を自分で構成する必要があります。

Quarkus と Graal VM は「比較的」新しいものです。したがって、いくつか問題がある可能性があります。ただし、デュアル モード (JVM またはネイティブ) のためです。ネイティブ バージョンの一部のコンポーネントが動作しなくなった場合に備えて、フォールバックが常に用意されており、これは新しい問題に対する優れた回避策となります。

一方、Golang では、ジェネリックが必要であることを認めるまでに、誕生から 10 年かかりました。そして、フレームワークが多くの魔法の操作を使用するのは確かに好ましくありません。これは多くの点で良いことでもあり、悪いことでもあります。さらに、Go コミュニティは素晴らしい仕事をしていますが、利用できるツールやライブラリは比較的少ないです。ただし、コンパイルとビルドのプロセスはより高速かつ簡単です。また、すべての Golang パッケージと互換性があり、Java ネイティブ プラットフォームによってもたらされる制限はありません。

結論は

Java はクラウドネイティブに対応しており、Golang もそれほど先を進んでいません。今後、クラウドネイティブJavaが大規模に利用されるようになると考えています。

元のアドレス: https://medium.com/swlh/cloud-native-java-vs-golang-2a72c0531b05

この記事はWeChatの公開アカウント「高可用性アーキテクチャ」から転載したものです。以下のQRコードからフォローできます。この記事の転載については、Igor Domrevの公式アカウントまでご連絡ください。

<<:  Spring Boot Redis は分散ロックを実装しているので、とても良いです! !

>>:  OpenStack Cinder サービスステータスのトラブルシューティング

推薦する

百度の青大根アルゴリズムは、1人を逃がすよりも、ミスで1,000人を殺したがる

Baidu が最近行った検索アルゴリズム(青大根アルゴリズム)のアップグレードに関して、このアルゴリ...

機密情報サイトでお金を稼ぐのは簡単ではない。革新的な収益モデルが鍵となる

機密情報ネットワークの運用環境は、最近かなり危険になっているようだ。過去数年間、58.com と G...

シリコーン産業のネットワーク推進戦略

インターネット技術の継続的な革新と進歩に伴い、マーケティング モデルも絶えず変化しています。21 世...

ブログマーケティングでは、独立したブログを構築するか、無料のブログを構築するかを選択する必要がありますか?

ブログマーケティングとWeiboマーケティングはもはや同じではありませんが、ブログマーケティングを無...

シュガーホスト - 10月の30%オフプロモーション

ホスティング会社 sugarhost は 10 月のプロモーションを開始し、通常の仮想ホスティングと...

ブランドマーケティングプランを作成するには?使い方マニュアルをまとめました!

私自身の業務経験や情報をもとにまとめたブランドマーケティング運用マニュアルです。ブランド マーケティ...

O2O運用と潜在的および既存のバンユーザー管理

最近、地元の新興インターネット企業をいくつか見てきました。彼らの良い発展を楽しみにしていますが、同時...

微博は疲れた、オアシスは私の渇きを癒さない

蔡旭坤ファンと周杰倫ファンによる微博超話題戦争からほぼ1年が経ち、微博は突如ショート動画分野への参入...

Namecheap - .me ドメイン 初年度 0.98 ドル

Namecheap は個人ドメイン名 .me を初年度 0.98 ドルで開始します。更新にいくらかか...

Wooservers 仮想ホスティング 年間 20 ドル - 無料ドメイン名 + 独立 IP

Wooservers は英国に登録されたホスティング会社です (英国登録番号: 07207169)。...

Xshell で VPS サーバーに接続するチュートリアル

Xshell は、Windows で Linux VPS サーバーに接続するための一般的なソフトウェ...

警戒すべきクラウドコンピューティング攻撃手法7つ

セキュリティの専門家が、サイバー攻撃者が企業のクラウド コンピューティング環境に対して使用する一般的...

ブランド マーケティング: インターネット ブランドを「目立たせる」にはどうすればよいでしょうか?

インターネットブランドは、オフラインで活動し、人々の空間に侵入し、現実世界で見られるようになることが...

SEOを成功させるには個人の英雄的行為ではなくチームワークが必要

ウェブサイトの最初から、開発プロセスと参加プロセス全体を決定する必要があります。 SEO プロジェク...

APPプロモーションチャンネルでの不正行為の方法、APPプロモーションでの不正行為を防ぐ方法は?

APPプロモーションチャネルでは不正行為が頻繁に発生します。今日は、APPプロモーションの不正行為防...