反向代理负载均衡之nginx

一、集群

1.1 什么是集群

  集群是一组相互独立的、通过高速网络互联的计算机,它们构成了一个组,并以单一系统的模式加以管理。一个客户与集群相互作用时,集群像是一个独立的服务器。集群配置是用于提高可用性和可缩放性。 和传统的高性能计算机技术相比,集群技术可以利用各档次的服务器作为节点,系统造价低,可以实现很高的运算速度,完成大运算量的计算,具有较高的响应能力,能够满足当今日益增长的信息服务的需求。 而集群技术是一种通用的技术,其目的是为了解决单机运算能力的不足、IO能力的不足、提高服务的可靠性、获得规模可扩展能力,降低整体方案的运维成本(运行、升级、维护成本)。只要在其他技术不能达到以上的目的,或者虽然能够达到以上的目的,但是成本过高的情况下,就可以考虑采用集群技术

1.2 集群的特点

1) 提高性能
一些计算密集型应用,如:天气预报、核试验模拟等,需要计算机要有很强的运算处理能力,现有的技术,即使普通的大型机器计算也很难胜任。这时,一般都使用计算机集群技术,集中几十台甚至上百台计算机的运算能力来满足要求。提高处理性能一直是集群技术研究的一个重要目标之一。
2) 降低成本
通常一套较好的集群配置,其软硬件开销要超过100000美元。但与价值上百万美元的专用超级计算机相比已属相当便宜。在达到同样性能的条件下,采用计算机集群比采用同等运算能力的大型计算机具有更高的性价比。
3) 提高可扩展性
用户若想扩展系统能力,不得不购买更高性能的服务器,才能获得额外所需的CPU 和存储器。如果采用集群技术,则只需要将新的服务器加入集群中即可,对于客户来看,服务无论从连续性还是性能上都几乎没有变化,好像系统在不知不觉中完成了升级。
4) 增强可靠性
集群技术使系统在故障发生时仍可以继续工作,将系统停运时间减到最小。集群系统在提高系统的可靠性的同时,也大大减小了故障损失。

1.3 常见的集群类型

1.3.1 负载均衡集群

  负载均衡集群为企业需求提供了更实用的系统。负载均衡集群使负载可以在计算机集群中尽可能平均地分摊处理。负载通常包括应用程序处理负载和网络流量负载。这样的系统非常适合向使用同一组应用程序的大量用户提供服务。每个节点都可以承担一定的处理负载,并且可以实现处理负载在节点之间的动态分配,以实现负载均衡。对于网络流量负载,当网络服务程序接受了高入网流量,以致无法迅速处理,这时,网络流量就会发送给在其它节点上运行的网络服务程序。同时,还可以根据每个节点上不同的可用资源或网络的特殊环境来进行优化。与科学计算集群一样,负载均衡集群也在多节点之间分发计算处理负载。它们之间的最大区别在于缺少跨节点运行的单并行程序。大多数情况下,负载均衡集群中的每个节点都是运行单独软件的独立系统。
  但是,不管是在节点之间进行直接通信,还是通过中央负载均衡服务器来控制每个节点的负载,在节点之间都有一种公共关系。通常,使用特定的算法来分发该负载。
负载均衡集群典型搭配:

1.3.2 高可用性集群

  当集群中的一个系统发生故障时,集群软件迅速做出反应,将该系统的任务分配到集群中其它正在工作的系统上执行。考虑到计算机硬件和软件的易错性,高可用性集群的主要目的是为了使集群的整体服务尽可能可用。如果高可用性集群中的主节点发生了故障,那么这段时间内将由次节点代替它。次节点通常是主节点的镜像。当它代替主节点时,它可以完全接管其身份,因此使系统环境对于用户是一致的。
  高可用性集群使服务器系统的运行速度和响应速度尽可能快。它们经常利用在多台机器上运行的冗余节点和服务,用来相互跟踪。如果某个节点失败,它的替补者将在几秒钟或更短时间内接管它的职责。因此,对于用户而言,集群永远不会停机。
  在实际的使用中,集群的这三种类型相互交融,如高可用性集群也可以在其节点之间均衡用户负载。同样,也可以从要编写应用程序的集群中找到一个并行集群,它可以在节点之间执行负载均衡。从这个意义上讲,这种集群类别的划分是一个相对的概念,不是绝对的。

1.4 集群的选择

1.4.1 不同类型企业对集群的选择

1)当业务重要,技术力量又薄弱,有钱买商业产品,如银行、证券、金融等
2)对于门户网站,会用并用软硬件分担单一产品的风险,融资企业。
3)中小型互联网公司,起步没利润,希望通过开源软件。

1.4.2运对于维人员集群的选择

中小型互联网并发和总访问量不是很大的情况下,建议首选nginx负载均衡,nginx配置简单,使用方便,安全稳定,社区活跃,另一个产品haproxy(支持L4和L7负载均衡,nginx1.9之前只支持L7,新版支持L4,不过处于测试阶段)。
nginx+keepalived实现高可用,理由安装配置简单,安全稳定,类似的还有heartbeat(使用复杂,不建议初学者使用)
商业负载均衡产品:成本高、性能好、更稳定、缺点不能二次开发;开源软件相反。

1.4.3 生产环境集群建议选择

lvs简单L4转发,实现ip负载均衡;L7层反向代理使用nginx/haproxy均可,以实际情况和技术栈定

二、反向代理负载均衡

详情请参考另一篇博文反向代理负载均衡之apache

三、使用nginx实现反向代理负载均衡实战

3.1 环境准备:两台虚拟机

第一台

  1. [root@linux-node1 ~]# uname -m
  2. x86_64
  3. [root@linux-node1 ~]# uname -r
  4. 3.10.0-229.el7.x86_64
  5. [root@linux-node1 ~]# cat /etc/hostname
  6. linux-node1.example.com
  7. [root@linux-node1 ~]# cat /etc/hosts
  8. 127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
  9. ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
  10. 192.168.56.11 linux-node1.example.com
  11. 192.168.56.12 linux-node2.example.com
  12. [root@linux-node1 ~]# rpm -ivh http://mirrors.aliyun.com/epel/epel-release-latest-7.noarch.rpm
  13. [root@linux-node1 ~]# yum install -y gcc glibc gcc-c++ make screen tree lrzsz

第二台

  1. [root@linux-node2 ~]# uname -m
  2. x86_64
  3. [root@linux-node2 ~]# uname -r
  4. 3.10.0-229.el7.x86_64
  5. [root@linux-node2 ~]# cat /etc/hostname
  6. linux-node2.example.com
  7. [root@linux-node2 ~]# cat /etc/hosts
  8. 127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
  9. ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
  10. 192.168.56.11 linux-node1.example.com
  11. 192.168.56.12 linux-node2.example.com
  12. [root@linux-node2 ~]# rpm -ivh http://mirrors.aliyun.com/epel/epel-release-latest-7.noarch.rpm
  13. [root@linux-node2 ~]# yum install -y gcc glibc gcc-c++ make screen tree lrzsz

3.2 部署应用实战

在两台机器部署apache作为RS
linux-node1.example.com

  1. [root@linux-node1 ~]# yum install -y httpd
  2. [root@linux-node1 ~]# sed -i 's/Listen 80/Listen 8080/g' /etc/httpd/conf/httpd.conf
  3. [root@linux-node1 ~]# systemctl start httpd
  4. [root@linux-node1 ~]# echo "chuck-test2" > /var/www/html/index.html
  5. [root@linux-node1 ~]# curl http://192.168.56.11:8080/
  6. chuck-test1

linux-node2.example.com

  1. [root@linux-node2 ~]# yum install -y httpd
  2. [root@linux-node2 ~]# sed -i 's/Listen 80/Listen 8080/g' /etc/httpd/conf/httpd.conf
  3. [root@linux-node2 ~]# systemctl start httpd
  4. [root@linux-node2 ~]# echo "chuck-test2" > /var/www/html/index.html
  5. [root@linux-node2 ~]# curl http://192.168.56.12:8080/
  6. chuck-test2

在linux-node1上编译安装nginx作为反向代理服务器

  1. [root@linux-node1 ~]# useradd -s /sbin/nologin -M www
  2. [root@vpn-node3 src]# wget http://nginx.org/download/nginx-1.9.12.tar.gz
  3. [root@linux-node1 src]# tar zxf nginx-1.9.12.tar.gz
  4. [root@linux-node1 src]# cd nginx-1.9.12
  5. [root@linux-node1 nginx-1.9.12]#./configure --prefix=/usr/local/nginx-1.9.12 \
  6. --user=www --group=www --with-http_ssl_module \
  7. --with-http_stub_status_module --with-file-aio
  8. [root@linux-node1 nginx-1.9.12]# make && make install
  9. [root@linux-node1 ~]# ln -s /usr/local/nginx-1.9.12/ /usr/local/nginx

测试配置并启动Nginx

  1. [root@linux-node1 ~]# /usr/local/nginx/sbin/nginx -t
  2. nginx: the configuration file /usr/local/nginx-1.9.12/conf/nginx.conf syntax is ok
  3. nginx: configuration file /usr/local/nginx-1.9.12/conf/nginx.conf test is successful
  4. [root@linux-node1 ~]# /usr/local/nginx/sbin/nginx

修改nginx配置文件,并添加proxy.conf,重载nginx

  1. [root@linux-node1 conf]# cat nginx.conf
  2. worker_processes 1;
  3. events {
  4. worker_connections 1024;
  5. }
  6. http {
  7. include mime.types;
  8. default_type application/octet-stream;
  9. sendfile on;
  10. keepalive_timeout 65;
  11. server {
  12. listen 80;
  13. server_name www.chuck-blog.com;
  14. location / {
  15. proxy_pass http://chuck-blog;
  16. include proxy.conf;
  17. }
  18. }
  19. upstream chuck-blog {
  20. server 192.168.56.11:8080;
  21. server 192.168.56.12:8080;
  22. }
  23. }
  24. [root@linux-node1 conf]# cat proxy.conf
  25. proxy_set_header Host $host;
  26. proxy_set_header X-Forwarded-For $remote_addr;
  27. proxy_connect_timeout 60;
  28. proxy_send_timeout 60;
  29. proxy_read_timeout 60;
  30. proxy_buffer_size 4k;
  31. proxy_buffers 4 32k;
  32. proxy_busy_buffers_size 64k;
  33. proxy_temp_file_write_size 64k;
  34. [root@linux-node1 conf]# ../sbin/nginx -s reload


四、location指令以及动静分离

4.1 location的介绍

  Nginx中的location指令是NginxHnpCoreModule中重要指令。Location指令比较简单, 也比较常用。Sets a configuration based on a request URI。
  location指令,是用来对url进行匹配的,URI即语法中的/Uiri/,可以是宇符串或正则表达式,如果是正则表达,则必须指定前缀。 location指令根据URI来应用不同的配罝,这 个指令允许根据不同URI来应用不同的配置。

4.2通过location动静分离的实现


第一种方案:根据不同pool分离

  1. [root@lb01 conf]# cat nginx.conf
  2. worker_processes 1;
  3. events {
  4. worker_connections 1024;
  5. }
  6. http {
  7. include mime.types;
  8. default_type application/octet-stream;
  9. sendfile on;
  10. keepalive_timeout 65;
  11. upstream static_pools {
  12. server 10.0.0.9:80 weight=1;
  13. }
  14. upstream upload_pools {
  15. server 10.0.0.6:80 weight=1;
  16. }
  17. upstream default_pools {
  18. server 10.0.0.9:8000 weight=1;
  19. }
  20. server {
  21. listen 80;
  22. server_name www.chuck-blog.com;
  23. location / {
  24. proxy_pass http://default_pools;
  25. include proxy.conf;
  26. }
  27. location /static/ {
  28. proxy_pass http://static_pools;
  29. include proxy.conf;
  30. }
  31. location /upload/ {
  32. proxy_pass http://upload_pools;
  33. include proxy.conf;
  34. }
  35. }

第二种方案:根据if判断路径分离

  1. [root@lb01 conf]# cat nginx.conf
  2. worker_processes 1;
  3. events {
  4. worker_connections 1024;
  5. }
  6. http {
  7. include mime.types;
  8. default_type application/octet-stream;
  9. sendfile on;
  10. keepalive_timeout 65;
  11. server {
  12. listen 80;
  13. server_name www.chuck-blog.com.com;
  14. location / {
  15. if ($request_uri ~* "^/static/(.*)$" )
  16. {
  17. proxy_pass http://static/$1;
  18. }
  19. if ($request_uri ~* "^/upload/(.*)$" )
  20. {
  21. proxy_pass http://upload/$1;
  22. }
  23. proxy_pass http://dynamic/$1;
  24. include proxy.conf;
  25. }
  26. }
  27. upstream upload {
  28. server Web-A1:8000;
  29. }
  30. upstream static {
  31. server Web-A2;
  32. }
  33. upstream dynamic {
  34. server Web-A1;
  35. }
  36. }

五、使用user_agent辨别浏览器标识实现pc和移动端分离

  1. [root@lb01 conf]# cat nginx.conf
  2. worker_processes 1;
  3. events {
  4. worker_connections 1024;
  5. }
  6. http {
  7. include mime.types;
  8. default_type application/octet-stream;
  9. sendfile on;
  10. keepalive_timeout 65;
  11. upstream static_pools {
  12. server 10.0.0.9:80 weight=1;
  13. }
  14. upstream upload_pools {
  15. server 10.0.0.6:80 weight=1;
  16. }
  17. upstream default_pools {
  18. server 10.0.0.9:8000 weight=1;
  19. }
  20. server {
  21. listen 80;
  22. server_name www.chuck-blog.com;
  23. location / {
  24. if ($http_user_agent ~* "MSIE")
  25. #如果请求的浏览器为微软IE浏览器(MSIE),则让请求由static_pools池处理
  26. {
  27. proxy_pass http://static_pools;
  28. }
  29. if ($http_user_agent ~* "Chrome")
  30. #如果请求的浏览器为谷歌浏览器(Chrome),则让请求由upload_pools池处理
  31. {
  32. proxy_pass http://upload_pools;
  33. }
  34. proxy_pass http://default_pools;
  35. }
  36. }

weight = NUMBER – 设置服务器权重,默认为1。
max_fails = NUMBER – 在一定时间内(这个时间在fail_timeout参数中设置)检查这个服务器是否可用时产生的最多失败请求数,默认为1,将其设置为0可以关闭检查,这些错误在proxy_next_upstream或fastcgi_next_upstream(404错误不会使max_fails增加)中定义。
fail_timeout = TIME – 在这个时间内产生了max_fails所设置大小的失败尝试连接请求后这个服务器可能不可用,同样它指定了服务器不可用的时间(在下一次尝试连接请求发起之前),默认为10秒,fail_timeout与前端响应时间没有直接关系,不过可以使用proxy_connect_timeout和proxy_read_timeout来控制。
down – 标记服务器处于离线状态,通常和ip_hash一起使用。
backup – (0.6.7或更高)如果所有的非备份服务器都宕机或繁忙,则使用本服务器(无法和ip_hash指令搭配使用)。

6.2 upstream模块调度算法介绍

rr轮询(默认):按客户端顺序把客户端的请求注意分配到不同的后端服务器,如果后端服务器宕机(默认情况只检测80端口,如果后端报502,404,403,503,还是会直接返回给用户),后端宕机的服务器会被自动剔除,使用户访问不瘦影响,请求会分配给正常的服务器。
weight权重:在轮询算法的基础上加权重,权重轮询和访问成正比,权重越大,转发的请求也就越多,可以根据服务器的配置和性能指定权重值大小,可有效解决新旧服务器性能不均进行请求分配问题。
ip_hash:每个请求按访问ip的hash结果分配,当心的请求到达时,先将其客户端ip通过hash算法计算出一个值,在随后请求客户端中,只要ip的hash值相同,就会被分配至同一台服务器,该调度算法可以解决动态网页session共享问题,但有时会导致请求分配不均,即无法保证1:1的负载均衡。在国内都是NAT上网,多个PC,对应一个外部IP。
fair(第三方):按照后端服务器相应时间来分配,响应时间短的优先分配,比以上两个更加智能的负载均衡算法。此算法那可以依据页面大小和页面大小和加载时间长短智能地进行负载均衡,也就是根据后端服务器的响应时间来分配请求,响应时间段的优先分配,nginx本身是不支持fair的,如果需要使用这种调度算法,必须加载nginx的upstream_fair模块。
url_hash(第三方):按照url的hash结果来分配请求,让没给url定向到同一个后端服务器,后端服务器为缓存服务器时效果显著。在upstream中加入hash语句,server语句中不能写入weight等其他的参数。nginx本身是不支持url_hash的,如果需要使用这种电镀算法,必须安装nginx的hash软件包。
least_conn:最少连接数,哪个server连接数就分配给哪个server。

6.3 http_proxy重点内容

1)proxy_set_header
语法:proxy_set_header header value
默认值: Host and Connection
使用字段:http, server, location
这个指令允许将发送到被代理服务器的请求头重新定义或者增加一些字段。这个值可以是一个文本,变量或者它们的组合。
proxy_set_header在指定的字段中没有定义时会从它的上级字段继承。
默认只有两个字段可以重新定义:

  1. proxy_set_header Host $proxy_host;
  2. proxy_set_header Connection Close;

未修改的请求头“Host”可以用如下方式传送:

  1. proxy_set_header Host $http_host;

但是如果这个字段在客户端的请求头中不存在,那么不发送数据到被代理服务器。这种情况下最好使用$Host变量,它的值等于请求头中的”Host”字段或服务器名:

  1. proxy_set_header Host $host;

此外,可以将被代理的端口与服务器名称一起传递:

  1. proxy_set_header Host $host:$proxy_port;

如果设置为空字符串,则不会传递头部到后端,例如下列设置将禁止后端使用gzip压缩:

  1. proxy_set_header Accept-Encoding "";

2)proxy_set_header X-Forwarded-For $remote-addr;
保留客户机的真实IP。包含客户端请求头中的”X-Forwarded-For”,与$remote_addr用逗号分开,如果没有”X-Forwarded-For”请求头,则$proxy_add_x_forwarded_for等于$remote_addr。

0
未经许可,不得转载,否则将受到作者追究,博主联系方式见首页右上角

该文章由 发布

这货来去如风,什么鬼都没留下!!!
发表我的评论
取消评论
代码 贴图 加粗 链接 删除线 签到