10

このエラーは私を夢中にさせています。Apache と Tomcat を実行するサーバーがあり、複数の異なるサイトにサービスを提供しています。通常、サーバーは正常に動作しますが、間違ったページ (他の誰かが要求したページ) が表示されるというエラーが発生することがあります。

手がかり:

  • 配信されているページは、別のユーザーが最近要求したページであり、それ以外は正しく配信されています。2 つの同時リクエストがスワップされることが知られています。私が知る限り、誤って配信されたページはどれも、数分以上前のものではありません.
  • Tomcat によって提供されているファイルにのみ影響します。画像などの静的ファイルは影響を受けません。
  • それはいつも起こるわけではありません。それが起こるとき、それは誰にとっても起こります。
  • 需要のピーク時に発生するようです。ただし、需要はまだそれほど高くはありません。Apache が対処できる範囲内にあることは確かです。
  • Tomcat を再起動すると修正されましたが、数分間だけでした。Apache を再起動すると修正されましたが、数分間だけでした。
  • サーバーは、Gentoo で Java 6 VM を使用して、Apache 2 と Tomcat 6 を実行しています。接続は AJP13 で、ブロックJkMount内のディレクティブ<VirtualHost>は正しいです。
  • ログファイルには何も役に立ちません。

さらに詳しい情報:

Apache では、いかなる形式のキャッシュも有効になっていません。httpd.conf および関連するインポート内のキャッシュ関連のすべてのエントリは、たとえば次のようになります。

<IfDefine CACHE>
  LoadModule cache_module modules/mod_cache.so
</IfDefine>

Apache のオプションにはそのフラグが含まれていませんが、次のようになります。

APACHE2_OPTS="-D DEFAULT_VHOST -D INFO -D LANGUAGE -D SSL -D SSL_DEFAULT_VHOST -D PHP5 -D JK"

同様に、Tomcat にはキャッシュ オプションがオンになっていません。

ツールキットの提案は良かったのですが、この場合は適切ではありませんでした。エラーが自分のコード内にあるはずがないと信じるようになったのは、転送されているのは単なるいくつかの値ではなく、URL、パラメーター、セッション Cookie、すべてを含む要求全体であるということです。明らかにログインしていないのに、「あなたは John としてログインしています」というページが戻ってきます。


アップデート:

何人かからの提案に基づいて、Tomcat が提供するページに次の HTTP ヘッダーを追加して、すべての形式のキャッシュを無効にします。

Cache-Control: no-store
Vary: *

これらのヘッダーが Apache だけでなく、他のキャッシュやプロキシによっても尊重されることを願っています。残念ながら、このエラーを意図的に再現する方法はありません。そのため、再び発生するかどうかを確認する必要があります。

次のヘッダーが含まれていることに気付きました。これらは何らかの形で関連している可能性がありますか?

Connection: Keep-Alive
Keep-Alive: timeout=5, max=66

アップデート:

どうやらこれは私が眠っている間に再び起こったようですが、今は起こらなくなりました。繰り返しますが、私が見ることができるログには何も役に立たないので、実際に何が起こっていたのか、またはそれを防ぐ方法についての手がかりがありません.

これを診断しやすくするために、Apache または Tomcat のログに追加できる情報はありますか?


アップデート:

これが数回繰り返されたため、Apache が Tomcat に接続する方法を変更して、影響があるかどうかを確認しました。mod_jk次のようなディレクティブを使用していました。

JkMount /portal ajp13

mod_proxy_ajp次のように、 を使用するように切り替えました。

ProxyPass /portal ajp://localhost:8009/portal

違いがあるかどうかを確認します。このエラーは常に厄介なほど予測不可能であったため、機能したかどうかを明確に判断することはできません.


アップデート:

を使用していたサイトで一時的にエラーが発生しましたが、 を使用mod_jkしている同じサーバー上の姉妹サイトでmod_proxy_ajpはエラーが表示されませんでした。これは何も証明しませんが、切り替えmod_proxy_ajpが助けになった可能性があるという証拠を提供します.


アップデート:

昨夜、 を使用しているサイトで再びエラーが発生したmod_proxy_ajpので、明らかに解決していませんmod_jk。問題の原因ではありませんでした。永続的な接続をオフにするという匿名の提案を試してみます。

KeepAlive Off

それでもダメなら、必死になってGlassFishの調査を始めます。


アップデート:

くそっ!問題はすぐに戻ってきました。しばらく見てなかったので、やっと整理できたかなと思い始めていました。私はハイゼンバグが嫌いです。

4

11 に答える 11

6

サーブレットのスレッドセーフでしょうか?

サーブレットはインスタンス メンバーに情報を保存しますか。

たとえば、次のような単純なことで、スレッド関連の問題が発生する可能性があります。

public class MyServlet ... {
    private String action;

    public void doGet(...) {
         action = request.getParameter("action");
         processAction(response);
    }

    public void processAction(...) {
         if (action.equals("foo")) {
             // send foo page
         } else if (action.equals("bar")) {
             // send bar page
         }
     }
}

サーベットは複数のスレッドによってアクセスされるため、アクション インスタンス メンバーが誰かのリクエストによって破壊されず、間違ったページを送り返すという保証はありません。

この問題の簡単な解決策は、インスタンス メンバーの代わりにローカル変数を使用することです。

public class MyServlet ... {
    public void doGet(...) {
         String action = request.getParameter("action");
         processAction(action, response);
    }

    public void processAction(...) {
         if (action.equals("foo")) {
             // send foo page
         } else if (action.equals("bar")) {
             // send bar page
         }
     }
}

注:ビューのためにそれらにディスパッチしていた場合、これは JavaServer Pages にも拡張されますか?

于 2008-10-29T12:14:51.370 に答える
3

ヘッダーが正しいVaryHTTP ヘッダーなしでキャッシュを許可しているかどうかを確認します (たとえば、セッション Cookie を使用し、キャッシュを許可する場合は、VaryHTTP ヘッダーに Cookie ヘッダーのエントリが必要です。または、キャッシュ/プロキシがキャッシュされたバージョンのあるユーザーから別のユーザーへのページ)。

問題は Web サーバー上のキャッシュではなく、キャッシュの別の層 (Web サーバーの前のリバース プロキシ、またはユーザーの近くのプロキシ) にある可能性があります。クライアントが NAT の背後にある場合は、透過プロキシの背後にもある可能性があります (また、デバッグをさらに難しくするために、透過プロキシがヘッダーに表示されないように構成されている可能性があります)。

于 2008-10-29T23:00:11.927 に答える
2

セットアップで mod_cache が有効になっていないと述べましたが、mod_cache を有効にして (静的コンテンツであっても) 同じ問題に遭遇した可能性がある他の人にとって、解決策は Set-Cookie HTTP ヘッダーで次のディレクティブが有効になっていることを確認することです。

CacheIgnoreHeaders Set-Cookie

mod_cache である理由は、他のユーザーに提供される可能性のある Set-Cookie ヘッダーをキャッシュします。これにより、最後にキャッシュをいっぱいにしたユーザーから別のユーザーにセッション ID が漏洩します。

于 2011-01-24T19:25:15.983 に答える
2

質問の8回の更新後、テスト/再現に使用するもう1つの問題がありますが、公開サイトでは難しい(または費用がかかる)場合があります。

サイトで https を有効にすることができます。これにより、少なくとも途中で他のプロキシキャッシュが消去されます. トラフィックを妨害する忘れられたロードバランサーや会社のキャッシュが途中にあるのを見るのは悪いことです.

公開サイトの場合、これは鍵の信頼できる証明書を意味するため、いくらかの費用がかかります。自己署名鍵のテストには十分かもしれません。また、トラフィックを復号化して再暗号化する透過プロキシが含まれていないことを確認してください。(元のサーバーと同じ証明書/キーを使用できないため、簡単に検出できます)

于 2009-04-19T07:06:09.640 に答える
1

私はこの問題を抱えていました、そしてそれは本当に私を狂わせました。理由はわかりませんが、http.confでKeepAliveをオフにして解決しました

から

キープアライブオン

キープアライブオフ

私のアプリケーションはキープアライブ機能を使用していないので、非常にうまく機能しました。

于 2009-01-26T07:08:57.463 に答える
1

これを試して:

response.setHeader("Cache-Control", "no-cache"); //HTTP 1.1
response.setHeader("Pragma", "no-cache"); //HTTP 1.0
response.setDateHeader("Expires", 0); //prevents caching at the proxy server
于 2009-04-19T05:59:35.807 に答える
1

このサイトを見てください。mod_jk の問題について説明しています。非常によく似た問題を見ているときに、あなたの投稿に出くわしました。基本的に、修正は mod_jk の新しいバージョンにアップグレードすることです。サーバーに変更を実装する機会はまだありませんが、明日これを試して、役立つかどうかを確認します.

http://securitytracker.com/alerts/2009/Apr/1022001.html

于 2009-06-17T01:42:52.900 に答える
0

キャッシュの問題ではない可能性があります。apache2.confのMaxClientsパラメーターを増やしてみてください。低すぎる場合(デフォルトでは150?)、Apacheはリクエストのキューイングを開始します。mod_proxyを介してキューに入れられたリクエストを処理することを決定すると、間違ったページが表示されます(または、すべてのキューイングを実行することにストレスがかかる可能性があります)。

于 2010-03-26T20:35:43.100 に答える
0

私は専門家ではありませんが、奇妙なネットワーク アドレス変換の問題でしょうか?

于 2008-10-29T17:28:30.520 に答える
0

誰かがリクエストしたページ、またはパラメータのないページであると確信していますか? apache の背後にある tomcat サーバーの server.xml で connectionTimeout が短すぎると、奇妙なエラーが発生する可能性があります。値を大きくしてください:

デフォルト設定:

  <Connector port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443" />

かわった:

  <Connector port="8080" protocol="HTTP/1.1"
               connectionTimeout="2000000"
               redirectPort="8443" />
于 2012-07-07T14:11:30.480 に答える
0

Apache を AJP によるプロキシから HTTP によるプロキシに切り替えました。これまでのところ、問題は解決したか、少なくとも大幅に軽減されたようです。問題は数か月間報告されておらず、それ以来、アプリの使用が増加しています.

変更は Apache の httpd.conf にあります。から始めてmod_jk

JkMount /portal ajp13

に切り替えましたmod_proxy_ajp

ProxyPass /portal ajp://localhost:8009/portal

次に、最後にストレートにmod_proxy

ProxyPass /portal http://localhost:8080/portal

ポート 8080 で HTTP を提供するように Tomcat が設定されていることを確認する必要が/あります/

ProxyPass / http://localhost:8080/
于 2009-11-16T17:49:16.460 に答える