基于 nginx 的七层负载均衡实现初步



0x01 此次演示环境

1
2
3
4
NginxHttp ip: 192.168.3.49 作为负载均衡器,测试域名为 `lb.org`,生产环境中,最好自己新建个虚拟ip来做负载均衡,方便后续迁徙
OldLamp ip: 192.168.3.45 后端真实处理请求的web服务器 httpd-2.2.34
OldLnmp ip: 192.168.3.42 后端真实处理请求的web服务器 nginx-1.12.2
NewLnmp ip: 192.168.3.43 作为访问客户端,测试各种负载均衡算法是否工作

先改下当前nginx负载均衡器的host解析,即NginxHttp机器,因为等会儿要直接用机器名去访问后端的web节点

1
2
3
# vi /etc/hosts
192.168.3.42 test.bwapp.org bwapp.org
192.168.3.45 bwapp.cc www.bwapp.cc

再来改下Newlnmp机器的host解析,添加如下内容,因为等会儿要用它来进行测试访问

1
2
# vi /etc/hosts
192.168.3.49 lb.org

0x02 以下是一些常用的负载均衡调度算法

1
2
3
4
5
6
rr [ 正常轮询 ] 即按照事先给定的后端节点顺序挨个轮询,适合性能相近,业务相同的场景
wrr [ 权重轮询 ] 即按照事先设置好的后端节点轮询比例,进行轮询,适合机器性能差距较大,业务相同的场景
ip_hash [ ip hash ] 也就是说只要客户端ip不变,在一段时间内就只访问固定的后端节点,`常用于会话保持`,如session,cookie,不过这样保持,负载就不均衡了
fair [ 动态算法 ] 属于第三方算法,即根据节点的响应时间来分配请求,响应快的节点优先分配
url_hash [ 节点取模 ] 也属于第三方节点,根据url来分配后端节点,命中率比较低,不过非常适合做web缓存
一致性 hash ...

0x03 在 nginx 中可用来实现负载均衡的主要模块

1
2
upstream 模块 定义好后端节点及所使用调度算法,大致工作过程是这样的,它会先读取upstream中的配置,然后通过server标签中的proxy_pass来进行实际的调用
http_proxy 模块 主要负责实际的转发行为

0x04 先在用来做负载均衡的机器上安装好 nginx 1.12.2

1
2
3
4
5
6
7
8
9
10
11
12
13
# yum install pcre pcre-devel openssl openssl-devel -y
# useradd -s /sbin/nologin -M nginx
# wget http://nginx.org/download/nginx-1.12.2.tar.gz
# tar xf nginx-1.12.2.tar.gz
# cd nginx-1.12.2
# ./configure --prefix=/usr/local/nginx-1.12.2 --user=nginx --group=nginx \
--with-http_ssl_module \
--with-http_stub_status_module \
--with-http_gzip_static_module \
--with-mail_ssl_module
# make && make install
# ln -s /usr/local/nginx-1.12.2/ /usr/local/nginx

0x05 关于上述两个模块的简单使用样例

1
upstream 模块,主要用来定义后端的真实web服务器节点和要使用的调度算法,配置详情如下

1
2
3
4
5
6
7
upstream backend { # 先定义好后端web节点
server 192.168.3.45 weight=3; # 选择权重轮询方式,默认不指定会按正常逐个节点轮询
server 192.168.3.42 ;
server backup1.example.com:8080 backup; # 当上面的节点都挂掉时才会启用这个,相当于自带的高可用
server backup2.example.com:8080 backup;
}
1
http_proxy 模块,主要负责请求转发,但转发的方式有很多种,不过用nginx做反向代理通常会使用 `proxy_pass`
1
2
3
4
5
server { # 此时再到指定的server标签段中去引用刚刚的定义,即可实现简单的负载均衡效果
location / {
proxy_pass http://backend;
}
}

0x06 接下来,开始真正在nginx上配置负载均衡及反向代理

1
2
3
4
5
# mkdir /usr/local/nginx/conf/extra/
# cd /usr/local/nginx/conf/
# mv nginx.conf nginx.conf.bak
# egrep -v "^$|#" nginx.conf.bak > nginx.conf
# vi /usr/local/nginx/conf/nginx.conf

先在nginx.conf 文件中定义好如下配置,这里先以正常轮询为例进行演示

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# vi /usr/local/nginx/conf/nginx.conf
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
log_format main '$remote_addr - $remote_user [$time_local] '
' "$request" $status $body_bytes_sent '
' "$http_referer" "$http_user_agent" "$http_x_forwarded_for" ';
include extra/lb.conf;
upstream server_pools{ # 设置后端web节点,可同时规定好要使用的轮询算法
server test.bwapp.org:80;
server www.bwapp.cc:80;
}
}

然后再到 lb.conf 文件中去定义好要进行负载均衡的域名,即[server标签段],引用上面nginx.conf文件中upstream定义好的后端web节点

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# vi /usr/local/nginx/conf/extra/lb.conf
server{
listen 80;
server_name lb.org;
location / {
# 下面的语句就表示把请求转发到指定的后端web节点上
proxy_pass http://server_pools;
# 在往后端抛的时候务必要带上主机头,因为后端的web节点是根据这个主机头来确定,是哪个虚拟机主机
proxy_set_header Host $host;
# 另外,记得要把原始客户端ip也带上,不然后端web节点日志中的就只能记录到负载均衡器的ip,而没有客户端的真实ip
proxy_set_header X-Forwarded-For $remote_addr;
}
}

0x07 nginx 负载均衡基本工作流程简述

1
2
3
4
当客户端访问 `lb.org` 域名时请求会最先到达负载均衡器,负载均衡器就会去读取自己server标签段中的配置
到location里面一看,原来这是一个要往后端web节点抛的请求
而后,nginx通过 `server_pools` 在自己的主配置文件找到了事先定义好的后端web节点
最后,按照事先设置好的轮询算法,把请求带上主机头和客户端原始ip一起抛给后端准备好的web服务器

0x08 所配置完成之后,我们回到NewLnmp机器上进行轮询测试,看访问是否正常

1
2
# /usr/local/nginx/sbin/nginx -t
# /usr/local/nginx/sbin/nginx

在你没指定负载均衡算法的情况下,默认是按照事先定义好的后端web节点顺序逐个轮询的,如下

1
# for i in `seq 10`; do curl lb.org;sleep 1 ;done

接下来,我们让它权重轮询看看,定义方法很简单,只需要把前面http标签段的内容修改为下面这个样子即可

1
2
3
4
5
6
7
8
http {
...
upstream server_pools{
server test.bwapp.org:80 weight=3; # 设置权重比例
server www.bwapp.cc:80;
}
...
}

最后,再去看看基于ip hash的轮询算法是个什么样子

1
2
3
4
5
6
7
8
9
http {
...
upstream server_pools{
ip_hash; # 基于ip hash的轮询算法
server test.bwapp.org:80;
server www.bwapp.cc:80;
}
...
}

0x09 最后,再回到OldLamp和OldLnmp 机器上看看日志有没有被正确记录到

1
# tail -f /usr/local/httpd/logs/bwapp-access_20171204.log

1
# tail -f /usr/local/nginx/logs/access_bwapp.log



小结:
    这里提到的只是一部分,更详细具体的用法,请直接参考nginx官方文档,另外,nginx负载均衡较适合用于日pv 2000W以下的站点