Doubles téléchargements
Depuis que nous sommes passés d'une simple instance d'Apache à un environnement à répartition de charge, il y a parfois des problèmes de répétition des requêtes POST. Nous utilisons nginx comme proxy inverse. Le contenu statique est servi par nginx lui-même, et le contenu dynamique est servi par deux backends Apache.
J'ai vérifié qu'il ne s'agit pas d'une erreur d'interface/utilisateur. Un petit exemple : un simple chargement d'image entraîne un double chargement de l'image. La requête/POST n'est pas envoyée deux fois par un double clic ou une erreur de l'utilisateur. Je n'ai trouvé aucune preuve que le navigateur envoie la demande deux fois, je soupçonne donc le serveur. (Notez qu'il ne s'agit que de soupçons.) La plupart de ces demandes sont internes, c'est-à-dire qu'elles proviennent d'employés, et je peux donc vérifier comment elles se produisent.
La seule chose qui ne va pas, c'est que nginx enregistre un message de type 499
erreur dans ces cas. Je ne suis cependant pas sûr que ce soit la cause ou juste un effet (secondaire) du problème. (Je suis conscient que 499 n'est pas un statut http par défaut, c'est un statut nginx qui signifie "le client a fermé la connexion").
demande
Les requêtes POST répétées sont presque toutes des requêtes qui peuvent prendre un certain temps. Celle que je montre ici à titre d'exemple est un simple téléchargement d'image, mais le script fait quelques trucs en arrière-plan (l'image doit être convertie en différents formats/tailles, et doit être distribuée aux deux serveurs, etc).
journaux
Par exemple, le téléchargement d'une image. nginx enregistre une requête '499' et une requête 200, mais Apache reçoit (et traite !) deux requêtes.
Apache
[17:17:37 +0200] "POST ***URL** HTTP/1. 0" 200 9045
[17:17:47 +0200] "POST ***URL** HTTP/1. 0" 200 20687
nginx
[17:17:47 +0200] "POST ***URL** HTTP/1.1" 499 0
[17:17:52 +0200] "POST ***URL** HTTP/1.1" 200 5641
Soupçons
Il me semble que les téléchargements les plus volumineux et les plus lents souffrent davantage de ce problème, je soupçonne donc un délai d'attente. J'ai essayé de me documenter sur l'erreur 499 : les conclusions semblent être qu'il s'agit d'une "connexion fermée par le client". Cela pourrait être le cas en arrière-plan, mais je ne suis pas sûr que cela signifie qu'une deuxième demande devrait être émise et il n'y a certainement pas quelque chose comme "l'utilisateur a fermé le navigateur".
Actuellement, il semble aider à briser les requêtes POST plus lentes (s'il y a plusieurs choses à faire, il suffit de faire en sorte que l'utilisateur en choisisse une et effectue un second POST pour l'autre), mais cela pourrait simplement réduire les chances que cela se produise. Je ne suis pas sûr.
Il s'agit évidemment d'une solution temporaire. Si elle est un délai d'attente, je dois trouver où et augmenter les nombres correspondants, mais je ne suis pas sûr de la raison pour laquelle un délai d'attente provoquerait ce comportement : je soupçonnerais un message " well, that went wrong ", pas une répétition.
Questions
Je cherche à savoir quel processus/situation peut entraîner la répétition d'un POST. Bien sûr, tout "je ne suis pas sûr de la raison, mais cela sera corrigé en augmentant ce délai" sera également apprécié.
configurations de nginx
NGINX.conf
user nginx;
worker_processes 2;
worker_rlimit_nofile 10240;
error_log /var/log/nginx/error.log error;
pid /var/run/nginx.pid;
events {
multi_accept on;
worker_connections 4096;
use epoll;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
tcp_nodelay off;
client_max_body_size 30m;
keepalive_timeout 65;
include /etc/nginx/conf.d/*.conf;
}
conf.d
J'ai supprimé certaines lignes spécifiques à l'IP dans le geo
ainsi que les SSL
variations, pour rester simple. Si nécessaire, je peux les remplacer, mais cela se résume à un supplément d'argent. geo
pour les backends ssl, et les upstreams et fichiers conf correspondants.
geo $backend {
default apache-backend;
}
upstream apache-backend {
ip_hash;
server SERVER1 max_fails=3 fail_timeout=30s weight=2;
server SERVER2 max_fails=3 fail_timeout=30s weight=3;
}
conf.d/somestring.conf
limit_conn_zone $binary_remote_addr zone=somestring:10m;
server {
listen ip1:80;
listen ip2:80;
server_name name.tld www.name.tld;
root PATH
access_log PATH/name.log main;
location / {
proxy_pass http://$backend;
}
//*some more locations**//
gzip on;
gzip_http_version 1.0;
gzip_comp_level 2;
gzip_proxied any;
gzip_min_length 1100;
gzip_buffers 16 8k;
gzip_types text/plain text/css application/x-javascript text/xml application/xml application/xml+rss text/javascript;
}
conf.d/proxy.conf
proxy_set_header Accept-Encoding "";
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_buffering on;
proxy_read_timeout 90;
proxy_buffer_size 32k;
proxy_buffers 8 32k;
proxy_busy_buffers_size 32k;
proxy_temp_file_write_size 32k;