Nginx 负载均衡反向代理

一、集群介绍以及常用集群硬件知识介绍及选型

1、负载均衡以及高可用集群的作用
1)、负载均衡集群的作用:
a、分担用户访问请求及数据流量(负载均衡)
b、保持业务连续性,即 7x24 小时服务(高可用性)
c、应用于 web 业务及数据库从库等服务器的业务。
负载均衡集群典型的开源软件:LVS、Nginx、Haproxy
2)、高可用集群的作用:
a、当一台机器宕机时,另外一台机器接管宕机的机器的 IP 资源和服务资源,提供服务。
b、常用于不易实现负载均衡的应用,比如负载均衡器,主数据库、主存储对之间。
高可用集群常用的开源软件:Keepalived、Heartbeat(架构师班讲)
2、对于集群软硬件产品如何选型
a、当企业业务重要,技术力量又薄弱,并且希望出钱购买产品及获取刚好的服务时,可以选择硬件负载均衡产品,如 F5、Netscaler、Radware 等,此类公司多为传统的大型非互联网企业,如银行、证券、金融、宝马、奔驰等。(硬件负载均衡服务器价格几十万,好的上百万)
b、对于门户网站来说,大多会并用软件及硬件产品来分担单一产品的风险,如淘宝、腾讯、新浪等。融资了的企业会购买企业硬件产品,如赶集等网站。
c、中小型互联网企业,由于起步阶段无利润可赚或利润很低,会希望通过使用开源免费的方案来解决问题,因此会雇佣专门的运维人员进行维护。例如,51CTO 等。
相比较而言,商业的负载均衡产品成本高,性能好,更稳定,缺点是不能二次开发,开源的负载均衡软件对运维人员的能力要求较高,如果运维及开发能力强,那么开源软件的负载均衡是不错的选择,目前的互联网行业更偏向使用开源的负载均衡软件。
Nginx 负载均衡反向代理
Netscaler 负载均衡产品
Nginx 负载均衡反向代理
F5 负载均衡产品

二、Nginx 负载均衡

正向代理:代理代替局域网内的用户去访问外部站点资源
反向代理:代理代替用户去访问后面的 web 节点或者应用服务器
1、实现 nginx 负载均衡的组件模块有两个,见下表:
Nginx 负载均衡反向代理
2、负载均衡实验环境准备:
Nginx 负载均衡反向代理
3、安装 Nginx 并测试:(Nginx 安装过程略)
1)、配置首页文件:

[root@lamp01 ~]# cat /var/html/www/index.html 
www.etiantian.org 133
[root@lnmp02 ~]# cat /application/nginx/html/www/index.html 
www.etiantian.org 135

2)、在 lb01 负载均衡器上 curl 两个 web 服务器的 IP 结果:

[root@lb01 ~]# curl 192.168.153.133
www.etiantian.org 133
[root@lb01 ~]# curl 192.168.153.135
www.etiantian.org 135

3)、编辑 lb01 负载均衡器 nginx 的配置文件如下:

[root@lb01 ~]# 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 www_server_pools{    #  定义的服务器节点。
   # ip_hash;
   server 192.168.136.150:80  weight=1;
   server 192.168.136.151:80  weight=1;
}
server {      #  定义一个代理的负载均衡域名虚拟主机。
        listen       80;
        server_name  www.etiantian.org;
        location / {
                proxy_pass http://www_server_pools;   
#  访问 www.etiantian.org ,请求发送给 www_server_pools 里面定义的节点。
        }
   }    
}

4)、配置好检查语法并平滑加载配置:

[root@lb01 ~]# /application/nginx/sbin/nginx -t
nginx: the configuration file /application/nginx-1.6.3/conf/nginx.conf syntax is ok
nginx: configuration file /application/nginx-1.6.3/conf/nginx.conf test is successful
[root@lb01 ~]# /application/nginx/sbin/nginx -s reload

5)、在本地做 hosts 解析:

[root@lb01 ~]# vi /etc/hosts
192.168.153.141 www.etiantian.org

6)、测试负载均衡实现的效果:

[root@lb01 ~]# for n in `seq 10`;do curl www.etiantian.org;done
www.etiantian.org 135
www.etiantian.org 155
www.etiantian.org 135
www.etiantian.org 155
www.etiantian.org 135
www.etiantian.org 155
www.etiantian.org 135
www.etiantian.org 155
www.etiantian.org 135
www.etiantian.org 155

至此,已经实现了 Nginx 的负载均衡。
4、有关 Nginx 模块的详细说明:
详见官方文档:http://nginx.org/en/docs/http/ngx_http_upstream_module.html
1)、上面涉及到的 upstream 模块示例:

Example Configuration
upstream backend {    #  定义的服务器池名字。
server backend1.example.com  weight=5;    #  没有加端口,表示默认 80 端口,权重为 5 。    
server backend2.example.com:8080;    #  没有加权重,默认权重为 1 。    
server unix:/tmp/backend3;    server backup1.example.com:8080   backup;    #  热备节点,Web 挂点由它接替。     
server backup2.example.com:8080   backup;    #  热备节点,Web 挂点由它接替。
  提示:端口前面可以是 IP 也可以是域名,通过 DNS 做负载均衡,甚至可以是 VIP 向后转发。
} server {    location / {        proxy_pass http://backend;   #  用户访问到此,转发到定义好的 backend 服务器池,进而访问真实的 Web 服务器。  
} }

2)、upstream 模块内部 server 标签参数说明:
Nginx 负载均衡反向代理
3)、权重,将 web01 的权重改为5,测试如下:

[root@lb01 ~]# /application/nginx/sbin/nginx -s reload      
[root@lb01 ~]# for n in `seq 10`;do curl www.etiantian.org;done        
www.etiantian.org 155
www.etiantian.org 155
www.etiantian.org 155
www.etiantian.org 135
www.etiantian.org 155
www.etiantian.org 155
www.etiantian.org 155
www.etiantian.org 155
www.etiantian.org 155
www.etiantian.org 135

4)、热备配置 web 的高可用(backup 参数):
编辑配置文件把 web02 设为热备服务器:
server 192.168.153.155:80 weight=1;
server 192.168.153.135:80 weight=1 backup;
测试如下:

[root@lb01 ~]# for n in `seq 10`;do curl www.etiantian.org;done
www.etiantian.org 155
www.etiantian.org 155
www.etiantian.org 155
www.etiantian.org 155
www.etiantian.org 155
www.etiantian.org 155
www.etiantian.org 155
www.etiantian.org 155
www.etiantian.org 155
www.etiantian.org 155

关掉 web01 服务器上的 nginx 服务测试:

[root@lb01 ~]# for n in `seq 10`;do curl www.etiantian.org;done
www.etiantian.org 135
www.etiantian.org 135
www.etiantian.org 135
www.etiantian.org 135
www.etiantian.org 135
www.etiantian.org 135
www.etiantian.org 135
www.etiantian.org 135
www.etiantian.org 135
www.etiantian.org 135

5、upstream 调度算法:
调度算法一般分为两类:
第一类为静态调度算法,即负载均衡器根据自身设定的规则进行分配,不需要考虑后端节点服务器的情况;
第二类为动态调度算法,即负载均衡器会根据后端节点的当前状态来决定是否分发请求,例如:连接数少的优先获得请求,响应时间短的优先获得请求。
1)、静态调度算法:
① rr 轮询(默认调度算法,静态调度算法);
② wrr 权重轮询(解决新旧服务器性能不均带来的请求分配问题);
③ ip_hash (会话保持,但会导致负载不均衡)。
2)、动态调度算法:
① fair 算法:
此算法会根据后端节点服务器的响应时间来分配请求,响应时间短的优先分配,这是更加智能的调度算法,此算法可以依据页面大下和加载时间长短智能地进行负载均衡。Nginx 本身是不支持 fair 调度算法的,若需要这种调度算法,需要下载 Nginx 的相关模块。
② least_conn 算法:
此算法会根据后端节点的连接数来决定分配情况,哪个机器连接数少就分发。
③ url_hash 算法:
和 Ip_hash 类似,这里是根据访问 URL 的 hash 结果来分配请求的,让每个 URL 定向到同一个后端服务器,后端服务器为缓存服务器时效果显著。在 upstream 中加入 hash 语句,server 语句中不能写入 weight 等其他参数,hash_method 使用的是 hash 算法。
url_hash 按访问 URL 的 hash 结果来分配请求,使每个 URL 定向到同一个后端服务器,可以进一步提高后端缓存服务器的效率命中率。Nginx 本身是不支持该算法的,若需要使用这个算法,需要安装 Nginx 的 hash 模块软件包。
④ 一致性 HASH 算法:
一致性 HASH 算法一般用于代理后端业务为缓存服务(squid、memcached)的场景,通过将用户请求的 URI 或者指定字符串进行计算,然后调度到后端的服务器上,此后用户查找同一个 URI 或者指定字符串都会被调度到这一台服务器上,因此后端的每个节点缓存的内容都是不同的,一致性 HASH 算法可以解决后端某个或几个节点宕机后,缓存的数据动荡最小,该算法比较复杂。
6、Http_proxy_module 模块
1)、Proxy_pass 指令介绍:
Proxy_pass 指令属于 ngx_http_proxy_module 模块,此模块可以将请求转发到另一台服务器,在实际的反向代理工作中,会通过 location 功能匹配指定的 URL,然后把接收到的符合匹配 URI 的请求通过 proxy_pass 抛给定义好的 upstream 节点池。
2)、Http_proxy 模块相关参数:
Nginx 负载均衡反向代理
7、经过反向代理后的节点服务器记录真实 IP 企业案例:
准备工作:打开一台服务器模拟负载均衡的客户端,做 hosts 解析并访问负载均衡服务器。

[root@lb01 ~]# vi /etc/hosts
192.168.153.141 www.etiantian.org bbs.etiantian.org
[root@lb01 ~]# for n in `seq 10`;do curl www.etiantian.org;done       # 轮询两个 web 服务器
www.etiantian.org 155
www.etiantian.org 135
www.etiantian.org 155
www.etiantian.org 135
www.etiantian.org 155
www.etiantian.org 135
www.etiantian.org 155
www.etiantian.org 135
www.etiantian.org 155
www.etiantian.org 135

① 开启 web 服务器记录访问日志功能:

server {
        listen       80;
        server_name  www.etiantian.org;
        location / {
            root   html/www;
            index  index.html index.htm;
     }
            access_log logs/access_www.log main;
}

② 在负载均衡服务器添加如下配置:

[root@lb01 ~]# 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 www_server_pools{
   # ip_hash;
   server 192.168.153.135:80  weight=1;
   server 192.168.153.155:80  weight=1;
}
server {
        listen       80;
        server_name  www.etiantian.org;
        location / {
          proxy_pass http://www_server_pools;
          proxy_set_header Host    $host;
          proxy_set_header X-Forwarded-For $remote_addr;
          }
        }
        #include extra/lb_www.conf;
        #include extra/lb_bbs.conf;
    # $remote_addr 这是客户端的 IP 地址,将客户端的地址传给 X-Forwarded-For ,实现在访问日志中记录客户端用户的真实 IP 。

③ Nginx 反向代理重要参数说明
Nginx 负载均衡反向代理
④ Http proxy 模块相关参数的配置:

[root@lb01 conf]# vim proxy.conf
  1 proxy_set_header Host $host;
  2 proxy_set_header X-Forward-For $remote_addr;
  3 proxy_connect_timeout 60;
  4 proxy_send_timeout 60;
  5 proxy_read_timeout 60;
  6 proxy_buffer_size 4k;
  7 proxy_buffers 4 32k;
  8 proxy_busy_buffers_size 64k;
  9 proxy_temp_file_write_size 64k;
[root@lb01 conf]# cat 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{
   # ip_hash;
   server 192.168.153.155:80  weight=1;
   server 192.168.153.135:80  weight=1;
}
server {
        listen       80; 
        server_name  www.etiantian.org;
        location / {
          proxy_pass http://www_server_pools;
          include proxy.conf;     #  把上面配置参数的文件通过 include 功能包含到主配置文件里。
         }
        }    
        #include extra/lb_www.conf;
        #include extra/lb_bbs.conf;
        #include extra/lb_blog.conf;
}
[root@lb01 conf]# ../sbin/nginx -t
[root@lb01 conf]# ../sbin/nginx -s reload 
问题:检查语法没有问题,但修改成为以上的 include 后访问日志看不到用户真实 IP 了。

8、根据 URL 中的目录地址实现代理转发
1)、案例背景:
通过 Nginx 实现动静分离,即通过 Nginx 反向代理配置规则实现让动态资源和静态资源及其他业务分别由不同的服务器解析,以解决网站性能、安全、用户体验等重要问题。
Nginx 负载均衡反向代理
上图为企业常见的动静分离集群架构图,此架构图适合网站前端只使用同一个域名提供服务的场景,例如用户访问的域名是 www.etiantian.org,然后当用户请求 www.etiantian.org/upload/xx 地址的时候,代理会分配请求到上传服务器池处理数据;当用户请求www.etiantian.org/static/xx 地址的时候,代理会分配请求到静态服务器池请求数据;当用户请求 www.etiantian.org/xx 地址的时候,即不包含上述指定的目录地址路径的时候,代理会分配请求到默认的动态服务器池请求数据(提示:上述 xx 可以表示任何路径)。
2)、案例配置模拟场景准备:
Nginx 负载均衡反向代理
① 静态数据服务器环境准备: LNMP01

[root@lnmp01 ~]# cd /application/nginx/html/www/
[root@lnmp01 www]# mkdir static                     # 创建站点目录(模拟静态数据目录)
[root@lnmp01 www]# cd static/
[root@lnmp01 static]# vim index.html               # 编辑首页文件 
static content 
[root@lnmp01 static]# vim /etc/hosts
192.168.153.155 www.etiantian.org
[root@lnmp01 static]# curl www.etiantian.org/static/index.html        # hosts 解析本地测试成功
static content

② 上传数据服务器环境准备: LNMP02

[root@lnmp02 ~]# cd /application/nginx/html/www/
[root@lnmp02 www]# mkdir upload
[root@lnmp02 www]# cd upload/
[root@lnmp02 upload]# vim index.html
upload content
[root@lnmp01 static]# vim /etc/hosts
192.168.153.135 www.etiantian.org
[root@lnmp02 upload]# curl www.etiantian.org/upload/index.html
upload content

③ 默认的动态服务器环境准备: LNMP03

[root@lnmp03 ~]# cd /application/nginx/html/www/
[root@lnmp03 www]# mkdir default
[root@lnmp03 www]# cd default/
[root@lnmp03 default]# vim index.html
default content
[root@lnmp01 static]# vim /etc/hosts
192.168.153.156 www.etiantian.org
[root@lnmp03 default]# curl www.etiantian.org/default/index.html
default content

3)、案例配置实战:
方案一:以 location 方案实战:

[root@lb01 conf]# cat 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{
# ip_hash;
#       server 192.168.153.155:80  weight=1;
#       server 192.168.153.135:80  weight=1;
#}
upstream default_pools {
        server 192.168.153.156:80 weight=1;
}
upstream static_pools { 
        server 192.168.153.155:80 weight=1;
}
upstream upload_pools {  
        server 192.168.153.135:80 weight=1;
}
        server {
                listen       80;
                server_name  www.etiantian.org;
#               location / {
#                       proxy_pass http://www_server_pools;
#                       include proxy.conf;
#                }
                location / {
                        proxy_pass http://default_pools;    #  将所有不符合 static 和 upload 的请求全部交给 default_pools 处理。     
                        include proxy.conf;
                 }
                location /static/ {
                        proxy_pass http://static_pools; # 将符合 static 的请求交给 static_pools 处理。
                        include proxy.conf;
                 }
                location /upload/ {
                        proxy_pass http://upload_pools; # 将符合 upload 的请求交给 upload_pools 处理。
                        include proxy.conf;
                 }    
        }
}

通过 Windows 浏览器访问测试配置结果:
① 访问静态数据服务器的请求:
Nginx 负载均衡反向代理
② 访问上传服务器的请求:
Nginx 负载均衡反向代理
③ 访问默认的动态请求:
Nginx 负载均衡反向代理
④ 在默认的动态请求上传图片测试:
Nginx 负载均衡反向代理
方案二:以 if 语句实现:【略略略】
Nginx 负载均衡反向代理
4)、根据 URL 目录地址转发的应用场景:
·· 根据 http 的 URL 进行转发的应用情况,被称为第 7 层(应用层)的负载均衡,而 LVS 的负载均衡一般用于 TCP 等的转发,因此被称为第 4 层(传输层)的负载均衡。
在企业中,有时希望只用一个域名对外提供服务,不希望使用多个域名对应同一个产品业务,此时就需要在代理服务器上通过配置规则,使得匹配不同规则的请求会交给不同的服务器池处理。
① 业务的域名没有拆分或者不希望拆分,但希望实现动静分离、多业务分离;
② 不同的客户端设备(例如手机和 PC 端)使用同一个域名访问同一个业务网站,就需要根据规则将不同设备的用户请求交给后端不同的服务器处理,以便得到最佳的用户体验。
9、通过识别 user_agent 分发请求案例:
此案例发生的背景:
Nginx 负载均衡反向代理
解决此方案的架构逻辑图:
Nginx 负载均衡反向代理
实践操作:根据客户端设备(user_agent)转发请求实战:
实现的思路:
① 如果请求的浏览器为 IE 浏览器(MSIE),则让请求由 static_pools 池处理;
② 如果请求的浏览器为谷歌浏览器(Chrome),则让请求由 upload_pools 处理。
③ 如果请求的浏览器为其他的,则抛给 default_pools 处理
1)、据电脑客户端浏览器的不同设置对应的匹配规则:

location / {
    if ($http_user_agent ~* "MSIE")
       {
          proxy_pass http://static_pools;
       }
    if ($http_user_agent ~* "Chrome")
        {
          proxy_pass http://upload_pools;
        }
}

2)、配置过程及结果如下:

[root@lb01 conf]# cp nginx.conf nginx.conf.yu.20180727
[root@lb01 conf]# vim nginx.conf
[root@lb01 conf]# cat 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_pools {
             server 192.168.153.156:80 weight=1;
           }
        upstream static_pools {
             server 192.168.153.155:80 weight=1;
           }
        upstream upload_pools {
             server 192.168.153.135:80 weight=1;
           }    
        server {
          listen       80;
          server_name  www.etiantian.org;
          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;
               include proxy.conf;
            }
         }
  } 

3)、以上配置可以实现的效果:
① 访问 static 出现 404 错误(静态 static 服务器只有 MSIE 浏览器才能访问到):
Nginx 负载均衡反向代理
② 访问 upload 代理可以转发请求到上传服务器匹配成功):
Nginx 负载均衡反向代理
Nginx 负载均衡反向代理
4)、此时可通过查看访问日志看到用户是从哪个浏览器访问到服务器的:
① 在 156 默认的动态浏览器查看访问日志:(默认,都可以匹配)

192.168.136.161 - - [23/May/2018:17:59:44 +0800] "GET /default/ HTTP/1.0" 304 0 "-" "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.90 Safari/537.36 2345Explorer/9.3.2.17331"
192.168.136.161 - - [23/May/2018:18:00:03 +0800] "GET /images/oldgirl.jpg HTTP/1.0" 200 98431 "-" "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.90 Safari/537.36 2345Explorer/9.3.2.17331"

② 在 135 上传浏览器查看访问日志:(上传匹配谷歌浏览器)

192.168.136.161 - - [22/Jun/2018:21:52:43 +0800] "GET /static/ HTTP/1.0" 404 570 "-" "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.90 Safari/537.36 2345Explorer/9.3.2.17331"
192.168.136.161 - - [22/Jun/2018:21:54:32 +0800] "GET /upload/ HTTP/1.0" 304 0 "-" "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.90 Safari/537.36 2345Explorer/9.3.2.17331"

③ 在 155 静态服务器查看访问日志:(因为本人不是 MSIE 浏览器)
192.168.136.161 - - [22/Jun/2018:16:10:41 +0800] "GET / HTTP/1.0" 200 22 "-" "curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.21 Basic ECC zlib/1.2.3 libidn/1.18 libssh2/1.4.2
5)、其他案例:还可以通过判断用户的手机来代理转发不同的服务器:
配置如下(过程略):

location / {
    if ($http_user_agent ~* "android")
       {
          proxy_pass http://static_pools;
       }
    if ($http_user_agent ~* "iphone")
        {
          proxy_pass http://upload_pools;
        }
}
  提示:以上配置可以实现代理将客户端不同手机系统的请求转发给适合用户的不同的浏览器。

10、根据扩展名转发的应用场景:
可根据扩展名实现资源动静分离访问,例如:图片、视频等请求静态服务器池,PHP、JSP 请求动态服务器池,示例代码如下:(略)
Nginx 负载均衡反向代理
11、Nginx 负载均衡检测节点状态:
利用第三方 Nginx 插件监控代理后端节点的服务器:
淘宝技术团队开发了一个 Tengine(Nginx 的分支)模块 nginx_upstream_check_module,用于提供主动式后端服务器健康检查,通过它可以检测后端 realserver 的健康状态,如果后端 RS 不可用,则所有的请求就不会转发到该节点上。
Tengine 原生支持这个模块,但是 Nginx 需要通过打补丁的方式将该模块添加到 Nginx 中,补丁下载地址:(https://github.com/yaoweibin/nginx_upstream_check_module

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章