Django - 应用水平扩展

使用 Tengine 和负载均衡

简介

Tengine 是由淘宝网发起的 Web 服务器项目。它在 Nginx 的基础上,针对大访问量网站的需求,添加了很多高级功能和特性。Tengine 的性能和稳定性已经在大型的网站如淘宝网天猫商城等得到了很好的检验。它的最终目标是打造一个高效、稳定、安全、易用的 Web 平台。

特性

  1. 安装 Tengine

  2. 指定 pcre 源码目录安装 tengine

最简单的配置:路由转发请求到 Gunicorn/uWSGI 服务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
server {
listen 80;
server_name recruit.mycompany.com;

location / {
# 转发请求到gunicorn进程处理
proxy_pass http://127.0.0.1:8000;

proxy_set_header Host $http_host;
proxy_set_header x-Real-IP $remote_addr;

# 包含了客户端地址,以及各级代理IP的完整IP链
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}

使用 Tengine/Nginx 负载均衡

Tengine

  • 请求路由到两台后端服务器
  • 两台后端服务器 Upstream
    • 服务器运行 Gunicorn/uWSGI
    • 单台服务器运行有两个实例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#vim /data/tengine/conf.d/recruitment.conf

upstream django-server {
# max_fails = 3为允许失败的次数,默认值为1。对后端节点做健康检查。
# 20s内,当max_fails次失败后,暂停将请求分发到该服务器
server 192.168.1.2:8001 max_fails=3 fail_timeout=20s;
server 192.168.1.2:8002 max_fails=3 fail_timeout=20s;
server 192.168.1.3:8001 max_fails=3 fail_timeout=20s;
server 192.168.1.3:8002 max_fails=3 fail_timeout=20s;
}
server {
listen 80;
server_name www.mycompany.com;

access_log /data/tengine/logs/recruitment-access.log main;
error_log /data/tengine/logs/recruitment-error.log;

location / {
proxy_pass http://django-server;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header REMOTE-HOST $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}

Tengine 的分流策略

负载分流策略

  • round-robin — 平均分配流量:轮询模式
  • least-connected — 最少连接优先,下一个请求分到活跃连接最少的服务器
  • ip-hash — 按照客户端 IP 哈希来分配服务器 IP
  • 带权重流量分配
  • 一致性哈希 (Tengine)
  • 会话保持 (Tengine 特性)

最少连接优先

  • 前面配置的为平均分配流量;
  • 按照最少连接优先 /ip hash 的配置:
    1
    2
    3
    4
    5
    6
    7
    upstream django-upstream {
    least_conn; # for ip hash: ip_hash;
    server 192.168.1.2:8001;
    server 192.168.1.2:8002;
    server 192.168.1.3:8001;
    server 192.168.1.3:8002;
    }

按权重分配

  • 按照权重分配(适合机器配置不一样时)
  • 6 个请求里面,3 个走到第一台,其它 3 台没台 1 个请求。
    1
    2
    3
    4
    5
    6
    upstream django-upstream {
    server 192.168.1.2:8001 weight=3;
    server 192.168.1.2:8002;
    server 192.168.1.3:8001;
    server 192.168.1.3:8002;
    }

会话保持

  • 尽可能保证同一个客户端访问的都是同一个后端服务器
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    # 默认配置:cookie=route mode=insert fallback=on
    upstream django-upstream {
    server 192.168.0.1;
    server 192.168.0.2;
    session_sticky;
    }

    server {
    location / {
    proxy_pass http://django-upstream;
    }
    }

健康检查自动容错

  • 被动健康检查

    ngx_http_upstream_module 实现了被动的健康检查功能

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    # 被动健康检查
    upstream backend {
    server 127.0.0.1:8000 max_fails=2 fail_timeout=20s;
    server 127.0.0.1:8001 max_fails=2 fail_timeout=20s;
    }

    server {
    listen 80;
    server_name recruit.mycompany.com;

    location / {
    proxy_pass http://backend;
    }
    }
  • 主动健康检查

    http_upstream_check_module,主动定时检查

    1
    2
    3
    4
    5
    6
    7
    8
    # 主动健康检查
    upstream django-upstream {
    server 192.168.1.2:8000;
    server 192.168.1.3:8000;
    check intervel=3000 rise=2 fall=3 timeout=1000 type=http;
    check_http_send "HEAD / HTTP/1.0\r\n\r\n";
    check_http_expect_alive http_2xx http_3xx;
    }
    1
    2
    3
    4
    5
    6
    7
    指令后面的参数意义是:
    interval:向后端发送的健康检查包的间隔。
    fall(fall_count):如果连续失败次数达到fall_count,服务器就被认为是down。
    rise(rise_count):如果连续成功次数达到rise_count,服务器就被认为是up。
    timeout:后端健康请求的超时时间。

    上面配置的意思是,对django_upstream的所有节点,每个3秒(3000毫秒)检测一次,请求2次正常则标记realserver状态为up,如果检测3次都失败,则标记realserver的状态为down,超时时间为1秒。