集群
集群是指一组(若干个)相互独立的计算机,利用高速通信网路组成的一个较大的计算机服务系统,每个集群节点(即集群中的每台计算机)都是运用各自服务的独立服务器。这些服务器之间可以彼此通信,协同向用户提供应用程序,系统资源和数据,并以单一系统的模式加以管理。当用户客户机请求集群系统时,集群给用户的感觉就是一个单一独立的服务器,而实际上用户请求的是一组集群服务器。
特点:
(1)高性能
用户通过Internet到公司的网关,网关通过防火墙,调载到前端的主负载均衡服务器上(有主有备,预防单点问题),主负载均衡根据算法传送给web集群中的一台LNMP Web服务器,动态nginx传送给php,PHP找到数据库,数据库寻找主数据库(还有备份数据库),利用主从复制架构(主负责写,从负责读),此时分离出三个“从”同为从的数据 库前端有一组负载均衡(一主一从,负担读的压力),都是负责读;当用户读取数据是,直接到读的负载均衡器
时间久了,随着集群的扩大,MySQL主库压力过大,承受不了,进行主从复制,读写分离(select读,insert写),
(静态网页由Nginx处理,动态网页由PHP找数据库,其中PHP通过解析开发写的代码然后找MySQL)
(2)价格有效性
(3)可伸缩性
(4)高可用性
(5)透明性
(6)可管理性
(7)可编程性
##### 集群的常见分类
计算机集群架构按功能和结构可以分成以下几类:
1. 负载均衡集群,简称LBC或者LB
分摊用户访问请求及数据流量(负载均衡)
保持业务连续性,即7*24小时服务(高可用性)。
应用于Web业务及数据库从库等服务器的业务
负载均衡集群典型的开源软件包括LVS,Nginx,Haproxy等。
![在这里插入图片描述](https://img-blog.csdnimg.cn/20181129142350834.?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzMwNDgwNA==,size_16,color_FFFFFF,t_70)
LVS:四层负载均衡设备,通过修改IP头部和MAC头部实现对数据包的完全==转发==;速度快,效率高,但由于只能到四层,因此实现功能少
Nginx:七层负载均衡设备,效率低,但是实现的功能多
Nginx==反向代理==接收访问用户的请求后,会代理用户重新发起请求代理下的节点服务器,最后把数据返回给客户端用户,在节点服务器看来,访问的节点服务器的客户端用户就是反向代理服务器了,而非真实的网站访问用户。
==LVS等的负载均衡是转发用户请求的数据包,而Nginx反向代理是接收用户的请求然后重新发起请求去请求其后面的节点。==
2. 高可用性集群,简称HAC
指在集群中任意一个节点失效的情况下,该节点上的所有任务会自动转移到其他正常的节点上。此过程并不影响整个集群的运行。
高可用性集群的作用为:
当一台机器宕机时,另外一台机器接管宕机的机器的IP资源和服务资源,提供服务。
常用于不易实现负载均衡的应用,比如负载均衡器,主数据库,主存储对之间。
高可用性集群常用的开源软件包括Keepalived,Heartbeat等。
![在这里插入图片描述](https://img-blog.csdnimg.cn/20181129144449910.?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzMwNDgwNA==,size_16,color_FFFFFF,t_70)
3. 高性能计算集群,简称HPC
高性能计算集群也称并行计算。通常,高性能计算集群涉及为集群开发的并行应用程序,以解决复杂的科学问题(天气预报,石油勘探,核反应模拟等)。高性能计算集群对外就好像一个超级计算机,这种超级计算机内部由数十至上万个独立服务器组成,并且在公共消息传递层上进行通信以运行并行应用程序。在生产环境中实际就是把任务切成蛋糕,然后下发到集群节点计算,计算后返回结果,然后继续领新任务计算,如此往复。
4. 网格计算集群
###### 对于集群软硬件产品如何选型
当企业业务重要,技术力量又薄弱,并且希望出钱购买产品及获取更好的服务时,可以选择硬件负载均衡产品,如F5,Netscaler,Radware等,此类公司多为传统的大型非互联网企业,如银行,证券,金融业及宝马,奔驰公司等
对于门户网站来说,大多会并用软件及硬件产品来分担单一产品的风险,如淘宝,腾讯,新浪等。融资了的企业会购买硬件产品,如赶集等网站。
中小型互联网企业,由于起步阶段无利润可赚或者利润很低,会希望通过使用开源免费的方案来解决问题,因此会雇佣专门的运维人员进行维护。例如:51CTO等
### 负载均衡环境搭建
环境部署:一台nginx服务器(编译安装nginx),两台WEB服务器(web01与web02配置环境完全相同,编译安装nginx)
nginx服务端 192.168.239.129
web01服务器 192.168.239.130
web02服务器 192.168.239.131
1.nginx安装
```
[root@localhost ~]# tar xf nginx-1.10.2.tar.gz -C /usr/src/
[root@localhost ~]# cd /usr/src/nginx-1.10.2/
[root@localhost ~]# mount /dev/sr0 /media/cdrom
[root@localhost nginx-1.10.2]# yum -y install pcre-devel openssl-devel
[root@localhost nginx-1.10.2]# useradd -s /sbin/nologin -M www
[root@localhost nginx-1.10.2]# ./configure --user=www --group=www --prefix=/usr/local/nginx --with-http_stub_status_module --with-http_ssl_module
[root@localhost nginx-1.10.2]# make && make install
[root@localhost nginx-1.10.2]# ln -s /usr/local/nginx/sbin/* /usr/local/sbin/
[root@localhost conf]# cd /usr/local/nginx/conf/
[root@localhost conf]# egrep -v "#|^$" nginx.conf.default > nginx.conf
[root@localhost conf]# vim nginx.conf
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
upstream default_server { # upstream服务器池 default_server市服务器池的名字
server 192.168.239.130; #server就是一个RS节点,默认权重weight=1(负载均衡是按照权重比分配的)
server 192.168.239.131;
}
server {
listen 80;
server_name www.yunjisuan.com;
location / {
proxy_pass http://default_server;
proxy_set_header host $host; #在代理向后端服务器发送的http请求头中加入host字段信息,用于当后端服务器配置有多个虚拟主机时,可以识别代理的是哪个虚拟主机。这是节点服务器多虚拟主机时的关键配置。
proxy_set_header x-forward-for $remote_addr; #在代理向后端服务器发送的http请求头中加入X-Forwarded-For字段信息,用于后端服务器程序,日志等接收记录真实用户的IP,而不是代理服务器的IP
}
}
}
[root@localhost conf]# /usr/local/nginx/sbin/nginx
[root@localhost conf]# netstat -antup | grep 80
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 4187/nginx
# nginx编译完毕
[root@www html]# vim /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.239.129 www.yunjisuan.com
```
2.配置 web服务器的nginx.conf配置文件
web01与weo02配置文件相同
```
[root@localhost conf]# vim nginx.conf
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
log_format main '$remote_addr- $remote_user[$time_local]"$request"' #来源IP、来源用户、时间、请求
'$status $body_bytes_sent "$http_referer"' #状态码、主体(显示发送的大小)、来源浏览器、用户客户端、用户的IP
'"$http_user_agent""$http_x_forwarded_for"'; #日志格式化,节点服务器需要的访问日志如果要记录用户的真实IP,还必须进行日志格式配置,这样才能把代理传过来的X-Forwarded-For头信息记录下来
server {
listen 80;
server_name bbs.yunjisuan.com;
location / {
root html/bbs;
index index.html index.htm;
}
access_log logs/access_bbs.log main; #启用日志main(相对路径)
}
server {
listen 80;
server_name www.yunjisuan.com;
location / {
root html/www;
index index.html index.htm;
}
access_log logs/access_www.log main;
}
}
[root@localhost conf]# /usr/local/nginx/sbin/nginx
[root@localhost conf]# netstat -antup | grep 80
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 4187/nginx
[root@localhost nginx]# mkdir /usr/local/nginx/html/{www,bbs}
[root@localhost nginx]# echo "`hostname -I `www" >> /usr/local/nginx/html/www/index.html
[root@localhost nginx]# cat /usr/local/nginx/html/www/index.html
192.168.239.130 www
[root@localhost nginx]# echo "`hostname -I `bbs" >> /usr/local/nginx/html/bbs/index.html
[root@localhost nginx]# cat /usr/local/nginx/html/bbs/index.html
192.168.239.130 bbs
[root@localhost conf]# vim /etc/hosts
192.168.239.130 www.yunjisuan.com bbs.yunjisuan.com
[root@localhost conf]# curl www.yunjisuan.com
192.168.239.130 www
[root@localhost conf]# curl bbs.yunjisuan.com
192.168.239.130 bbs
# web02同上操作
```
3. 检查负载均衡测试结果
```
[root@localhost conf]# hostname -I
192.168.239.129
[root@localhost conf]# vim /etc/hosts
192.168.239.129 www.yunjisuan.com
[root@localhost conf]# curl www.yunjisuan.com
192.168.239.130 www
[root@localhost conf]# curl www.yunjisuan.com
192.168.239.131 www
```
#### Nginx负载均衡核心组件介绍
##### Nginx upstream模块
ngx_http_upstream_module模块允许Nginx定义一组或多组节点服务器组,使用时可以通过proxy_pass代理方式把网站的请求发送到事先定义好的对应Upstream组的名字上,具体写法为“proxy_pass http:// www_server_pools”,其中www_server_pools就是一个Upstream节点服务器组名字。
upstream服务器池自带健康监测功能
```
upstream default_server { # upstream服务器池 default_server市服务器池的名字
server 192.168.239.130; #server就是一个RS节点,默认权重轮询weight=1(负载均衡是按照权重比分配的)
server 192.168.239.131; #server关键字是固定的,后面可以接域名或IP。如果不指定端口,默认是80端口。weight代表权重,数值越大被分配的请求越多
}
```
使用域名及socket
```
upstream backend {
server backend1.example.com weight=5;
server backend2.example.com:8080; #域名加端口。转发到后端的指定端口上
server unix:/tmp/backend3; #指定socket文件
#提示:server后面如果接域名,需要内网有DNS服务器或者在负载均衡器的hosts文件做域名解析。
server 192.168.0.223;
server 192.168.0.224:8080;
server backup1.example.com:8080 backup;
#备份服务器,等上面指定的服务器都不可访问的时候会启动,backup的用法和Haproxy中用法一样
server backup2.example.com:8080 backup;
}
```
![在这里插入图片描述](https://img-blog.csdnimg.cn/20181129152227282.?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzMwNDgwNA==,size_16,color_FFFFFF,t_70)
```
upstream backend {
server backend1.example.com weight=5; #如果就是单个Server,没必要设置权重
server 127.0.0.1:8080 max_fail=5 fail_timeout=10s;
#当检测次数等于5的时候,5次连续检测失败后,间隔10s再重新检测。
server unix:/tmp/backend3;
server backup1.example.com:8080 backup; #热备机器设置
}
```
如果是Nginx代理Cache服务,可能需要使用hash算法,此时若宕机,可通过设置down参数确保客户端用户按照当前的hash算法访问
```
upstream backend {
ip_hash;
server backend1.example.com;
server backend2.example.com;
server backend3.example.com down;
server backend4.example.com;
}
#weight:调节服务器的请求分配权重。
check:开启对该服务器健康检查。
inter:设置连续两次的健康检查间隔时间,单位毫秒,默认值2000
rise:指定多少次连续成功的健康检查后,即可认定该服务器处于可用状态。
fall:指定多少次不成功的健康检查后,即认为服务器为宕机状态,默认值3.
maxconn:指定可被发送到该服务器的最大并发连接数。
```
##### upstream模块调度算法
调度算法一般分为两类:
第一类为静态调度算法,即负载均衡器根据自身设定的规则进行分配,不需要考虑后端节点服务器的情况,例如:rr,wrr,ip_hash等都属于静态调度算法。
第二类为动态调度算法,即负载均衡器会根据后端节点的当前状态来决定是否分发请求,例如:连接数少的优先获得请求,响应时间短的优先获得请求。例如:least_conn,fair等都属于动态调度算法。
(1) rr轮询(默认调度算法,静态调度算法 1:1)
按客户端请求顺序把客户端的请求逐一分配到不同的后端节点服务器,这相当于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来源地址永远返回给同一节点服务器,达到会话保持的效果,失去负载均衡作用,导致后方请求数不均衡)
==将session存储在数据库缓存中,达到session共享的问题==
```
upstream yunjisuan_lb{
ip_hash;
server 192.168.0.223:80;
server 192.168.0.224:8080;
}
upstream backend{
ip_hash;
server backend1.example.com;
server backend2.example.com;
server backend3.example.com down;
server backend4.example.com;
}
```
当负载调度算法为ip_hash时,后端服务器在负载均衡调度中的状态不能有weight和backup,即使有也不会生效。
(4)fair(动态调度算法)
此算法会根据后端节点服务器的响应时间来分配请求,响应时间短的优先分配。这是更加智能的调度算法。此种算法可以根据页面大小和加载时间长短智能地进行负载均衡,也就是根据后端服务器的响应时间来分配请求,响应时间短的优先分配。Nginx本身不支持fair调度算法,如果需要使用这种调度算法,必须下载Nginx相关模块upstream_fair。
(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模块软件包。
(7)一致性hash算法
一致性hash算法一般用于代理后端业务为缓存服务(如Squid,Memcached)的场景,通过将用户请求的URI或者指定字符串进行计算,然后调度到后端的服务器上,此后任何用户查找同一个URI或者指定字符串都会被调度到这一台服务器上,因此后端的每个节点缓存的内容都是不同的,一致性hash算法可以解决后端某个或几个节点宕机后,缓存的数据动荡最小。
```
http {
upstream test {
consistent_hash $request_uri; #算法
server 127.0.0.1:9001 id=1001 weight=3;
server 127.0.0.1:9002 id=1002 weight=10;
server 127.0.0.1:9003 id=1003 weight=20;
}
}
```
##### http_proxy_module模块
proxy_pass指令属于ngx_http_proxy_module模块,此模块可以将请求转发到另一台服务器,在实际的反向代理工作中,会通过location功能匹配指定的URI,然后把接收到的符合匹配URI的请求通过proxy_pass抛给定义好的upstream节点池。
(1)将匹配URI为name的请求抛给http://127.0.0.1/remote/.
```
location /name/ {
proxy_pass http://127.0.0.1/remote/;
}
```
(2)将匹配URI为some/path的请求抛给http://127.0.0.1
```
location /some/path/ {
proxy_pass http://127.0.0.1;
}
```
(3)将匹配URI为name的请求应用指定的rewrite规则,然后抛给http://127.0.0.1
```
location /name/ {
rewrite /name/( [^/]+ ) /username=$1 break;
proxy_pass http://127.0.0.1;
}
```
![在这里插入图片描述](https://img-blog.csdnimg.cn/20181129161029444.?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzMwNDgwNA==,size_16,color_FFFFFF,t_70)
![在这里插入图片描述](https://img-blog.csdnimg.cn/20181129161042288.?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzMwNDgwNA==,size_16,color_FFFFFF,t_70)
![在这里插入图片描述](https://img-blog.csdnimg.cn/20181130114232498.?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzMwNDgwNA==,size_16,color_FFFFFF,t_70)
##### nginx反向代理的优化
```
[root@localhost conf]# vim nginx.conf
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
upstream default_server { # upstream服务器池 default_server市服务器池的名字
server 192.168.239.130; #server就是一个RS节点,默认权重weight=1(负载均衡是按照权重比分配的)
server 192.168.239.131;
}
server {
listen 80;
server_name www.yunjisuan.com;
location / {
proxy_pass http://default_server;
proxy_set_header host $host;
proxy_set_header x-forward-for $remote_addr;
include proxy.conf; #proxy.conf文件中包含优化的参数
}
}
}
[root@localhost conf]# vim 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;
```
##### 根据URL中的目录地址实现代理转发
案例背景:
通过Nginx实现动静分离,即通过Nginx反向代理配置规则实现让动态资源和静态资源及其他业务分别由不同的服务器解析,以解决网站性能,安全,用户体验等重要问题。
下图为企业常见的动静分离集群架构图,此架构图适合网站前端只使用同一个域名提供服务的场景,例如,用户访问的域名是www.yunjisuan.com,然后,当用户请求www.yunjisuan.com/upload/xx地址时候,代理会分配请求到上传服务器池处理数据;当用户请求www.yunjisuan.com/static/xx地址的时候,代理会分配请求到静态服务器池请求数据;当用户请求www.yunjisuan.com/xx地址的时候,即不包含上述指定的目录地址路径时,代理会分配请求到默认的动态服务器池请求数据(注意:上面的xx表示任意路径)。
上传服务器需要挂载NFS共享存储;动态服务器无需挂载NFS共享存储,因为浏览器解析该文本内容,题目文字直接解析到了浏览器上,当遇到图片的时候,浏览器顺着图片的链接直接去读取图片。
![在这里插入图片描述](https://img-blog.csdnimg.cn/20181130124941359.?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzMwNDgwNA==,size_16,color_FFFFFF,t_70)
先进行企业案例需求梳理:
当用户请求www.yunjisuan.com/upload/xx地址时,实现由upload上传服务器池处理请求。
当用户请求www.yunjisuan.com/static/xx地址时,实现由静态服务器池处理请求。
除此以外,对于其他访问请求,全都由默认的动态服务器池处理请求。
了解了需求后,就可以进行upstream模块服务器池的配置了。
同时,当用户访问动态页面(图片)时,跳转到static下的图片。
环境部署
nginx服务器 192.168.239.129
web01节点 192.168.239.130 static_server
web02节点 192.168.239.131 upload_server
web03节点 192.168.239.128 default_server
1.nginx服务器
```
[root@www html]# cd /usr/local/nginx/conf/
[root@www conf]# vim nginx.conf
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
upstream static_server {
server 192.168.239.130;
}
upstream upload_server {
server 192.168.239.131;
}
upstream default_server{
server 192.168.239.128;
}
server {
listen 80;
server_name www.yunjisuan.com;
location /static/ {
proxy_pass http://static_server;
include proxy.conf;
}
location /upload/ {
proxy_pass http://upload_server;
include proxy.conf;
}
location / {
proxy_pass http://default_server;
include proxy.conf;
}
}
}
[root@www conf]# vim 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@www conf]# /usr/local/nginx/sbin/nginx -s reload
```
2. web服务端的部署
```
[root@localhost conf]# vim nginx.conf
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
log_format main '$remote_addr- $remote_user[$time_local]"$request"' #来源IP、来源用户、时间、请求
'$status $body_bytes_sent "$http_referer"' #状态码、主体(显示发送的大小)、来源浏览器、用户客户端、用户的IP
'"$http_user_agent""$http_x_forwarded_for"'; #日志格式化,节点服务器需要的访问日志如果要记录用户的真实IP,还必须进行日志格式配置,这样才能把代理传过来的X-Forwarded-For头信息记录下来
server {
listen 80;
server_name bbs.yunjisuan.com;
location / {
root html/bbs;
index index.html index.htm;
}
access_log logs/access_bbs.log main; #启用日志main(相对路径)
}
server {
listen 80;
server_name www.yunjisuan.com;
location / {
root html/www;
index index.html index.htm;
}
access_log logs/access_www.log main;
}
}
[root@localhost conf]# /usr/local/nginx/sbin/nginx
[root@localhost conf]# netstat -antup | grep 80
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 4187/nginx
[root@localhost nginx]# mkdir /usr/local/nginx/html/{www,bbs}
[root@localhost nginx]# echo "`hostname -I `www" >> /usr/local/nginx/html/www/index.html
[root@localhost nginx]# cat /usr/local/nginx/html/www/index.html
192.168.239.130 www
[root@localhost nginx]# echo "`hostname -I `bbs" >> /usr/local/nginx/html/bbs/index.html
[root@localhost nginx]# cat /usr/local/nginx/html/bbs/index.html
192.168.239.130 bbs
[root@localhost conf]# vim /etc/hosts
192.168.239.130 www.yunjisuan.com bbs.yunjisuan.com
[root@localhost conf]# curl www.yunjisuan.com
192.168.239.130 www
[root@localhost conf]# curl bbs.yunjisuan.com
192.168.239.130 bbs
# web02、web03同上操作
```
3.web01中创建static目录,并插入图片
```
[root@localhost conf]# cd /usr/local/nginx/html/www/
[root@localhost www]# mkdir static
[root@localhost www]# echo "static_pools" >> static/index.html
[root@localhost www]# curl http://www.yunjisuan.com/static/index.html #这里的www.yunjisuan.com是解析过的Web01的本地IP
static_pools
[root@www static]# ls
111.jpeg index.html # 在静态池web01中加入图片
```
4. web02中创建upload目录,并测试
```
[root@localhost ~]# cd /usr/local/nginx/html/www/
[root@localhost www]# mkdir upload
[root@localhost www]# echo "upload_pools" >> upload/index.html
[root@localhost www]# curl http://www.yunjisuan.com/upload/index.html #这里的www.yunjisuan.com是解析过的Web02的本地IP
upload_pools
```
5. web03动态服务节点,添加图片访问路径
```
[root@localhost www]# cd /usr/local/nginx/html/www
[root@localhost www]# vim index.html
default_pools
<img src="http://192.168.239.129/static/111.jpeg" > #反向代理的IP地址
[root@localhost www]# curl http://www.yunjisuan.com
default_pools
<img src="http://192.168.239.130/static/111.jpeg" >
```
6. 测试访问图片
![在这里插入图片描述](https://img-blog.csdnimg.cn/20181130230135822.)
![在这里插入图片描述](https://img-blog.csdnimg.cn/20181130230209596.)
==其中,location语句可以通过以if语句实现。==
```
if ($request_uri ~* "^/static/(.*)$")
{
proxy_pass http://static_pools/$1;
}
if ($request_uri ~* "^/upload/(.*)$")
{
proxy_pass http://upload_pools/$1;
}
location / {
proxy_pass http://default_pools;
include proxy.conf;
}
```
##### 根据URL目录地址转发的应用场景
根据HTTP的URL进行转发的应用情况,被称为第7层(应用层)的负载均衡,而LVS的负载均衡一般用于TCP等的转发,因此被称为第4层(传输层)的负载均衡。
在企业中,有时希望只用一个域名对外提供服务,不希望使用多个域名对应同一个产品业务,此时就需要在代理服务器上通过配置规则,使得匹配不同规则的请求会交给不同的服务器池处理。这类业务有:
业务的域名没有拆封或者不希望拆分,但希望实现动静分离,多业务分离,这在前面已经讲解过案例了。
不同的客户端设备(例如:手机和PC端)使用同一个域名访问同一个业务网站,就需要根据规则将不同设备的用户请求交给后端不同的服务器处理,以便得到最佳用户体验。这也是非常重要的,接下来,我就带同学们看看这类的相关案例。
##### 根据客户端的设备(user_agent)转发实践需求
(1)常规4层负载均衡解决方案架构
在常规4层负载均衡架构下,可以使用不同的域名来实现这个需求,例如,人为分配好让移动端用户访问wap.yunjisuan.com,PC客户端用户访问www.yunjisuan.com,通过不同域名来引导用户到指定的后端服务器,该解决方案的架构图如下:
![在这里插入图片描述](https://img-blog.csdnimg.cn/20181130233748519.?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzMwNDgwNA==,size_16,color_FFFFFF,t_70)
此解决方案的最大问题就是不同客户端的用户要记住对应的域名!而绝大多数用户只会记住www.yunjisuan.com,不会记住wap.yunjisuan.com,这样一来就会导致用户体验不是很好。有没有办法让所有客户端用户只访问一个统一的www.yunjisuan.com这个地址,还能让不同客户端设备都能有更好的访问体验呢?当然有!那就是下面的第7层负载均衡解决方案。
(2)第7层负载均衡解决方案
在第7层负载均衡架构下,就可以不需要人为拆分域名了,对外只需要用一个域名,例如www.yunjisuan.com,通过获取用户请求中的设备信息(利用$http_user_agent获取),根据这些信息转给后端合适的服务器处理,这个方案最大好处就是不需要让用户记忆多个域名了,用户只需要记住主网站地址www.yunjisuan.com,剩下的由网站服务器处理,这样的思路大大地提升了用户访问体验,这是当前企业网站非常常用的解决方案。
![在这里插入图片描述](https://img-blog.csdnimg.cn/20181130233810509.?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzMwNDgwNA==,size_16,color_FFFFFF,t_70)
```
location / {
if ($http_user_agent ~* "MSIE")
#如果请求的浏览器为微软IE浏览器(MSIE),则让请求由static_pools池处理
{
proxy_pass http://static_pools;
}
if ($http_user_agent ~* "Chrome")
#如果请求的浏览器为谷歌浏览器(Chrome),则让请求由upload_pools池处理
{
proxy_pass http://upload_pools;
}
proxy_pass http://default_pools;
#其他客户端,由default_pools处理
include proxy.conf;
}
```
除了针对浏览器外,上述“$http_user_agent”变量也可针对移动端,比如安卓,苹果,Ipad设备进行匹配,去请求指定的服务器,具体细节配置如下:
```
location / {
if ($http_user_agent ~* "android")
{
proxy_pass http://android_pools; #这里是android服务器池
}
if ($http_user_agent ~* "iphone")
{
proxy_pass http://iphone_pools; #这里是iphone服务器池
}
proxy_pass http://pc_pools; #这里是默认的pc服务器池
include extra/proxy.conf;
}
```
##### 根据文件扩展名实现代理转发
除了根据URI路径及user_agent转发外,还可以实现根据文件扩展名进行转发
相关server配置
```
#先看看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;
}
```
根据扩展名转发的应用场景
可根据扩展名实现资源的动静分离访问,如图片,视频等请求静态服务器池,PHP,JSP等请求动态服务器池。
```
location ~ .*\.(gif|jpg|jpeg|png|bmp|swf|css|js)$ {
proxy_pass http://static_pools;
include proxy.conf;
}
location ~ .*\.(php|php3|php5)$ {
proxy_pass http://dynamic_pools;
include proxy.conf
}
```
在开发无法通过程序实现动静分离的时候,运维可以根据资源实体进行动静分离,而不依赖于开发,具体实现策略是先把后端的服务器分成不同的组。注意,每组服务器的程序都是相同的,因为开发没有把程序拆开,分组后,在前端代理服务器上通过讲解过的路径,扩展名进行规则匹配,从而实现请求的动静分离。
##### Nginx负载均衡检测节点状态
淘宝技术团队开发了一个Tengine(Nginx的分支)模块Nginx_upstream_check_module,用于提供主动式后端服务器健康检查。通过它可以检测后端realserver的健康状态,如果后端realserver不可用,则所有的请求就不会转发到该节点上。
Tengine原生支持这个模块,而Nginx则需要通过打补丁的方式将该模块添加到Nginx中。补丁下载地址:https://github.com/yaoweibin/nginx_upstream_check_module。
(1)安装nginx_upstream_check_module模块
```
#系统已经安装了nginx-1.10.2软件
[root@lb01 ~]# /usr/local/nginx/sbin/nginx -V
nginx version: nginx/1.10.2
#下载补丁包
[root@lb01 ~]# wget https://codeload.github.com/yaoweibin/nginx_upstream_check_module/zip/master
[root@lb01 ~]# unzip master
[root@lb01 ~]# ls
anaconda-ks.cfg install.log install.log.syslog master nginx-1.10.2.tar.gz nginx_upstream_check_module-master
[root@lb01 nginx-1.10.2]# mv ~/nginx_upstream_check_module-master /usr/src/
#因为是对源程序打补丁,所以还需要Nginx源程序
[root@lb01 ~]# cd /usr/src/nginx-1.10.2/
[root@lb01 nginx-1.10.2]# patch -p0 < /usr/src/nginx_upstream_check_module-master/check_1.9.2+.patch
patching file src/http/modules/ngx_http_upstream_hash_module.c
patching file src/http/modules/ngx_http_upstream_ip_hash_module.c
patching file src/http/modules/ngx_http_upstream_least_conn_module.c
patching file src/http/ngx_http_upstream_round_robin.c
patching file src/http/ngx_http_upstream_round_robin.h
#备份源安装程序
[root@lb01 nginx-1.10.2]# cd /usr/local/
[root@lb01 local]# ls
bin etc games include lib lib64 libexec nginx sbin share src
[root@lb01 local]# mv nginx{,.ori}
[root@lb01 local]# ls
bin etc games include lib lib64 libexec nginx.ori sbin share src
[root@lb01 local]# cd /usr/src/nginx-1.10.2/
#重新进行编译,编译的参数要和以前一致,最后加上 --add-module=/usr/src/nginx_upstream_check_module-master/
[root@lb01 nginx-1.10.2]# ./configure --prefix=/usr/local/nginx --user=nginx --group=nginx --with-http_ssl_module --with-http_stub_status_module --add-module=/usr/src/nginx_upstream_check_module-master/
[root@lb01 local]# /usr/local/nginx/sbin/nginx -V
nginx version: nginx/1.10.2
built by gcc 4.4.7 20120313 (Red Hat 4.4.7-4) (GCC)
built with OpenSSL 1.0.1e-fips 11 Feb 2013
TLS SNI support enabled
configure arguments: --prefix=/usr/local/nginx --user=nginx --group=nginx --with-http_ssl_module --with-http_stub_status_module --add-module=/usr/src/nginx_upstream_check_module-master/
#拷贝源配置文件到当前Nginx的安装目录下
[root@lb01 local]# pwd
/usr/local
[root@lb01 local]# cp nginx.ori/conf/nginx.conf nginx/conf/
cp: overwrite `nginx/conf/nginx.conf'? y
[root@lb01 local]# cp nginx.ori/conf/proxy.conf nginx/conf/
[root@lb01 local]# /usr/local/nginx/sbin/nginx -t
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful
```
(2)配置Nginx健康检查
```
[root@lb01 local]# cat 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 static_pools {
server 192.168.0.223:80 weight=1;
server 192.168.0.224:80 weight=1;
check interval=3000 rise=2 fall=5 timeout=1000 type=http; #对static服务器池开启健康监测
}
upstream default_pools {
server 192.168.0.225:80 weight=1;
}
server {
listen 80;
server_name www.yunjisuan.com;
location / {
proxy_pass http://default_pools;
include proxy.conf;
}
location ~ .*\.(gif|jpg|jpeg|png|bmp|swf|css|js)$ {
proxy_pass http://static_pools;
include proxy.conf;
}
location /status {
check_status; #启动健康检查模块
access_log off; #关闭此location的访问日志记录
}
}
}
```
重启lb1的nginx服务
```
[root@lb01 local]# /usr/local/nginx/sbin/nginx
[root@lb01 local]# netstat -antup | grep nginx
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 7008/nginx
#注意此处必须重启Nginx,不能重新加载
```
check interval=3000 rise=2 fall=5 timeout=1000 type=http;
上面配置的意思时,对static_pools这个负载均衡条目中的所有节点,每隔3秒检测一次,请求2次正常则标记realserver状态为up,如果检测5次都失败,则标记realserver的状态为down,超时时间为1秒,检查的协议是HTTP。
详细用法见官网:http://tengine.taobao.org/document_cn/http_upstream_check_cn.html
访问页面时,显示如下图所示:
![在这里插入图片描述](https://img-blog.csdnimg.cn/2018120100270811.?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzMwNDgwNA==,size_16,color_FFFFFF,t_70)
在lb1配置文件的upstream default_pools{}里也加入健康监测命令
```
[root@lb01 local]# cat 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 static_pools {
server 192.168.0.223:80 weight=1;
server 192.168.0.224:80 weight=1;
check interval=3000 rise=2 fall=5 timeout=1000 type=http; #对static服务器池开启健康监测
}
upstream default_pools {
server 192.168.0.225:80 weight=1;
check interval=3000 rise=2 fall=5 timeout=1000 type=http; #对default服务器池开启健康监测
}
server {
listen 80;
server_name www.yunjisuan.com;
location / {
proxy_pass http://default_pools;
include proxy.conf;
}
location ~ .*\.(gif|jpg|jpeg|png|bmp|swf|css|js)$ {
proxy_pass http://static_pools;
include proxy.conf;
}
location /status {
check_status; #启动健康检查模块
access_log off; #关闭此location的访问日志记录
}
}
}
```
再次访问健康监测页面时,显示如下图所示:
![在这里插入图片描述](https://img-blog.csdnimg.cn/20181201002743588.?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzMwNDgwNA==,size_16,color_FFFFFF,t_70)
关闭任意一个RS节点后(3个Web服务器任选一个关闭nginx服务)
```
#关闭Web02的nginx服务
[root@web02 ~]# /usr/local/nginx/sbin/nginx -s stop
```
再次访问健康监测页面时,显示如下图所示:
![在这里插入图片描述](https://img-blog.csdnimg.cn/201812010028157.?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzMwNDgwNA==,size_16,color_FFFFFF,t_70)
#### proxy_next_upstream 参数补充
当Nginx接收后端服务器返回proxy_next_upstream参数定义的状态码时,会将这个请求转发给正常工作的后端服务器,例如500,502,503,504,此参数可以提升用户的访问体验,具体配置如下:
```
server {
listen 80;
server_name www.yunjisuan.com;
location / {
proxy_pass http://static_pools;
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504; #表示如果在反向代理给某一个服务器池的时候,返回报头出现error、timeout、无效报头、500、502、503、504时,不返回给用户,而是在进行一次反向代理。
include proxy.conf;
}
}
```