Nginx负载均衡
2015 年 02 月 02 日
nginx

    当后端Web服务器为了支撑更大的吞吐量, 减少请求延迟时, 就需要部署多个Web服务器同时提供服务, 这个时候我们也需要用到Web代理的负载均衡了.

  • 为多个Web服务器设置server组

  • # 我们首先需要定义一组虚拟主机, 如:
    upstream web_server {
        server 192.168.1.14:8080; # web1
        server 192.168.1.10:8080; # web2
    }
                
    # 当然还得将nginx请求转发到web_server:
    server {
        listen 80;
        server_name  *.xxx.com;
    
        location / {
            proxy_pass http://web_server;
        }
    }
    # 这时用户访问*.xxx.com, 请求将根据负载均衡策略状态到web1或web2去.
                
  • 选择负载均衡策略, Nginx支持如下负载均衡策略:

  • # 1.轮询(round-robin): 请求被均匀地分发到Web服务器(考虑web服务器权重), 这也是默认的策略.
    # 2.最少连接(least_conn): 每次将请求转发到当前激活连接数最少的web服务器(考虑web服务器权重):
    upstream web_server {
        least_conn;
    
        server 192.168.1.14:8080; # web1
        server 192.168.1.10:8080; # web2
    }
                
    # 3.ip_hash: nginx通过客户端IP(IPv4的前3段或整个IPv6)地址计算hash值, 这样可以保证同样的IP请求到同样的web服务器:
    upstream web_server {
        ip_hash;
    
        server 192.168.1.14:8080; # web1
        server 192.168.1.10:8080; # web2
    }
                
    # 4.通用hash: nginx可以通过对文本, 变量等进行hash值计算, 若源IP, 端口或者URI:
    upstream web_server {
        hash $request_uri consistent; # consistent表示一致性哈希
    
        server 192.168.1.14:8080; # web1
        server 192.168.1.10:8080; # web2
    }
                
    # 若想临时移除某个web服务器, 可以使用down标记:
    upstream web_server {
        server 192.168.1.14:8080; # web1
        server 192.168.1.10:8080 down; # web2
    }
                
  • web服务器权重

  • # 可以通过weight参数指定web服务器权重:
    upstream web_server {
        server 192.168.1.14:8080 weight=5; # web1, 默认weight=1, 这时来6个请求, 会有5个请求到web1, 1个请求到web2
        server 192.168.1.10:8080; # web2
    }
                
  • 延迟web服务器启动

  • upstream web_server {
        server 192.168.1.14:8080 slow_start=30s; # web1, slow_start设置web服务器恢复权重的时间
        server 192.168.1.10:8080; # web2
    }
                
  • 开启Session保持, 即nginx将标识用户session, 并且将该session的request都转发到相同的Web服务器, nginx支持3种会话保持策略(需要nginx-sticky-module模块):

  • # 1. sticky cookie, 当web服务器第一次响应request时, nginx会向client写入一个cookie, 下次client再请求, 则会被转发到同一台机器:
    upstream web_server {
        server 192.168.1.14:8080; # web1
        server 192.168.1.10:8080; # web2
        sticky cookie {cookie_name} expires=1h domain={cookie域} path={cookie路径};
    }
                
    # 2. sticky route, 当nginx收到client第一个请求时, 会分配一个叫"route"的cookie给client, 后续请求将被转发到对应route的Web服务器上:
    upstream web_server {
        server 192.168.1.14:8080 route=web1; # web1
        server 192.168.1.10:8080 route=web2; # web2
        sticky route $route_cookie $route_uri;
    }
                
    #  3. cookie learn, nginx第一次会根据request和response找到session标识符, 并且nginx会学会哪个web服务器对应哪个session标识符, 这些标识符通常在HTTP Cookie中:
    upstream web_server {
        server 192.168.1.14:8080; # web1
        server 192.168.1.10:8080; # web2
    
        sticky learn
            create=$upstream_cookie_sessionid # 必须, nginx会通过cookie中的SESSIONID来创建会话
            lookup=$cookie_sessionid          # 必须, 通过cookie中的SESSIONID来查询存在的会话
            zone=client_sessions:1m           # 必须, 指定session信息保存的内存区域叫client_seesions, 并1M大小
            timeout=1h;
    }
                
  • 在nginx plus中限制连接数

  • upstream web_server {
        server 192.168.1.14:8080 max_conns=30; # web1, 超过最大连接数后, 请求将被放入queue中等待
        server 192.168.1.10:8080; # web2
    
        queue 100 timeout=70;   #若queue放满, 70s后, client将收到错误
    }
                
  • 被动的健康监控

  • # 当nginx察觉到web服务器不可用时, 会暂时停止向该web服务器转发请求
    upstream web_server {
        server 192.168.1.14:8080 max_fails=3 fail_timeout=30s; # 若在30s内, nginx发现3次web服务器响应失败, 则认为该web服务器不可用
        server 192.168.1.10:8080;
    }
                
  • 主动的健康监控(nginx_upstream_check_module)

  • # nginx周期性向web服务器发送特定的请求, 然后检查web服务器的响应是否满足某个条件, 来判定web服务器是否可用
    upstream web_server {
        zone backend 64k;  # 定义多个worker processes共享的内存大小及该server组的配置信息
    
        server 192.168.1.14:8080;
        server 192.168.1.10:8080;
    }
    server {
        listen 80;
        server_name  *.xxx.com;
    
        location / {
            proxy_pass http://web_server;
            health_check; # 默认nginx每隔5秒会向web_server组下的web服务器的"/"路径发送请求, 若发生错误nginx会认为该web服务器不可用, 直到下次检查该web_server可用。
        }
    }
                
  • 多个工作进程共享数据

  • 1. 如果upstream没有指定zone, 那么每个工作进程将保留一份server的配置, 并且维护各自的计数器集。
    2. 当我们使用health_check和runtime modification时, zone配置是必须的, 也就是说所有工作进程应该共享这些配置, 计数器等数据。

好人,一生平安。