web-dev-qa-db-ja.com

Apache mod_proxyおよびTomcatでの不正なGateway 502エラー

Tomcat 6およびApache mod_proxy 2.2.3でWebアプリを実行しています。次のような多くの502エラーが表示されます。

悪いゲートウェイ!プロキシサーバーがアップストリームサーバーから無効な応答を受信しました。

プロキシサーバーは、GET /the/page.doのリクエストを処理できませんでした。

理由:リモートサーバーからの読み取りエラー

これがサーバーエラーだと思われる場合は、ウェブマスターにお問い合わせください。

エラー502

Tomcatには多数のスレッドがあるため、スレッドの制約はありません。 JMeterを介してアプリに対して2400人のユーザーをプッシュしています。すべてのボックスは、高速でアンロードされたネットワーク上のファイアウォール内にあるため、ネットワークに問題はありません。

誰もが見たり試してみたりするための提案がありますか?次にtcpdumpに向かいます。

UPDATE 10/21/08:まだこれを理解していません。負荷がかかっているこれらのごく少数のみを表示します。以下の答えは、魔法の答えを提供していません...まだ。 :)

46
Alex Miller

そこで、ここで自分の質問に答えます。最終的に、Tomcatスレッドのタイムアウトにより、ロードバランサーで502および503エラーが発生していると判断しました。短期的には、タイムアウトを増やしました。長期的には、最初にタイムアウトを引き起こしていたアプリの問題を修正しました。 Tomcatのタイムアウトがロードバランサーで502および503エラーとして認識されていた理由は、まだ少し謎です。

13
Alex Miller

いくつかの特定の設定を追加するために、同様のセットアップを行いました(Apache 2.0.63をTomcat 5.0.27にリバースプロキシする)。

特定のURLでは、Tomcatサーバーがページを返すのにおそらく20分かかる場合があります。

最終的に、Apache構成ファイルの以下の設定を変更して、プロキシ操作でタイムアウトにならないようにしました(Tomcatがページを返すのに時間がかかった場合に大きなオーバーフロー要因が発生しました)。

Timeout 5400
ProxyTimeout 5400

いくつかの背景

ProxyTimeout だけでは十分ではありませんでした。 Timeout I'mguessing(不明)のドキュメントを見ると、これはApacheが待機しているためですTomcatからの応答では、Apacheとブラウザー(またはHTTPクライアント)の間でトラフィックが流れないため、Apacheはブラウザーへの接続を閉じます。

タイムアウト設定をデフォルト(300秒)のままにしておくと、Tomcatへのプロキシ要求が応答を得るのに300秒以上かかった場合、ブラウザに「502プロキシエラー」ページが表示されることがわかりました。このメッセージは、ブラウザへの接続を閉じる前にリバースプロキシとして機能しているという認識のもとで、Apacheによって生成されたと考えています(これは私の現在の理解です-欠陥があるかもしれません)。

プロキシエラーページには次のように表示されます。

プロキシエラー

プロキシサーバーがアップストリームサーバーから無効な応答を受信しました。プロキシサーバーは要求GETを処理できませんでした。

理由:リモートサーバーからの読み取りエラー

...これは、ProxyTimeout設定が短すぎることを示唆していますが、調査により、ApacheのTimeout設定(Apacheとクライアント間のタイムアウト)もこれに影響していることがわかります。

42
Neil Salter

Proxy-initial-not-pooledを使用できます

http://httpd.Apache.org/docs/2.2/mod/mod_proxy_http.html を参照してください:

この変数が設定されている場合、クライアント接続が初期接続である場合、プールされた接続は再利用されません。これにより、プロキシによる接続チェックの後、プロキシから送信されたデータがバックエンドに到達する前に、バックエンドサーバーがプールされた接続を閉じたという競合状態によって引き起こされる「プロキシ:リモートサーバーからのステータスラインの読み取りエラー」エラーメッセージが回避されます。特にHTTP/1.0クライアントでは、この変数を設定するとパフォーマンスが低下することに注意してください。

この問題もありました。追加して修正しました

SetEnv proxy-nokeepalive 1
SetEnv proxy-initial-not-pooled 1

すべてのサーバーでkeepAliveをオフにします。

mod_proxy_httpはほとんどのシナリオで問題ありませんが、高負荷で実行しているため、まだ理解できないタイムアウトの問題がいくつかあります。

ただし、上記のディレクティブがニーズに合っているかどうかを確認してください。

9
Janning

Apache confのサンプル:

#Default value is 2 minutes
**Timeout 600**
ProxyRequests off
ProxyPass /app balancer://MyApp stickysession=JSESSIONID lbmethod=bytraffic nofailover=On
ProxyPassReverse /app balancer://MyApp
ProxyTimeout 600
<Proxy balancer://MyApp>
    BalancerMember http://node1:8080/ route=node1 retry=1 max=25 timeout=600
    .........
</Proxy>
3
sibnick

次のようにProxyPassディレクティブでプロキシタイムアウトを指定することにより、グローバルタイムアウトまたは仮想ホストの使用を回避できます。

ProxyPass /svc http://example.com/svc timeout=600
ProxyPassReverse /svc http://example.com/svc timeout=600

timeout=600秒に注意してください。

ただし、ロードバランサーがある場合、これは常に機能するとは限りません。その場合、両方の場所にタイムアウトを追加する必要があります(Apache 2.2.31でテスト済み)

ロードバランサーの例:

<Proxy "balancer://mycluster">
     BalancerMember "http://member1:8080/svc" timeout=600
     BalancerMember "http://member2:8080/svc" timeout=600
</Proxy> 

ProxyPass /svc "balancer://mycluster" timeout=600
ProxyPassReverse /svc "balancer://mycluster" timeout=600

副次的注意:ProxyPasstimeout=600は、Chrome=がクライアントだった場合は必要ありません(理由はわかりません))でしたが、ProxyPassでこのタイムアウトなしでInternet Explorer(11)サーバーによって接続がリセットされました。

私の理論は:

ProxyPassタイムアウトは、クライアント(ブラウザー)とApacheの間で使用されます。

BalancerMemberタイムアウトは、Apacheとバックエンドの間で使用されます。

Tomcatまたはその他のバックアップを使用している場合は、HTTPコネクタのタイムアウトにも注意を払うことをお勧めします。

3
bhantol

タイムアウトとproxyTimeoutパラメーターを600秒に設定することで、この問題を解決できるはずです。しばらく戦った後、それは私のために働いた。

2
tallguy

Mod_proxy_http(またはプロキシバランサー)の使用を推測しています。

Tomcatログ(localhost.logまたはcatalina.log)を調べてください。Tomcatワーカーが接続しているソケットをバブルアップして閉じているWebスタックで例外が発生しているようです。

2
Dave Cheney

ほとんどの場合、Apache confのタイムアウトパラメータを増やす必要があります(デフォルト値は120秒)

1
sibnick

これでこの質問に答えられないことはわかっていますが、nodeJSサーバーでも同じエラーが発生したため、ここに来ました。私は解決策を見つけるまで長い間立ち往生しています。私のソリューションでは、スラッシュまたはproxyreserve Apacheの最後に/を追加するだけです。

私の古いコードは:

ProxyPass / http://192.168.1.1:3001
ProxyPassReverse / http://192.168.1.1:3001

正しいコードは次のとおりです。

ProxyPass / http://192.168.1.1:3001/
ProxyPassReverse / http://192.168.1.1:3001/