Keepalive+nginx实现高可用负载均衡方案
作者:尹正杰
版权声明:原创作品,谢绝转载!否则将追究法律责任。
一.nginx做高可用工作在第几层?
上个月我发表了一篇keepalive+lvs的高可用负载均衡方案,lvs调用内核模块ip_vs模块去工作,有四种常用的LVS模式,分别是”DR模式“,”NAT模式“,”FULLNAT模式“,”tunnel模式“(其中的工作原理可以参考:http://www.cnblogs.com/yinzhengjie/p/6194313.html)。这种模式适合大并发的门户网站,像目前淘宝用的就是这种模式,但是也有缺点啊:由于是调用内核去处理请求的数据,这就限制了它处于osi模型的传输层(它工作在第四次,我们通常称做L4)。如果想基于扩展名成转发以*png,*jpg等文件就比较困难啦,不适合用来做动静分离!这个时候开业用nginx来处理,把四层和七层的应用分开,所以现在大家明白了nginx如果是做负载均衡的话应该是工作在应用层(第七层)。一般大型企业的话会2个一起结合使用,有的公司还会用到haproxy(更专注做反向代理)。
二.nginx能做什么?
这个网上百度出来会有很多奇葩的回答,长篇大论上百字没说明白用途,上来就说模块的使用,建议参考官网文档说明,我所知道的nginx有以下三个功能:
1.web服务器;
2.反向代理;
3.缓存(需要用到squid这个软件)
现在您应该明白相比apache为什么很多人喜欢nginx了吧~说道Nginx不得不提一下Tengine,Tengine是由淘宝网发起的Web服务器项目。它在Nginx的基础上,针对大访问量网站的需求,添加了很多高级功能和特性。开源,而且目前51cto用的就是这个开源软件,建议还是用Nginx,因为nginx比较普及嘛,不过你牛逼你也是可以研究一下的,只要你能驾驭的好就OK!连接地址是:http://tengine.taobao.org/
三.对比nginx和lvs。
nginx反向代理适合日均1000w到2000W(适合业务比较单一的) PV的中小型互联网公司,如果贵公司规模较大建议不要使用这种模式,因为nginx反向代理是处理客户端请求,之后去后台真是的服务器上去取数据,最后把取到的数据返回给客户端,整个处理过程都要经过nginx调度器,想对与lvs的DR模式来说,这就是决定2者负载能力的差异性。当然也有解决方案。我们可以在nginx调度器下设置proxy代理服务器,让proxy代理去给主的nginx交换压力,(这个很类似企业部署zabbix监控系统的架构,也会有proxy,假设贵公司是做dns域名解析的,在美国,香港,全国各地都有服务器需要监控,我们只需要监控每个地区的proxy的机器就好,每一必要监控每一天服务器哟)一般大型企业是不会只是用单一的lvs或者nginx来去解决负载均衡的,会根据业务的需求,是否要实行动静分离,用lvs做转发,用nginx实现动静分离。我们今天的主角不是动静分离,而是用其的负载均衡。有时间的话我会写一篇关于nginx实现动静分离的方案的。
四.根据生产场景选择适合您的方案.
在工作中LVS和Proxy都可以是多实例。根据公司的需求,看看公司的产品是否是有必要都走四层或者七层,可以根据实际情况来进行分工处理,如果不需要基于扩展名的话就不要用proxy体系了,直接用lvs去实现性能效果更佳,如果业务量不大,功能要求还很高的话可以直接用Nginx proxy。大型互联网公司的话会用到3个生产场景。
一般的生产场景:
1.大并发 简单L4转发 LVS
2.大并发 功能要求URI转发 LVS+NGINX
3.并发不大 nginx/haproxy(后者更专注做反向代理)
五.upstream模块配置解析
nginx的负载均衡功能依赖于ngx_http_upstream_module模块,所支持的代理有proxy_pass(反向代理),fastcgi_pass(处理动态的应用程序),memcahed_pass().语法格式可以参考官方文档:http://nginx.org/en/docs/http/ngx_http_upstream_module.html。
我截取了官方文档的一些配置进行汉化说明:
我们把上面的配置代码单独取出来进行文字说明:
Example:
upstream yinzhengjie{ server backend1.example.com weight=5;
#server是固定的,后面可以接域名(门户会用)或IP。如果不加端口,默认是80端口 weight代表的是权重,值越大分配的几率越高;(提示:server如果接域名,需要内网有DNS服务器,或者在负载均衡器的hosts文件做域名解析。server后面可以直接还可以直接接IP或IP加端口)server 127.0.0.1:8080 max_fails=3 fail_timeout=30s;
#域名加端口,转发到后台的指定端口上,类似于NAT。server unix:/tmp/backend3;
#指定socket文件server backup1.example.com backup;
#备份服务器,等上面指定的服务器都不可以访问的时候会启用,backup的用法和haproxy中用法一样,其实2台keepalive+http做高可用,我们可以直接用nginx的backup参数就可以实现了。}
weight
=
number参数说明:
max_fails
=
number
Nginx尝试链接后端主机失败的次数,这个数值是配合proxy_next_upstream,fastcgi_next_upstream,and memcached_next_upstream这三个参数来使用的,当nginx接受后端服务器返回这三个参数定义的状态吗的时候会将这个请求转发给正常工作的后端服务器,例如:404,502,503.max_fails默认值为1
fail_timeout
=
time
如果max_fails是5,他就检查5次,如果5次都是502.那么,他就会根据fail_timeout的值,等待10s再去检查
4>.backup
这标志着这个服务器作为备份服务器,当主服务器全部宕机的时候,才会向他转发请求。(注意,当负载均衡算法为ip_hash时,后端服务器在负载均衡调度中的状态不能是weight或者backup!)
5>.down
这标志着服务器永远不可用,这个参数一直配合ip_hash使用。而且这个参数要慎用啊,仅限于你机器比较多的情况下,如果你就两三台服务器的话,那你就得注意了哟!
七.upstream的算法
1.rr轮询(默认)
按照客户请求顺序把客户端的请求逐一分配到不同的后端的服务器,这相当于LVS中rr算法,如果后端服务器宕机(默认情况下只检测80端口,如果后端报502,404,403,503,还是会直接返还给用户),宕机服务会被自动剔除,使用户访问不受影响。请求会分配给正常的服务器。
2.weight权重(rr+weight)
在轮询的算法基础上加上权重(默认是rr+weight),权重轮询和访问成正比,权重越大,转发的请求也就越多。可以根据服务器的配置和性能指定权重值的大小,可以有效解决新旧服务器性能不均进行请求分配问题。
可以配置相同的权重,使得后台的服务器得到访问情况均衡起来,例如:
3.ip_hash算法
每个请求按访问ip的hash结果分配,这样每个访客固定访问一个后端服务器,可以解决session的问题。(注意:当负载调度算法为ip_hash时候,会导致分配不均!因为后端服务器在负载均衡调度中的状态不能是weight和backup),制定算法的格式如下:如果不指定的话默认是rr算法哟~
4.fair(第三方,需要下载upstream_fair模块)
按照后端服务器的响应时间来分配请求,相应时间短的有限分配。比上面两个更加智能的负载均衡算法。此种算法可以一句页面大小和加载时间长短只能的进行负载均衡,也就是根据后端服务器的响应时间来分配请求,响应时间短的优先分配。nginx本身不支持fail算法的,如果需要使用这种调度算法,必须下载nginx的upstream_fair模块。配置如下:
5.url_hash(第三方,需要下载hash软件包)
按照访问url的hash结果来分配请求,让每个url定向到同一个后端服务器,后端服务器为缓存服务器时效显著,在upstream中加入hash语句,server语句中不能写入weight等其他的参数,hash_method是使用的hash算法。url_hash,按访问url的hash结果来分配请求,使每个url定向到同一个后端服务器,可以进一步提高后端缓存服务器的命中几率。Nginx本身是不支持url_hash的,如果需要使用这种调度算法,必须安装nginx的hash软件包。
6.least_conn
对比后台的服务器的链接数,哪个机器连接数少就分发给谁。
7.least_time header
| last_byte
;
8.NTLMM
这个功能可以实现Nginx代理的节点访问日志记录客户的IP而不是代理的IP,这个要注意你的nginx版本
9.一致性hash模块,这个算法感兴趣的朋友可以参考一下:
这种算法多用于缓存,上面的这个链接有如何配置配置,已经如果安装这个模块的教程。
八.location具体参数及说明
location / {
#用来指定代理的后端服务器地址和端口, 地址可以是主机名或者 IP 地址, 也可以是通过 upstream 指令设定的负载均衡组名称。
proxy_pass http://yinzhengjie;
#用来定义故障转移策略(如果做的是负载均衡的话,后面需要跟着upstream定义的名称哟),当后端服务节点返回 500、 502、 503、504 和执行超时等错误时,自动将请求转发到upstream负载均衡组中的另一台服务器,实现故障转移。
proxy_next_upstream http_500 http_502 http_503 error timeout invalid_header;
#禁止重定向
proxy_redirect off;
#proxy_set_header设置由后端的服务器获取用户的主机名或真实IP地址,以及代理者的真实IP地址。
proxy_set_header Host $host:$proxy_port;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# 用于指定客户端请求主体缓冲区大小,可以理解为先保存到本地再传给用户。
client_body_buffer_size 128k;
#表示与后端服务器连接的超时时间,即发起握手等候响应的超时时间。一般建议不要超过75s,默认时间60s。
proxy_connect_timeout 90;
#表示后端服务器的数据回传时间,即在规定时间之内后端服务器必须传完所有的数据,否则,Nginx将断开这个连接。默认时间60s。
proxy_send_timeout 90;
#设置Nginx从代理的后端服务器获取信息的时间,表示连接建立成功后,Nginx等待后端服务器的响应时间,其实是Nginx已经进入后端的排队之中等候处理的时间。默认时间60s。
proxy_read_timeout 90;
#设置缓冲区大小,默认该缓冲区大小等于指令proxy_buffers设置的大小。
proxy_buffer_size 4k;
#设置缓冲区的数量和大小。Nginx从代理的后端服务器获取的响应信息,会放置到缓冲区。
proxy_buffers 4 32k;
#用于设置系统很忙时可以使用的 proxy_buffers 大小, 官方推荐的大小为 proxy_buffers*2。
proxy_busy_buffers_size 64k;
#指定 proxy 缓存临时文件的大小。
proxy_temp_file_write_size 64k;
}
九.配置nginx的负载均衡
这个server定义了一个虚IP(这个IP是绑定在eth0上的一个虚接口IP,请暂时让我这么叫它),其实可以帮助我们做很多的事情的,比如在生产环境中我们可以定义多个虚IP来实现域名的转发,这样用户就没有必要敲击端口了,(当然也可以指定域名哟)只不过得在hosts文件中做一个映射。我把这段话先放在这里,以后我要是忘记了,还可以来看自己留下的笔记,因为我是哪种部署一个服务过1天就忘记的人,等下次看笔记的时候又能想起来,哈哈~建议大家也要多写写工作中的笔记,也方便你自己查问题,比如跟我一样申请一个博客园,哈哈~
测试配置是否正确:
[root@yinzhengjie conf]# /usr/local/nginx/sbin/nginx -s reload #进行平滑重启
备注:reload的话 是不再处理新建立的请求 处理完之前接收的请求然后再重启;但是我在做实验的时候发现这个参数不好使,经过高人指点用killall nginx干掉该进程,之后在启动服务,实验效果就出来了,如果大家遇到了类似的情况建议也使用该参数试试,系统重启后ngix reload不生效原因分析 :http://blog.chinaunix.net/uid-25057421-id-5611774.html
配置完毕以上操作,下面就开始测试环境啦:
我没有制定nginx的调度算法,默认就用的轮询,在这里我也没有加权重的参数。只是用了轮询的算法
十.Keepalive+nginx实现高可用负载均衡方案
前面都是虚的:只是给小白扫个盲而已,下面我们进行我开始部署一个简单的高可用的环境:最少需要4虚拟机完成该操作.
我们在上面的架构就用了3台服务器完成了负载均衡,我们只需要添加一台服务器就可以实现高可用啦
从上图得知,我们需要至少4台机器完成整个架构,我们可以负载均衡的架构上的配置都不动,然后新增一台机器,配置和172.30.1.60一样就好,而且服务都能正常调度。之后我们安装配置keepalived软件就好使了哟。
1.安装keepalived软件,172.30.1.60与172.30.1.196步骤一样。
[root@yinzhengjie ~]# mkdir /yinzhengjie/keepalived && cd /yinzhengjie/keepalived
[root@yinzhengjie keepalived]# wget http://www.keepalived.org/software/keepalived-1.3.2.tar.gz
[root@yinzhengjie keepalived]# ln -s /usr/local/etc/keepalived/keepalived.conf ./
[root@yinzhengjie keepalived]# ln -s /usr/local/sbin/keepalived /usr/bin/
[root@yinzhengjie keepalived]# more keepalived.conf
! Configuration File for keepalived
global_defs {
notification_email {
[email protected]
}
notification_email_from [email protected]
smtp_server exmail.qq.com
smtp_connect_timeout 30
router_id 100
}
vrrp_script check_nginx_services {
script "/usr/local/etc/keepalived/check_nginx.sh"
interval 3
weight -10
}
vrrp_instance VI_1 {
state BACKUP #2台机器的状态都为BACKUP,这样的话就可以实现仅仅用prority来决定主备了,不用等待master恢复后又重新争夺资源,其实尽管这个参数是master,但是他的活跃值(priority )小鱼backup的话照样不不能是真正的主哟~所以我们不要理解用这个参数去决定主备的主要因素哟,很多网友都这么配置,我也就跟风了,感兴趣的小伙伴也可以做下试验的哟!
interface eth0
virtual_router_id 51
priority 150
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
172.30.1.200
}
track_script
{
check_nginx_services
}
}
[root@yinzhengjie keepalived]#
[root@yinzhengjie keepalived]# more /usr/local/etc/keepalived/check_nginx.sh #这个脚本是用来检测nginx服务是否正常的,如果不正常就直接干掉keepalived,我这里配置的是单实例,至于多实例就要另外考虑了哟!
#!/bin/bash
count=`ps aux | grep -v grep | grep -v check_nginx.sh |grep nginx | wc -l` #我在这个地方踩了一个坑“check_nginx.sh”脚本名称和被“grep nginx”找到了,所以导致count不是我想要得到的数据呢!最后用-v取反参数搞定,我先写在这里,要是有小伙伴跟我一样遇到这个问题的时候可以找到错误的地方,哈哈。
if [ $count -gt 0
then
exit 0
else
killall keepalived
fi
[root@yinzhengjie keepalived]#
3.防火墙设置vip放行策略(不知道是否是版本的问题,一旦我运行keepalived服务的时候就会默认将我的VIP给DROP掉,防火墙关闭也不好使,所以我就干脆给手动配置了一条策略)
[root@yinzhengjie ~]# iptables -I INPUT -d 172.30.1.200 -j ACCEPT
[root@yinzhengjie ~]# service iptables save #记得要保存配置哟。
4.启动keepalived服务
如果您不清楚如何启动,可以查看外置keepalived命令的帮助信息
从上面看貌似是使用-f参数可以加载配置文件呢!
[root@yinzhengjie ~]# keepalived -f /yinzhengjie/keepalived/keepalived.conf
检测服务是否启动成功:172.30.1.60
检测服务是否启动成功:172.30.1.196
5.检测,关闭主机的NGINX服务,查看keepalived是否自动切换VIP
172.30.1.60上的操作:
172.30.1.196观察VIP是否成功切换过来了
测试服务是否正常运行:
好了,以上就是我们配置nginx+keepalived服务,如果你做到了,那么恭喜你成功了!默认的日志存放在/var/log/messages ,当然你可以通过修改配置文件达到输入日志存放其他路径的目的!详情请参考:http://www.cnblogs.com/yinzhengjie/p/6217758.html