分析NGINX 健康检查和负载均衡机制
nginx 是优秀的反向代理服务器,这里主要讲它的健康检查和负载均衡机制,以及这种机制带来的问题。所谓健康检查,就是当后端出现问题(具体什么叫出现问题,依赖于具体实现,各个实现定义不一样),不再往这个后端分发请求,并且做后续的检查,直到这个后端恢复正常。所谓负载均衡,就是选择后端的方式,如何(根据后端的能力)将请求均衡的分发到后端。此外,当请求某个后端失败时,要将该请求分发到其它后端(redispatch)。这里以ngx_http_upstream_round_robin(简称RR)做为负载均衡模块,以ngx_http_proxy_module(检查proxy)作为后端代理模块。
nginx 的健康检查和负载均衡是密切相关的,它没有独立的健康检查模块,而是使用业务请求作为健康检查,这省去了独立健康检查线程,这是好处。坏处是,当业务复杂时,可能出现误判,例如后端响应超时,这是可能是后端宕机,也可能是某个业务请求自身出现问题,跟后端无关。如果后端宕机,nginx还要在将它标记为不可用之后,仍不时的将业务请求分发给它,以检查后端是否恢复。
nginx 完成客户端请求Header部分的解析,upstream 调用RR模块的peer.get 选择具体的后端。当请求结束,upstream 调用RR模块的peer.free,向RR反馈后端的健康情况。当upstream和后端通信时,出现错误会调用 ngx_http_upstream_next,
void ngx_http_upstream_next(ngx_http_request_t *r, ngx_http_upstream_t *u, ngx_uint_t ft_type); 第三个参数指明错误类型,共有如下错误类型
#define NGX_HTTP_UPSTREAM_FT_ERROR 0x00000002
#define NGX_HTTP_UPSTREAM_FT_TIMEOUT 0x00000004
#define NGX_HTTP_UPSTREAM_FT_INVALID_HEADER 0x00000008
#define NGX_HTTP_UPSTREAM_FT_HTTP_500 0x00000010
#define NGX_HTTP_UPSTREAM_FT_HTTP_502 0x00000020
#define NGX_HTTP_UPSTREAM_FT_HTTP_503 0x00000040
#define NGX_HTTP_UPSTREAM_FT_HTTP_504 0x00000080
#define NGX_HTTP_UPSTREAM_FT_HTTP_404 0x00000100
#define NGX_HTTP_UPSTREAM_FT_UPDATING 0x00000200
#define NGX_HTTP_UPSTREAM_FT_BUSY_LOCK 0x00000400
#define NGX_HTTP_UPSTREAM_FT_MAX_WAITING 0x00000800
#define NGX_HTTP_UPSTREAM_FT_NOLIVE 0x40000000
ngx_http_upstream_next,只要错误类型不是 NGX_HTTP_UPSTREAM_FT_HTTP_404,都认为后端有问题(NGX_PEER_FAILED)
if (ft_type == NGX_HTTP_UPSTREAM_FT_HTTP_404) {
state = NGX_PEER_NEXT;
} else {
state = NGX_PEER_FAILED;
}
ngx_http_upstream_next 调用RR的peer.free,RR根据state判断刚才接受请求的后端是否健康。
if (ft_type != NGX_HTTP_UPSTREAM_FT_NOLIVE) {
u->peer.free(&u->peer, u->peer.data, state);
}
ngx_http_upstream_next 如果超过最大重试次数(默认为后端的个数,每试过一个,就减1),或者proxy设置不允许redispatch,则向客户端返回响应status。
if (u->peer.tries == 0 || !(u->conf->next_upstream & ft_type)) {
ngx_http_upstream_finalize_request(r, u, status);
}
proxy 模块的 proxy_next_upstream 配置,在何种情况下将请求redispatch到下一个后端。
刚刚谈到,只要错误类型不是 NGX_HTTP_UPSTREAM_FT_HTTP_404,都认为后端有问题。这里的错误类型包括,连接后端失败,连接,读写后端超时,后端返回了500,502,504等。这个策略是有待商榷的,尤其是读写后端超时也判断为后端不可用。因为某个业务请求,可能因为自身的原因而导致读写超时。注意,在proxy_next_upstream 中指定timeout,http_504 是不同的,前者表示upstream连接,读写后端超时,后者表示后端返回的http code 是504。
实际上健康检查不是必须的,因为redispatch的存在保证了,就算有后端宕机,客户端仍将收到正确的响应。那么我们考虑关掉健康检查。通过upstream 的server配置的max_fails 参数
RR 的peer.get,如果max_fails 为0,则该后端总是可用的(就算它真有问题)。
if (peer->max_fails == 0
|| peer->fails < peer->max_fails)
{
break;
}
因为redispatch的次数,取决于后端的个数,所以后端的个数稍微多一点是有好处的。
下面是一些佐证分析的测试。
upstream test {
server 127.0.0.1:8060 max_fails=0;
server 127.0.0.1:8070 max_fails=0;
server 127.0.0.1:8080 max_fails=0;
server 127.0.0.1:8090 max_fails=0;
}
只有8060,8070是存活的,8080,8090处于不可用状态,这里max_fails=0,关闭了健康检查。
proxy_read_timeout 2;
读超时设为2S。
proxy_next_upstream error timeout;
默认当 error 和 timeout发生时,redispatch。
测试请求的sleep参数指定后端的sleep时间,code参数指定后端返回的http code。根据time和sleep时间的对比,判断重试了几个后端。
time curl "http://127.0.0.1:8099/index.php?sleep=3" -vv
real 0m4.014s
sleep=3,读超时,重试了2个后端。
修改配置 proxy_next_upstream error;
time curl "http://127.0.0.1:8099/index.php?sleep=3" -vv
real 0m2.018s
读超时,不再redispatch,重试了1个后端。
修改配置 proxy_next_upstream error http_504;
time curl "http://127.0.0.1:8099/index.php?sleep=1" -vv
real 0m1.022s
这个是正常请求。
time curl "http://127.0.0.1:8099/index.php?sleep=1&code=504" -vv
real 0m2.023s
让后端返回504,此时nginx会做redispatch,重试了2个后端
但是nginx返回给客户端的是502,不是504,因为所有的后端都返回504,nginx认为后端不可用,返回502.
测试健康检查,关掉redispatch。proxy_next_upstream off;
curl "http://127.0.0.1:8099/index.php?sleep=3" -vv
返回了两次502,两次504。存活的后端返回504,有问题的返回502。
修改 max_fails server 127.0.0.1:8060 max_fails=1; 对8060开启健康检查。
curl "http://127.0.0.1:8099/index.php?sleep=3" -vv
第一轮4次请求,返回两次502,两次504
8080和8090有问题,返回502,8060和8070响应超时,返回504,因为8060开启了健康检查,并且返回了504,所以被标记为不可用。
第二轮4次请求,返回三次502,一次504。8070没有开启健康检查,所以仍然返回504。
根据测试分析,业务请求(sleep 3s,或者 输出 http 504)可以让nginx误以为后端宕了,而这时后端活得好好的。在私有云平台,这个通常不是问题,把超时设大点,不返回5XX错误,可以避免这个问题。但是在公有云平台,这是致命的,因为业务可以编程输出5XX错误。有两种方法应对,一种是关闭健康检查,一种是修改nginx的代码,仅对 NGX_HTTP_UPSTREAM_FT_ERROR 判定为后端有问题。
分析NGINX 健康检查和负载均衡机制的更多相关文章
- nginx 健康检查和负载均衡机制分析
nginx 是优秀的反向代理服务器,这里主要讲它的健康检查和负载均衡机制,以及这种机制带来的问题.所谓健康检查,就是当后端出现问题(具体什么叫出现问题,依赖 于具体实现,各个实现定义不一样),不再往这 ...
- 【翻译】Nginx的HTTP负载均衡
本文为翻译文,原文地址:http://nginx.org/en/docs/http/load_balancing.html 介绍 将请求负载均衡到多个应用实例是一个常用的技术,它起到优化资源使用率.最 ...
- octavia的实现与分析(一)·openstack负载均衡的现状与发展以及lvs,Nginx,Haproxy三种负载均衡机制的基本架构和对比
[负载均衡] 大量用户发起请求的情况下,服务器负载过高,导致部分请求无法被响应或者及时响应. 负载均衡根据一定的算法将请求分发到不同的后端,保证所有的请求都可以被正常的下发并返回. [主流实现-LVS ...
- openstack octavia的实现与分析(一)openstack负载均衡的现状与发展以及lvs,Nginx,Haproxy三种负载均衡机制的基本架构和对比
[负载均衡] 大量用户发起请求的情况下,服务器负载过高,导致部分请求无法被响应或者及时响应. 负载均衡根据一定的算法将请求分发到不同的后端,保证所有的请求都可以被正常的下发并返回. [主流实现-LVS ...
- Nginx/LVS/HAProxy 负载均衡软件的优缺点详解
Nginx/LVS/HAProxy 负载均衡软件的优缺点详解 Nginx/LVS/HAProxy是目前使用最广泛的三种负载均衡软件,本人都在多个项目中实施过,参考了一些资料,结合自己的一些使用经验 ...
- 总结)Nginx/LVS/HAProxy负载均衡软件的优缺点详解
总结)Nginx/LVS/HAProxy负载均衡软件的优缺点详解 PS:Nginx/LVS/HAProxy是目前使用最广泛的三种负载均衡软件,本人都在多个项目中实施过,参考了一些资料,结合自己的一些使 ...
- Nginx/LVS/HAProxy负载均衡软件的优缺点详解【转】
转自 (总结)Nginx/LVS/HAProxy负载均衡软件的优缺点详解http://www.ha97.com/5646.html PS:Nginx/LVS/HAProxy是目前使用最广泛的三种负载均 ...
- (总结)Nginx/LVS/HAProxy负载均衡软件的优缺点详解
Nginx/LVS/HAProxy负载均衡软件的优缺点详解 PS:Nginx/LVS/HAProxy是目前使用最广泛的三种负载均衡软件,参考了一些资料,结合自己的一些使用经验,总结一下. 一般对负载均 ...
- nginx+php负载均衡集群环境中的session共享方案梳理
在网站使用nginx+php做负载均衡情况下,同一个IP访问同一个页面会被分配到不同的服务器上,如果session不同步的话,就会出现很多问题,比如说最常见的登录状态. 下面罗列几种nginx负载均衡 ...
随机推荐
- Struts2--简单的数据校验
action没有request, response等属性, 无法往前台传信息, 出来一个概念, valuestack: 存放action的属性, 还有各种error等... <s:propert ...
- 关于python 函数参数
函数参数:必选参数.默认参数.可选参数.关键字参数 1.默认参数 默认参数可以简化函数的调用.设置默认参数时,有几点要注意: 一是必选参数在前,默认参数在后,否则Python的解释器会报错: 二是如何 ...
- 微信小程序实例教程(三)
第七章:微信小程序编辑名片页面开发 编辑名片有两条路径,分为新增名片流程与修改名片流程. 用户手填新增名片流程: 首先跳转到我们的新增名片页面 1 需要传递用户的当前 userId,wx.na ...
- 支持持久化的内存数据库-----Redis
一.Redis概述 1.1.什么是Redis Redis是一种高级key-value数据库.它跟memcached类似,不过数据 可以持久化,而且支持的数据类型很丰富.有字符串,链表,集 合和有序集合 ...
- hibernate--一对多单向关联 (重点!!!)
多对一是在多的类上存在一的对象 一对多是在一的类上存在多的集合. 多的类 user.java: package com.bjsxt.hibernate; import javax.persistenc ...
- Linux下的强大工具之一sed(转),Shell必备
sed命令基本用法sed是一个非交互式文本编辑器,它可以对文本文件和标准输入进行编辑,标准输入可以是来自键盘输入.文件重定向.字符串.变量.来自管道的文本等等.sed从文本的一个文本行或标准输入中读取 ...
- [Unity Shader]光照模型对物体的假设
什么是光照模型 光照模型就是模拟光在物体间的传递过程,以确保物体可见表面每一点的亮度和颜色. 当光照射到一个物体表面时,光可能被吸收.反射或折射.反射和折射的光使物体可见.如果入射光全部被吸收,物体将 ...
- linux动态链接库---一篇讲尽
一般我们在Linux下执行某些外部程序的时候可能会提示找不到共享库的错误, 比如: tmux: error while loading shared libraries: libevent-1.4.s ...
- arm-linux学习笔记3-linux内存管理与文件操作
配置好linux系统之后需要vim配置一下,有助于我们的编程,主要的配置如下 在/etc/vim/vimrc文件中 "显示行号 set number "自动缩进 set autoi ...
- Tyvj P3276
题目链接:http://www.tyvj.cn/p/3276 这题是一个动归题,一直没有想出动归的做法,后来求教别人之后写了一个记忆化搜索,只有出题者又给我提供了DP的解法,下面我来写写DP的写法 设 ...