8

私たちは Java EE でのミッション クリティカルなアプリケーションの開発を検討しています。私が本当に感銘を受けたことの 1 つは、プラットフォームにセッション分離がないことです。シナリオを説明しましょう。

私たちはネイティブ Windows アプリケーション (完全な ERP ソリューション) を持っており、まばらな貢献者から毎月約 2,000 の LoC と 50 のバグ修正を受け取ります。スクリプトもサポートしているため、顧客は独自のロジックを追加できますが、そのようなロジックが何をするかについてはわかりません. スレッド プールを使用する代わりに、各サーバー ノードにはブローカーとプロセス プールがあります。ブローカはクライアントのリクエストを受信し、プールされたインスタンスが解放されるまでそれをキューに入れ、そのインスタンスにリクエストを送信し、クライアントにレスポンスを配信して、インスタンスをプロセス プールに解放します。

非常に多くのまばらなコントリビューションとカスタム スクリプトにより、展開されたバージョンに無限ループ、長時間待機する悲観的ロック、メモリ破損、メモリ リークなどの深刻なバグが発生することは珍しくありません。メモリ制限、リクエストのタイムアウト、シンプルなウォッチドッグを実装しました。一部のプロセスが時間通りに正しく応答しない場合は常に、ブローカーは単純にそのプロセスを強制終了するため、ウォッチドッグは別のインスタンスを検出して開始します。プロセスがリクエストへの応答を開始する前にクラッシュした場合、ブローカーは同じリクエストを別のプールされたインスタンスに送信し、ユーザーはサーバー側での障害について知りません (管理者ログを除く)。一部のインスタンスは、リクエストを処理するときに偽のコードによってゆっくりと破棄されるため、これは便利です。

現在、Java EE への移行を検討していますが、Glassfish や JBoss などの仕様や一般的なアプリケーション サーバーで同様のものを見つけることができませんでした。はい、ほとんどのクラスター実装がセッション レプリケーションを使用して透過的なフェールオーバーを行うことは知っていますが、単純な 2 ノード クラスターでシステムを使用する小さな会社があります (また、1 ノード サーバーでシステムを使用する冒険家もいます)。 . スレッドプールを使用すると、バグのあるスレッドがノード全体をダウンさせる可能性があることを理解しています。これは、サーバーがスレッドを検出して安全に強制終了できないためです。ノード全体をダウンさせることは、単一のプロセスを強制終了することよりもはるかに最悪です。各ノードに約 100 のプールされたプロセス インスタンスがある展開があります。

私は、IBM と SAP がこの問題を認識していることを知っています。

、 それぞれ。しかし、最近の JSR、フォーラム、およびオープンソース ツールに基づくと、コミュニティでの活動はあまりありません。

それでは質問です!

  1. 同様のシナリオで Java EE を使用している場合、どのように解決しましたか?

  2. この問題に対処できる、今後のオープンソース製品または Java EE 仕様の変更について知っていますか?

  3. .NET にも同じ問題がありますか? 参考文献を説明または引用できますか?

  4. この問題に対処でき、ERP ビジネス ロジックを実行する価値のある最新のオープン プラットフォームについて知っていますか?

お願いしますが、これ以上のテストや QA への投資については言わないでください。なぜなら、私たちはお客様に独自のスクリプトでこれを行うように強制することはできないからです. また、緊急のバグ修正が QA をバイパスしなければならない場合もあり、顧客にこれを受け入れるように強制しますが、バグのあるソフトウェア部分がさまざまな無関係な機能に影響を与える可能性があることを顧客に受け入れさせることはできません. これは、開発プロセスではなく、堅牢なアーキテクチャに関する問題です。

ご清聴ありがとうございました!

4

3 に答える 3

6

あなたが遭遇したのは、Javaと「敵対的な」アプリケーションの使用に関する根本的な問題です。

これは、Java EEレベルだけでなく、コアJVMレベルでも根本的な問題です。利用可能な一般的なJVMには、「安全でないコード」のロードに関するあらゆる種類の問題があります。メモリリーク、クラスローダーのリーク、リソースの枯渇、クリーンでないスレッドキルなど、一般的なJVMは、共有環境で正常に動作しないコードを処理するのに十分な堅牢性を備えていません。

簡単な例は、Javaヒープのメモリ枯渇です。基本的なルールとして、NOBODY(そして誰もが特にコアJavaライブラリとそこにある他のほぼすべてのサードパーティライブラリを意味します)はOutOfMemory例外をキャッチします。そうすることはめったにありませんが、彼らでさえそれについてほとんど何もできません。典型的なコードは、処理することを「期待する」例外を処理しますが、他の人は失敗します。ランタイム例外(OOMが1つ)は、コールスタックを介して一番上までうまくバブルし、チェックされていないクリティカルパスコードの残骸を残し、あらゆる種類のものを不明な状態のままにします。

「失敗できない」コンストラクターや静的初期化子など、「決してnullではない」初期化されていないクラスメンバーを残します。これらの破損したクラスは、単に破損していることを知りません。それらが損傷していることを誰も知らず、それらをクリーンアップする方法はありません。OOMにヒットするヒープは安全でないイメージであり、ほとんど再起動する必要があります(もちろん、すべてのコードを自分で作成または監査した場合を除きます。当然、誰がそうしますか?)。

さて、より適切に動作し、より適切に制御できるベンダー固有のJVMが存在する可能性があります。Sun / Oracle JVMに基づくもの(つまり、それらのほとんど)はそうではありません。

したがって、これは必ずしもJava EEの問題ではなく、JVMの問題です。

JVMで敵対的なコードをホストすることは悪い考えです。それが実用的な唯一の方法は、スクリプト言語をホストし、そのスクリプト言語が何らかのリソース制御を実装している場合です。それは可能であり、最初に既存のもの(JavaScript、Groovy、JPython、JRuby)を微調整することができます。これらの言語がユーザーにJavaライブラリへの直接アクセスを提供するという事実は、それらを潜在的に危険なものにするため、スクリプトハンドラーによってラップされた側面のみに制限する必要があるかもしれません。ただし、この時点で、「なぜJavaを使用するのか」という質問が浮かび上がります。

GoogleAppEngineはこれらのいずれも実行しないことに注意してください。実行中のアプリケーションごとに個別のJVMをスプールしますが、それでも、特に既存のJavaセキュリティモデルを介して、それらのJVM内で実行できることを大幅に制限します。ここでの違いは、これらのインスタンスは、起動とシャットダウンの処理コストに耐えられないように「長寿命」になる傾向があることです。私は言うべきです、彼らは長生きするべきであり、そうでない人はそれらの費用を負担します。

JVMのいくつかのインスタンスを自分で作成し、ロジックの要求を処理するためのインフラストラクチャを少し与え、クラスローダーのリークから保護するためのカスタムクラスローダーロジックを与え、最小限にインスタンスを強制終了させることができます(単純にプロセス)必要に応じて。これは機能する可能性があり、呼び出しの粒度とロジックの「起動」時間によっては、おそらく「正常」に機能します。起動時間は、最小限、実行から実行へのロジックのクラスのロードであり、それだけでこれは悪い考えになる可能性があります。そして、それは確かに「JavaEE」ではありません。Java EEは、この種のことを行うように設定されていません。しかし、どのJavaEE機能を見ているのかはっきりしていません。

事実上、これはApacheと「mod_php」が行うことです。プロセスとしてのいくつかのインスタンスは、リクエストを個別に処理し、必要に応じて一度強制終了されると、動作が悪くなります。これが、PHPが共有ホスティングビジネスで一般的である理由です。この構造では、基本的に「安全」です。

于 2011-03-09T20:56:10.673 に答える
0

あなたのシナリオは非常に典型的ではないと思います。したがって、このニーズに対応する既製のフレームワーク/プラットフォームがあるとは考えにくいです。Java EE は、リクエスト処理コードがアプリの残りの部分と同じチームによって記述されていることを想定しているため、頻繁に分離、監視、リセットする必要はなく、バグ修正はアプリケーションのすべての部分で同じ方法で処理されます。システム。この前提により、ほとんどのプロジェクトの開発、展開、テストなどが大幅に簡素化され、必要のないものにお金を払う必要がなくなります。もちろん、すべての人に適しているわけではありません。根本的に異なるものが必要な場合は、かなりの量のフェイルオーバー ロジックを自分で実装する必要があります。ただし、Java EE はこのための基本的なビルディング ブロックを提供します。

私は (それを証明する具体的な経験はありませんが) .NET やその他のプラットフォームは基本的に同様の想定に基づいて構築されていると考えています。

于 2011-03-09T20:23:07.043 に答える
0

私たちは、非常に巨大な Perl サイトの Java への同様の移植 (それほど深刻ではありませんが) を行いました。HTTP リクエストを受信すると、クラスをインスタンス化し、その processRequest メソッドを呼び出します。try-catch と時間測定に囲まれています。スレッドを強制終了するには、タイマーとスレッドを追加するだけで十分です。実生活ではこれで十分でしょう。

Glassfish のような Java EE サーバーは、より多くの分離手段を持つ可能性のある OSGi コンテナーです。

また、中央の Web アプリケーションを介してリクエストをディスパッチする一連の (Web またはローカル) アプリケーションを実行することもできます。これらのアプリケーションは分離されます。

さらに分離されているのは、シリアル化されたセッションと、新しい JVM を開始するオペレーティング システム プロセスです。

于 2011-11-23T14:39:42.463 に答える