七年开发浅谈Nginx负载均衡
一 特点
1.1 应用情况
Nginx做为一个强大的Web服务器软件,具有高性能、高并发性和低内存占用的特点。此外,其也能够提供强大的反向代理功能。俄罗斯大约有超过20%的虚拟主机采用Nginx作为反向代理服务器,在国内也有腾讯、新浪、网易等多家网站在使用Nginx作为反向代理服务器。据Netcraft统计,世界上最繁忙的网站中有11.48%使用Nginx作为其服务器或者代理服务器。基于反向代理的功能,Nginx作为负载均衡主要有以下几点理由:
- 高并发连接
- 内存消耗少
- 配置文件非常简单
- 成本低廉
- 支持Rewrite重写规则
- 内置的健康检查功能
- 节省带宽
- 稳定性高
1.2 架构
nginx在启动后,会以daemon的方式在后台运行,后台进程包含一个master进程和多个worker进程。工作进程以非特权用户运行。
master进程主要用来管理worker进程,包含:接收来自外界的信号,向各worker进程发送信号,监控worker进程的运行状态,当worker进程退出后(异常情况下),会自动重新启动新的worker进程。
worker进程则是处理基本的网络事件。多个worker进程之间是对等的,他们同等竞争来自客户端的请求,各进程互相之间是独立的。一个请求,只可能在一个worker进程中处理,一个worker进程,不可能处理其它进程的请求。
开发模型:epoll和kqueue。
支持的事件机制:kqueue、epoll、rt signals、/dev/poll 、event ports、select以及poll。
支持的kqueue特性包括EV_CLEAR、EV_DISABLE、NOTE_LOWAT、EV_EOF,可用数据的数量,错误代码.
支持sendfile、sendfile64和sendfilev;文件AIO;DIRECTIO;支持Accept-filters和TCP_DEFER_ACCEP.
1.3 性能
Nginx的高并发,官方测试支持5万并发连接。实际生产环境能到2-3万并发连接数。10000个非活跃的HTTP keep-alive 连接仅占用约2.5MB内存。三万并发连接下,10个Nginx进程,消耗内存150M。淘宝tengine团队说测试结果是“24G内存机器上,处理并发请求可达200万”。
二 负载均衡
2.1 协议支持
Nginx工作在网络的7层,可以针对http应用本身来做分流策略。支持七层HTTP、HTTPS协议的负载均衡。对四层协议的支持需要第三方插件-yaoweibin的ngx_tcp_proxy_module实现了tcp upstream。
此外,nginx本身也逐渐在完善对其他协议的支持:
nginx 1.4.0对Websocket和SPDY都做了正式的支持。
nginx 1.6.0对SPDY 3.1的正式支持
nginx 1.10.0正式支持HTTP/2
目前,nginx最新稳定版为1.10.2,主线开发版本已经到了1.11.5。Tengine最新版本则继承到了nginx的1.6.2版本。
2.2 均衡策略
nginx的负载均衡策略可以划分为两大类:内置策略和扩展策略。内置策略包含加权轮询和ip hash,在默认情况下这两种策略会编译进nginx内核,只需在nginx配置中指明参数即可。扩展策略有很多,如fair、通用hash、consistent hash等,默认不编译进nginx内核。
①、加权轮询(weighted round robin)
轮询的原理很简单,首先我们介绍一下轮询的基本流程。如下是处理一次请求的流程图:
图中有两点需要注意,第一,如果可以把加权轮询算法分为先深搜索和先广搜索,那么nginx采用的是先深搜索算法,即将首先将请求都分给高权重的机器,直到该机器的权值降到了比其他机器低,才开始将请求分给下一个高权重的机器;第二,当所有后端机器都down掉时,nginx会立即将所有机器的标志位清成初始状态,以避免造成所有的机器都处在timeout的状态,从而导致整个前端被夯住。
②、ip hash
ip hash是nginx内置的另一个负载均衡的策略,流程和轮询很类似,只是其中的算法和具体的策略有些变化,如下图所示:
ip hash算法的核心实现如下:
for(i = 0;i < 3;i++){
hash = (hash * 113 + iphp->addr[i]) % 6271;
}
p = hash % iphp->rrp.peers->number;
从代码中可以看出,hash值既与ip有关又与后端机器的数量有关。经过测试,上述算法可以连续产生1045个互异的value,这是该算法的硬限制。对此nginx使用了保护机制,当经过20次hash仍然找不到可用的机器时,算法退化成轮询。因此,从本质上说,ip hash算法是一种变相的轮询算法,如果两个ip的初始hash值恰好相同,那么来自这两个ip的请求将永远落在同一台服务器上,这为均衡性埋下了很深的隐患。
③、fair
fair策略是扩展策略,默认不被编译进nginx内核。其原理是根据后端服务器的响应时间判断负载情况,从中选出负载最轻的机器进行分流。这种策略具有很强的自适应性,但是实际的网络环境往往不是那么简单,因此要慎用。
④、通用hash、一致性hash
这两种也是扩展策略,在具体的实现上有些差别,通用hash比较简单,可以以nginx内置的变量为key进行hash,一致性hash采用了nginx内置的一致性hash环,可以支持memcache。
⑤、session_sticky
此种策略就是一次会话内的请求都会落到同一个结点上。在做分布式架构时可以使用,但是当一个结点挂掉时,会话信息同时也会丢失,如果使用session同步方案同步session信息到所有结点的话代价又会很高,慎重使用此方案。nginx默认不支持此种策略,tengine提供了支持: http://tengine.taobao.org/document_cn/http_upstream_session_sticky_cn.html.
2.2 配置示例
①、HTTP
upstream upstream_test{
server 192.168.0.1:8080;
server 192.168.0.2:8080;
#ip_hash;
keepalive 30;
## tengine config
#check interval=300 rise=10 fall=10 timeout=100 type=http port=80;
#check_http_send "GET / HTTP/1.0 ";
#check_http_expect_alive http_2xx http_3xx;
## tengine config
#session_sticky cookie=cookieTest mode=insert;
}
location / {
proxy_pass http://upstream_test;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
②、TCP - ngx_tcp_proxy_module
tcp {
upstream cluster {
# simple round-robin
server 192.168.0.1:8080;
server 192.168.0.2:8080;
check interval=3000 rise=2 fall=5 timeout=1000;
#check interval=3000 rise=2 fall=5 timeout=1000 type=ssl_hello;
#check interval=3000 rise=2 fall=5 timeout=1000 type=http;
#check_http_send "GET / HTTP/1.0 ";
#check_http_expect_alive http_2xx http_3xx;
}
server {
listen 8888;
proxy_pass cluster;
}
}
三 动态负载均衡
3.1 自身监控
内置了对后端服务器的健康检查功能。如果Nginx proxy后端的某台服务器宕机了,会把返回错误的请求重新提交到另一个节点,不会影响前端访问。它没有独立的健康检查模块,而是使用业务请求作为健康检查,这省去了独立健康检查线程,这是好处。坏处是,当业务复杂时,可能出现误判,例如后端响应超时,这可能是后端宕机,也可能是某个业务请求自身出现问题,跟后端无关。
3.2 可扩展性
Nginx属于典型的微内核设计,其内核非常简洁和优雅,同时具有非常高的可扩展性。如下图所示:
Nginx是纯C语言的实现,其可扩展性在于其模块化的设计。目前,Nginx已经有很多的第三方模块,大大扩展了自身的功能。nginx_lua_module可以将Lua语言嵌入到Nginx配置中,从而利用Lua极大增强了Nginx本身的编程能力,甚至可以不用配合其它脚本语言(如PHP或Python等),只靠Nginx本身就可以实现复杂业务的处理。
3.3 配置修改
nginx的配置架构如下图所示:
Nginx支持热部署,几乎可以做到7*24不间断运行,即使运行数个月也不需要重新启动。能够在不间断服务的情况下,对软件版本进行进行升级。Nginx的配置文件非常简单,风格跟程序一样通俗易懂,能够支持perl语法。使用nginx –s reload可以在运行时加载配置文件,便于运行时扩容/减容。重新加载配置时,master进程发送命令给当前正在运行的worker进程worker进程接到命令后会在处理完当前任务后退出。同时,master进程会启动新的worker进程来接管工作。
四 优势和劣势
4.1 优势
- 可以很好地进行http 的头处理
- 对http协议以及https的良好支持
- 有足够的第三方插件供使用
- 支持热部署,更改后端是平滑的
4.2 劣势
- 缺少对session的支持
- 对四层tcp的支持不够好
- post请求写文件系统,造成500 error
- 缺乏主动的后端服务器健康监测
- 默认的监控界面统计信息不全
五 Tengine
Tengine是淘宝基于nginx开源代码二次开发一款服务器软件,在继承了nginx的特性以外,提供了一些nginx商业版才有的功能。基本上同步于nginx的更新,目前最新的版本已经继承了nginx 1.6.2稳定版。
5.1 特性
tengine的特性包括但不限于:
- 更友好的运维信息显示
- 动态模块加载机制
- 自动根据CPU数目设置进程个数和绑定CPU亲缘性
- 更方便的命令行参数,如列出编译的模块列表、支持的指令等
- 更加强大的负载均衡能力,包括一致性hash模块、会话保持模块,还可以对后端的服务器进行主动健康检查,根据服务器状态自动上线下线
- 动态脚本语言Lua支持。扩展功能非常高效简单
- 输入过滤器机制支持。通过使用这种机制Web应用防火墙的编写更为方便
5.2 负载均衡
负载均衡方面,Tengine主要有以下几个特点,基本上弥补了nginx在负载均衡方面的欠缺:
- 支持一致性Hash模块
- 会话保持模块
- 对后端服务器的主动健康检查。
- 增加了请求体不缓存到磁盘的机制
写在最后:欢迎留言讨论,加关注,持续更新!
七年开发浅谈Nginx负载均衡的更多相关文章
- 浅谈Nginx负载均衡和F5的区别
前言 笔者最近在负责某集团网站时,同时用到了Nginx与F5,如图所示,负载均衡器F5作为处理外界请求的第一道"墙",将请求分发到web服务器后,web服务器上的Nginx再进行处 ...
- 浅谈Nginx负载均衡与F5的区别
前言 笔者最近在负责某集团网站时,同时用到了Nginx与F5,如图所示,负载均衡器F5作为处理外界请求的第一道“墙”,将请求分发到web服务器后,web服务器上的Nginx再进行处理,静态内容直接访问 ...
- 【转】浅谈Nginx负载均衡与F5的区别
前言 笔者最近在负责某集团网站时,同时用到了Nginx与F5,如图所示,负载均衡器F5作为处理外界请求的第一道“墙”,将请求分发到web服务器后,web服务器上的Nginx再进行处理,静态内容直接访问 ...
- 浅谈Nginx负载均衡原理与实现
1.Nginx能做什么? Nginx可以两件事: -- HTTP请求 经过官方测试Nginx可以承受5万的并发量.可用来做静态资源的图片服务器 --负载均衡,如下解释什么是负载均衡. 2.负载均衡 ...
- 从小故事来谈nginx负载均衡
负载均衡 负载均衡是任何一个有一定规模的互联网企业都会考虑的问题,负载方式很多,有依靠硬件实现的,也有依靠软件实现负载的. 今天来聊聊使用软件来负载的方式 你可能听过各自负载的方式,比如常见的ngin ...
- 浅谈一个网页打开的全过程(涉及DNS、CDN、Nginx负载均衡等)
1.概要 从用户在浏览器输入域名开始,到web页面加载完毕,这是一个说复杂不复杂,说简单不简单的过程,下文暂且把这个过程称作网页加载过程.下面我将依靠自己的经验,总结一下整个过程.如有错漏,欢迎指正. ...
- 【转】浅谈一个网页打开的全过程(涉及DNS、CDN、Nginx负载均衡等)
1.概要 从用户在浏览器输入域名开始,到web页面加载完毕,这是一个说复杂不复杂,说简单不简单的过程,下文暂且把这个过程称作网页加载过程.下面我将依靠自己的经验,总结一下整个过程.如有错漏,欢迎指正. ...
- Nginx(七):keepalived实现Nginx负载均衡服务器的双机高可用
前言 之前咱们通过 Nginx(六):Nginx HTTP负载均衡和反向代理的配置与优化 和 Nginx+tomcat组合实现高并发场景的动静分离和负载均衡方案 这两篇文章了解了Nginx对高并发应用 ...
- FastDFS分布式文件系统&Nginx负载均衡最小环境安装配置[超级详解]
1.背景 FastDFS 是一款开源的.分布式文件系统(Distributed File System),由淘宝开发平台部资深架构师余庆开发.该开源项目的主页是 http://code.google. ...
随机推荐
- PostgreSQL中的partition-wise join
与基于继承的分区(inheritance-based partitioning)不同,PostgreSQL 10中引入的声明式分区对数据如何划分没有任何影响.PostgreSQL 11的查询优化器正准 ...
- matlab中可用于进行轮廓提取的函数
本文主要总结一下在matlab中可用于进行轮廓提取的函数. 1 bwperim 根据参考资料[2]的提示,可以使用bwperim()函数进行轮廓提取,具体代码如下: %读取原图im = imread( ...
- openstack虚拟机获取不到ip
一.现象描述: openstack平台中创建虚拟机后,虚拟机在web页面中显示获取到了ip,但是打开虚拟机控制台后查看网络状态,虚拟机没有ip地址,下图为故障截图: 二.分析思路: (1)查看neut ...
- [LeetCode] 123. Best Time to Buy and Sell Stock III 买卖股票的最佳时间 III
Say you have an array for which the ith element is the price of a given stock on day i. Design an al ...
- [LeetCode] 231. Power of Two 2的次方数
Given an integer, write a function to determine if it is a power of two. Example 1: Input: 1 Output: ...
- Kubernetes 健康状态检查(九)
强大的自愈能力是 Kubernetes 这类容器编排引擎的一个重要特性.自愈的默认实现方式是自动重启发生故障的容器.除此之外,用户还可以利用 Liveness 和 Readiness 探测机制设置更精 ...
- UE4的内存模型
转自:https://blog.csdn.net/noahzuo/article/details/73565259 UObject和FUObjectItem UE4运行的基本单位是UObjet,然而U ...
- 通过cmd命令控制台关闭已经打开的端口号
通过cmd命令控制台关闭已经打开的端口号 在出现的窗口里面输入 netstat -ano, 就会出现所有的端口号, Local Address下面的是端口号, PID就是某程序占用的进程号, 这个进程 ...
- Oracle和Mysql中的字符串的拼接
SQL允许两个或者多个字段之间进行计算,字符串类型的字段也不例外.比如我们需要 以"工号+姓名"的方式在报表中显示一个员工的信息,那么就需要把工号和姓名两个字符 串类型的字段拼接计 ...
- php_mvc实现步骤八
shop34-10-框架类 框架类(框架初始化类) 将原来入口文件中功能,放在该类中完成,入口文件变得简单,轻量! 将入口文件中的各个功能,由框架类的各个方法,完成: 为了简单化,使用纯静态的类.(看 ...