サーバーの動作がおかしいので、原因を特定できません。私は至る所を探してきました。
これを理解できる人なら誰でも200 $相当のビットコインを支払います。
Apache(ページ、画像、css、js)からリソースを要求すると、応答に非常に長い時間がかかることがあります。約半分の時間、接続がリセットされます。 (Chromeの場合:net :: ERR_CONNECTION_RESET)これはまれに、ランダムに発生し、完全に予測不可能です。さらに混乱しますが、1つの要求がハングしているように見えますが、完全に機能する追加の要求を作成できます。
私は、debian 9のphp7.0でApache2.4 mpm-preforkを実行しています。Apacheモジュールは、certbotのmod_rewriteとssl-certificateを使用します。場合によっては、phpがinkscapeを呼び出してsvgをpngにレンダリングします。
サーバーの負荷は非常に低く(0.02)、Apache以外では何も実行されません。
Wiresharkでtcpトラフィックを分析したところ、疑わしい動作がいくつかありました。接続がフリーズしているとき、いくつかのTCP Out-of-Order、Retransmission、ACKed unseen segment packets ...がありますが、何が起こっているのかを知るために必要な低レベルの知識がありませんオン。
すべてのヒントはすばらしく見習われます!
これはmpm_prefork設定です:
<IfModule mpm_prefork_module>
StartServers 10
MinSpareServers 10
MaxSpareServers 50
MaxRequestWorkers 300
MaxConnectionsPerChild 0
</IfModule>
私は運が良かったので、サーバーとクライアントの両方でtcpスニファーが再度実行されたときに実行されました。ここに、最後の〜30秒までトリミングされたpcapファイルがあります。
知識のある人がそれをざっと見て、何が起こっているのか教えてもらえたら、私は感激します。
少なくともKeepAliveをオンにして、エラーを再現可能にしました。リクエストが終了してコンテンツが提供されると、tcp接続は5秒後にFIN-ACKで閉じます。 FIN-ACKから5〜12秒の時間枠で別のリクエストを行うと、接続がフリーズします。
ただし、KeepAliveをオフにすると、これは発生しなくなり、同時に複数のリソースをロードするときにエラーがさらに頻繁に発生します。しかし、それはもはや再現可能ではありません。
同じことが私に起こったので、私は問題を見つけたと確信しています:-)。
[〜#〜] two [〜#〜]以上のプロセスがポート80(またはSSL接続の場合は443)を処理していると思います。次のように、ポート80のコマンドと、問題があったシステムからの出力を使用して、次のように確認できます。
_# netstat -tupan | grep ":80.*LISTEN"
Proto Recv-Q Send-Q Local Foreign State PID/Program name
Address Address
tcp6 0 0 :::80 :::* LISTEN 22718/Apache2
tcp6 0 0 :::80 :::* LISTEN 1794/Apache2
_
同じポートから同じIPアドレスを提供する2つのプロセスは、ポートオプション_SO_REUSEADDR
_および_SO_REUSEPORT
_で実際に可能です。 here および here を参照してください(セクション「Linux> = 3.9」について)。
カーネルが_SO_REUSEPORT
_で行うことは、着信TCP接続をそのポートを提供するプロセスに非決定的な方法で分散することです。1つのプロセスは、要求を適切に提供するApacheです。もう1つは、これまで何も答えない「何か」で、私の場合は、別のApache2プロセスでした。
Apacheプロセスが2つある場合は、最初にそれらのどれが「ゾンビ」であるかを調べます。そのためには、通常のApacheサーバー(_service Apache2 stop
_)を停止し、残っているサーバーを確認してください(_netstat -tupan | grep ":80.*LISTEN"
_)。それが「ゾンビ」です。そのPIDに注意してください。
この「ゾンビ」プロセスを誰または何が開始したかについて詳しく知るには、次のようにします。
その「ゾンビ」プロセスのPIDで_cat /proc/<pid>/loginuid
_を実行します。 _4294967295
_が表示されている場合は、ユーザーではなくシステムが起動したことを意味します( reason )。それ以外の場合は、検索できるのはユーザーのUIDです。
_ps auxf
_を実行して、「ゾンビ」プロセスのプロセス稼働時間を確認します。システムの稼働時間と一致する場合は、プロセスがなんらかの方法で起動時に開始されたことを意味します。
(おそらく)この「ゾンビ」プロセスの内部で何が起こっているのかを詳しく知るには、strace
を使用してそれにアタッチできます。これにより、読み取りが困難なログが大量に作成されますが、この「ゾンビ」プロセスの問題を再現するのは簡単ではないため、少なくともこれらのログの一部(そのプロセスに送信されるHTTPリクエストなど)を収集することをお勧めします。プロセスを終了します。 _$PID
_の代わりにプロセスのPIDを使用して実行します。
_strace -o strace.log -f -p $PID
_
当面の問題を解決するには、「ゾンビ」プロセスを強制終了して、PIDを_$PID
_:_kill $PID
_または必要に応じて_kill -9 $PID
_に指定します。
その「ゾンビ」プロセスが再起動後に再び稼働していることを確認します。稼働している場合は、の原因を調査して修正する必要があります。
通常のApacheサーバーと並行して実行され、「何も応答しない」だけで実行されるApache2の「ゾンビ」プロセスを手動で作成することは可能です(簡単ではありません)。ほぼ完全ではありますが、完全な手順を次に示します。
関連する設定ファイルのコピーを作成します。
_cp /etc/Apache2/envvars /etc/Apache2/envvars-zombie
cp /etc/Apache2/Apache2.conf /etc/Apache2/Apache2-zombie.conf
_
_/etc/Apache2/envvars-zombie
_を編集し、スクリプトの先頭で静的に_SUFFIX="-zombie"
_を設定して、その中の条件付き割り当てを上書きします。
_/etc/Apache2/Apache2-zombie.conf
_を編集し、VirtualHost構成ファイルが含まれないようにします。私の場合、対応する行を次のように変更します。
_# IncludeOptional sites-enabled/
_
デフォルトのリスンポートが_Apache2-zombie.conf
_ファイルに含まれていることを確認します。私の場合、これは_Include ports.conf
_を介してすでに発生しています。
Apache2の新しいインスタンスに必要なロックファイルとログディレクトリを作成し、新しいApache2を実行するユーザーがそれらにアクセスできるようにします。
_mkdir /var/log/Apache2-zombie
chown www-data /var/log/Apache2-zombie/
mkdir /var/lock/Apache2-zombie
chown www-data /var/lock/Apache2-zombie/
_
これで、「ゾンビ」Apacheプロセスを次のように開始できるはずです。
_cd /etc/Apache2/
source envvars-zombie
/usr/sbin/Apache2 -f Apache2-zombie.conf -k start
_
現在、Apache2の標準ポートで実行されている2番目のプロセス_netstat -tupan | grep ":80.*LISTEN"
_があることを確認します。
その2番目のApache2サーバーはまだ「ゾンビ」ではありません。「404見つかりません」と応答するか、または(SSLをセットアップしなかったため)ポート443でリクエストを行うとSSLエラーが発生します。ただし、その影響はすでに確認できます。そのいくつかのリクエストがこの新しいサーバーに送信され、これらのエラーが非決定的に発生します。 (私は実際にこの時点まで立ち上がった…)
「適切な」ゾンビApacheを作成するには、HTTPリクエストを受け入れる単純なスクリプトを設定し、数分間何もしないで(sleep()
)、ブラウザが応答をあきらめるようにします。 TCP接続がタイムアウトになるようにします。Apacheのデフォルトホストにインストールします。これにより、すべてのVirtualHost構成が無効になり、Apacheが見つけられないため、ポートへのすべてのHTTP要求に使用されます。あらゆるリクエストにより適したホストであり、デフォルトのホストを選択します。
TCPパケットがサーバーとクライアントの間で送信されるパケットのサイズを確認します。サイズが1500に近い場合は、多数の可能性のためにドロップされる可能性があります。
パケットにDNFビットが設定されていて、パケットがどこかで断片化されている場合、これはパケットがドロップされる原因となる問題である可能性があります
MTUが1500に設定されていて、パケットがトンネルや暗号化などを通過しているために、追加のヘッダーがパケットに追加されている場合、これもパケットのドロップを引き起こします。使用しているインターフェイスの両端のmtuを1500未満、おそらく1420以下に設定してみてください。