网站集群架构之负载均衡(Nginx)

一、集群负载均衡概述

1.负载均衡介绍:

  负载均衡是由多台服务器以对称的方式组成一个服务器集合,每台服务器都具有等价的地位,都可以单独对外提供服务而无须其他服务器的辅助。其工作模式为将外部发送来的请求均匀分配到对称结构中的某一台服务器上,而接收到请求的服务器独立地回应客户的请求。均衡负载能够平均分配客户请求到服务器列阵,基于此提供快速获取重要数据,解决大量并发访问服务问题。

2.集群的分类

  负载均衡集群(Load Balancing clusters),简称LBC或LB
  高可用性集群(High-Availability clusters),简称HAC
  高性能计算集群(High-performance clusters),简称HPC
  网络计算(Grid computing)

2.1 负载均衡集群
  负载均衡集群为了提供更为实用,性价比更高的系统架构解决方案,可以把很多客户集中的访问请求尽可能平均分摊在计算机集群中处理。
注意:要考虑每个节点的承受能力,防止雪崩。

作用:
  1)分担用户访问请求几数据流量(负载均衡)
  2)保持业务连续性,即7*24小时服务(高可用性)
  3)应用于web业务及数据库从库等服务器的业务
负载均衡开源的软件包括 LVS Nginx Haproxy

2.2 高可用性集群
  在集群任意一个节点失效的情况下,该节点的所有任务会自动转移到其他正常的节点上,并且不影响真个集群的运行。

作用:
  当一台机器宕机时,另外一台机器接管机器的IP资源和服务资源,提供服务。
  常用于不易实现负载均衡的应用,比如在均衡器,主数据库,主存储之间
高可用性集群常用的软件包括keepalived heartbeat等

2.3 高性能计算集群
  通常,高性能计算集群设置为集群开发的并行应用程序,以解决负复杂的科学问题(天气预报,石油勘探,核反应模拟等)
  高性能集群对外就好像一个超级计算机,这种超级计算机内部是有数十至上万台独立服务器组成,并且在公共消息传递层上进行通信运行并行应用程序。

二、负载均衡之Nginx组件模块

实现Nginx的负载均衡组件主要有两个:

  ngx_http_proxy_module #proxy代理模块,用于把请求后抛给服务器节点或upstream服务器池
  ngx_http_upstream_module #负载均衡模块,可以实现网站的负载均衡功能及节点的健康检查

2.1 upstream模块:
  upstream模块允许Nginx定义一组或多组服务器组,使用时可以通过 porxy_pass 代理方式吧网站的请求发送到实现定义好的对应 upstream组的名字上,具体写法为:
proxy_pass http://www_server_pools 其中www_server_pools 就是一个upstream节点服务器组名字
例如:

upstream www_server_pools {
server 10.0.0.17:80 weight=5;
server 10.0.0.17:80 weight=1 max_fails=1 fail_timeout=10s; #默认参数
server 10.0.0.18:80 weight=10 max_fails=2 fail_timeout=20s backup;
server 10.0.0.19:82 weight=15;
server unix:/tmp/backend3;
}

配置说明:

  upstream模块的内容应放于nginx.conf配置的http标签内,默认调度节点算法是wrr(权重轮询,weighted round-robin)
  server:负载均衡后面的rs配置,可以是ip或域名
  weight:服务器的权重,默认值为1,越大表示接受的请求比例越大
  max_fails:nginx尝试连接后端主机失败的次数,这个数值是配合proxy_net_upstream,fastcgi_next_upstream和memcached_next_upstream这三个参数来使用的,当nginx接收后端服务器返回这三个参数定义的状态码时,会将这个请求转发给正常工作的后端服务器,例如404,502,503
  backup:热备配置(rs节点的高可用),当前面激活的rs都失败后会自动启动用热备rs,这标志着这个服务器作为备份服务器,若主服务器全部宕机了,就会向它转发请求;当负载调度算法为ip_hash时,后端服务器在负载均衡调度中的状态不能是weight和backup
  fail_timeout:在max_fails定义的失败次数后,距离下次检查的时间间隔,默认10s
  down:表示服务器永远不可用,可配合ip_hash使用

对比 haproxy的配置参数:

  server php_server_1 10.12.25.68:80 cookie 1 check inter 2000 rise 3 fall 3 weight 2
  server php_server_2 10.12.25.72:80 cookie 2 check inter 2000 rise 3 fall 3 weight 1
  server php_server_bak 10.12.25.79:80 cookie 3 check inter 1500 rise 3 fall 3 backup

参数说明:

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

2.2 upstream模块调度算法
调度算法一般分为两类:

  1、第一类为静态调度算法,及负载均衡根据自身设定的规则进行分配,不需要考虑节点服务器的情况,例如: rr wrr ip hash等
  2.第二类为动态调度算法,即负载均衡会根据后端即节点的当前状态来决定是否分发请求,例如:连接数少的优先获取的请求,响应时间短的优先获取请求,例如,least conn fair等

补充:
  常见的调度算法
  rr轮询:round-robin,默认调度算法,静态调度算法,按照客户端请求顺序逐一分配到不同的后端节点服务器,宕机的服务器会被自动从节点服务器池中剔除。
  wrr权重轮询:静态调度算法,在rr轮询算法的基础上加上权重,权重和用户访问成正比,权重值越大,被转发的请求也就越多
  ip_hash:静态调度算法,每个请求按客户端IP的Hash值分配,当新的请求到达时,先将其客户端IP通过哈希算法计算出一个值,在随后的客户端请求中,客户端IP的哈希值只要相同,就会被分配到同一台服务器,可以解决动态网页的session共享问题,但也会引起分配不均的弊端
  fair:动态调度算法,此算法会根据后端节点服务器的响应时间来分配请求,响应时间短的优先分配,可以依据页面大小和加载时间舱段智能地进行负载均衡,也就是根据后端服务器的响应时间来分配请求,响应时间短的优先分配。需要下载Nginx的相关模块upstream_fair
  least_conn:根据后端节点的连接数来决定分配情况,哪个机器连接数少就分发
  url_hash:根据访问URL的hash结果来分配请求的,让每个URL定向到同一个后端服务器,后端服务器为缓存服务器时效果显著,如果需要使用这种调度算法,必须安装Nginx的hash模块软件包
  一致性hash:一般用于代理后端业务为缓存服务(squid,memcached)的场景,通过将用户请求的uri或者指定字符串进行计算,然后调度到后端的服务器上,此后任何用户查找同一个uri或者指定字符串都会被调度到这一台服务器上,因此后端的每个节点缓存的内容都是不同的,一致性hash算法可以解决后端某个或者几个节点宕机后,缓存的数据动荡最小。

2.3 http_proxy_module模块
  proxy_pass指令属于ngx_http_proxy_module模块,此模块可以将请求转发到另一台服务器,在实际的反向代理工作中,会通过location功能匹配指定的uri,然后把接收到的符合匹配URI的请求通过proxy_pass抛给定义好的upstream节点池
简单配置实例

location /name/ {
	proxy_pass http://127.0.0.1/remote/;
}

模块参数:

  proxy_set_header:设置http请求header项传给后端服务器节点,例如,可以实现让代理后端的服务器节点获取访问客户端用户真实的IP地址
  client_body_buffer_size:用于指定客户端请求主题缓冲区大小
  proxy_connect_timeout:表示反向代理与后端节点服务器连接的超时时间,即发起握手等候响应的超时时间
  proxy_send_timeout:表示代理后端服务器的数据回传时间,即在规定时间之内,后端服务器必须传完所有的数据,否则,nginx将断开这个连接
  proxy_read_timeout:设置nginx从代理的后端服务器获取信息的时间,表示连接建立成功后,Nginx等待后端服务器的响应时间,其实是nginx已经后端的排队之中等候处理的时间
  proxy_buffer_size:设置缓冲区大小,默认该缓冲区大小等于指令proxy_buffers设置的大小
  proxy_buffers:设置缓冲区的数量和大小,nginx从代理的后端服务器获取的响应信息,会放置在缓冲区
  proxy_busy_buffers_size:用于设置系统很忙时可以使用的proxy_buffers大小,官方推荐的大小为proxy_bufer*2
  proxy_temp_file_write_size:指定proxy缓存临时文件的大小

2.3.1 多虚拟机主机代理
  在多虚拟主机的环境下,当用户访问域名时,反向代理向下面节点重新发起请求时,默认并没有在请求头里告诉节点服务器要找哪台虚拟主机,所以web节点服务器接收到请求后发现没有主机头信息,因此,就把节点服务器上配置的第一个虚拟主机发给了反向代理。
解决方案:在Nginx代理虚拟主机配置里增加如下内容:

worker_processes  1;
events {
    worker_connections  1024;
}
http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;
	upstream www_server_pools {
	server 10.0.0.7:80 weight=1;
	server 10.0.0.8:80 weight=1;
}
    server {
        listen       80;
        server_name  www.liuliya.com;
        location / {
            proxy_pass http://www_server_pools;
            proxy_set_header Host $host;
        }
	}
}

2.3.2 反向代理记录用户IP
  默认情况,节点服务器对应的www虚拟主机的访问日志的第一个字段记录的并不是客户达un的IP,而是反向代理服务器的IP
解析方案,在Nginx代理虚拟主机配置中增加如下内容

worker_processes  1;
events {
    worker_connections  1024;
}
http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;
	upstream www_server_pools {
	server 10.0.0.7:80 weight=1;
	server 10.0.0.8:80 weight=1;
}
    server {
        listen       80;
        server_name  www.liuliya.com;
        location / {
            proxy_pass http://www_server_pools;
            proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $remote_addr;
        }
  }
}
#www节点服务器配置文件在http模块下增加如下内容
    log_format main '$remote_addr - $remote_user [$time_local] "$request" '
                    '$status $body_bytes_sent "$http_referer" '
                    '"$http_user_agent" "$http_x_forwarded_for" ';
  如果是apache作为反向代理节点,则配置文件作如下修改:
LogFormat "\"%{X-Forwarded-For}i\ %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" common
#LogFormat "%h %l %u %t \"%r\" %>s %b" common

2.4 代理的参数优化
  把常用的配置参数写成一个文件,使用include包含,看起来简洁规范

[root@lb01 nginx]# cat conf/proxy.conf
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_connect_timeout 60;
proxy_send_timeout 60;
proxy_read_timeout 60;
proxy_buffer_size 4k;
proxy_buffers 4 32k;
proxy_busy_buffers_size 64k;
proxy_temp_file_write_size 64k;
[root@lb01 nginx]# cat conf/nginx.conf
worker_processes  1;
events {
    worker_connections  1024;
}
http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;
	upstream www_server_pools {
	server 10.0.0.7:80 weight=1;
	server 10.0.0.8:80 weight=1;
}
    server {
        listen       80;
        server_name  www.liuliya.com;
        location / {
            proxy_pass http://www_server_pools;
            proxy_set_header Host $host;
            proxy_set_header X-Forwarded-For $remote_addr;
            include proxy.conf;
        }
    }
}

三、负载均衡之Nginx安装部署

#安装依赖包软件
yum install pcre pcre-devel openssl-devel -y
#创建www用户

useradd -u 1000 www -s /sbin/nologin -M
id www

#下载或上传软件包

mkdir -p /server/tools/
cd /server/tools/
wget -q http://nginx.org/download/nginx-1.8.1.tar.gz

#解压并编译安装

tar xf nginx-1.8.1.tar.gz
cd nginx-1.8.1
./configure --prefix=/application/nginx-1.8.1  --user=www --group=www  --with-http_ssl_module  --with-http_stub_status_module
make
make install

#创建软连接
ln -s /application/nginx-1.8.1/ /application/nginx
##创建简洁版配置文档

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

#更改nignx配置

#cd /application/nginx/conf
#vim/application/nginx/conf/nginx.conf
worker_processes  1;
events {
    worker_connections  1024;
}
http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;
    upstream backend {
      server 172.16.1.7:80 weight=1;
      server 172.16.1.8:80 weight=1;
    }
    server {
        listen       80;
        server_name  blog.liuliya.com;
        location / {
          proxy_pass http://backend;
          proxy_set_header Host      $host;
        proxy_set_header X-Real-IP $remote_addr;
        }
    }
server {
        listen       80;
        server_name  bbs.liuliya.com;
        location / {
          proxy_pass http://backend;
          proxy_set_header Host      $host;
proxy_set_header X-Real-IP $remote_addr;
        }
    }
server {
        listen       80;
        server_name  www.liuliya.com;
        location / {
          proxy_pass http://backend;
          proxy_set_header Host      $host;
         proxy_set_header X-Real-IP $remote_addr;
        }
    }
}

##测试:使用负载的IP解析到blog.liuliya.com
#基于浏览器访问

worker_processes  1;
events {
    worker_connections  1024;
}
http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;
	upstream upload_pools {
	  server 10.0.0.8:80;
	}
	upstream static_pools {
	  server 10.0.0.7:80;
	}
	upstream default_pools {
	  server 10.0.0.7:8080;
	}
    server {
        listen       80;
        server_name  www.liuliya.com;
       location / {
         if ($http_user_agent ~* "MSIE")
           {
            proxy_pass http://static_pools;
          }
         if ($http_user_agent ~* "Chrome")
          {
            proxy_pass http://upload_pools;
          }
        proxy_pass http://default_pools;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $remote_addr;
       }
    }
}

#基于域名访问

worker_processes  1;
events {
    worker_connections  1024;
}
http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;
    upstream web_pools {
      server 172.16.1.7 weight=1 max_fails=3 fail_timeout=10s;
      server 172.16.1.8 weight=1;
    }
    server {
        listen       80;
        server_name  www.liuliya.com;
        location / {
          proxy_pass http://web_pools;
          proxy_set_header Host $host;
          proxy_set_header X-Forwarded-For $remote_addr;
        }
    }
    server {
        listen       80;
        server_name  bbs.liuliya.com;
        location / {
          proxy_pass http://web_pools;
          proxy_set_header Host $host;
          proxy_set_header X-Forwarded-For $remote_addr;
        }
    }
    server {
        listen       80;
        server_name  blog.liuliya.com;
        location / {
          proxy_pass http://web_pools;
          proxy_set_header Host $host;
          proxy_set_header X-Forwarded-For $remote_addr;
        }
    }
}

#基于目录访问

worker_processes  1;
events {
    worker_connections  1024;
}
http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;
	upstream upload_pools {
	  server 10.0.0.8:80;
	}
	upstream static_pools {
	  server 10.0.0.7:80;
	}
	upstream default_pools {
	  server 10.0.0.7:8080;
	}
    server {
        listen       80;
        server_name  www.liuliya.com;
        location /upload {
          proxy_pass http://upload_pools;
          proxy_set_header Host $host;
          proxy_set_header X-Forwarded-For $remote_addr;
        }
        location /static {
          proxy_pass http://static_pools;
          proxy_set_header Host $host;
          proxy_set_header X-Forwarded-For $remote_addr;
        }
        location / {
          proxy_pass http://default_pools;
          proxy_set_header Host $host;
          proxy_set_header X-Forwarded-For $remote_addr;
        }
    }
}
#liuliya.com
worker_processes  1;
events {
    worker_connections  1024;
}
http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;
	upstream upload_pools {
	  server 10.0.0.8:80;
	}
	upstream static_pools {
	  server 10.0.0.7:80;
	}
	upstream default_pools {
	  server 10.0.0.7:8080;
	}
    server {
        listen       80;
        server_name  www.liuliya.comg;
       location / {
         if ($http_user_agent ~* "android")
           {
            proxy_pass http://static_pools;
          }
         if ($http_user_agent ~* "iphone")
          {
            proxy_pass http://upload_pools;
          }
        proxy_pass http://default_pools;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $remote_addr;
       }
    }
}

#hosts解析

  #lb01
[root@lb01 ~]# cat /etc/hosts
127.0.0.1  localhost.localdomain  localhost.localdomain  localhost4  localhost4.localdomain4  localhost
::1        localhost.localdomain  localhost.localdomain  localhost6  localhost6.localdomain6  localhost
172.16.1.5   lb01
172.16.1.6   lb02
172.16.1.7   web01
172.16.1.8   web02
172.16.1.51  db01
172.16.1.52  db02
172.16.1.31  nfs
172.16.1.41  backup
172.16.1.61  m01
10.0.0.5 www.liuliya.comg bbs.liuliya.comg blog.liuliya.comg
[root@lb01 ~]#

  

  #web01
[root@web01 ~]# cat /etc/hosts
127.0.0.1  localhost.localdomain  localhost.localdomain  localhost4  localhost4.localdomain4  localhost
::1        localhost.localdomain  localhost.localdomain  localhost6  localhost6.localdomain6  localhost
172.16.1.5   lb01
172.16.1.6   lb02
172.16.1.7   web01 www.liuliya.comg bbs.liuliya.comg blog.liuliya.comg
172.16.1.8   web02
172.16.1.51  db01
172.16.1.52  db02
172.16.1.31  nfs
172.16.1.41  backup
172.16.1.61  m01
[root@web01 ~]#
  #web02
[root@web02 ~]# cat /etc/hosts
127.0.0.1  localhost.localdomain  localhost.localdomain  localhost4  localhost4.localdomain4  localhost
::1        localhost.localdomain  localhost.localdomain  localhost6  localhost6.localdomain6  localhost
172.16.1.5   lb01
172.16.1.6   lb02
172.16.1.7   web01
172.16.1.8   web02 www.liuliya.comg bbs.liuliya.comg blog.liuliya.comg
172.16.1.51  db01
172.16.1.52  db02
172.16.1.31  nfs
172.16.1.41  backup
172.16.1.61  m01

#测试:
  使用负载的IP解析到blog.liuliya.comg。 在哪台机器上测试,就在哪台机器上解析对应负载的IP
在web02服务器上添加一个主页文件:

[root@web02 ~]# /application/apache/bin/apachectl start
[root@web02 ~]# echo apache www >/application/apache/htdocs/blog/index.html

在web01服务器上添加一个主页文件:

[root@web01 ~]# /application/nginx/sbin/nginx
[root@web01 ~]# echo nginx www >/application/nginx/html/blog/index.html

在lb服务器上添加hosts解析,并测试:

[root@lb01 ~]# curl blog.liuliya.comg/index.html
apache www
[root@lb01 ~]# curl blog.liuliya.comg/index.html
nginx www

拓展
#先看看location方法的匹配规则,如下:

location ~ .*.(gif|jpg|jpeg|png|bmp|swf|css|js)$ {
	proxy_pass http://static_pools;
	include proxy.conf;
}

#下面是if语句方法的匹配规则:

        if ($request_uri   ~*   ".*\.(php|php5)$")
        {
                proxy_pass http://php_server_pools;
        }
        if ($request_uri   ~*   ".*\.(jsp|jsp*|do|do*)$")
        {
                proxy_pass http://java_server_pools;
        }

总结:Nginx整体架构(负载均衡)

www.liuliya.com-->本地解析-->proxy代理模块-->地址池-->web服务器 -->nginx.conf -->extra/www(html/www)-->index.html

lb端

 1、浏览器输入www.liuliya.com
  本地hosts文件解析 10.0.0.5 blog.liuliya.com bbs.liuliya.com www.liuliya.com
 2、lb配置文件nginx.conf
   upstream
   用于定义可以被 proxy_pass、fastcgi_pass 以及memcached_pass 等指令引用的服务器群
   定义web服务器池web01_ip web02_ip
   server 172.16.1.7:80
   server定义代理的负载均衡域名虚拟主机
   域名访问、目录访问、浏览器访问、移动端访问
   proxy代理模块,用于把请求后抛给服务器节点或upstream服务器池

web端 (web01_ip web02_ip)

#1、nginx.conf配置文件
http {
include extra/www.conf;
include extra/bbs.conf;
include extra/blog.conf;
}
#2、extra目录
www.conf;
bbs.conf;
blog.conf;
#3、server
 站点目录index.html
 目录文件存放于:
 html/www
 html/bbs
 html/blog

发表评论

发表评论

*

沙发空缺中,还不快抢~