Java 開発者のための Heroku の概要
この記事の英語版に更新があります。ご覧の翻訳には含まれていない変更点があるかもしれません。
最終更新日 2019年12月16日(月)
Table of Contents
従来の Java EE アプリケーションサーバー上でアプリケーションを開発、デプロイ、運用するエンタープライズ Java 開発者またはサーバー管理者にとって、このガイドは Heroku で Java アプリケーションを開発およびデプロイする方法を理解するために役立ちます。
デプロイ用にビルドされるアプリケーション
Heroku は、アプリケーションの開発およびデプロイ用に明示的に設計されたプラットフォームです。これは、次のような流れをたどる “従来の” ソフトウェア配信プロセスとは異なります。
- 開発
- パッケージ化
- 配布
- インストール
- デプロイ
Heroku は、1 つのチームまたは複数のチーム内でアプリケーションを開発、デプロイ、運用する組織によって使用されます。コードがチームまたは組織を離れることはないため、パッケージ化、配布、またはインストールの要素はありません。これは Heroku がより俊敏である主な理由であり、これを念頭に置くと、Heroku をデプロイプラットフォームとして最適に使用する方法を決定することが容易になります。
デプロイ用にビルドされるアプリケーションは、配布用にビルドされるアプリケーションとは次のいくつかの領域で異なります。
バージョン管理が中心的な配布メカニズムである
外部の関係者が消費できるコードのパッケージをビルドする理由はありません。WAR、EAR、.exe インストーラ、または tarball は必要ありません。アプリケーション成果物が構造化される方法を自由に選択できます。通常、ランタイムは、ビルドプロセスによって生成されたファイル構造から直接アプリケーションを実行します。
設定をコードから外部化する必要がない
配布を目的にしたアプリケーションをビルドするときは多くの場合、コンシューマーに、デプロイ中にアプリケーションを設定するための柔軟性の高い方法を提供する必要があります。このことが、多数の XML ファイルを必要とすることの多い、設定のための非常に高度 (かつ複雑) なフレームワークにつながりました。アプリケーションの動作を外部の設定から大幅に制御できるようにすると、テストが非常に困難になり、予期される動作は開発者 (やオペレーター) がさらに理解しにくくなります。
デプロイ用にビルドされるアプリケーションにはこの要件がないため、この複雑さのすべてを解消し、代わりにコード内で (すべてではないにしても) ほとんどの設定を行うことができます。コード内で設定を行うことにより、コンパイル時のチェックを利用できるため、一般にはテストがはるかに容易になります。これが、俊敏性の向上と、配信プロセスの堅牢性につながります。このアプローチに向けた動向は、Guice などのより新しいフレームワークが設定ファイルを使用せず、Spring や Java EE などのより古いフレームワークがそこから離れているようすで確認することができます。
デプロイが高度に自動化されたパイプラインプロセスである
アプリケーションのエンドツーエンドのライフサイクルが 1 つのチームまたは組織によって所有および制御されるため、バージョン管理や標準のビルド自動化ツールを利用して配信プロセスを部分的または完全に自動化できます。これは、アプリケーション配信の俊敏性と堅牢性を向上させる上でのもう 1 つの重要な要因です。このパイプラインは、コードのコミットから一連のテスト段階を通って、新しいバージョンのリリースに進みます。自動化は多くの場合、継続的インテグレーションサーバーなどのツールによって支援された、プロジェクトのビルドシステムによって駆動されます。
Heroku でのエンタープライズ Java アプリケーション
Java EE の仕様では、デプロイ用のビルドより、配布用のビルドの方にはるかに近いアプリケーション配信プロセスが定義されます。これにより、アプリケーションを純粋にデプロイ用にビルドするときには必要のない、コンテナに依存しない設定、パッケージ化、アプリケーションのインストールと設定などのいくつかの概念が導入されます。時間の経過と共に、同じ Java EE API のすべてを使用するが、パッケージ化、配布、設定の各部分は使用しない、デプロイ用にビルドされるアプリケーションを設計するためのパターンやベストプラクティスが現れてきました。これらの習慣には、次のものが含まれます。
- アプリケーションはアプリケーションサーバーにデプロイされません。代わりに、自身をブートストラップし、アプリケーションコードで必要なすべてのサービスを設定します。この設定を支援するために IoC コンテナを使用する場合もあります。Jetty Web サーバーは、このアプローチの最前線に位置してきました。また、Tomcat も埋め込み可能です。
- サーブレットスタック、JDBC ドライバー、JSP などのライブラリやその他の Java EE ライブラリは、コンテナによって提供されるのではなく、依存関係管理を使用してアプリケーションにリンクされます。
- 外部の設定ファイルは、実際に必要性がないため、使用は最小限に抑えられます。
- コンテナ、サーブレット、JSP、JDBC が存在せず、JMS が最も一般的なサービスである場合でも、多くの Java EE サービスが引き続き使用されます。
Heroku は、Java の開発とデプロイに関してこのモデルに従います。Java EE ライブラリを必要な数だけ使用できます。ただし、アプリケーションはパッケージ化や配布ではなく、継続的なデプロイのために構成されます。
アプリケーションはコンテナなしで Java EE API をどのように使用するのですか?
Java EE API を使用する方法を示すいくつかの例を次に示します。
- 埋め込み Tomcat または Jetty ライブラリを使用して、サーブレットや JSP を記述できます。
- JSF や、Mojarra または MyFaces を使用するその他のレンダリングフレームワークを使用できます。
- javax.mail を使用して、Heroku Add-ons カタログにあるような外部の SMTP サービスの上にメール機能を構築できます。
- JDBC を使用して、Heroku Postgres サービスなどのデータベース、またはいずれかの MySQL アドオンに接続できます。
- Hibernate または DataNucleus JPA を使用して、SQL データベースまたは Database.com に基づいた ORM 永続性サービスを提供できます。
アプリケーションサーバーによって提供されるその他の多くの点についてはどうですか?
アプリケーションサーバーの主な目的は、アプリケーションのデプロイや操作のためのサービスを提供することです。これらの機能には、次のものがあります。
- デプロイ
- 起動/停止/再起動
- 変更のデプロイ
- クラスタリング (スケーリング)
- 負荷分散
- フェイルオーバーと高可用性
- ログ記録
- サービスのバインディング
アプリケーションを Heroku などのクラウドプラットフォームにデプロイすると、そのクラウドプラットフォームは、これらのすべての機能を提供する役割を担います。これらの機能を手に入れるために “独自の WebLogic または WebSphere サーバーを導入する” 必要はありません。これらは、クラウドプラットフォームの組み込みの一部です。
では、これらの各機能と、一般的な Java EE アプリケーションサーバーと比較して Heroku がどのように動作するかを見てみましょう。
デプロイ
Java EE アプリケーションサーバー
- WAR または EAR としてパッケージ化する
- さまざまなツールを使用してサーバーにアップロードする
- オプションで、サーバーコンソールで追加の設定を実行する
Heroku
Git ベースのワークフローです。
$ git push heroku master
起動/停止/再起動
Java EE アプリケーションサーバー
コンソールまたは API コマンドを使用して、アプリケーションを起動/停止/再起動します。サーバーとアプリケーションは同じ JVM 内で実行されるため、アプリケーションの再起動では多くの場合、エラーが発生しやすくなります。
Heroku
$ heroku restart
アプリケーションは、それぞれが独自の (相互に完全に分離された) dyno で実行されている個別の JVM で動作します。これにより、再起動が他のアプリケーションに悪影響を与えることはなく、非常に堅牢になります。これは、メモリやその他のリソースを共有している他の Java EE アプリケーションと同じプロセスで実行される Java EE アプリケーションの再起動とは対照的です。
変更のデプロイ
Java EE アプリケーションサーバー
- WAR または EAR に変更をパッケージ化する
- さまざまなツールを使用してサーバーにアップロードする
- コンソールまたはスクリプトを使用して、ダウンタイムを最小限に抑えるためのいくつかの戦略のうちの 1 つに従って再デプロイを実行する
Heroku
再デプロイは、単にコードを Heroku にもう 1 回プッシュするだけです。
$ git push heroku master
Heroku は自動的にアプリをビルドし、それを新しい dyno にデプロイして、既存の dyno を破棄します。
クラスタリング (スケーリング)
Java EE アプリケーションサーバー
複雑で、かつ非常にアプリサーバー固有の設定が必要です。クラスタリングは多くの場合、NAS や SAN などの共有ファイルシステムに依存します。Java EE アプリサーバーは多くの場合、追加の設定が必要な、クラスター全体にわたる複製を伴うステートフルセッションをサポートしています。
Heroku
Heroku アプリケーションは、1 つのコマンドでスケーリングされます。
$ heroku ps:scale web=2 worker=4 ...
Heroku は、ノード (dyno) の起動および停止を処理します。Heroku では、セッションの複製はサポートされていません。Heroku には、アプリケーションの設定やスケーリングを簡単にするシェアナッシングアーキテクチャがありますが、アプリケーションがこのアーキテクチャ用に設計されている必要があります。アプリケーションロジックがステートフルセッションに依存することはできません。
負荷分散
Java EE アプリケーションサーバー
負荷分散はほとんどの場合、個別に設定する必要がある外部のロードバランサーを使用して実現されます。通常、アプリサーバーのクラスターの前にロードバランサーを設定することは運用チームの責任です。
Heroku
負荷分散は自動的に行われます。アプリケーションをスケールアップまたはスケールダウンすると、個々のノード (dyno) がルーティングインフラストラクチャに自動的に登録または登録解除されます。リクエストは、ラウンドロビンを使用してアプリケーションノード (dyno) にルーティングされます。Heroku はセッションアフィニティをサポートしていますが、これはデフォルトでは有効になりません。
フェイルオーバーと高可用性
Java EE アプリケーションサーバー
アプリケーションサーバーは多くの場合、応答しなくなったノードを検出し、トラフィックを他のノードにルーティングできます。ただし、ノードを自動的には再起動しません。また、OS またはハードウェアレベルで発生する問題にも対応できません。これには、追加の監視ツールが必要です。負荷分散機能と統合して障害が発生したノードを検出できるようにすることはユーザーの責任です。
Heroku
Heroku は、アプリケーション内のノードがクラッシュしたかどうかを検出した後、それを再起動しようとします。再起動によって、完全に新しいノードのプロビジョニングがトリガーされます。つまり、OS レベル、場合によってはハードウェアレベルでの問題を再起動によって克服できます。Heroku はハードウェアノードを個別に監視して、停止したインスタンスを自動的に破棄し、それらのインスタンスによってホストされているノードを新しいインスタンスに移行します。
ログ記録
Java EE アプリケーションサーバー
ログサービスは、アプリケーションサーバーで設定されます。このサーバーは、ログのある程度のルーティングやログファイルのローテーションを実行できます。また、アプリケーションサーバーに、ログの検索やフィルター処理のための UI が用意されている場合もあります。サーバーで設定されているログサービスにバインドして使用するには、アプリケーションが適切に設定されている必要があります。
Heroku
アプリケーションは、ログイベントを標準出力に送信することが予測されます。Heroku は、標準出力で受信されたログイベントを Logplex にストリーミングします。アプリケーション所有者は、これらのストリームを消費する任意の数の “シンク” を設定できます。アプリケーションレベルで必要な設定はありません。
サービスのバインディング
Java EE アプリケーションサーバー
アプリケーションサーバーは、デプロイ記述子 (複数)、サーバーコンソール、JNDI ディレクトリサービスの組み合わせを使用して、アプリケーションがサービスにバインドする方法を設定します。
Heroku
サービスの設定は、OS 環境変数として提供されます。アプリケーションは、これらの変数を読み取り、接続パラメータに基づいてコネクターを適切に設定する役割を担います。これには Spring 設定ファイルなどの設定ファイルを使用できますが、さらに簡単なアプローチは、ブートストラップコードセグメントから設定を行うことです。
まとめ
ここまでの説明により、従来のエンタープライズ Java 開発と比較して Heroku がどのように動作するかについての詳細が明らかになりました。さらに学習するための最善の方法は試してみることです。