1 votes

Toutes les demandes sont placées dans la file d'attente ELB

Problème : il semble que chaque requête adressée à notre application aboutisse dans la file d'attente de l'ELB.

Exemple de diagramme de file d'attente : enter image description here

Nous avons un ELB classique sur AWS avec plusieurs boîtes EC2 derrière lui. Les listeners ELB sont configurés de la manière suivante

LB Protocol  LB Port  Instance Protocol  Instance Port  Cipher SSL  Certificate 
TCP          80       TCP                80              N/A        N/A

Sur une instance EC2, nous avons un serveur nginx avec le fichier nginx.conf suivant :

user nginx;
worker_processes 3;
pid /var/run/nginx.pid;
worker_rlimit_nofile 8192;
worker_rlimit_sigpending 32768;

events {
  worker_connections 2048;
  multi_accept on;
  use epoll;
  accept_mutex off;
}

http {
  sendfile on;
  tcp_nopush on;
  tcp_nodelay on;
  keepalive_timeout 65;
  types_hash_max_size 2048;
  map_hash_bucket_size 128;
  server_tokens off;
  client_max_body_size 0;
  server_names_hash_bucket_size 256;

  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" $request_time';

  access_log /app/log/nginx/access.log main;
  error_log /app/log/nginx/error.log;

  gzip on;
  gzip_disable "msie6";

  gzip_vary on;
  gzip_comp_level 4;
  gzip_buffers 16 8k;
  gzip_http_version 1.1;
  gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;

  client_body_temp_path /app/tmp/nginx;:q

  include /etc/nginx/sites-enabled/*;

  upstream tomcat {
    server localhost:8080;
  }

  upstream httpd {
    server localhost:9000;
  }

  upstream play {
    server localhost:9000;
  }

et le serveur virtuel sites.conf

log_format  proxylog  '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$proxy_protocol_addr" $request_time';

server { 
  server_name     www.my-site.com;
  rewrite ^(.*)   http://my-site.com$1 permanent;
}

server {
  listen 80 proxy_protocol;

  listen 443 ssl proxy_protocol;
  ssl_certificate      /etc/nginx/my-certificate.crt;
  ssl_certificate_key  /etc/nginx/my-key.key;
  ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
  ssl_ciphers "SECRET";
  ssl_prefer_server_ciphers on;

  set_real_ip_from 10.0.0.0/8;
  root /app/websites/my-site.com/httpdocs;
  index index.html index.htm;
  real_ip_header proxy_protocol;

  server_name my-site.com;
  access_log /app/log/nginx/my-site.com.access.log proxylog buffer=16k flush=2s;
  error_log /app/log/nginx/my-site.com.error.log;

  charset utf-8;

  location /foo {
    proxy_pass http://play;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
  }

  location /bar {
    add_header Access-Control-Allow-Origin "*" always;
    add_header Access-Control-Allow-Methods "GET,POST,OPTIONS,DELETE,PUT" always;
    add_header 'Access-Control-Allow-Headers' 'Origin, X-Requested-With, Content-Type, Accept, User-Agent, Authorization, Referer, Timestamp' always;
    add_header Access-Control-Allow-Credentials true always;
    proxy_pass http://play;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
  }

  location / {
    add_header Access-Control-Allow-Origin "*" always;
    add_header Access-Control-Allow-Methods "GET,POST,OPTIONS,DELETE,PUT" always;
    add_header 'Access-Control-Allow-Headers' 'Origin, X-Requested-With, Content-Type, Accept, User-Agent, Authorization, Referer, Timestamp' always;
    add_header Access-Control-Allow-Credentials true always;

    real_ip_header proxy_protocol;
    set_real_ip_from 10.0.0.0/8;

    proxy_read_timeout 90s;
    proxy_set_header X-Real-IP $proxy_protocol_addr;
    proxy_set_header X-Forwarded-For $proxy_protocol_addr;
    proxy_set_header X-Forwarded-Host $host;
    proxy_set_header X-Forwarded-Server $host;
    proxy_pass  http://play;
    proxy_set_header Host $http_host;

  }

  location ~ ^/(images|css|js|html) {
    root /app/websites/my-site.com/httpdocs;
  }

  error_page  404              /404.html;

  error_page   500 502 503 504  /50x.html;
  location = /50x.html {
    root   html;
  }
}

Je limite les suspects possibles d'un problème à ELB et nginx, et pas le plus évident - le serveur web réel qui traite les requêtes, parce que dans un de mes tests, j'ai complètement supprimé l'application java, et je l'ai remplacée par un serveur node.js factice qui répondait "hello world" à chaque requête, et je recevais toujours toutes ces requêtes enregistrées dans la file d'attente de surge.

J'ai également essayé d'ajuster worker_processes y keepalive_timeout pour voir si cela affecte quoi que ce soit, et ce n'est pas le cas.

Ce qui me gêne, c'est que cette file d'attente de 1 n'affecte pas les performances d'un service, puisqu'il semble que les demandes tendent à rester là quelques fractions de secondes, mais ce que je ne comprends pas, c'est pourquoi même une seule demande finit par passer par la file d'attente.

3voto

Reverend Tim Points 789

Votre ELB est-il réglé sur TCP ?

Si c'est le cas, votre ELB enregistrera chaque connexion dans la file d'attente. Je crains qu'il ne soit pas possible de contourner ce problème. Vous devez utiliser http ou https pour que la file d'attente fonctionne correctement.

--

Mise à jour de l'OP

J'ai créé une minuscule instance EC2, avec un simple serveur TCP qui répond simplement "patate" à chaque requête. Je l'ai placé derrière un ELB classique avec un listener TCP, et j'ai fait une seule requête à mon nouvel ELB, et j'ai vérifié le graphique de la file d'attente.

enter image description here

Consulter la documentation d'AWS Écoute pour votre équilibreur de charge classique

Lorsque vous utilisez TCP (lay votre équilibreur de charge transmet la demande aux instances back-end sans modifier les en-têtes. sans modifier les en-têtes. Après que votre équilibreur de charge reçoit la demande, il tente d'ouvrir une connexion TCP à l'instance de back-end sur la page d'accueil. sur le port spécifié dans la configuration de l'auditeur.

et ceci :

Pour chaque instance enregistrée et saine derrière Elastic Load Balancing ouvre et maintient une ou plusieurs connexions TCP et les maintient. Ces connexions garantissent qu'il y a toujours une connexion connexion établie prête à recevoir des requêtes HTTP/HTTPS.

Ce qui, d'après ce que j'ai compris, implique que chaque fois que nous faisons un appel à l'ELB configuré par TCP, il met notre demande de côté, pour pouvoir ouvrir une connexion à notre EC2, et ensuite seulement il transmet la demande à la machine.

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X