NGINX:如何在连接最少的情况下进行粘性会话

NGINX : How to have sticky session with least connected

我正在使用 ip_hash(Sticky Session),我有一个可以通过 Web 访问门户的 Web 门户场景,我们有支持模块,它也托管在同一个门户上,上游是使用 22 个节点进行负载平衡

  1. 使用粘性会话门户的客户没有问题。
  2. 从支持中心登录的用户遇到性能问题,因为粘性会话使上游指向具有相同外部 public IP 的所有用户的相同节点。

关于第 2 点需要帮助。我也想为他们分配负载,因为支持中心有 1000 个并发用户工作

我的配置看起来像

upstream appserver{
    ip_hash;
    server 192.168.0.x:3811;
    server 192.168.0.x:3812;
    server 192.168.0.x:3813;
    server 192.168.0.x:3814;
    server 192.168.0.x:3815;
    server 192.168.0.y:3811;
    server 192.168.0.y:3812;
    server 192.168.0.y:3813;
    server 192.168.0.y:3814;
    server 192.168.0.y:3815;
    ...
    ...
}    

server {
    location "/support" {
        allow ...;
        deny  all;
        alias ...;
        index index.html;
    }

    location / {
        proxy_pass         http://appserver;
        proxy_cookie_path / "/; secure;";
        proxy_set_header   X-IBanking   "127.0.0.1";
        proxy_set_header   X-Real-IP    $remote_addr;
        proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header   X-NginX-Proxy    true;
        proxy_set_header   X-Request-Id $txid;
        add_header X-Frame-Options "SAMEORIGIN";
        add_header Strict-Transport-Security max-age=15552000;
        proxy_http_version 1.1;
        proxy_redirect off;
    }

    gzip on;
    gzip_comp_level 2;
    gzip_proxied any;
    gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript application/javascript;
    gzip_buffers 16 8k;
    gzip_vary on;
}

我认为单独使用 nginx 是不可能的。 我正在使用 koa-generic-session 和 redis。通过这种方式,您所有的节点都连接到 redis 以 read/write 会话值,并且只要该服务器连接到您的 redis 服务器,seesion 就会跟随用户到任何上游服务器。

这个例子来自https://github.com/koajs/generic-session

var session = require('koa-generic-session');
var redisStore = require('koa-redis');
var koa = require('koa');

var app = koa();
app.keys = ['keys', 'keykeys'];
app.use(session({
  store: redisStore()
}));

app.use(function *() {
  switch (this.path) {
  case '/get':
    get.call(this);
    break;
  case '/remove':
    remove.call(this);
    break;
  case '/regenerate':
    yield regenerate.call(this);
    break;
  }
});

function get() {
  var session = this.session;
  session.count = session.count || 0;
  session.count++;
  this.body = session.count;
}

function remove() {
  this.session = null;
  this.body = 0;
}

function *regenerate() {
  get.call(this);
  yield this.regenerateSession();
  get.call(this);
}

app.listen(8080);

这是我目前在多上游环境中用于会话的内容。