Javaの進化、クラウドネイティブ時代の変革

Javaの進化、クラウドネイティブ時代の変革

[編集者注] クラウドネイティブ時代の到来は Java 開発者とどのような関係があるのでしょうか?クラウド ネイティブは Java にはまったく適していないと言う人もいます。しかし、この記事の著者は、クラウドネイティブ時代においても、Java は依然として「巨人」の役割を果たすことができると考えています。著者は一連の実験を通じて学生の視野を広げ、有益な思考を提供したいと考えています。

エンタープライズ ソフトウェアの分野では、Java は依然として絶対的な王者ですが、開発者の間では Java を愛する気持ちと嫌う気持ちが分かれています。一方では、豊富なエコシステムと完全なツール サポートにより、アプリケーション開発の効率が大幅に向上します。しかし、実行時の効率という点では、Java は「メモリを大量に消費する」および「CPU を大量に消費する」という悪評も持っており、NodeJS、Python、Golang などの新旧の言語からの挑戦を受け続けています。

テクノロジーコミュニティでは、Java テクノロジーはクラウドネイティブコンピューティングの開発トレンドに適合しなくなったと考え、Java テクノロジーを批判する人がよくいます。上記の観点はさておき、まずはアプリケーション ランタイムに対するクラウド ネイティブのさまざまな要件について考えてみましょう。

サイズが小さい:マイクロサービス分散アーキテクチャの場合、サイズが小さいほどダウンロード帯域幅が少なくなり、配布とダウンロードの速度が速くなります。

起動速度の高速化:従来のモノリシック アプリケーションの場合、起動速度は動作効率と比較して重要な指標ではありません。その理由は、これらのアプリケーションは再起動およびリリースされる頻度が比較的低いためです。ただし、迅速な反復と水平拡張を必要とするマイクロサービス アプリケーションの場合、起動速度が速いほど、配信効率が高くなり、ロールバックが速くなります。特に、何百ものコピーを持つアプリケーションをリリースする必要がある場合、起動速度が遅いと時間の無駄になります。サーバーレス アプリケーションの場合、エンドツーエンドのコールド スタート速度がさらに重要になります。基盤となるコンテナ テクノロジによって 100 ミリ秒以内にリソースを準備できたとしても、アプリケーションが 500 ミリ秒以内に起動できない場合、ユーザーはアクセスの遅延を感じます。

リソース使用量の削減:実行時のリソース使用量が少ないということは、展開密度が高くなり、コンピューティング コストが低くなることを意味します。同時に、JVM が起動すると、バイトコードをコンパイルするために大量の CPU リソースが消費されます。起動時のリソース消費を削減することで、リソースの競合を減らし、他のアプリケーションの SLA をより適切に保証できます。

水平拡張のサポート: JVM のメモリ管理方法では、大容量メモリの管理が比較的非効率的です。一般的に、アプリケーションはヒープ サイズを大きく構成してもパフォーマンスの向上を実現できません。 16G 以上のメモリを効果的に使用できる Java アプリケーションはほとんどありません。一方、メモリコストの低下と仮想化の普及により、大きなメモリ比率がトレンドになってきました。したがって、通常は水平拡張アプローチを採用し、複数のアプリケーション コピーを同時に展開します。リソースの使用率を向上させるために、アプリケーションの複数のコピーをコンピューティング ノードで実行できます。

準備し始める

Spring フレームワークに精通している開発者のほとんどは、Spring Petclinic にも精通しているでしょう。この記事では、この有名なサンプル アプリケーションを使用して、Java アプリケーションをより小型、高速、軽量、強力にする方法を説明します。

私たちは IBM の Michael Thompson の例をフォークし、いくつかの調整を加えました。

  1. $ git clone https://github.com/denverdino/adopt-openj9-spring-boot
  2. $ cd adopt-openj9-spring-boot

まず、PetClinic アプリケーション用の Docker イメージを構築します。 Dockerfile では、OpenJDK をベース イメージとして使用し、Maven をインストールし、Spring PetClinic アプリケーションをダウンロード、コンパイル、パッケージ化し、最後にイメージの起動パラメータを設定してイメージのビルドを完了します。

  1. $ cat Dockerfile.openjdk
  2. adoptopenjdk/openjdk8より
  3. 実行 sed -i 's/archive.ubuntu.com/mirrors.aliyun.com/' /etc/apt/sources.list
  4. apt-get updateを実行する 
  5. apt-get install -y \ を実行します
  6. git \
  7. メイヴン
  8. ワークディレクトリ /tmp
  9. git clone を実行します https://github.com/spring-projects/spring-petclinic.git
  10. ワークディレクトリ /tmp/spring-petclinic
  11. mvn install を実行
  12. ワークディレクトリ /tmp/spring-petclinic/ターゲット
  13. CMD [ "java" "-jar" "spring-petclinic-2.1.0.BUILD-SNAPSHOT.jar" ]

イメージをビルドして実行します:

  1. ビルド 1.0.1 以降では、Docker は openjdk ファイルをビルドします。
  2. $ docker run --name ホットスポット -p 8080:8080 --rm petclinic-openjdk-hotspot  
  3. |\ _,,, --,,_  
  4. /,`.- '`' ._ \-;;,_
  5. _______ __|,4- ) )_ .;.(__` '-' __ ___ __ _ ___ _______
  6. | | '---' '(_/._)-' (_\_) | | | | | | | | |
  7. | _ | ___|_ _| | | | | |_| | | | __ _ _
  8. | |_| | |___ | | | | | | | | | \ \ \ \
  9. | ___| ___| | | | _| |___| | _ | | _| \ \ \ \
  10. | | | |___ | | | |_| | | | | | |_ ) ) ) )
  11. |___| |_______| |___| |_______|_______|___|_| |__|___|_______| / / / /
  12. =================================================================/_/_/_/
  13. ...
  14. 2019-09-11 01:58:23.156 INFO 1 --- [main] osbwembedded.tomcat.TomcatWebServer: Tomcat がポート 8080 (http) でコンテキスト パス '' で起動しました 
  15. 2019-09-11 01:58:23.158 INFO 1 --- [main] osspetclinic.PetClinicApplication: PetClinicApplication を 7.458 秒で起動しました (JVM は 8.187 秒実行中)  

アプリケーション インターフェイスには、http://localhost:8080/ からアクセスできます。

ビルドされた Docker イメージを確認すると、「petclinic-openjdk-openj9」のサイズは 871 MB ですが、ベース イメージ「adoptopenjdk/openjdk8」はわずか 300 MB です。これは膨らみすぎです!

  1. $ docker イメージ petclinic-openjdk-hotspot
  2. リポジトリ タグ イメージ ID 作成サイズ 
  3. petclinic-openjdk-hotspot 最新 469f73967d03 26 時間前 871MB

その理由は、Spring アプリケーションをビルドするために、Git、Maven などの一連のコンパイル時の依存関係をイメージに導入し、大量の一時ファイルを生成したためです。ただし、これらのコンテンツは実行時には必要ありません。

有名な「ソフトウェアの 12 の要素」の 5 番目には、「ビルド段階と実行段階を厳密に分離する」と明記されています。ビルド段階と実行段階を厳密に分離することで、アプリケーションのトレーサビリティを向上させ、アプリケーション配信の一貫性を確保できるだけでなく、アプリケーションの配布サイズを縮小し、セキュリティ リスクを軽減することもできます。

鏡像痩身

Docker は、イメージのスリム化を実現できるマルチステージビルドを提供します。

イメージ構築は 2 つの段階に分かれています。

  • 「ビルド」フェーズでは、JDK が引き続きベースイメージとして使用され、Maven を使用してアプリケーションがビルドされます。
  • 最終的にリリースされるイメージでは、JRE バージョンをベース イメージとして使用し、生成された jar ファイルを「ビルド」イメージから直接コピーします。つまり、最終的にリリースされるイメージには実行時に必要なコンテンツのみが含まれ、コンパイル時の依存関係は含まれないため、イメージ サイズが大幅に削減されます。
  1. $ cat Dockerfile.openjdk-slim
  2. adoptopenjdk/openjdk8 ASビルドから
  3. 実行 sed -i 's/archive.ubuntu.com/mirrors.aliyun.com/' /etc/apt/sources.list
  4. apt-get updateを実行する 
  5. apt-get install -y \ を実行します
  6. git \
  7. メイヴン
  8. ワークディレクトリ /tmp
  9. git clone を実行します https://github.com/spring-projects/spring-petclinic.git
  10. ワークディレクトリ /tmp/spring-petclinic
  11. mvn install を実行
  12. adoptopenjdk/openjdk8: jre8u222 -b10-alpine-jre より
  13. コピー--from=build /tmp/spring-petclinic/target/spring-petclinic-2.1.0.BUILD-SNAPSHOT.jar spring-petclinic-2.1.0.BUILD-SNAPSHOT.jar  
  14. CMD [ "java" "-jar" "spring-petclinic-2.1.0.BUILD-SNAPSHOT.jar" ]

新しい画像サイズを確認してください。871 MB から 167 MB に削減されています。

  1. ビルド 1.0.1 以降では、Docker は openjdk ファイルをビルドします。
  2. ...
  3. $ docker イメージ petclinic-openjdk-hotspot-slim
  4. リポジトリ タグ イメージ ID 作成サイズ 
  5. petclinic-openjdk-hotspot-slim 最新 d1f1ca316ec0 26 時間前 167MB

イメージがスリム化されると、アプリケーションの配信速度が大幅に加速されます。アプリケーションの起動速度を最適化する方法はありますか?

JIT から AOT へ — スタートアップの高速化

Java 起動のパフォーマンスボトルネックを解決するには、まず JVM の実装原理を理解する必要があります。

「一度書けばどこでも実行できる」機能を実現するために、Java プログラムはアーキテクチャに依存しないバイトコードにコンパイルされます。 JVM は、実行時に実行するためにバイトコードをネイティブ マシン コードに変換します。この変換プロセスによって、Java アプリケーションの起動および実行速度が決まります。実行効率を向上させるために、JVM では JIT コンパイラ (Just in Time Compiler) が導入されました。その中でも、Sun/Oracle の HotSpot は最も有名な JIT コンパイラ実装です。

HotSpot は、コード実行中にクリティカル パスを動的に分析および検出し、コンパイルの最適化を実行できる適応型オプティマイザーを提供します。 HotSpot の登場により、Java アプリケーションの実行効率が大幅に向上し、Java 1.4 以降ではデフォルトの VM 実装になりました。ただし、HotSpot VM は起動時にのみバイトコードをコンパイルするため、起動時の実行効率が低下します。一方、コンパイルと最適化には多くの CPU リソースが必要となり、起動速度が低下します。このプロセスを最適化して起動速度を上げることはできますか?

Java の歴史に詳しい人なら、IBM のエンタープライズ レベルのソフトウェア製品で使用されている高性能 JVM である IBM J9 VM を知っているはずです。これにより、IBM は商用アプリケーション プラットフォーム ミドルウェアにおけるリーダーとしての地位を確立することができました。 2017 年 9 月、IBM は J9 を Eclipse Foundation に寄贈し、Eclipse OpenJ9 と改名してオープン ソースの旅を開始しました。

OpenJ9 は、Shared Class Cache (SCC 共有クラス キャッシュ) と Ahead-of-Time (AOT 事前コンパイル) テクノロジを提供し、Java アプリケーションの起動時間を大幅に短縮します。

SCC は、バイトコードとコンパイルされたネイティブ コードの J9 VM 実行分析情報を含むメモリ マップ ファイルです。 AOT コンパイルを有効にすると、JVM コンパイルの結果が SCC に保存され、その後の JVM 起動時に直接再利用できるようになります。 SCC から事前コンパイルされた実装をロードすると、起動時に JIT コンパイルするよりもはるかに高速になり、リソースの消費も少なくなります。起動時間を大幅に改善できます。

まず、AOT 最適化を含む Docker アプリケーション イメージを構築します。

  1. $ cat Dockerfile.openj9.warmed
  2. adoptopenjdk/openjdk8-openj9 ASビルドから
  3. 実行 sed -i 's/archive.ubuntu.com/mirrors.aliyun.com/' /etc/apt/sources.list
  4. apt-get updateを実行する 
  5. apt-get install -y \ を実行します
  6. git \
  7. メイヴン
  8. ワークディレクトリ /tmp
  9. git clone を実行します https://github.com/spring-projects/spring-petclinic.git
  10. ワークディレクトリ /tmp/spring-petclinic
  11. mvn install を実行
  12. adoptopenjdk/openjdk8-openj9:jre8u222-b10_openj9-0.15.1-alpineより
  13. コピー--from=build /tmp/spring-petclinic/target/spring-petclinic-2.1.0.BUILD-SNAPSHOT.jar spring-petclinic-2.1.0.BUILD-SNAPSHOT.jar  
  14. #クラスキャッシュを事前にウォームアップするためにJVM を起動および停止します
  15. /bin/sh -c 'java -Xscmx50M -Xshareclasses -Xquickstart -jar spring-petclinic-2.1.0.BUILD-SNAPSHOT.jar &' を実行します。睡眠20;追伸 | grep java | grep ペットクリニック | awk '{print $1}' | xargs キル -1
  16. CMD [ "java" "-Xscmx50M" "-Xshareclasses" "-Xquickstart" "-jar" "spring-petclinic-2.1.0.BUILD-SNAPSHOT.jar" ]

Java パラメータ -Xshareclasses は SCC を有効にし、-Xquickstart は AOT を有効にします。

Dockerfile では、SCC をウォームアップするためのトリックを使用しました。ビルド プロセス中に、JVM を起動してアプリケーションをロードし、SCC と AOT を有効にし、アプリケーションの起動後に JVM を停止します。これには、Docker イメージに生成された SCC ファイルが含まれます。

次に、Docker イメージをビルドしてテスト アプリケーションを起動します。

  1. ビルド 1.0 以降を実行している場合は、 docker を実行して、 openjdk ディレクトリにあるファイルをダブルクリックして開きます。
  2. $ docker run --name ホットスポット -p 8080:8080 --rm petclinic-openjdk-openj9-warmed-slim  
  3. ...
  4. 2019-09-11 03:35:20.192 INFO 1 --- [main] osbwembedded.tomcat.TomcatWebServer: Tomcat がポート 8080 (http) でコンテキスト パス '' で起動しました 
  5. 2019-09-11 03:35:20.193 INFO 1 --- [main] osspetclinic.PetClinicApplication: PetClinicApplication を 3.691 秒で起動しました (JVM は 3.952 秒実行中)  
  6. ...

ご覧のとおり、起動時間は 8.2 秒から 4 秒に短縮され、約 50% の改善が見られました。

このソリューションでは、時間とエネルギーを消費するコンパイル最適化プロセスをビルド時間に移行し、一方で、スペースと時間を交換する方法を使用して、事前コンパイルされた SCC キャッシュを Docker イメージに保存します。コンテナが起動すると、JVM はメモリマップされたファイルを直接使用して SCC をロードできるため、起動速度とリソース使用量が最適化されます。

この方法のもう 1 つの利点は、Docker イメージが階層化ストレージを使用するため、同じホスト上の複数の Docker アプリケーション インスタンスが同じ SCC メモリ マップを共有することになり、単一のマシン上で高密度に展開する際のメモリ消費を大幅に削減できることです。

次に、リソースの消費量を比較します。まず、HotSpot VM ベースのイメージを使用して 4 つの Docker アプリケーション インスタンスを同時に起動し、次に docker stats を使用して 30 秒後にリソースの消費量を表示します。

  1. ホットスポット4.shを実行します
  2. ...
  3. しばらくお待ちください...
  4. コンテナ ID名前CPU % メモリ使用量 / 制限 メモリ % ネット I/O ブロック I/O PID
  5. 0fa58df1a291 インスタンス4 0.15% 597.1MiB / 5.811GiB 10.03% 726B / 0B 0B / 0B 33
  6. 48f021d728bb インスタンス3 0.13% 648.6MiB / 5.811GiB 10.90% 726B / 0B 0B / 0B 33
  7. a3abb10078ef インスタンス2 0.26% 549MiB / 5.811GiB 9.23% 726B / 0B 0B / 0B 33
  8. 6a65cb1e0fe5 インスタンス1 0.15% 641.6MiB / 5.811GiB 10.78% 906B / 0B 0B / 0B 33
  9. ...

次に、OpenJ9 VM ベースのイメージを使用して、4 つの Docker アプリケーション インスタンスを同時に起動し、リソースの消費量を確認します。

  1. 実行ファイル: openj9.sh
  2. ...
  3. しばらくお待ちください...
  4. コンテナ ID名前CPU % メモリ使用量 / 制限 メモリ % ネット I/O ブロック I/O PID
  5. 3a0ba6103425 インスタンス4 0.09% 119.5MiB / 5.811GiB 2.01% 1.19kB / 0B 0B / 446MB 39
  6. c07ca769c3e7 インスタンス3 0.19% 119.7MiB / 5.811GiB 2.01% 1.19kB / 0B 16.4kB / 120MB 39
  7. 0c19b0cf9fc2 インスタンス2 0.15% 112.1MiB / 5.811GiB 1.88% 1.2kB / 0B 22.8MB / 23.8MB 39
  8. 95a9c4dec3d6 インスタンス1 0.15% 108.6MiB / 5.811GiB 1.83% 1.45kB / 0B 102MB / 414MB 39
  9. ...

HotSpot VM と比較すると、OpenJ9 シナリオでのアプリケーション メモリ使用量は平均 600 MB から 120 MB に減少しました。驚きますか?

一般的に、HotSpot JIT は AOT よりも包括的かつ詳細な実行パス最適化を実行できるため、運用効率が向上します。この矛盾を解決するために、OpenJ9 の AOT SCC は起動フェーズでのみ有効になり、その後の実行中は分岐予測やコード インライン化などの詳細なコンパイル最適化に JIT を引き続き使用します。

HotSpot もクラス データ共有 (CDS) と AOT で大きな進歩を遂げていますが、この点では IBM J9 の方が成熟しています。 Alibaba の Dragonwell が対応する最適化サポートを提供することを期待しています。

考え: C/C++、Golang、Rust などの静的にコンパイルされる言語とは異なり、Java は VM モードで実行されるため、パフォーマンスは多少犠牲になりますが、アプリケーションの移植性が向上します。 AOT を極限まで推し進めることができるでしょうか?バイトコードからネイティブコードへのコンパイルプロセスを完全に削除しますか?

ネイティブコードのコンパイル

Java アプリケーションをネイティブ実行可能コードにコンパイルするには、まず実行時の JVM とアプリケーション フレームワークの動的な課題に対処する必要があります。 JVM は柔軟なクラス ローディング メカニズムを提供し、Spring の依存性注入 (DI、Dependency-injection) により実行時に動的なクラス ローディングとバインディングを実現できます。 Spring フレームワークでは、リフレクションやアノテーション ランタイム プロセッサなどのテクノロジも広く使用されています。これらのダイナミクスにより、アプリケーション アーキテクチャの柔軟性と使いやすさが向上する一方で、アプリケーションの起動速度が低下し、AOT ネイティブ コンパイルと最適化が非常に複雑になります。

これらの課題に対処するために、コミュニティは多くの興味深い探求を行ってきましたが、Micronaut はその最も優れた代表例の 1 つです。 Spring フレームワークとは異なり、Micronaut はコンパイル時の依存性注入と AOP 処理機能を提供し、リフレクションと動的プロキシの使用を最小限に抑えます。 Micronaut アプリケーションは起動時間が短く、メモリ使用量が少なくなります。私たちにとってさらに興味深いのは、Micronaut が GraalVM との連携をサポートしており、Java アプリケーションをネイティブ実行可能コードにコンパイルしてフルスピードで実行できることです。

注: GraalVM は、Oracle がリリースした新しい汎用仮想マシンであり、複数の言語をサポートし、Java アプリケーションをローカル ネイティブ アプリケーションにコンパイルできます。

私たちの冒険を始めるには、Mitz が提供している PetClinic サンプル プロジェクトの Micronaut バージョンを使用し、いくつかの調整を行います。 (Graal VM 19.2 を使用)

  1. $ git clone https://github.com/denverdino/micronaut-petclinic
  2. $ cd マイクロノート ペットクリニック

Docker イメージの内容は次のとおりです。

  1. $ 猫 Dockerfile
  2. maven:3.6.1-jdk- 8からビルド
  3. コピー ./ /micronaut-petclinic/
  4. WORKDIR /micronaut-petclinic
  5. mvnパッケージを実行する
  6. oracle/graalvm-ce:19.2.0からgraalvmとして
  7. gu install native-imageを実行します。
  8. WORKDIR /作業 
  9. --from=build /micronaut-petclinic/target/micronaut-petclinic-*.jar にコピーします。  
  10. ネイティブイメージ--no-server -cp micronaut-petclinic-*.jarを実行します。  
  11. frolvlad/alpine-glibcより
  12. エクスポーズ8080
  13. ワークディレクトリ /app
  14. --from=graalvm /work/petclinic にコピーします。  
  15. コマンド [ "/app/petclinic" ]

で:

  • 「ビルド」フェーズでは、Mavenを使用してPetClinicアプリケーションのMicronautバージョンをビルドします。
  • 「graalvm」ステージでは、PetClinic jarファイルをnative-imageを介して実行可能ファイルに変換します。
  • 最終段階では、ローカル実行ファイルがAlpine Linuxベースイメージに追加されます。

アプリケーションをビルドします。

  1. $ docker-composeビルド

テスト データベースを起動します。

  1. $ docker-compose dbを起動します

テストアプリケーションを起動します。

  1. $ docker-compose アプリを起動する
  2. micronaut - petclinic_db_1最新です 
  3. micronaut-petclinic_app_1 を起動しています...完了
  4. micronaut-petclinic_app_1添付
  5. アプリ_1 | 04:57:47.571 [main] INFO org.hibernate.dialect.Dialect - HHH000400: 使用している方言: org.hibernate.dialect.PostgreSQL95Dialect
  6. アプリ_1 | 04:57:47.649 [main] INFO org.hibernate.type.BasicTypeRegistry - HHH000270: 型登録 [java.util.UUID] は以前のものを上書きします: org.hibernate.type.UUIDBinaryType@5f4e0f0
  7. アプリ_1 | 04:57:47.653 [main] INFO ohtuple.entity.EntityMetamodel - HHH000157: 遅延プロパティ フェッチが使用可能: com.example.micronaut.petclinic.owner.Owner
  8. アプリ_1 | 04:57:47.656 [main] INFO ohetjpiJtaPlatformInitiator - HHH000490: JtaPlatform 実装を使用しています: [org.hibernate.engine.トランザクション.jta.platform.internal.NoJtaPlatform]
  9. アプリ_1 | 04:57:47.672 [main] INFO io.micronaut.runtime.Micronaut - 起動が159ミリ秒完了しました。実行中のサーバー: http://1285c42bfcd5:8080

アプリケーションの起動速度は 159 ミリ秒に向上し、HotSpot VM の 1/50 にまで短縮されました。

Micronaut と Graal VM はまだ急速に開発が進んでおり、Spring アプリケーションを移行する際には考慮すべき作業がまだたくさんあります。さらに、Graal VM のデバッグ、監視、その他のツール チェーンはまだ完璧ではありません。しかし、これにより、Java アプリケーションとサーバーレスの世界が遠くないという希望が生まれました。

要約と追記

攻撃的な巨人として、Java テクノロジーもクラウド ネイティブ時代において絶えず進化しています。 JDK 8u191 および JDK 10 以降、JVM は Docker コンテナ内のリソース認識を強化しました。同時に、コミュニティはさまざまな方向から Java テクノロジー スタックの境界を探求しています。従来の VM のメンバーとして、JVM OpenJ9 は、既存の Java アプリケーションとの高い互換性を維持しながら、起動速度とメモリ使用量を詳細に最適化しています。 Spring などの既存のマイクロサービス アーキテクチャでの使用に適しています。

Micronaut/Graal VM は異なるアプローチを採用しています。プログラミングモデルとコンパイルプロセスを変更することで、コンパイル期間中にアプリケーションの動的な性質を可能な限り早く処理し、アプリケーションの起動時間を大幅に最適化し、サーバーレス分野で有望な将来を秘めています。これらのデザインのアイデアは学ぶ価値があります。

クラウドネイティブ時代においては、水平的なアプリケーション開発ライフサイクルにおける開発、デリバリー、運用保守の各プロセスを効果的に分割・再編成し、R&Dコラボレーションの効率を向上させる必要があります。徹底的な簡素化とシステム効率の向上を実現するには、垂直的なソフトウェア技術スタック全体において、プログラミング モデル、アプリケーション ランタイム、インフラストラクチャなどの複数のレベルでシステムの最適化を実行できる必要があります。

この時代に感謝し、私たちを助け、サポートしてくれるすべてのパートナーに感謝し、夢を追いかけるすべての技術者に感謝し、一緒にクラウドネイティブの未来を探求していきましょう。

<<:  Kafka ソースコード分析とブローカーエンドのグラフィック原理

>>:  平安科技は包括的なマルチクラウド管理能力を実証し、クラウド・トライポッド賞を受賞した。

推薦する

IBM のハイブリッド クラウド プラットフォーム: 企業にとっての価値が 2.5 倍に跳ね上がるのはなぜでしょうか?

[[354831]] 「IBM中国開発センターでは、同僚たちと私はIBMハイブリッドクラウドプラット...

Kubernetes オペレーターを構築するための原則

著者 |シルヴァン・カラシュ翻訳者 |張野貴 Kubernetes (略して K8s)上のデータ サ...

企業で働く SEO 担当者は、どうすれば SEO 目標を合理的に設定できるでしょうか?

SEO を行う人の中には、個人のウェブマスターではなく、企業にサービスを提供するタイプの人もいます。...

directspace-新しい VPS の簡単なレビュー (SSD ハード ドライブ)

Directspace に新しいバージョンの SSD ハード ディスク VPS があることを知りまし...

消費者がすぐに注文できるようにするためのマーケティング戦略をいくつか共有する

従来の考え方では、ユーザーがサイトの製品ページに長く滞在すればするほど、コンバージョン率が高くなると...

インフルエンサーマーケティングがユーザー行動に与える影響に関する4つの心理的要因の分析

月収10万元の起業の夢を実現するミニプログラム起業支援プラン最近、人気番組「The Rap of C...

ビッグシェアリング時代のSEO業界の展望

先日、友人とSEO業界の現状について話しました。SEO業界の現状は、ほとんどの人が一人で仕事をしてい...

モバイルゲームチャンネルの協力モデルが革新をもたらし、「共同運営+配信」が新たな標準に

ゲーム市場では「製品が王か」それとも「トラフィックが王か」という議論が絶えません。これまで明確な答え...

出会い系サイトの構築とプロモーションの経験を共有しましょう

近年、インターネット時代の「恋愛産業」は急速に発展し、大手企業が独自の出会い系サイトを立ち上げるよう...

ガートナーがクラウド製品評価レポートを発表:アリババクラウドのコンピューティング能力が世界第1位に

最近、国際的に有名なコンサルティング会社であるガートナーが、最新のクラウドベンダー製品評価レポートを...

フレンドリーリンク: 他の人の経験から学ぶ

みなさんこんにちは。私は長沙SEOのLong Junです。ウェブサイトの外部リンクの品質が高ければ高...

Redis 分散ロックで発生するシリアル化の問題

[[389269]]シナリオの説明最近、Redis を使用しているときに、分散ロックに似たシナリオに...

fadayun:香港+韓国+米国 - 1.1元 - 4Gメモリ/ 4コア/ 40g SSD、湖北省100G高防御クラウド - 58元 - 4Gメモリ/ 4コア/ 40g SSD / 10M帯域幅

fadayun.comは現在、ダブルイレブンプロモーションを実施しています。香港CN2、韓国CN2、...

ハイブリッドクラウドの定義と影響

[[287275]]企業がワークロードをクラウドに移行するケースが増えていますが、これまでは、規制上...