web-dev-qa-db-ja.com

PHP and mod_fcgid:ap_pass_brigade failed in handle_request_ipc function

これは以前に尋ねられて回答されました https://stackoverflow.com/a/12686252/219116 しかし、そこにある解決策は私にとってはうまくいきません。

mod_fcgid config

<IfModule mod_fcgid.c>
  AddHandler    fcgid-script .fcgi
  FcgidIPCDir /var/run/mod_fcgid/
  FcgidProcessTableFile /var/run/mod_fcgid/fcgid_shm

  FcgidIdleTimeout 60
  FcgidProcessLifeTime 120
  FcgidMaxRequestsPerProcess 500
  FcgidMaxProcesses 150
  FcgidMaxProcessesPerClass 144
  FcgidMinProcessesPerClass 0
  FcgidConnectTimeout 30
  FcgidIOTimeout 600
  FcgidIdleScanInterval 10
  FcgidMaxRequestLen 269484032

</IfModule>

php-cgiスクリプト

#!/bin/bassh
export PHPRC=/var/www/vhosts/example.com/etc/
export PHP_FCGI_MAX_REQUESTS=5000
exec /usr/bin/php-cgi

システムの詳細

  • CentOS Linuxリリース7.1.1503(コア)
  • httpd-2.4.6-31.el7.centos.x86_64
  • mod_fcgid-2.3.9-4.el7.x86_64
  • php56u-cli-5.6.12-1.ius.centos7.x86_64

したがって、FcgidMaxRequestsPerProcessは500に設定され、PHP_FCGI_MAX_REQUESTSは前の回答とApacheドキュメントで提案されているように10倍に設定されます。それでも、私はまだこれらのエラーを受け取ります

[Thu Nov 19 18:16:48.197238 2015] [fcgid:warn] [pid 6468:tid 139726677858048]
(32)Broken pipe: [client X.X.X.X:41098] mod_fcgid: ap_pass_brigade failed in handle_request_ipc function
17
Slashterix

この警告はFcgidxxxオプションとは関係がなく、サーバーが応答する前にクライアントが接続の側を閉じることによって引き起こされます。

実際のソースから:

/* Now pass any remaining response body data to output filters */
if ((rv = ap_pass_brigade(r->output_filters, brigade_stdout)) != APR_SUCCESS) {
    if (!APR_STATUS_IS_ECONNABORTED(rv)) {
        ap_log_rerror(APLOG_MARK, APLOG_WARNING, rv, r,
                      "mod_fcgid: ap_pass_brigade failed in "
                      "handle_request_ipc function");
    }

    return HTTP_INTERNAL_SERVER_ERROR;
}

信用は Avian's Blog に行きました。

5
aefxx

私も1年前に同じ問題を抱えていますが、その後多くのことを試しましたが、ついにドキュメントを読んだ後にいくつかのヒットと実行を行い、問題がなくなりました。まず、次のように設定する必要がある重要な事項:

FcgidBusyTimeout     300 [default]
FcgidBusyScanInterval    120 [default]

このディレクティブの目的は、ハングしたアプリケーションを終了するです。要求の処理に時間がかかる可能性があるアプリケーションの場合、デフォルトのタイムアウトを増やす必要がある場合があります。チェックはFcgidBusyScanIntervalで定義された間隔で実行されるため、リクエストの処理をより長い期間続行できる場合があります

FcgidProcessLifeTime     3600 [default]

クラスのプロセス数がFcgidMinProcessesPerClassを超えると、この時間よりも長く存在していたアイドル状態のアプリケーションプロセスは終了します。

このプロセスライフタイムチェックは、構成されたFcgidIdleScanIntervalの頻度で実行されます。

FcgidZombieScanInterval   3 [seconds default]

モジュールは、この間隔で終了したFastCGIアプリケーションをチェックします。この期間中、アプリケーションはプロセステーブルにゾンビとして存在する場合があります(Unix上)。

注:上記のすべてのオプションアプリケーションの処理時間またはニーズに応じて増減するか、特定の仮想ホストに適用します。

しかし、私の問題はこのオプションで解決します:

上記のオプションは私のサーバーを微調整しましたが、しばらくするとエラーが再び発生するように見えますが、エラーはこれにより本当に解決されます:

 FcgidOutputBufferSize   65536 [default]

に変更しました

 FcgidOutputBufferSize   0

これは、モジュールがクライアントにデータをフラッシュする前にFastCGIアプリケーションから読み取る応答データの最大量です。これにより、64KBのバイトを待たずに即座にデータがフラッシュされ、プロセスをより高速にフラッシュできます。

私が得た他の問題

nginxのタイムアウトによる500エラーの場合。修正:

/ etc/nginx/nginx.conf

keepalive_timeout  125;
proxy_read_timeout 125;
proxy_connect_timeout 125;
fastcgi_read_timeout 125;

断続的にMySQLの「MySQLサーバーがなくなった」というエラーが表示されますが、これにはもう1つの調整が必要です:/ etc/my.conf

wait_timeout = 120

それから、ファンシーのために、念のためにPHPメモリ制限を引き上げました:/ etc/php.ini

memory_limit = 256M

SuExecを使用する

mod_fastcgiSuExecの下ではApache 2.xはまったく機能しません。私はそこからのトラブル以外に何もありませんでした(テストでは他にも多くの問題がありました)。問題の本当の原因はSuExecです

私の場合は、Apacheを起動するためのスタートアップでした。mod_fcgidは各vhostに対して正確に5つのプロセスを生成します。現在、単純なアップロードスクリプトを使用して4〜8 KBを超えるファイルを送信すると、スクリプトが実行された特定のvhostのすべての子プロセスが一度に強制終了されます。

手がかりを与える可能性があるmod_fcgidでデバッグビルドを作成したり、ログを記録したりすることが可能かもしれません。

その間、mod_fastcgiを1年間試しましたが、私も多くの人に、SuExecは面倒であり、すべてのケースでスムーズに実行できないと言っています。

15
Vineet1982