当前位置:首页 > 综合

nginx反向代理与负载均衡

凌晨两点,向代我盯着监控面板上那台服务器的理负CPU曲线,它像一条直线冲上了天花板。载均用户报障的向代电话已经打爆了运维同事的手机。那台可怜的理负机器,正独自扛着整个网站所有的载均请求,像一个人用肉身堵枪眼。向代

后来我们加了nginx。理负它站在用户和服务器之间,载均像一扇旋转门。向代用户只看到nginx的理负脸,而nginx背后,载均一群服务器排着队等活儿干。向代这就是理负反向代理——它藏住了真实的服务器,所有请求先过它这一关。载均它还能干点小动作:把静态文件直接自己吞了,不往后端传;或者给请求头加点料,让后端知道用户从哪儿来。

但真正救命的,是负载均衡。

nginx把进来的请求按策略分发到后端集群。最简单的是轮询,一个接一个,雨露均沾。可这策略太天真——万一某台机器性能差,它会被活活累死,而旁边的空转。所以得加上权重。比如那台老机器weight=1,新买的双路至强weight=3,nginx就会按比例分配。我见过一个哥们,把所有服务器权重都设成一样,结果一台老机器频繁宕机,他愣是没发现是权重问题,排查了三天。

还有更聪明的策略。ip_hash,根据用户IP算个哈希值,同一个IP永远打到同一台服务器。这玩意儿对需要session的应用特别友好——不用在集群里同步session了。但有个坑:如果某个IP是公司出口的NAT,那几千个员工全被扔到同一台机器上。我踩过这坑,当时那台机器流量直接翻十倍,我还以为是攻击。

least_conn,哪个服务器当前连接数少就发给谁。这策略适合长连接场景,比如WebSocket。但nginx的least_conn不是实时统计,是近似值,高并发下会有点偏差,不过够用了。

配置本身不复杂,一个upstream块加一个server块的事。

upstream backend {  server 192.168.1.10:8080 weight=3; server 192.168.1.11:8080 weight=1; server 192.168.1.12:8080 backup; } server {  listen 80; location / {  proxy_pass http://backend; proxy_set_header Host $host; } } 

那个backup关键字很关键,平时它不干活,只有前面两台全挂时才顶上。我建议生产环境至少留一台backup,不然nginx会把请求直接甩给一个不存在的地址,报502。

健康检查是另一个坑。默认nginx只做TCP端口检查,后端进程卡死但端口还开着,它照样转发流量。得配主动检查——每隔几秒发个HTTP请求,拿到200才认为活着。nginx开源版没这功能,得用nginx plus或者自己写lua脚本。我们当时用了个折中方案,写个shell脚本定期curl后端,不正常的就从upstream里摘出去,虽然糙,但管用。

最后说个细节。proxy_next_upstream这个参数,默认是error和timeout。如果后端返回500,nginx不会自动换一台重试。加上proxy_next_upstream http_500,就能在遇到500时自动跳到下一台服务器。这招能救不少用户体验——用户刷新一下可能就好了,虽然背后的服务器其实在报错。

别迷信负载均衡能解决所有问题。它只是把流量摊开,如果后端每个节点都是豆腐渣,那摊得再平也是碎一地。先保证单机能扛住,再谈集群。nginx不是银弹,它只是把问题从一台机器转移到了多台机器——但至少,凌晨两点不用再一个人盯着那条直线了。

分享到: