nginx的负载均衡配置及原理

摘要 nginx是十分的强大,不仅在web方面的高并发承载能力,在反向代理方面也是非常的优秀。而且,nginx可以按照调度规则实现动态、静态页面的分离,可以按照轮询、ip哈希、URL哈希、权重等多种方式对后端服务器做负载均衡。其健康状态检测也是非常的优秀,可以解决实现后端项目假死的监控,以及自动的剔除。如果在配合监控报警,那真是格外的酸爽。
windows和Linux下配置Nginx负载的写法一样,故不分开介绍.

nginx负载均衡策略
nginx 的 upstream目前支持5种方式的分配式。

1)轮询(默认)
每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务器down掉,能自动剔除。
2)weight
指定轮询几率,weight和访问比率成正比,用于后端服务器性能不均的情况。
3)ip_hash
每个请求按访问ip的hash结果分配,这样每个访客固定访问一个后端服务器,一定程度上可以解决session的问题(排除同一个公网地址多内网的情况下)。
4)fair(第三方)
按后端服务器的响应时间来分配请求,响应时间短的优先分配。
5)url_hash(第三方)
按访问URL的hash结果来分配请求,使每个URL定向到同一个后端服务器,后端服务器为缓存时比较适用。另外,在upstream中加入hash语句后,server语句不能写入weight等其他参数。

 
nginx负载均衡的配置
在http节点里添加:


upstream 每个设备的状态解释:

down 表示当前的server暂时不参与负载
weight 默认为1.weight越大,负载的权重就越大。
max_fails:允许请求失败的次数默认为1.当超过最大次数时,返回proxy_next_upstream 模块定义的错误。
fail_timeout:max_fails 次失败后,暂停的时间。
backup:其它所有的非backup机器down或者忙的时候,请求backup机器。所以这台机器压力会最轻。

Nginx还支持多组的负载均衡,可以配置多个upstream 来服务于不同的Server。
配置负载均衡比较简单,但是最关键的一个问题是怎么实现多台服务器之间session的共享
下面有几种方法

1.ip_hash的方式实现session保持
nginx中的ip_hash技术能够将某个ip的请求定向到同一台后端,这样一来这个ip下的某个客户端和某个后端就能建立起稳固的session,ip_hash是在upstream配置中定义的:

但是,如前文所说。nginx的ip_hash在面对同一个公网下,N个内网IP的负载能力非常差。而且,这个方案要保证nginx拿到的用户IP地址一定是真实的,也就是说需要让nginx作为最前端的服务器接收器,如果nginx不是第一个接受的用户信息,那么有可能获得不到用户的真是ip,比如我前端还有一个F5设备那么我获取到的IP就是F5的IP,那么分发就毫无意义了。还需要保证nginx后端服务器直接处理,而不是后端还有其他的分发服务器,那么如果那个后端分发服务器又使用其他分发规则的话,还是无法让同一个IP访问同一台机器

2.服务器集群 进行session共享
例如tomcat 集群后session共享,weblogic集群和session共享,这样情况下需要牺牲服务器的一部分性能用来保持session同步,
对于性能要求不是很高,并且服务器负载不是很严重的情况可以考虑,这种方案可以节省很多不必要的成本,不需要单独开发程序进行维护,只需要让服务器配置集群即可。

3.使用cookie代替session
把session改成cookie,就能避开session的一些弊端,在从前看的一本J2EE的书上,也指明在集群系统中不能用session,否则惹出祸端来就不好办。如果系统不复杂,就优先考虑能否将session去掉,改动起来非常麻烦的话,再用下面的办法。
如果可以的话使用cookie代替session,但是需要一些限制条件,比如:浏览器不能设定限制cookie的使用.
如果担心cookie安全的问题可以使用加密的cookie进行处理..

cookie代替session大体的思路如下:
cookie的存储过程:
1.将要保存的javabean转成json字符串(用gson工具)
2.des加密json字符串
3.设置到根域名的cookie中cookie.setDomain("itmmd.com");
解析过程:
1.遍历所有cookie
2.找到对应的cookie
3.des解密json字符串
4.还原为javabean(gson).

4.使用数据库服务器存储session共享
asp.net可以用数据库或memcached来保存session,从而在asp.net本身建立了一个session集群,用这样的方式可以令 session保证稳定,即使某个节点有故障,session也不会丢失,适用于较为严格但请求量不高的场合。但是它的效率是不会很高的,不适用于对效率 要求高的场合。

5.upstream_hash
为了解决ip_hash的一些问题,可以使用upstream_hash这个第三方模块,这个模块多数情况下是用作url_hash的,但是并不妨碍将它用来做session共享:
假如前端是squid,他会将ip加入x_forwarded_for这个http_header里,用upstream_hash可以用这个头做因子,将请求定向到指定的后端:
在文档中是使用$request_uri做因子,稍微改一下:

这样就改成了利用x_forwarded_for这个头作因子,在nginx新版本中可支持读取cookie值,所以也可以改成:

假如在php中配置的session为无cookie方式,配合nginx自己的一个userid_module模块就可以用nginx自发一个cookie.

可参见userid模块的英文文档:
http://wiki.nginx.org/NginxHttpUserIdModule
另可用姚伟斌编写的模块upstream_jvm_route:http://code.google.com/p/nginx-upstream-jvm-route/
可见这篇文档:http://www.sudone.com/nginx/nginx_url_hash.html

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: