顾名思义,就是Nginx的增强版或者扩展版。咱们知道Nginx是开源的、免费的,可是NGINX Plus的不少功能就须要收费了。Nginx Plus 能够做为一个负载均衡器,一个web服务器,还能够做为一个内容缓存。既然是Nginx的增强版,那无疑功能会比Nginx更增强大。NGINX Plus在开源Nginx已有的功能基础上,提供了许多适合生产环境的专有功能,包括session一致性、实时更新API配置、有效的健康检查等。php
NGINX Plus R5 和更新的版本能够支持基于TCP应用的负载均衡(好比MySQL)。这就不只仅限制于Http的负载均衡,而是大大扩充了Nginx做为负载均衡器的做用范围。R6中TCP负载均衡功能获得很大的扩充,加入了健康检查、动态更新配置、SSL终端等。等到了R7,TCP负载均衡功能就基本和Http负载均衡差很少了。z再到了R9,就能够支持UDP了。经过这些更新,NGINX Plus 远远超过了web应用的层面,成为了一款意义更为普遍的负载均衡器。毕竟协议是基础层面的东西,支持的协议越多,应用面也越广。从最初的Http/SMTP到TCP再到UDP,NGINX Plus一步步的变得愈来愈强大。html
开源Nginx和NGINX Plus 都支持HTTP, TCP, 和UDP应用的负载均衡。但NGINX Plus 提供了一些企业级别的功能,这些功能是收费的,包括session一致性,健康检查,动态更新配置等。mysql
NGINX Plus对Http负载均衡作了不少功能优化,诸如HTTP 升级、长链接优化、内容压缩和响应缓存等。在NGINX Plus中Http负载均衡的实现也很是简单:nginx
http { upstream my_upstream { server server1.example.com; server server2.example.com; } server { listen 80; location / { proxy_set_header Host $host; proxy_pass http://my_upstream; } } }
能够经过proxy_set_header
指令来设置Host,而proxy_pass
将请求转发到上游的my_upstream
中。web
HTTP长链接——HTTP Keepalives,是指NGINX PLus和上游服务器创建的长链接。客户端和NGINX PLus创建长链接的话,能够在客户端指定Http协议为1.1/2.0。redis
HTTP协议是用的底层TCP协议来传输请求,接收响应的。HTTP1.1/2.0支持TCP的长链接或者重利用,以避免反复的建立和销毁TCP链接所带来的开销。算法
咱们看看客户端到NGINX PLus之间的Http长链接:sql
NGINX是一个彻底意义的反向代理,在长链接上也绝不含糊。它管理因此来从客户端到Nginx的长链接,一样也会管理从Nginx到上游服务器的长链接,两者是彻底独立的。json
Nginx管理的长链接:后端
NGINX 将链接上游服务器的空闲链接作了“缓存”,并不直接关掉它们。若是有请求过来,NGINX先从缓存的活跃链接中去拿一个使用,而不是立马建立一个新的,若是缓存为空那么NGINX 再去新建一个链接。这种操做保持了和上游之间链接的最小必要的数目,从而下降了Nginx和上游服务器之间的延迟并减小了临时端口的利用率,因此NGINX能处理大的并发。这种技术加上别的负载均衡技术,有时候能够被称为链接池,或者链接复用。
为了配置闲置长链接缓存,你须要指定几个指令:proxy_http_version,proxy_set_header,keepalive
server { listen 80; location / { proxy_pass http://backend; proxy_http_version 1.1; # 只有Http1.1/2.0才能支持长链接 proxy_set_header Connection ""; } } upstream backend { server webserver1; server webserver2; # maintain a maximum of 20 idle connections to each upstream server keepalive 20; # 闲置长链接缓存时间为20 }
做为对HTTP协议的扩展,NGINX Plus能够直接支持基于TCP和UDP协议的应用。基于TCP的如MySQL,支持UDP的如DNS 和RADIUS应用。对于TCP请求来讲,NGINX Plus接收了客户端的TCP请求,而后再建立一个TCP请求对上游服务器发起访问。
stream { upstream my_upstream { server server1.example.com:1234; server server2.example.com:2345; } server { listen 1123 [udp]; proxy_pass my_upstream; #注意这里没有http://了 } }
对TCP请求的支持出如今NGINX Plus R5,R6和R7版本主要是在优化这个功能,到R7时TCP请求的负载均衡已经强大到足够媲美Http负载均衡了,到了R9,则能够支持UDP了。这里先有个印象,后面会更加详细介绍TCP负载均衡功能。
你还能够为负载均衡作链接数量限制。这里说的链接是指NGINX Plus发给上游服务器的HTTP/TCP/UDP请求链接(对于UDP则是会话)。有了链接数限制的功能,当上游服务器的Http/TCP链接数量,或者UDP的会话数量超过必定的值时,NGINX Plus就再也不建立新的链接或者会话。客户端多出的请求链接能够被放进队列等候,也能够不被处理。能够经过max_conns,queue
指令来实现这一点:
upstream backend { zone backends 64k; queue 750 timeout=30s; server webserver1 max_conns=250; server webserver2 max_conns=150; }
server
指令表示webserver1 最多承载250个链接而webserver2 最多150个,多出来的能够放在队列queue当中等候。在队列queue中等候的链接数量和等候时间也是有限制的。当webserver1 和webserver2 链接数下降到各自最大链接数如下时,等候在队列queue中的链接随时就补上去。
queue 750 timeout=30s
表示总共能够有750个链接排队等候,每一个链接等候30s。
Limiting connections 是十分有用的,能够为客户端提供可持续可预见的服务——没必要由于某台server负载过大致使挂掉。通常来讲一台server大概能承载多少负荷是能够经过某些手段测试出来的,所以把这个可承受的上线做为max_conns指令的值即可以保证server的相对安全。
在NGINX Plus R6中增长了一种新的均衡算法——Least Time,将相应时间也考虑进去,算得上对最少链接均衡算法(Least Connections)的扩展。
这种算法同时考虑当前链接数和链接池里各个节点的平均响应时间。目的是使得当前请求选择当下响应更快、链接更少的服务器,而不是选择响应更慢、链接更多的。
当链接池的各个服务器节点有着明显不一样的响应延时时,这种算法就要优于其余的几种(round-robin/ip-hash/lease connections)。一个典型的应用场景是,若是有两个分布在不一样的地域的数据中心,那么本地的数据中心就要比异地的数据中心延时要少得多,这个时候就不能仅仅考虑当下链接数了,这个响应的延时也要被计入考量。Least Time算法就更倾向于选择本地的,固然这只是“更倾向于”的问题,并不能代替Nginx最基本的错误转移功能,哪怕本地的数据中心响应再快,若是它挂掉了Nginx Plus也能立刻切换到远端数据中心。
“最少时间”能够有两种计算方式,一种是从请求发出到上流服务器接返回响应头部算的时间,另外一种是从请求发出到接收到所有请求体的时间,分别以header_time
和response_time
来表示。
Session一致性(Session Persistence)问题除了能够经过指定ip-hash的均衡算法来实现,还有更为通用的实现方式,这是在NGINX Plus 中实现的。
NGINX Plus能够识别用户Session,从而可以鉴别不一样的客户端,而且能够未来自同一个客户端的请求发往同一个上游服务器。这在当应用保存了用户状态的状况下很是有用,能够避免负载均衡器按照某个算法将请求发到别的服务器上去。另外,在共享用户信息的集群服务器这种方式也很是有用。
session一致性的要求同一个客户端每次的请求都选择同一个服务器,而负载均衡要求咱们利用一种算法去服务器链接池里面去选择下一个,那么这两种矛盾的方式能够共存么?能够的,NGINX Plus按照以下的步骤决策到底选用哪种:
为了能保证session一致性,Nginx Plus提供了sticky cookie,sticky learn和sticky route几种规则。
对于 sticky cookie 规则,当客户端的第一个请求选择了某个上游服务器,并从这个上游服务器返回响应时,NGINX Plus 为这个响应添加一个session cookie,用来鉴别这个上游服务器。当后面的请求再过来时,NGINX Plus取出这个cookie,分析是哪一台服务器,再把请求发往这台相同的服务器。
使用指令sticky cookie
,配置以下:
upstream backend { server webserver1; server webserver2; sticky cookie srv_id expires=1h domain=.example.com path=/; }
cookie的名字就叫srv_id,用来“记住”是哪个server;过时时间1h,domain为.example.com
;path为/
NGINX Plus在第一次响应中,插入一个名称为srv_id
的cookie
,用来“记住”这第一次请求是发个哪一个上游的,后面的请求带上这个cookie
,一样再被NGINX Plus甄别一下,再发往同一个的服务器。这样就能保证session的一致了。
和sticky cookie
规则相似,只不过“记住”上游服务器的方式不一样而已。
在客户端发起第一次请求时,接收它的服务器为其分配一个route,此后这个客户端发起的全部请求都要带上这个route信息,或者在cookie中或者在uri中。而后和server指令中的route参数作对比,决定选取哪一个server。若是指定的服务器没法处理,那交给负载均衡算法去选择下一个服务器。
map $cookie_jsessionid $route_cookie { ~.+\.(?P<route>\w+)$ $route; } map $request_uri $route_uri { ~jsessionid=.+\.(?P<route>\w+)$ $route; } upstream backend { server backend1.example.com route=a; server backend2.example.com route=b; # select first non-empty variable; it should contain either 'a' or 'b' sticky route $route_cookie $route_uri; }
在这里,route在JSESSIONID
的cookie
中选择,如其包含a那么选择服务器backend1
;如其包含b则选择backend2
,若是都不包含那么在$request_uri
中再作相似的选择,以此类推。
无论是选哪一种方式保持session一致,若是选择出的server没法使用,那么将会按照负载均衡算法(如round-robin)在服务器列表中的选择下一台server继续处理。
前面提到过,Nginx有两大功能:一个是扩展,增长更多的server以知足更大的并发;二是检测失效server,以便及时排除。那么,如何定义一个“失效server”(failed server)就变得很是重要。这一节就是来讨论这个问题——实时健康检查(Active Health Checks)。这是NGINX Plus 才有的功能,而且是收费的。
开源版本NGINX 能够提供简单的健康检查,而且能够自动作故障转移。可是如何定义一个上游server“失效”开源NGINX 却作的很简单。NGINX Plus为此提供了一个能够自定义的、综合式的评判标准,除此以外NGINX Plus还能够平缓的添加新的服务器节点到集群当中。这个功能使得NGINX Plus可能甄别更为多元化的服务器错误,十分有效的增长了HTTP/TCP/UDP
应用的可靠性。
这里要用到的指令有:health_check,match
等指令:
upstream my_upstream { zone my_upstream 64k; server server1.example.com slow_start=30s; } server { # ... location /health { internal; health_check interval=5s uri=/test.php match=statusok; proxy_set_header HOST www.example.com; proxy_pass http://my_upstream } } match statusok { # 在/test.php 作健康检查 status 200; header Content-Type = text/html; body ~ "Server[0-9]+ is alive"; }
health_check
中interval=5s
表示每隔5s检测一次;uri=/test.php
表示在/test.php
里进行健康检查,NGINX Plus自动发起uri的请求,uri能够自定义,你在里面具体执行检查的逻辑,好比mysql/redis这些是否正常,而后做出必定的响应;而后在match指令中,就经过一些规则来匹配/test.php
的响应。/test.php
的响应能够包括status,header,body
这些,供后面这些指令作匹配。所有检查经过,就算健康,server被标记为活跃;若是一项匹配未经过,好比Content-Type = text/json
或者status = 201
那都算检测失败,server不健康,被标记为不活跃。
Nginx Plus一启动就会进行DNS解析而且自动永久缓存解析出的域名和IP,可是某些情形下须要从新解析下,这时候可使用下面的指令来实现:
resolver 127.0.0.11 valid=10s; upstream service1 { zone service1 64k; server www.example.com service=http resolve; }
127.0.0.11是默认的DNS服务器的地址,此例中NGINX Plus每10s中DNS服务器发起一次从新解析的请求。
NGINX Plus Release 7主要给增长了TCP负载均衡的安全性。好比访问控制(Access Controls)和DDoS保护。
你如今能够容许或者拒绝对作反向代理的或者作负载均衡的TCP服务器的访问,仅仅经过配置简单的IP或者一个IP范文就能实现:
server { # ... proxy_set_header Host www.example.cn; proxy_pass http://test; deny 72.46.166.10; deny 73.46.156.0/24; allow all; }
第一个deny指令拒绝一个IP的访问,第二个拒绝一个IP范围,除去这两个剩下的都是被容许访问的。被拒绝访问的IP,会被返回403错误。
除了能够限定上游服务器链接数,还能够限定客户端链接数,NGINX Plus R7 中实现了这个功能。你能够限制客户端发往由NGINX Plus代理的TCP应用的请求数量,防止对TCP的请求数量过多。在你的应用中,可能一部分的比另外一部分要慢一些。好比说,请求你的应用的某块,将会产生大量的MySQL请求,或者fork出一大堆的work进程。那么攻击者将会利用这点产生成千上万个请求,导致你的服务器负载太重而瘫痪。
可是有了链接数限制功能,你能够经过配置limit_conn my_limit_conn
指令限制同一个客户端(IP)所能发起的最大请求数,以此将上述的攻击风险降到最低。
stream { limit_conn_zone $binary_remote_addr zone=my_limit_conn:10m; # ... server { limit_conn my_limit_conn 1; # ... } }
这条指令限定了每一个IP同时只能有一个链接。
R7 还新增了一项功能——限制每一个客户端链接的上传和下载的最大带宽(Bandwidth Limiting) 。
server { # ... proxy_download_rate 100k; proxy_upload_rate 50k; }
有了这个配置,客户端最多只能以100kbytes/s的速度下载,以50kbytes/s的速度上传。由于客户端能够开多个链接,所以若是要限制总的上传/下载速度,同时还得限制下单个客户端的链接数。
这是在R6中增长的功能。你能够在R6和之后的版本中使用无缓冲的上传,意味Nginx Plus能够经过更大的Http请求好比上传。无缓冲的上传能够在这些请求一过来便进行上传,而不是像以前那样先是缓冲全部的上传内容,再将其转发给你上游服务器。
默认状况下,Nginx 在上传时,接收到数据时会先放进缓冲区进行缓冲,以免将资源和基于worker进程的后端脚本绑定,可是针对事件驱动的后端语言如Node.js,缓冲是几乎没有必要的。这个修改改进了服务器对上传大文件的响应性,由于应用能够一接收到数据就立刻对作出响应,使得上传进度条变成实时的和准确的。一样,这个改进也减小了磁盘I/O。
在R6中,能够在和上游的HTTPS 或者 uwSGI 服务器打交道时为客户端提供一个证书。这大大提升了安全性,尤为是在和不受保护网络上的安全服务进行通讯的时候。R6 支持IMAP, POP3, 和SMTP的SSL/TLS 客户端认证。
proxy_cache 指令能够支持变量了,这个简单的改进觉得着你能够定义几个基于磁盘的缓存,而且根据请求数据作自由的选择。当你打算建立巨大的内容缓存,而且将其保存到不一样的磁盘时是很是有用的。
upstreem模块的一些指令,不光能够经过手动去修改,还能够经过Restful Api的方式去修改,而且立刻自动更新。有了这个功能,NGINX Plus的一些功能,你均可以经过API的方式去改变。应用性获得很大提高。固然这也是收费的:
upstream backend { zone backends 64k; server 10.10.10.2:220 max_conns=250; server 10.10.10.4:220 max_conns=150; } server { listen 80; server_name www.example.org; location /api { api write=on; } }
有了API,你就可使用curl工具来动态修改配置了,好比用POST命令来增长一个集群的节点:
$ curl -iX POST -d '{"server":"192.168.78.66:80","weight":"200","max_conns":"150"}' http://localhost:80/api/1/http/upstreams/backend/servers/
至关于添加了一个这样的配置:
upstream backend { zone backends 64k; server 10.10.10.2:220 max_conns=250; server 10.10.10.4:220 max_conns=150; #此处是经过api添加的 server 192.168.78.66:80 weight=200 max_conns=150; }
若是须要修改一个节点配置,你能够用服务器节点在链接池中的天然顺序(从0开始)做为它们各自惟一的ID,而后使用PATCH/DELETE方法去操做它们:
$ curl -iX PATCH -d '{"server":"192.168.78.55:80","weight":"500","max_conns":"350"}' http://localhost:80/api/1/http/upstreams/backend/servers/2
这条命令是修改以上链接池中的第三个server 192.168.78.66:80 max_conns=200;
为:
server 192.168.78.55:80 weight=500 max_conns=350;
若是要返回全部的节点信息,可使用:
$ curl -s http://localhost:80/api/1/http/upstreams/backend/servers/
返回的是一个JSON字符串。
{ "backup": false, "down": false, "fail_timeout": "10s", "id": 0, "max_conns": 250, "max_fails": 1, "route": "", "server": "10.10.10.2:220", "slow_start": "0s", "weight": 1 }, { "backup": false, "down": false, "fail_timeout": "10s", "id": 1, "max_conns": 150, "max_fails": 1, "route": "", "server": "10.10.10.4:220", "slow_start": "0s", "weight": 1 }, { "backup": false, "down": false, "fail_timeout": "10s", "id": 2, "max_conns": 200, "max_fails": 1, "route": "", "server": "192.168.78.66:80", "slow_start": "0s", "weight": 200 } }
为不一样个应用配置建立各自的目录和文件,并用include
指令再合并到一块儿是个很是好的习惯。标准的 NGINX Plus配置是将各个应用的配置文件放到各自的conf.d directory目录下:
http { include /etc/nginx/conf.d/*.conf; } stream { include /etc/nginx/stream.d/*.conf; }
http 和 stream 模块的各自分属不一样的目录,而在http 下的都是http请求的配置,stream 都是TCP/UDP请求的配置。没有统一的标准,主要是看开发者本身能便于识别和修改。