Délai d'expiration du proxy Apache2

23

J'ai Apache2 avec PHP + PHP-FPM configuré selon:

http://wiki.apache.org/httpd/PHP-FPM

J'écris un script qui prendra beaucoup de temps à exécuter sur un Vhost interne, mais continuez à expirer, tout fonctionne parfaitement si le script s'exécute en moins de 30 secondes.

Mon journal Apache me dit:

[Wed Apr 17 21:57:23.075175 2013] [proxy_fcgi:error] [pid 9263:tid 140530454267648] (70007)The timeout specified has expired: [client 58.169.202.172:49017] AH01075: Error dispatching request to :, referer:

Lorsque j'essaie d'exécuter le script, je reçois un 503 Service Unavailabledélai d'exécution de 30 secondes exactement. Logiquement, cela signifierait que j'ai une directive de délai d'attente ou un paramètre défini sur 30 secondes, mais je les ai dans la configuration de mon Vhost:

Timeout 600
<IfModule proxy_module>
    ProxyPassMatch ^/(.*\.php)$ fcgi://127.0.0.1:9001/home/pyrokinetiq/scripts/$1 timeout=600
    ProxyTimeout 600
</IfModule>

(php-fpm fonctionne sur le port 9001 pour moi)

J'ai aussi essayé de placer le Timeoutet ProxyTimeouten httpd.confsans différence.

Il semble qu'il y ait un autre paramètre de délai d'attente quelque part qui soit spécifique à mod_proxy_fcgi, mais je ne le trouve pas. J'ai installé Apache2 httpd à partir de l'archive tar officielle, aucun des mods ne semble être venu avec des fichiers de configuration.

Si quelqu'un peut m'orienter dans la bonne direction, ce serait très apprécié.

wyqydsyq
la source

Réponses:

32

J'ai finalement résolu ce problème après avoir testé plusieurs paramètres de configuration. J'ai testé la solution deux fois, supprimant toutes les modifications précédentes. Un seul paramètre était nécessaire pour que je puisse le réparer.

Pour les dernières versions de httpd et mod_proxy_fcgi, vous pouvez simplement ajouter timeout=à la fin de la ProxyPassMatchligne, par exemple:

ProxyPassMatch ^/(.+\.php.*)$ fcgi://127.0.0.1:9000/<docroot>/$1 timeout=1800

Pour les anciennes versions, c'était un peu plus compliqué, par exemple:

<Proxy fcgi://127.0.0.1:9000>
  ProxySet timeout=1800
</Proxy>
ProxyPassMatch ^/(.+\.php.*)$ fcgi://127.0.0.1:9000/<docroot>/$1

J'ai dû ajouter la directive Proxy pour définir le délai d'expiration à 30 minutes. Dans certaines applications, généralement lors de l'exploitation d'une base de données, certaines routines peuvent prendre plus de 10 minutes à exécuter. J'ai temporairement mis le délai d'attente à 30 minutes pour m'assurer qu'ils se terminent. Particulièrement utile lors de l'utilisation de l'assistant d'installation, ce qui prend trop de temps (à mon humble avis).

Au fait, l'entrée initiale qui m'a aidé à résoudre ce problème a été trouvée dans l' adresse URL suivante .

Jordi Ferran
la source
1
Il semble que cela ne fonctionne pas sous les versions récentes d'Apache, AH00526: ProxyPass / <Proxy> et ProxyPassMatch / <ProxyMatch> ne peuvent pas être utilisés avec le même nom de travailleur
Stewart Adam
4
J'ai résolu ce qui précède en ajoutant un paramètre «timeout = 120» à la fin de la ligne ProxyPassMatch.
Stewart Adam
@Palantir heureux de l'entendre! Soumis comme réponse .
Stewart Adam
Deux autres choses dont j'avais besoin: Tout d'abord, vous devez définir "Timeout" et "ProxyTimeout" dans votre fichier de configuration global apache pour être plus long que les autres délais FPM. Deuxièmement, mon pool FPM écoutait sur un socket Unix et j'utilise SetHandler comme ceci: [SetHandler "proxy: unix: /var/run/php/example.com-php7.0-fpm.sock | fcgi: // localhost: 8000 "]. Mais <Proxy> correspond à la partie fcgi: // localhost de la ligne SetHandler (la partie APRÈS le | ... qui n'est même pas réellement utilisée!) Et NON à l'unix: / var / run / part. donc pour configurer les délais d'attente pour l'utilisation ci-dessus: <Proxy fcgi: // localhost: 8000> et non <Proxy unix: / var / run / ...
Professor Falken
9

Je voulais souligner que bien que cette réponse fonctionne très bien pour les anciennes versions, elle se casse sous les versions récentes d'Apache 2.4 avec le code d'erreur AH00526. ProxyPasset ProxyPassMatchou <Proxy>et <ProxyMatch>ne peuvent pas être utilisés ensemble sous le même nom de travailleur. Cela fonctionnait très bien, donc je ne sais pas si cela a été modifié par conception ou s'il s'agit d'un bogue.

Quoi qu'il en soit, vous pouvez résoudre ce problème en utilisant uniquement un ProxyPassMatch avec le paramètre 'timeout = 120' (ou quelle que soit la valeur souhaitée), par exemple:

ProxyPassMatch ^/(.*\.php)$ fcgi://127.0.0.1:9001/path/to/webroot/$1 timeout=120
Stewart Adam
la source
6

J'ai Apache 2.4.6, mais le correctif pour le corriger est fourni dans Apache> = 2.4.8. La clé ici est de démarrer votre sortie immédiatement afin qu'Apache (mod_proxy_fcgi) pense que la connexion est active.

Par exemple, j'utilise PHP et la requête DB pour mon appel AJAX prend> 30 secondes. Parce que je sais que la réponse globale sera "Content-Type: application / json", j'envoie cet en-tête immédiatement.

#1: Start output immediately
#Note: Sending the header is innocuous
#   it can be changed later using the $replace parameter
#   (see #3)
header( 'Content-Type: application/json' );

#2: Run slow query
mysql_query( "SELECT * FROM giant_table" );

#3: Change header as needed
header( 'Content-Type: application/csv', true );

#output content
Chris
la source
2

Cela ne devrait-il pas être:

<IfModule mod_proxy.c>

Assurez-vous que le paramètre php.ini max_execution_time est également défini sur 600. (vérifiez phpinfo () sur la page en direct pour vous assurer que vous voyez la valeur réelle utilisée)

Comme l'a dit Jenny, définissez le paramètre php-fpm

request_terminate_timeout 610s

(notez les s à la fin)

Il n'y a pas grand-chose à configurer avec mod_proxy_fcgi lui-même, comme vous pouvez le voir sur la page apache. http://httpd.apache.org/docs/current/mod/mod_proxy_fcgi.html

Activez également la journalisation du débogage php-fpm afin que vous puissiez voir où cela arrive. http://php-fpm.org/wiki/Configuration_File (activez également catch_workers_output)

Et activez la journalisation du niveau de débogage pour les modules mod_proxy et mod_proxy_fcgi puisque vous utilisez apache 2.4. Très belle fonctionnalité, activez uniquement pour les modules dont vous avez besoin: http://httpd.apache.org/docs/current/mod/core.html#loglevel

Si cela ne vous aide pas, postez votre fichier de configuration php-fpm.

En dernier recours, peut-être qu'un démon tue un long processus?

troseman
la source
2

J'ai remarqué que vous utilisez PHP-FPM. Moi aussi je l'utilise, mais avec Apache 2.4.6.

En supposant que le problème existe depuis un certain temps, il semble que la valeur du délai d'attente mod_proxy_fcgisoit codée en dur . J'ai écrit ce que j'ai trouvé ici

monsieur
la source
1

Étant donné que vous avez corrigé les paramètres de délai d'attente dans apache, cela ne devrait pas être le problème. Le deuxième endroit à rechercher serait tout équipement réseau, mais comme vous êtes mandataire sur votre propre serveur, cela est également peu probable. L'endroit restant à regarder est donc le serveur principal.

Ih le fichier de configuration pour php-pfm, recherchez

; This is a hard kill switch on php execution.  It ignores the
; max_execution_time that can be set/changed with php_ini.  Basically
; it avoids timeout issues between apache and php-fpm.
request_terminate_timeout=30

Ce paramètre doit être identique ou légèrement inférieur au paramètre de délai d'expiration dans apache.

Jenny D dit de réintégrer Monica
la source
1
J'ai mis le request_terminate_timeoutà 400, toujours pas de changement :( J'ai le sentiment qu'il y a quelque chose que je dois régler mod_proxy_fcgi, mais il ne semble pas venir avec des fichiers de configuration.
wyqydsyq
0

En plus du délai d'expiration, définissez enablereuse = off. J'ai trouvé que lorsque c'était sur certaines demandes, des scripts de longue durée fonctionneraient correctement et d'autres seraient tués tôt.

ctlq
la source
0

Ce message a changé toute l'affaire pour moi.

Il semble que le mod_reqtimeout d'Apache n'utilise pas la valeur par défaut.

Ajoutez les lignes suivantes à votre fichier httpd.conf :

<IfModule reqtimeout_module>
  RequestReadTimeout header=20-40,MinRate=500 body=20,MinRate=500
</IfModule>
Frosty Z
la source