nginx负载均衡实践初探

nginx logo

0x00 负载均衡、分布式、集群

名词满天飞的上云时代,这些个概念,大概不需要人去解释罢。打开谷歌,一搜一大把。

这些东西,大概是运维接触得比较多,敲代码的估计是没多少人会深入研究。闹太套,这种观念是不太对的。代码敲得多了,总该将技能的触角深入到“其他领域”,即便只需要知道那么一些。

不管是分布式、集群,负载均衡是最基本的,负载均衡是大型构架的一个重要的、基础环节。

根据应用、系统的构架,负载均衡会存在于很多地方。从DNS解析,请求路由,应用服务器每个环节都可以做负载均衡。负载均衡不是一个新的技术和概念,只是最近几年尤其火热。

身为全世界最好语言的拥趸,了解服务器方面的东西,势当必行。

0x01 实践环境

这次的实验环境使用了6台服务器。其中

1
2
Windows*1
Ubuntu*5

其中的Windows是一台i7 CPU + 8g 内存的配置还算可以的物理机器。而5台ubuntu则是架设在该物理机器上面,基于VirtualBox的Ubuntu16.10的Server版本的虚拟机。

Show My Ubuntus

安装Server版本是因为图省事儿、省资源。服务器版本的ubuntu可以选择性的安装很多服务器运行软件,其中包括一套完整的apache + MySQL + PHP;相比桌面版的ubuntu,服务器版本的ubuntu不会默认启用桌面,因此资源上面省了很大一截。

需要注意的是,虚拟机的网络配置需要设置称为桥接。

虚拟机网络设置为桥接模式

1
2
3
Tips:
安装虚拟机事实上只需要完整的安装一台,其他的可以通过复制的方式复制第一台。
复制的时候选择重置网络配置即可。

0x02 假装是构架

当然,应用层负载均衡的实现有很多方案,HAProxy、LVS、Nginx……总有一款适合你。

呐,不过个人觉得nginx应该是最简单的方案了,尤其是对于码农而言。所以这里采用的是nginx。所以,我才用了如图的构架:

服务器构架

千言万语不如一张图。如果所示的,是本次试验采用的构架方式,U00~U03是本次的应用服务器组。UShare则是准备用来共享Session的session存储服务器。DBServers则表示日后扩展出数据库集群服务器。当然,本次重点仅在蓝色部分。

1
由于只关注负载均衡,图示并没有画出完成的从request到response的过程,同时也没有详细的描述出session和数据库的存储。

这样一个“构架”,大概是最基本的结构了。

1
这里负载均衡的机器是宿主机器,也就是我在windows上面放了nginx(别惊讶,这里只是测试,生产环境当中,科学的做法是放到Linux当中)。

0x03 软件安装

所谓软件安装,其实就是宿主机器上面的nginx安装、虚拟机上面的LAMP安装,当然这一切都是建立在安装了VirtualBox的基础上的。由于是采用Server版本的ubuntu,安装操作系统的时候默认安装了LAMP,所以这里省了很多事儿。

即便不采用服务器版本的Ubuntu这里LAMP的安装也和传统的“单机”服务器安装没啥差别,这里不再啰嗦。有需要的请自行谷歌。

那么,接下来就只有一件事情了————在宿主机器上安装nginx。这里就更简单了,到nginx官网下载zip,解压缩。Done。。。

0x04 配置Nginx

老实说,这一段儿才是这篇文档的重点。。。

打开nginx.conf文件(一般在-nginx安装目录-/conf/目录下)

文件中添加区域A,修改区域B:

1
2
3
4
5
6
7
8
http {
...其它代码...
# 区域A upstream balance { server 192.168.6.13; server 192.168.6.14; server 192.168.6.15; server 192.168.6.16; } server { listen 80; server_name localhost; location / { root html;
index index.html index.htm; # 区域B proxy_connect_timeout 3; proxy_send_timeout 30; proxy_read_timeout 30; proxy_pass http://balance/; proxy_redirect default; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
}

其中区域A的代码:

1
2
3
4
5
6
upstream balance {
server 192.168.6.13;
server 192.168.6.14;
server 192.168.6.15;
server 192.168.6.16;
}

balance是分流均衡的名称,可以是你定义的任何东西。同时nginx是支持一台nginx给多个应用分流的,用不同的分流名称是可以造就不同的分流应用的。

这段代码指定了负载均衡的分摊机器,这里是通过IP地址来分流的。这样写是最基本的写法,直接列出IP地址即可。

事实上,这里还可以指定参数。格式如下:

1
server IP:PORT WEIGHT

其中,IP自然是指的IP地址,port是指的端口号(所以,我们可以在同一台机器上开不同端口的应用,然后当作不同的分流机器使用),weight则表示权重。权重的取值可以是:

1
2
3
4
down 表示不参与负载均衡
weight=n 根据n的权重参与负载均衡
backup 作为备份服务器参与负载均衡
留空 默认的方式参与负载均衡

例子:server 192.168.1.88:8080 weight=10 & server 192.168.1.188 backup

顺便copy了一段关于nginx复杂均衡的分配方式说明:

1
2
3
4
5
6
nginx 的 upstream目前支持 4 种方式的分配
1)、轮询(默认):每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务器down掉,能自动剔除。
2)、weight :指定轮询几率,weight和访问比率成正比,用于后端服务器性能不均的情况。
2)、ip_hash :每个请求按访问ip的hash结果分配,这样每个访客固定访问一个后端服务器,可以解决session的问题。
3)、fair(第三方):按后端服务器的响应时间来分配请求,响应时间短的优先分配。
4)、url_hash(第三方)

代码区域B的说明如下:

1
2
3
4
5
6
7
8
proxy_connect_timeout 3; #连接超时时间
proxy_send_timeout 30; #发送超时时间
proxy_read_timeout 30; #读取超时时间
proxy_pass http://balance/; #指定负载均衡分流的方式
proxy_redirect default; #代理跳转方式
proxy_set_header Host $host; #设置请求头
proxy_set_header X-Real-IP $remote_addr; #设置请求头
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; #设置请求头

0x05 Nginx负载均衡vs反向代理

从配置上看,负载均衡的配置有些类似反向代理:

1
proxy_pass http://127.0.0.1/; #甚至直接按照负载均衡的方式配置,在upstream留一行server的配置

0x06 测试一下

到这里,负载均衡的配置是完了。接下来,我们可以测试一番。

为了方便观察,我们可以将U00~U03的四台机器web服务器的首页改成不同的内容。
接下来,访问nginx所在机器。多次刷新,nginx会将我们的请求分发到不同的web服务器。

0x07 后续

分布式之后负载固然得到了改善,但是新的问题就来了:

1.不同的服务器session怎么同步?(怎么保证用户不感知服务器切换)

2.应用程序是分布式了,那么数据库怎么解决?

且听下回分解。。。