haproxy: conserver les sessions existantes sous forte charge, servir '503' aux nouveaux arrivants

12

Essayer de faire ce qu'il dit dans le titre: conserver les sessions existantes sous une charge élevée et diffuser un message 503 aux visiteurs nouvellement arrivés.

Problème: cela fonctionne, mais les sessions ne durent pas au-delà d'environ 90 secondes.

Les résultats actuels me font me demander s'il y a un paramètre de délai d'attente qui me manque.

Objectif

J'essaie d'obtenir un haproxy pour:

  • envoyer des demandes de nouvelles sessions au backend-001 lorsque le nombre total de sessions sur le frontend est inférieur à un certain seuil.
  • servir une erreur 503 aux nouvelles sessions lorsque le nombre total de sessions sur le frontend est supérieur à ce seuil
  • autoriser les demandes de sessions existantes même si le nombre de sessions dépasse le seuil

De cette façon, les visiteurs qui sont en train de remplir un formulaire en plusieurs étapes ne seront pas surpris par une erreur 503, et les nouveaux visiteurs peuvent être invités à "revenir plus tard, car nous sommes vraiment occupés en ce moment".

Installer

La configuration est la suivante:

            {visitors}
                ↓ 
            [haproxy]
                ↓ 
[rails app on unicorn served by nginx]   (right now just one 
                                            backend: 'backend-001')

approche actuelle

Pour atteindre ce qui précède, j'utilise la configuration ci-dessous.

Celui-ci est destiné aux tests, avec une limite très basse (10 connexions en front-end (fe_conn gt 10)), pour faciliter les tests.

Pour mettre le serveur sous une certaine charge, j'utilise httperf comme suit:

httperf --hog --server staging.machine.tld --uri / do_some_things --wsess = 500,10,30 --rate 2

global
    daemon
    maxconn 10000

defaults
    mode        http
    timeout connect 6s
    timeout client  60s
    timeout server  60s
    balance roundrobin
    option http-server-close

frontend http-in
    bind [PUBLIC_IP]:80

    default_backend backend-001

    acl too_many fe_conn gt 10
    use_backend b_too_many if too_many

backend backend-001
    fullconn 10
    appsession _session_id len 128 timeout 7200s

    cookie SERVERID insert maxidle 7200s
    server Server1 127.0.10.1:80 cookie backend-001 check

backend b_too_many
    errorfile 503 /var/www/50x.html

problème

Comme mentionné ci-dessus, le problème est: cela fonctionne presque, mais les sessions ne durent pas au-delà d'environ 90 secondes.

Si vous continuez à cliquer sur, vous pouvez conserver votre session même s'il y a 10 sessions occupées.

Si vous essayez d'ouvrir une page sur le serveur avec une autre instance de navigateur, vous obtenez l'erreur 503.

Donc, on dirait que j'y suis presque. Quelqu'un at-il une idée de ce qui pourrait être à l'origine des courts temps de session?

Et surtout comment je peux le réparer :)

(modifier: suppression du «poids 1 maxconn 10» de la ligne «serveur», non pertinent et peut prêter à confusion) (modifier le 2e: «10 sessions corrigées sur le front-end» à «10 connexions sur le front-end»)

Apenootje
la source
Peut-être une question stupide - quel est le paramètre keep_alive dans nginx? Apparemment, c'est 75 ans par défaut - cela pourrait-il être le problème?
Aidan Kane

Réponses:

4

Malheureusement, il semble que vous confondiez complètement les connexions avec les sessions au niveau de l'application. Un utilisateur visitant le site peut avoir un cookie qui vous fait penser qu'il possède une connexion alors que ce n'est pas nécessairement le cas. Il peut ouvrir autant de connexions que nécessaire pour récupérer des objets et parcourir les pages.

Les 90 secondes que vous observez sont sûrement le délai d'expiration du navigateur pour les connexions inactives.

Il est possible d'obtenir ce que vous voulez, mais c'est un peu plus complexe que cela, car vous devez également tenir compte de la présence du cookie de persistance dans la demande pour déterminer si le visiteur est nouveau ou non.

De plus, en général, il est plus efficace de s'appuyer sur le nombre moyen de connexions par serveur que sur le nombre de connexions frontales. La raison en est que lorsqu'un serveur meurt, vous devez réajuster ce nombre. La façon la plus efficace de le faire est de configurer une valeur maxconn du serveur pour activer la mise en file d'attente et d'utiliser avg_queue afin que la limite s'applique au nombre moyen de demandes en file d'attente sur les serveurs. Cela vous permet de gérer correctement les visiteurs connus tout en déplaçant doucement les nouveaux utilisateurs vers un autre backend lorsque la charge augmente en raison des visiteurs existants.

Willy Tarreau
la source
1
Merci merci! Cela a beaucoup éclairci. Je le fais maintenant fonctionner (entre autres choses) en vérifiant le cookie backend avec hdr_sub (Donc, "hdr_sub (cookie) SERVERID = backend-001"). Je posterai une configuration de travail quand elle sera terminée.
Apenootje