2012-03-02 35 views
1

私はWebアプリケーション用にSpring MVC 3 + Tilesを使用しています。私は操作が遅く、待ってください。Spring MVC + Apache Tilesのページをお待ちください

私の知っていること、ページをお待ちくださいするには、2つの主要なアプローチがあります。

  1. 長期性の要求:レンダリングとページのビットを「お待ちください」フラッシュが、要求を完了していないが、アクションが終了するまで、あなたはいくつかのjavascriptを使ってレスポンスの残りの部分をストリームアウトして、ページをリダイレクトまたは更新することができます。
  2. すぐに戻り、バックグラウンドスレッドで処理を開始します。クライアントはサーバーをポーリングし(JavaScriptやページの更新を介して)、バックグラウンドスレッドが終了するとリダイレクトされます。

(1)それはすべてのシングルスレッド動作を続けるといいですが、ページを組み立てて、クライアントに返される前に、各JSPがフルにレンダリング完了しなければならないとして、タイルでは可能ていないようです。

私は(2)の実装を開始しました。私の実装では、最初の要求は、@Async注釈を使用して、Future<Result>を返すバックグラウンドスレッドで操作を開始します。その後、ユーザーに「しばらくお待ちください」というページが表示され、数秒ごとに更新されます。

待機待ちページがリフレッシュされると、コントローラはバックグラウンドスレッドの進行状況を確認する必要があります。これを行う最善の方法は何ですか?

  1. 私がFutureオブジェクトをセッションに直接配置すると、ポーリング要求スレッドはスレッドをプルアウトしてスレッドの進行状況を確認できます。しかし、これは私のセッションがシリアライズ可能でないことを意味しないので、私のアプリは複数のWebサーバー(スティッキーセッションを必要とせずに)でデプロイできませんか?
  2. 私はセッションに何らかの種類のステータスフラグを入れて、終了時にバックグラウンドスレッドがセッションを更新するようにすることができます。私は非常にHttpSessionオブジェクトを非要求スレッドに渡すと、エラーをデバッグするのが難しくなることに非常に懸念しています。これは許可されていますか?誰でもどのような文書を引用することができますか?セッションがメモリ内にある場合はうまく動作しますが、セッションがデータベースに格納されている場合はどうなりますか?複数のWebサーバーがある場合はどうなりますか?
  3. 私は自分のデータベースにセッションフラグを設定したり、セッションIDをキーにしたり、遅い操作の何か他の側面を置くことができます。私のドメインデータベースにはセッションデータがありません。セッションではなく、少なくとも私はデータベースがスレッドセーフであることを知っています。
  4. もう一つの選択肢はありますか?

答えて

1

問題のSpring MVCの部分は、Spring MVCとは何の関係もないので、簡単です。この回答の可能な解決策を参照してください:https://stackoverflow.com/a/4427922/734687

コードでわかるように、著者は将来を保存するためにtokenServiceを使用しています。実装は含まれていません。ここでは、フェールオーバーが必要なときに、すでに認識しているように問題が始まります。

  • 将来をシリアル化して、2番目のサーバーインスタンスにジャンプさせることはできません。スレッドは特定のインスタンス内で実行されるため、そこにとどまる必要があります。したがって、セッションストレージはオプションではありません。
  • 例のリンクのように、トークンサービスを使用できます。これは、通常はオブジェクトを格納し、トークン(String識別子)を介して後で再度アクセスできるHashMapです。しかし、これはトークンサービスがシングルトンである場合、同じWebアプリケーション内でのみ機能します。

解決策は未来を救うのではなく、仕事の状態(作業中、終了、結果で失敗)です。クエリセッションと実行中のスレッドが異なるマシン上にあっても、状態にアクセス可能でシリアル化できる必要があります。しかし、どうやってそれをしますか?これは、データベースまたはファイルシステム(上記の例ではzipファイルが利用可能かどうかをチェックすることができます)またはキー/値ストアまたはキャッシュまたは共通オブジェクトストア(Terracota)に格納することで実装できます。 ...

実際、すべてのバッチフレームワーク(Springバッチなど)はこのように動作します。ジョブの現在の状態をデータベースに格納します。ドメインデータと操作データを混在させることに懸念があります。しかし、ほとんどのアプリケーションが行います。大規模なアプリケーションでは、2つのデータベースインスタンス、運用データとドメインデータを使用する可能性があります。

したがって、作業の状態と結果をデータベースに保存することをお勧めします。
希望に役立ちます。

+0

私は答えを(2)最初のリストから要約し、(3)を2番目のリストから要約するのは正しいですか?データベースにセッションスコープのデータがあるという主な問題が1つあります。データベースは自動的にセッションスコープではないため、デッドセッションデータをデータベースで定期的にチェックして削除するクリーンアップジョブを追加する必要があります。 2番目のリストから(2)が実行可能であると思いますか?要求されていないスレッドからSessionオブジェクトにアクセスすることが安全かどうかの証拠はありますか?スコープの不一致を避けることができます。 – Rich

+0

私は2-3に固執し、2-2に固執しません。私はセッションを更新しません。私はこれがまったく不可能だとは思わない。セッション1はサーバ1上でアクティブであり、サーバ2上のバックグラウンドスレッドもセッションを変更したいと言います。これは不可能です。 – ChrLipp

+0

通常、このアーキテクチャは次のようなものです。期間が3分未満の場合、オンラインでアクションを実行します。長い実行アクションがある場合は、その要求をデータベースに格納し、バッチスケジューラから処理させます。スケジューラーは追加のサーバー上で実行できます。セッションに何も保存する必要はありません。 – ChrLipp

関連する問題