くり しゅう
tubas****@yahoo*****
2010年 5月 17日 (月) 20:09:03 JST
矢野さま 栗本です その節はお世話になりました。 疑問に感じていた部分が無事に判明しすっきりしました。 早急な回答ありがとうございました。 --- Tsutomu Yano <t_yano****@me*****> wrote: > 矢野です。 > > そのエラーは,おっしゃるとおり,Pagemapのロックが1分以 上継続したことにより発生するものです。 > > > > 同一セッションを利用してリクエストを投げた場合に、先行 のリクエストがPagemapをロックしてしまい、先行のリクエス トが処理に1分以上かかってしまうと、 > > > Wicket側で後続のリクエストを破棄し、表記のエラーをthrow しているところまではわかっているのですが。 > > まさしくこれが回答だと思います。 > > > このエラーはPagemapというリソースの更新が競合するのを 抑止するのがひとつの目的ですが,別の目的として,重い処理 の連続起動を抑止する目的もあります。 > > Wicketはページマップ単位でユーザのリクエストを処理しま す(ページマップは,おおざっぱにいうとセッションをもう少 し細分化したもので,もともとはブラウザウインドウ単位に用 意される物でした。現在は少し違いますが)。ページマップ毎 にリクエスト処理は直列に処理されます。前のリクエストがま だ処理中であれば,次のリクエストは一定時間,前の処理の完 了を待ちます。この「一定時間」がデフォルトでは1分で,1 分たっても前の処理が終わらなければ,リクエストをアボート して例外をスローします。 > > これによって,重い処理が行われるボタンをダブルクリック した場合に,重い処理が二回三回と連続起動することを抑止し ています。 > > 重い処理の二重クリックへの対策としては > > 1. 前の処理を落として新しいリクエストを処理する > 2. 前の処理の完了を待つ > 3. > 前の処理は放置して実行させておき,新しいリクエストの処 理を開始して,ブラウザには新しい処理の結果を返す > > というくらいの選択がありますが,1 > はサーブレットコンテナのスレッドを無理矢理終了する必要 があり,3 > は,重い処理が複数個並列実行されるうえに,並列実行され ることにより正しい結果が返るかどうか不安定になるという危 険があります。結果として,Wicketには2の制御が組み込まれ ているのです。 > > いつまでも待つわけには行かないので,タイムアウト時間を 設けて,その間だけ待つことになっています。タイムアウト時 間は,IRequestCycleSettings#setTimeout(Duration)によって 変更することが出来ます。デフォルトは1分です。 > > > 結局のところ > > > > 表記の件につきまして、どういった場合にこのようなエラー が発生するのか現状良くわかっておりません。 > > > 1分以上かかる重い処理を起動するURLに,同じページマッ プで,1分以内に,複数回アクセスすることで発生します。一 番あり得るのは,あるボタンを押すと1分以上かかる重い処理 が起動するケースで,そのボタンをダブルクリックなど繰り返 しクリックした場合,です。 > > > > このエラーが出た時の対策は > > 1. > リクエストの処理に1分以上かかるのは重すぎると考えて, リクエストは処理の受付だけにとどめて,実際の処理はバック グラウンド化して,ユーザには別の画面で結果を確認出来るよ うにする > 2. > ユーザが1分でも5分でも待つのなら,敢えてタイムアウト 時間を延ばす > > のいずれかになるかと思います。ただ,2の場合は,処理は 完了するものの,ユーザのブラウザには結果を返却できない可 能性が高いです。ブラウザはすでに新しいリクエストを投げて いるので,その新しいリクエストのレスポンスを待っているか らです。 > > 現状のWicketのコードを見る限り,前述の3択対策の1つ目 は組み込まれていません。 > > > # > SessionクラスのgetPage()メソッド内でこの処理が行われて います。 > > > エラーが発生したときに「ダブルクリックしましたね? > やめてね?」という画面を表示する必要もあるでしょう。こ れは,WebApplicationクラスのnewRequestCycleProcessor()メ ソッドをオーバーライドし,独自のWebRequestCycleProcessor オブジェクトを返すことで実現できます。WebRequestCycleProcessor のonRuntimeException()メソッドをオーバーライドすると,こ のロック例外を捕捉できます。onRuntimeException()でPageオ ブジェクトを返却すると,Wicketはそのページに遷移しますの で,独自のエラー画面を返すことで適切なメッセージを表示で きます。 > > onRuntimeExceptionメソッドにはRuntimeExceptionオブジェ クトが渡されますので,getCause()メソッドで原因例外を再帰 的にたどっていき,原因がWicketRuntimeExceptionでなおかつ メッセージが「is > still locked > by」を含んでいれば,このロック例外と見なすことが出来ま す。 > > > > 補足として,ページマップについて簡単に解説しておくと, 今のWicketのデフォルト設定では,セッション=ページマップ です。複数のウインドウが同一のセッションIDで接続している 場合,すべて同じページマップになります。 > > IPageSettings#setAutomaticMultiwindowSupport(true) > を呼び出すことで,同一セッションであっても,ブラウザウ インドウ毎にページマップが分かれるようになります。この状 態ですと,あるウインドウで起動した重い処理は,別のウイン ドウで起動した重い処理をブロックしません。今回のエラーが 発生した場合でも,別のブラウザウインドウを開いて起動すれ ば,エラーが発生せずに処理が起動します。 > > 代わりに,セッションに格納されるオブジェクト数が増加す ることになりますし,重い処理が複数個起動することになりま す。 > > > 業務アプリケーションでは割と5分かかる処理をボタンで起 動してのんびり待ってる,なんてこともありますが,ウェブア プリケーションとしては,リクエストに対する返事はせめて秒 単位で返ってくるべきでしょうから,この機能とデフォルト1 分のタイムアウトというのは,割と合理的なのかな,と思いま す。 > > > という感じです。お役に立てばいいのですが。 > > > > > > On 2010/05/13, at 14:39, くり しゅう wrote: > > > 栗本です。 > > 初めて投稿させてもらいます。 > > > > > 表記の件につきまして、どういった場合にこのようなエラー が発生するのか現状良くわかっておりません。 > > > > > 同一セッションを利用してリクエストを投げた場合に、先行 のリクエストがPagemapをロックしてしまい、先行のリクエス トが処理に1分以上かかってしまうと、 > > > Wicket側で後続のリクエストを破棄し、表記のエラーをthrow しているところまではわかっているのですが。 > > > > 【発生時のログ】 > > After 1 minute the Pagemap null is still locked > by: > > Thread[http-11080-Processor12,5,main], giving up > trying to get the page for path: 156:logout > > > > > わかる方がいらっしゃいましたら、回答をよろしくお願いし ます。 > > > > > > > > > > > > 2010 FIFA World Cup News [Yahoo!Sports/sportsnavi] > > _______________________________________________ > > Wicket-ja-user mailing list > > Wicke****@lists***** > > > http://lists.sourceforge.jp/mailman/listinfo/wicket-ja-user > > _______________________________________________ > Wicket-ja-user mailing list > Wicke****@lists***** > http://lists.sourceforge.jp/mailman/listinfo/wicket-ja-user > -------------------------------------- 2010 FIFA World Cup News [Yahoo!Sports/sportsnavi] http://pr.mail.yahoo.co.jp/southafrica2010/