Nginx反向代理与负载均衡

Nginx反向代理与负载均衡

一、集群

(1)高性能

  一些国家重要的计算密集型应用(如天气预报,核试验模拟等),需要计算机有很强的运算处理能力。以全世界现有的技术,即使是大型机,其计算能力也是有限的,很难单独完成此任务。因为计算时间可能会相当长,也许几天,甚至几年或更久。因此,对于这类复杂的计算业务,便使用了计算机集群技术,集中几十上百台,甚至成千上万台计算机进行计算。

  假如你配一个LNMP环境,每次只需要服务10个并发请求,那么单台服务器一定会比多个服务器集群要快。只有当并发或总请求数量超过单台服务器的承受能力时,服务器集群才会体现出优势。

(2)价格有效性

通常一套系统集群架构,只需要几台或数十台服务器主机即可。与动辄价值上百万元的专用超级计算机相比便宜了很多。在达到同样性能需求的条件下,采用计算机集群架构比采用同等运算能力的大型计算机具有更高的性价比。

早期的淘宝,支付宝的数据库等核心系统就是使用上百万元的小型机服务器。后因使用维护成本太高以及扩展设备费用成几何级数翻倍,甚至成为扩展瓶颈,人员维护也十分困难,最终使用PC服务器集群替换之,比如,把数据库系统从小机结合Oracle数据库迁移到MySQL开源数据库结合PC服务器上来。不但成本下降了,扩展和维护也更容易了。

(3)可伸缩性

当服务负载,压力增长时,针对集群系统进行较简单的扩展即可满足需求,且不会降低服务质量。

通常情况下,硬件设备若想扩展性能,不得不增加新的CPU和存储器设备,如果加不上去了,就不得不够买更高性能的服务器,就拿我们现在的服务器来讲,可以增加的设备总是有限的。如果采用集群技术,则只需要将新的单个服务器加入现有集群架构中即可,从访问的客户角度来看,系统服务无论是连续性还是性能上都几乎没有变化,系统在不知不觉中完成了升级,加大了访问能力,轻松地实现了扩展。集群系统中的节点数目可以增长到几千乃至上万个,其伸缩性远超过单台超级计算机。

(4)高可用性

单一的计算机系统总会面临设备损毁的问题,如CPU,内存,主板,电源,硬盘等,只要一个部件坏掉,这个计算机系统就可能会宕机,无法正常提供服务。在集群系统中,尽管部分硬件和软件也还是会发生故障,但整个系统的服务可以是7*24小时可用的。

集群架构技术可以使得系统在若干硬件设备故障发生时仍可以继续工作,这样就将系统的停机时间减少到了最小。集群系统在提高系统可靠性的同时,也大大减小了系统故障带来的业务损失,目前几乎100%的互联网网站都要求7*24小时提供服务。

(5)透明性

多个独立计算机组成的松耦合集群系统构成一个虚拟服务器。用户或客户端程序访问集群系统时,就像访问一台高性能,高可用的服务器一样,集群中一部分服务器的上线,下线不会中断整个系统服务,这对用户也是透明的。

(6)可管理性

整个系统可能在物理上很大,但其实容易管理,就像管理一个单一映像系统一样。在理想状况下,软硬件模块的插入能做到即插即用。

(7)可编程性

在集群系统上,容易开发及修改各类应用程序。

二、计算机集群架构按功能和结构的分类

负载均衡集群,简称LBC或LB
高可用性集群,简称HAC
高性能计算集群,简称HPC
网络计算集群

三、负载均衡集群的作用

分摊用户访问请求及数据流量(负载均衡)

保持业务连续性,即7*24小时服务(高可用性)

应用于Web业务及数据库从库等服务器的业务

负载均衡集群典型的开源软件包括LVS,Nginx,Haproxy等,如下图所示

常见的开源集群软件有:Nginx,LVS,Haproxy,Keepalived,heartbeat
常用的商业集群硬件有:F5,Netscaler,Radware,A10等,(要钱的)

 四、反向代理与负载均衡概念简介

  严格地说,Nginx仅仅是作为Nginx Proxy反向代理使用的,因为这个反向代理功能表现的效果是负载均衡集群的效果,所以本文称之为Nginx负载均衡。那么,反向代理和负载均衡有什么区别呢?

  普通负载均衡软件,例如大名鼎鼎的LVS,其实功能只是对请求数据包的转发(也可能会改写数据包),传递,其中DR模式明显的特征是从负载均衡下面的节点服务器来看,接收到的请求还是来自访问负载均衡器的客户端的真实用户,而反向代理就不一样了,反向代理接收访问用户的请求后,会代理用户重新发起请求代理下的节点服务器,最后把数据返回给客户端用户,在节点服务器看来,访问的节点服务器的客户端用户就是反向代理服务器了,而非真实的网站访问用户。

一句话,LVS等的负载均衡是转发用户请求的数据包,而Nginx反向代理是接收用户的请求然后重新发起请求去请求其后面的节点。

Nginx是七层结构的,通过nginx本身来转发,可以有多种方式进行负载均衡,实现的功能多,nginx可以分业务

LVS是四层结构的,通过转发数据包mac或ip头部,不能对数据进行修改,来实现的负载均衡,实现的功能少但效率高,LVS的WEB内容都给是一样的。

LVS:四层,读不到四层以上的,只能修改MAC头部和IP头部,
  通过转发来实现负载均衡,效率高,实现的功能少。
Nginx:七层,效率没有LVS高,但是实现的功能多,用户的发起请求,
  通过第七层,nginx代替用户重新发起请求向web,更改了源IP,和源MAC,
  access_log记录的ip都是nginx自己的。
Nginx里的location可以实现反向代理分业务,可以通过用户搜索的URL进入不同的web服务器。

实现Nginx负载均衡的组件主要有两个,如下表

五、反向代理与负载均衡的搭建

 需要三台装nginx的虚拟机:反向代理,webA,webB

 安装nginx依赖包

yum -y install openssl openssl-devel pcre pcre-devel

创建nginx程序用户

useradd -M -s /sbin/nologin nginx

解压nginx安装包至/usr/src

tar xf nginx-1.10.2.tar.gz -C /usr/src

 进入解压后的包进行安装编译

cd /usr/src/nginx-1.10.2
./configure --user=nginx --group=nginx --prefix=/usr/local/nginx --with-http_stub_status_module --with-http_ssl_module && make && make install

将nginx命令做软连接

ln -s /usr/local/nginx/sbin/* /usr/local/sbin/

将Nginx配置文件多余的东西过滤掉

egrep -v "#|^$" nginx.conf.default > nginx.conf

进入nginx配置文件,如下图所示

vim /usr/local/nginx/conf/nginx.conf

upstream服务器池 www_server服务器池的名字
upstream是关键字必须有,后面的www_server为一个Upstream集群组的名字,可以自己起名,调用时就用这个名字
server就是一个RS节点 weight==>权重(负载均衡是按照权重比分配的)
server关键字是固定的,后面可以接域名(门户会用)或IP。如果不指定端口,默认是80端口。
weight代表权重,数值越大被分配的请求越多,结尾有分号,别忘了。
proxy_pass http://www_server;==>后面接域名找池,推给www_server池

 upstream池内容server后也可以加上down和backup

 

六、upstream模块相关说明

upstream模块的内容应放于nginx.conf配置的http{}标签内,其默认调度节点算法是wrr(weighted round-robin,即权重轮询)。下图为upstream模块内部server标签部分参数说明。

 

特别提示

 如果是两台Web服务器做高可用,常规方案就需要keepalived配合,那么这里使用Nginx的backup参数通过负载均衡功能就可以实现Web服务器集群了,对于企业应用来说,能做集群就不做高可用。

hash算法访问

  1. upstream backend {
  2. ip_hash;
  3. server backend1.example.com;
  4. server backend2.example.com;
  5. server backend3.example.com down;
  6. server backend4.example.com;
  7. }

需要特别说明的是,如果是Nginx代理Cache服务,可能需要使用hash算法,此时若宕机,可通过设置down参数确保客户端用户按照当前的hash算法访问,这一点很重要

开启对后端服务器的健康检测

  1. #开启对后端服务器的健康检测,通过GET /test/index.php来判断后端服务器的健康情况
  2. server php_server_1 192.168.0.223:80 cookie 1 check inter 2000 rise 3 fall 3 weight 2
  3. server php_server_2 192.168.0.224:80 cookie 2 check inter 2000 rise 3 fall 3 weight 1
  4. server php_server_bak 192.168.0.225:80 cookie 3 check inter 1500 rise 3 fall 3 backup

健康检测命令详解

  1. weight:调节服务器的请求分配权重。
  2. check:开启对该服务器健康检查。
  3. inter:设置连续两次的健康检查间隔时间,单位毫秒,默认值2000
  4. rise:指定多少次连续成功的健康检查后,即可认定该服务器处于可用状态。
  5. fall:指定多少次不成功的健康检查后,即认为服务器为宕机状态,默认值3.
  6. maxconn:指定可被发送到该服务器的最大并发连接数。

七、upstream模块调度算法

 调度算法一般分为两类: 
第一类为静态调度算法,即负载均衡器根据自身设定的规则进行分配,不需要考虑后端节点服务器的情况,例如:rr,wrr,ip_hash等都属于静态调度算法。 
第二类为动态调度算法,即负载均衡器会根据后端节点的当前状态来决定是否分发请求,例如:连接数少的优先获得请求,响应时间短的优先获得请求。例如:least_conn,fair等都属于动态调度算法。

(1) rr轮询(默认调度算法,静态调度算法)

按客户端请求顺序把客户端的请求逐一分配到不同的后端节点服务器,这相当于LVS中的rr算法,如果后端节点服务器宕机(默认情况下Nginx只检测80端口),宕机的服务器会被自动从节点服务器池中剔除,以使客户端的用户访问不受影响。新的请求会分配给正常的服务器。

(2)wrr(权重轮询,静态调度算法)

在rr轮询算法的基础上加上权重,即为权重轮询算法,当使用该算法时,权重和用户访问成正比,权重值越大,被转发的请求也就越多。可以根据服务器的配置和性能指定权重值大小,有效解决新旧服务器性能不均带来的请求分配问题。

(3)ip_hash(静态调度算法)(会话保持)

每个请求按客户端IP的hash结果分配,当新的请求到达时,先将其客户端IP通过哈希算法哈希出一个值,在随后的客户端请求中,客户IP的哈希值只要相同,就会被分配至同一台服务器,该调度算法可以解决动态网页的session共享问题,但有时会导致请求分配不均,即无法保证1:1的负载均衡,因为在国内大多数公司都是NAT上网模式,多个客户端会对应一个外部IP,所以,这些客户端都会被分配到同一节点服务器,从而导致请求分配不均。LVS负载均衡的-p参数,Keepalived配置里的persistence_timeout 50参数都类似这个Nginx里的ip_hash参数,其功能都可以解决动态网页的session共享问题。

当负载调度算法为ip_hash时,后端服务器在负载均衡调度中的状态不能有weight和backup,即使有也不会生效。

  1. upstream yunjisuan_lb{
  2. ip_hash;
  3. server 192.168.0.223:80;
  4. server 192.168.0.224:8080;
  5. }
  6. upstream backend{
  7. ip_hash;
  8. server backend1.example.com;
  9. server backend2.example.com;
  10. server backend3.example.com down;
  11. server backend4.example.com;
  12. }

(4)fair(动态调度算法)

此算法会根据后端节点服务器的响应时间来分配请求,响应时间短的优先分配。这是更加智能的调度算法。此种算法可以根据页面大小和加载时间长短智能地进行负载均衡,也就是根据后端服务器的响应时间来分配请求,响应时间短的优先分配。Nginx本身不支持fair调度算法,如果需要使用这种调度算法,必须下载Nginx相关模块upstream_fair。

  1. upstream yunjisuan_lb{
  2. server 192.168.0.223;
  3. server 192.168.0.224;
  4. fair;
  5. }

(5)least_conn(最小连接)

least_conn算法会根据后端节点的连接数来决定分配情况,哪个机器连接数少就分发。 
除了上面介绍的这些算法外,还有一些第三方调度算法,例如:url_hash,一致性hash算法等,介绍如下。

(6)url_hash算法(web缓存节点)

与ip_hash类似,这里是根据访问URL的hash结果来分配请求的,让每个URL定向到同一个后端服务器,后端服务器为缓存服务器时效果显著。在upstream中加入hash语句,server语句中不能写入weight等其他的参数,hash_method使用的是hash算法。

url_hash按访问URL的hash结果来分配请求,使每个URL定向到同一个后端服务器,可以进一步提高后端缓存服务器的效率命令率。Nginx本身是不支持url_hash的,如果需要使用这种调度算法,必须安装Nginx的hash模块软件包。

  1. upstream yunjisuan_lb {
  2. server squid1:3128;
  3. server squid2:3128;
  4. hash $request_uri;
  5. hash_method crc32;
  6. }

(7)一致性hash算法(Nginx没有)

一致性hash算法一般用于代理后端业务为缓存服务(如Squid,Memcached)的场景,通过将用户请求的URI或者指定字符串进行计算,然后调度到后端的服务器上,此后任何用户查找同一个URI或者指定字符串都会被调度到这一台服务器上,因此后端的每个节点缓存的内容都是不同的,一致性hash算法可以解决后端某个或几个节点宕机后,缓存的数据动荡最小,一致性hash算法知识比较复杂,详细内容可以参考百度上的相关资料,这里仅仅给出配置示例

  1. http {
  2. upstream test {
  3. consistent_hash $request_uri;
  4. server 127.0.0.1:9001 id=1001 weight=3;
  5. server 127.0.0.1:9002 id=1002 weight=10;
  6. server 127.0.0.1:9003 id=1003 weight=20;
  7. }
  8. }

虽然Nginx本身不支持一致性hash算法,但Nginx得分支Tengine支持。详细可参考http://tengine.taobao.org/document_cn/http_upstream_consistent_hash_cn.html

八、http_proxy_module模块

proxy_pass指令介绍

proxy_pass指令属于ngx_http_proxy_module模块,此模块可以将请求转发到另一台服务器,在实际的反向代理工作中,会通过location功能匹配指定的URI,然后把接收到的符合匹配URI的请求通过proxy_pass抛给定义好的upstream节点池。该指令官方地址1见:http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_pass

proxy_pass的使用案例

(1)将匹配URI为name的请求抛给http://127.0.0.1/remote/

  1. location /name/ {
  2. proxy_pass http://127.0.0.1/remote/;
  3. }

(2)将匹配URI为some/path的请求抛给http://127.0.0.1

  1. location /some/path/ {
  2. proxy_pass http://127.0.0.1;
  3. }

(3)将匹配URI为name的请求应用指定的rewrite规则,然后抛给http://127.0.0.1

  1. location /name/ {
  2. rewrite /name/( [^/]+ ) /username=$1 break;
  3. proxy_pass http://127.0.0.1;
  4. }

http proxy模块参数详解

Nginx的代理功能是通过http proxy模块来实现的。默认在安装Nginx时已经安装了http proxy模块,因此可直接使用http proxy模块。下面详细解释模块1中每个选项代表的含义,见下表

九、反向代理后的节点服务器记录用户IP测试

 测试会发现,节点服务器对应的sl虚拟主机的访问日志的第一个字段记录的并不是客户端的IP,而是反向代理服务器的IP,最后一个字段也是。

解决办法同样是在反向代理服务器增加如下一行参数:

proxy_set_header X-Forwarded-For $remote_addr;

这是反向代理时,节点服务器获取用户真实IP的必要功能配置

在反向代理请求后端节点服务器的请求头中增加获取的客户端IP的字段信息,然后节点后端可以通过程序或者相关的配置接收X-Forwarded-For传过来的用户真实IP的信息。

  1. worker_processes 1;
  2. events {
  3. worker_connections 1024;
  4. }
  5. http {
  6. include mime.types;
  7. default_type application/octet-stream;
  8. sendfile on;
  9. keepalive_timeout 65;
  10. upstream www_server {
  11. server 192.168.200.68:80 weight=1;
  12. server 192.168.200.69:80 weight=1;
  13. }
  14. server {
  15. listen 80;
  16. server_name sl.yunjisuan.com;
  17. location / {
  18. proxy_pass http://www_server;
  19. proxy_set_header host $host;
  20. proxy_set_header X-Forwarded-For $remote_addr;
  21. }
  22. }
  23. }

 特别注意,虽然反向代理已经配好了,但是节点服务器(WEBA和B)需要的访问日志如果要记录用户的真实IP,还必须进行日志格式配置,这样才能把代理传过来的X-Forwarded-For头信息记录下来,具体配置为

  1. worker_processes 1;
  2. events {
  3. worker_connections 1024;
  4. }
  5. http {
  6. include mime.types;
  7. default_type application/octet-stream;
  8. sendfile on;
  9. keepalive_timeout 65;
  10. server_tokens off;
  11. log_format main '$remote_addr-$remote_user[$time_local]"$request"'
  12. '$status $body_bytes_sent "$http_referer"'
  13. '"$http_user_agent""$http_x_forwarded_for"';
  14. server {
  15. listen 80;
  16. server_name bbs.yunjisuan.com;
  17. location / {
  18. root html/bbs;
  19. index index.html index.htm;
  20. }
  21. access_log logs/access_bbs.log main;
  22. }
  23. server {
  24. listen 80;
  25. server_name sl.yunjisuan.com;
  26. location / {
  27. root html/sl;
  28. index index.html index.htm;
  29. }
  30. access_log logs/access_sl.log main;
  31. }
  32. }
  33. 配置文件详解
  34. log_format --->记录字段顺序
  35. $remote_addr --->来源IP
  36. $remote_user --->来源用户
  37. [$time_local] --->来源时间
  38. $request --->请求
  39. $status --->状态码
  40. $body_bytes_sent --->主体,发送的大小
  41. $http_referer --->来源的浏览器
  42. $http_user_agent --->用户的客户端
  43. $http_x_forwarded_for --->这是反向代理时,节点服务器获取用户真实IP的必要功能配置
  44. 如果希望在第一行显示,可以替换掉第一行的$remote_addr变量

十、反向代理相关重要基础参数的总结

原文地址:https://www.cnblogs.com/heroke/p/9968182.html