28

多数のコンピューターで実行されるJavaサーバーアプリケーションがあります。これらはすべてインターネットに接続されており、一部はファイアウォールの背後にあります。アプリ自体に目立った中断を与えることなく、中央サイトからJARファイルと起動スクリプトをリモートで更新する必要があります。

このプロセスは無人で誰にでもできるものでなければなりません(つまり、インターネットがタイムリーに停止したためにアプリを中断する余裕はありません)。

これまで、さまざまな外部スクリプトとユーティリティを使用して同様のタスクを処理してきましたが、それらには独自の依存関係があるため、結果の保守が難しく、移植性が低くなります。何か新しいものを作る前に、コミュニティから意見を聞きたいと思います。

誰かがこれに対する良い解決策をすでに見つけましたか?何かアイデアや提案がありますか?

明確にするために:このアプリはサーバーですが、Webアプリケーション用ではありません(ここにはWebアプリケーションコンテナーやWARファイルはありません)。これは単なる自律型Javaプログラムです。

4

9 に答える 9

10

サーバーアプリのタイプを指定していませんでした-Webアプリを実行していないと仮定します(WARのデプロイはすでにあなたが話していることを実行しており、プルタイプを実行するためにWebアプリが必要になることはほとんどありません個々のファイルの代わりに WAR ファイルの更新チェックとピンポンを実装するだけです)。

jnlp をご覧になることをお勧めします - WebStart はこれに基づいています (これはクライアント アプリケーションの展開テクノロジです) が、サーバー タイプのアプリの更新を実行するように調整できると確信しています。いずれにせよ、jnlp は、必要な JAR の必要なバージョンをダウンロードするために使用できる記述子を提供するという非常に優れた仕事をしています...

これに関するいくつかの一般的な考え (同じバケットに複数のアプリがあり、自動更新メカニズムを検討しています):

  1. アプリケーションを起動する前に、jnlp ファイルを読み取り、必要な/更新された jar をダウンロードできる bootstrap.jar ファイルを用意することを検討してください。

  2. JAR ファイルは、アプリの実行中でも更新できます (少なくとも Windows では、実行中のファイルのロックを保持する可能性が最も高い OS です)。カスタムクラスローダーを使用している場合、またはいつでもロードまたはアンロードされる可能性のあるJARがたくさんある場合、問題が発生する可能性がありますが、これを防ぐメカニズムを作成する場合は、JARを上書きしてからアプリを再起動する必要があります.更新には十分です。

  3. JAR を上書きすることは可能ですが、lib パスのピンポン アプローチを検討することをお勧めします (lib フォルダー内のすべての jar ファイルを自動読み取りして追加するようにアプリ ランチャーをまだ構成していない場合)。クラスパスを自動的に変更する場合、それはあなたが本当にやりたいことです)。ピンポンの仕組みは次のとおりです。

アプリが起動し、lib-ping\version.properties と lib-pong\version.properties を調べて、どちらが新しいかを判断します。lib-ping のバージョンが新しいとしましょう。ランチャーは lib-ping*.jar を検索し、起動中にそれらのファイルを CP に追加します。更新を行うときは、jar ファイルを lib-pong にダウンロードします (または、帯域幅を節約したいのに、JAR が実際に変更されていない場合は、lib-ping から jar ファイルをコピーします。ただし、これは努力する価値はほとんどありません!)。すべての JAR を lib-pong にコピーしたら、最後に version.properties ファイルを作成します (そうすることで、部分的な lib フォルダーになる中断された更新を検出して削除できます)。最後に、アプリを再起動すると、ブートストラップは lib-pong が目的のクラスパスであることを検出します。

  1. ping-pong as described above allows for a roll-back. If you design it properly, you can have one piece of your app that you test the heck out of and then never change that checks to see if it should roll-back a given version. That way if you do mess up and deploy something that breaks the app, you can invalidate the version. This part of the application just has to delete the version.properties file from the bad lib-* folder, then re-launch. It's important to keep this part dirt simple because it's your fail safe.

  2. You can have more than 2 folders (instead of ping/pong, just have lib-yyyymmdd and purge all but the newest 5, for example). This allows for more advanced (but more complicated!) rollback of JARs.

于 2008-09-24T05:18:29.150 に答える
6

OSGi は、これらのケース (特に組み込み製品) のためだけに作成されたものであり、多くの企業で使用されています。アプリの実行中に、jar の「バンドル」を更新したり、それらを追加および削除したりできます。私はそれを自分で使用したことがないので、オープンソースのフレームワーク/サーバーの品質についてはわかりませんが、始めるのに役立つリンクがたくさんあります:

http://www.osgi.org/Main/HomePage
http://www.aqute.biz/Code/Bnd
http://blog.springsource.com/2008/02/18/creating-osgi-bundles/
http: //blog.springsource.com/
http://www.knopflerfish.org/
http://felix.apache.org/site/index.html

于 2008-09-24T06:27:49.293 に答える
4

マルチサーバー展開にはCapistranoをお勧めします。Railsアプリをデプロイするために構築されていますが、Javaアプリケーションのデプロイに正常に使用されていることを確認しました。

リンク: Capistrano2.0はRailsだけではありません

于 2008-09-24T04:29:13.823 に答える
4

特にデータベースを更新する必要がある場合は、更新をアトミックにするのは非常に困難です。

ただし、そうでない場合は、最初に、アプリケーションが相対パスから実行できることを確認してください。つまり、アプリを特定のディレクトリに置くことができ、重要なファイルはすべてその場所からの相対パスで見つかるため、実際のインストール場所はあまり重要ではありません。

次に、インストールを複製します。これで、「実行中」のバージョンと「新しい」バージョンができました。

好きな技術 (FTP、rsync、紙テープ、ボートに浮かぶもの) を使用して、「新しい」バージョンを更新します。

インストールを検証します (チェックサム、クイック ユニット テストなど、必要なものは何でも -- 必要に応じてテスト ポートで起動することもできます)。

新しいインストールに問題がなければ、元の実行中のインスタンスを停止し、元のディレクトリの名前を変更し (mv application application_old)、新しいディレクトリの名前を変更し (mv application_new application)、バックアップを開始します。

ダウンタイムは、サーバーのシャットダウンと起動時間に短縮されます (名前の変更は「無料」であるため)。

偶然、重大なエラーを検出した場合でも、元のバージョンが残っています。新しいサーバーを停止し、名前を元に戻して、古いサーバーを再起動します。非常に高速なフォールバック。

もう 1 つの良い点は、サービス インフラストラクチャが静的であることです (rc スクリプト、cron ジョブなどのように)。これらは "application" ディレクトリを指しており、変更されません。

ディレクトリの名前を変更する代わりに、ソフトリンクを使用して行うこともできます。どちらでもいいです。

しかし、この手法は単純で、アプリケーションが連携すれば防弾に近いものです。

さて、DB の変更がある場合、それはまったく別の厄介な問題です。理想的には、DB の変更を「後方互換」にすることができれば、古いアプリケーション バージョンが新しいスキーマで実行できることを願っていますが、それが常に可能であるとは限りません。

于 2008-09-24T06:04:58.243 に答える
3

JVMがその上で実行されている間は、JARを変更できず、エラーが発生します。私は同様のタスクを試しましたが、私が思いついた最善の方法は、更新されたJarのコピーを作成し、起動スクリプトを移行してそのJarを確認することです。更新されたJarを入手したら、それを起動し、古いJarが終了するのを待ってから、そうするように信号を送ります。残念ながら、これはGUIなどが1秒間失われることを意味しますが、Javaでほとんどの構造をシリアル化するのは簡単で、実際に閉じる前に現在のGUIを更新されたアプリケーションに転送できます(ただし、シリアル化できないものもあります)。

于 2008-09-24T04:30:04.397 に答える
3

ansible を使用して複数のサーバーに jar を配布し、更新スクリプトを実行します。

更新がユーザーに気付かれないようにするには、アプリケーションは古いインスタンスを停止して新しいインスタンスを非常に迅速に起動する必要がありますが、これには Java アプリはあまり適していません。

ダウンタイムなしで更新する方法はありますが、どれも無料ではありません。ソリューションを選択する際は、許容できるダウンタイムと、それを達成するために許容できるコストを検討する必要があります。

2 つのオプションが表示されます。

  1. ローリング更新。つまり、更新するたびに新しいバージョンでインスタンスをスピンアップし、正常に動作しているかどうかを検証し、正常に動作している場合は古いバージョンを強制終了します。このソリューションには、トラフィックを有効なインスタンスに転送するある種のプロキシ (haproxy など) が必要です。
  2. アプリケーションの起動時間を最適化します。

Will Hartung が述べたように、データベース スキーマなどの外部依存関係も考慮する必要があります。これも更新する必要があります。シームレスな更新を取得するために、データベースでローリング更新を実行することもできます。アプリケーションの 2 つの連続したリリースの間に重大な変更を導入しないようにする必要があります。例えば。列を削除する場合、最初のリリースではアプリケーション内の列へのすべての参照を削除し、次のリリースではデータベース内の列を削除できます。

于 2020-07-21T18:04:42.083 に答える
2

SpringSource dm Serverのような OSGi ベースのアプリ サーバーを使用すれば、JAR ファイルをホット デプロイできると思います。私自身は使用したことがありませんが、Spring ポートフォリオの一般的な品質を知っているので、一見の価値があると確信しています。

于 2008-09-24T05:25:55.247 に答える
0

最新バージョンのJavaWebStartでは、実際にプログラムを呼び出さなくてもローカルキャッシュにアプリケーションを挿入でき、「オフライン」としてマークを付けることができます。キャッシュはプログラムを呼び出すために使用されるものであるため、次回の実行時にのみ更新されます。これを機能させるには、名前にバージョン番号が含まれるjarが必要になる可能性があります(例:our-library-2009-06-01.jar)。

于 2009-06-01T16:03:27.077 に答える
0

OSGi の更新システムである Eclipse を使用しており、経験は非常に優れています。

おすすめされた!

于 2008-09-24T07:36:44.747 に答える