
负载均衡是我们大流量网站要做的一个东西,下面我来给大家介绍在Nginx服务器上进行负载均衡配置方法,希望对有需要的同学有所帮助哦。
先来简单了解一下什么是负载均衡,单从字面上的意思来理解就可以解释N台服务器平均分担负载,不会因为某台服务器负载高宕机而某台服务器闲置的情况。那么负载均衡的前提就是要有多台服务器才能实现,也就是两台以上即可。
测试环境
由于没有服务器,所以本次测试直接host指定域名,然后在VMware里安装了三台CentOS。
测试域名 :a.com
A服务器IP :192.168.5.149 (主)
B服务器IP :192.168.5.27
C服务器IP :192.168.5.126
部署思路
A服务器做为主服务器,域名直接解析到A服务器(192.168.5.149)上,
由A服务器负载均衡到B服务器(192.168.5.27)与C服务器(192.168.5.126)上。
nginx 的 upstream目前支持 4 种方式的分配
0)、轮询(默认)
每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务器down掉,能自动剔除。
1)、weight
指定轮询几率,weight和访问比率成正比,用于后端服务器性能不均的情况。
2)、ip_hash
每个请求按访问ip的hash结果分配,这样每个访客固定访问一个后端服务器,可以解决session的问题。
3)、fair(第三方)
按后端服务器的响应时间来分配请求,响应时间短的优先分配。
4)、url_hash(第三方)
以追加的方式添加fair模块
//下载地址:
https://github.com/gnosek/nginx-upstream-fair
//目录不存在就自己新建 (将下载的所有文件放入这个目录中)
/usr/local/tengine-2.3.3/modules/ngx_http_upstream_fair_module
//查看已安装的模块:
#cd /usr/local/tengine/sbin
./nginx -V
Tengine version: Tengine/2.3.3
nginx version: nginx/1.18.0
built by gcc 8.5.0 20210514 (Red Hat 8.5.0-4) (GCC)
built with OpenSSL 1.1.1k FIPS 25 Mar 2021
TLS SNI support enabled
configure arguments: --prefix=/usr/local/tengine --with-http_v2_module --with-http_ssl_module --with-http_realip_module --with-http_stub_status_module --with-ipv6 --with-http_lua_module --with-luajit-inc=/usr/local/luajit/include/luajit-2.0 --with-luajit-lib=/usr/local/luajit/lib
1.备份原来的nginx
mv /usr/local/tengine/sbin/nginx /usr/local/tengine/sbin/nginx_back
2.用上边复制过的配置参数,加上--add-module=/xxx/ngx_http_upstream_fair_module,生成Makefile
3.执行make开始编译,但不要执行make install
注意事项:已安装Nginx,配置第三方模块时,只需要--add-module=/第三方模块目录,然后make编译一下就可以,不要 make install 安装。编译后复制objs下面的Nginx到指定目录下。
#cd /usr/local/tengine-2.3.3
./configure --prefix=/usr/local/tengine --with-http_v2_module --with-http_ssl_module --with-http_realip_module --with-http_stub_status_module --with-ipv6 --with-http_lua_module --with-luajit-inc=/usr/local/luajit/include/luajit-2.0 --with-luajit-lib=/usr/local/luajit/lib --add-module=/usr/local/tengine-2.3.3/modules/ngx_http_upstream_fair_module
//红色部分对应上面新建的目录
#make (不要执行 make install)
//编译完成后,复制/usr/local/tengine-2.3.3/objs/nginx 到/usr/local/tengine/sbin 下
upstream indexhandel(指定的域名){
server 127.0.0.1:9090 down;
server 127.0.0.1:8080 weight=2;
server 127.0.0.1:6060;
server 127.0.0.1:7070 backup;
}
[down]表示单前的server暂时不参与负载
[weight=2]默认为1.weight越大,负载的权重就越大。
[max_fails=2]允许请求失败的次数默认为1.当超过最大次数时,返回proxy_next_upstream 模块定义的错误
[fail_timeout=2s] 次失败后,暂停的时间。
[backup]备用服务器其它非backup机器或down或者忙的时候,才会请求backup机器。所以这台机器压力会最轻。
[ip_hash] 此技术能够将某个ip的请求定向到同一台后端,这样一来这个ip下的某个客户端和某个后端就能建立起稳固的session,ip_hash是在upstream配置中定义的:
upstream indexhandel{
ip_hash;
server 127.0.0.1:8080 max_fails=3 fail_timeout=20s;
server 127.0.0.1:9090 ;
}
ip_hash是容易理解的,但是因为仅仅能用ip这个因子来分配后端,因此ip_hash是有缺陷的,不能在一些情况下使用:
1.nginx不是最前端的服务器。ip_hash要求nginx一定是最前端的服务器,否则nginx得不到正确ip,就不能根据ip作hash。譬如使用 的是squid为最前端,那么nginx取ip时只能得到squid的服务器ip地址,用这个地址来作分流是肯定错乱的。
2.nginx的后端还有其它方式的负载均衡。假如nginx后端又有其它负载均衡,将请求又通过另外的方式分流了,那么某个客户端的请求肯定不能定位到同一 台session应用服务器上。这么算起来,nginx后端只能直接指向应用服务器,或者再搭一个squid,然后指向应用服务器。最好的办法是用 location作一次分流,将需要session的部分请求通过ip_hash分流,剩下的走其它后端去。
A服务器nginx.conf设置
在http段加入以下代码
upstream indexhandel{
ip_hash;
server 192.168.5.126:80; //转发到C服务器
server 192.168.5.27:80; //转发到B服务器
server 127.0.0.1:8080; //交由自己处理 8080
}
server{
listen 80;
server_name a.com;
location / {
proxy_pass http://indexhandel; #代理回本机最好用http
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
server{ #本机对本机的转发处理
listen 8080;
server_name 127.0.0.1;
root /usr/share/nginx/html;
location / {
set $args "";
proxy_pass http://chickencdn.info;
proxy_set_header Host chickencdn.info;
proxy_http_version 1.1;
}
}
保存重启nginx
B、C服务器nginx.conf设置
打开nginx.conf,在http段加入以下代码
upstream indexhandle{
ip_hash;
server 127.0.0.1:8081;
server 127.0.0.1:8082 max_fails=3 fail_timeout=20s;
}
#图片服务器... 响应
server {
listen 80;
listen 443 ssl;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_certificate /etc/letsencrypt/live/xx.net/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/xx.net/privkey.pem;
server_name media.xx.net;
include conf.d/set.ban.conf;
#root /usr/share/nginx/html;
#index index.php index.html index.htm;
location / {
expires 720d;
include conf.d/set.proxy.conf;#基本代理设置
proxy_pass http://indexhandle; #代理回本机最好用http
#proxy_pass https://xx.xx.net:209; #8443
include conf.d/set.proxy_cache.conf;#开启x-cache设置 缓存命中率·MISS 未命中
}
}
server {
listen 8081;
server_name 127.0.0.1;
root /usr/share/nginx/html;
location / {
include conf.d/set.proxy.conf;#基本代理设置
proxy_pass https://xmedia.xxx.net:2096;
}
}
server {
listen 8082;
server_name 127.0.0.1;
root /usr/share/nginx/html;
location / {
include conf.d/set.proxy.conf;#基本代理设置
proxy_pass https://xmedia.xxx.net:8443;
}
}
保存重启nginx
测试:
当访问a.com的时候,为了区分是转向哪台服务器处理我分别在B、C服务器下写一个不同内容的index.html文件,以作区分。
打开浏览器访问a.com结果,刷新会发现所有的请求均分别被主服务器(192.168.5.149)分配到B服务器(192.168.5.27)与C服务器(192.168.5.126)上,实现了负载均衡效果。
一、负载均衡不是nginx独有,著名鼎鼎的apache也有,但性能可能不如nginx。
二、多台服务器提供服务,但域名只解析到主服务器,而真正的服务器IP不会被ping下即可获得,增加一定安全性。
三、upstream里的IP不一定是内网,外网IP也可以。不过经典的案例是,局域网中某台IP暴露在外网下,域名直接解析到此IP。然后又这台主服务器转发到内网服务器IP中。
四、某台服务器宕机、不会影响网站正常运行,Nginx不会把请求转发到已宕机的IP上
一、Session问题
当我们确定一系列负载的服务器后,那我们的WEB站点会分布到这些服务器上。这个时候如果采用Test2 每一次请求随机访问任何一台服务器上,这样导致你访问A服务器后,下一次请求又突然转到B服务器上。这个时候与A服务器建立的Session,传到B站点 服务器肯定是无法正常响应的。我们看一下常用的解决方案:
- Session或凭据缓存到独立的服务器
- Session或凭据保存数据库中
- nginx ip_hash 保持同一IP的请求都是指定到固定的一台服务器
第一种缓存的方式比较理想,缓存的效率也比较高。但是每一台请求服务器都去访问Session会话服务器,那不是加载重了这台Session服务器的负担吗?
第二种保存到数据库中,除了要控制Session的有效期,同时加重了数据库的负担,所以最终的转变为SQL Server 负载均衡,涉及读,写,过期,同步。
第三种通过nginx ip_hash负载保持对同一服务器的会话,这种看起来最方便,最轻量。
正常情况下架构简单的话, ip_hash可以解决Session问题,但是我们来看看下面这种情况
