前言
- 本文章的目的旨在使用Nginx解决高并发情况下的负载均衡问题,也就是通常我们所说的集群。
读前准备
- 本文章涉及nginx的一些知识内容,以及正向代理和反向代理的概念理解,这些知识可参考我的博客里Nginx分类模块的内容。
- 我的博客关于nginx的内容地址为:https://blog.csdn.net/zengwende/article/category/8635956
解决问题
当访问量剧增的时候,单个服务器已经无法满足要求,此时应该要多个服务器一起分担压力,需要实现负载均衡请求分发(集群)
实验环境
1、三个不同端口的Tomcat(我三个tomcat的端口分别是8080、8081、8082)
2、Nginx(我的nginx版本为1.14.2)
解决方案
注:所有的代码修改都在nginx的nginx.conf文件上,192.168.3.38设置为我的本地IP
1、轮询(默认方式)
每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务器挂掉,能自动剔除,指定轮询几率,weight和访问比率成正比,用于后端服务器性能不均的情况。(如果不配权重weight,那就是按照顺序分配,相当于配置的weight都等于1)
#关键的代码
upstream zengwd.com {
server 192.168.3.38:8080 weight=1 max_fails=2 fail_timeout=2s;
server 192.168.3.38:8081 weight=2 max_fails=2 fail_timeout=2s;
server 192.168.3.38:8082 weight=2 max_fails=2 fail_timeout=2s;
}
server {
listen 80;
server_name 192.168.3.38;
#charset koi8-r;
#access_log logs/host.access.log main;
location / {
proxy_pass http://zengwd.com;
proxy_redirect default;
proxy_connect_timeout 2s;
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
拓展:
这个等待响应的时间我们是可以配置的。
这个时间由以下3个参数控制:
proxy_connect_timeout:与服务器连接的超时时间,默认60s
fail_timeout:当该时间内服务器没响应,则认为服务器失效,默认10s
max_fails:允许连接失败次数,默认为1
实验步骤
1、访问192.168.3.38(为什么访问这个地址?因为我们nginx的虚拟主机的server_name已经配置了192.168.3.38,相当于nginx已经代理了192.168.3.38,而我们访问192.168.3.38相当于访问192.168.3.38的80端口,nginx的默认端口也是80,所以访问192.168.3.38地址,就会通过nginx的代理)
2、观察现象(连续访问5次)
实验结果
第一次访问
第二次访问
第三次访问
第四次访问
第五次访问
从上面简单地实验现象我们可以看出访问8080、8081、8082的比例为1:2:2,这跟我们配置的轮询的权重策略一致,因此,在轮询的策略中,权重值越高,访问的概率越高,且按照分配的权重的比例来轮询。
2、ip_hash
每个请求按访问ip的hash结果分配,这样每个访客固定访问一个后端服务器,可以解决session的问题。
#关键的代码
upstream zengwd.com{
ip_hash;
server 192.168.3.38:8080 max_fails=2 fail_timeout=2s;
server 192.168.3.38:8081 max_fails=2 fail_timeout=2s;
server 192.168.3.38:8082 max_fails=2 fail_timeout=2s;
}
server {
listen 80;
server_name 192.168.3.38;
#charset koi8-r;
#access_log logs/host.access.log main;
location / {
proxy_pass http://zengwd.com;
proxy_redirect default;
proxy_connect_timeout 2s;
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
# proxy the PHP scripts to Apache listening on 127.0.0.1:80
#
#location ~ \.php$ {
# proxy_pass http://127.0.0.1;
#}
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
#location ~ \.php$ {
# root html;
# fastcgi_pass 127.0.0.1:9000;
# fastcgi_index index.php;
# fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
# include fastcgi_params;
#}
# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /\.ht {
# deny all;
#}
}
实验步骤
1、访问192.168.3.38
2、观察现象(连续访问5次)
实验结果
第一次访问
第二次访问
第三次访问
第四次访问
第五次访问
从上面简单地实验现象我们可以看出无论我怎么访问我就只能访问到tomcat1,也就是8080端口,因为nginx的ip_hash策略就是一个IP固定只能访问同一台服务器,与轮询不同。
3、最少连接
把请求分配到连接数最少的server,这样使得服务器之间的压力差不会过大。
#关键的代码
upstream zengwd.com{
least_conn;
server 192.168.3.38:8080 max_fails=2 fail_timeout=2s;
server 192.168.3.38:8081 max_fails=2 fail_timeout=2s;
server 192.168.3.38:8082 max_fails=2 fail_timeout=2s;
}
server {
listen 80;
server_name 192.168.3.38;
#charset koi8-r;
#access_log logs/host.access.log main;
location / {
proxy_pass http://zengwd.com;
proxy_redirect default;
proxy_connect_timeout 2s;
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
# proxy the PHP scripts to Apache listening on 127.0.0.1:80
#
#location ~ \.php$ {
# proxy_pass http://127.0.0.1;
#}
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
#location ~ \.php$ {
# root html;
# fastcgi_pass 127.0.0.1:9000;
# fastcgi_index index.php;
# fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
# include fastcgi_params;
#}
# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /\.ht {
# deny all;
#}
}
实验就不做了,步骤都是大同小异。最小连接这样的策略方式能够平均服务器的压力,不会出现有的负荷过重,有的几乎无压力的情况。
4、fair(第三方)
按后端服务器的响应时间来分配请求,响应时间短的优先分配。这个需要安装第三方的插件,如果有需要的我出安装fair教程,请在评论区下留言。
#关键的代码
upstream zengwd.com{
server 192.168.3.38:8080 max_fails=2 fail_timeout=2s;
server 192.168.3.38:8081 max_fails=2 fail_timeout=2s;
server 192.168.3.38:8082 max_fails=2 fail_timeout=2s;
fair;
}
server {
listen 80;
server_name 192.168.3.38;
#charset koi8-r;
#access_log logs/host.access.log main;
location / {
proxy_pass http://zengwd.com;
proxy_redirect default;
proxy_connect_timeout 2s;
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
# proxy the PHP scripts to Apache listening on 127.0.0.1:80
#
#location ~ \.php$ {
# proxy_pass http://127.0.0.1;
#}
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
#location ~ \.php$ {
# root html;
# fastcgi_pass 127.0.0.1:9000;
# fastcgi_index index.php;
# fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
# include fastcgi_params;
#}
# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /\.ht {
# deny all;
#}
}
结语
大家可以根据自己服务器的状况自由搭配分配策略,以上的策略基本上能够满足集群的需求。其实还有一个问题,以上的问题都是解决服务器的压力问题,这都是建立在nginx的服务器没有挂掉的情况。如果nginx服务器挂掉了,等于整个系统都挂掉了,所以这是不是要考虑nginx的集群?还是其他措施?可关注我后续的文章,有兴趣的请留言。
彩蛋
nginx的conf文件最好不要出现Tab等特殊字符或者隐藏字符,否则很容易报错。当然具体的原因可以看下nginx下的logs的error日志。