Nginx反向代理与负载均衡

集群

特点

(1)高性能
一些国家重要的计算机密集型应用(如天气预报,核试验模拟等),需要计算机有很强的运算处理能力。以全世界现有的技术,即便是大型机,其计算能力也是有限的,很难单独完成此任务。因为计算时间可能会相当长,也许几天,甚至几年或更久。因此,对于这类复杂的计算业务,便使用了计算机集群技术,集中几十上百台,甚至成千上万台计算机进行计算。
在这里插入图片描述
假如你配一个LNMP环境,每次只需要服务10个并发请求,那么单台服务器一定会比多个服务器集群要快。只有当并发或总请求数量超过单台服务器的承受能力时,服务器集群才会体现出优势。

(2)价格有效性
通常一套系统集群架构,只需要几台或数十台服务器主机即可。与动辄价值上百万元的专用超级计算机相比便宜了很多。在达到同样性能需求的条件下,采用计算机集群架构比采用同等运算能力的大型计算机具有更高的性价比。
早期的淘宝,支付宝的数据库等核心系统就是使用上百万元的小型机服务器。后因使用维护成本太高以及扩展设备费用成几何级数翻倍,甚至成为扩展瓶颈,人员维护也十分困难,最终使用PC服务器集群替换之,比如,把数据库系统从小机结合Oracle数据库迁移到MySQL开源数据库结合PC服务器上来。不但成本下降了,扩展和维护也更容易了。

(3)可伸缩性
当服务负载,压力增长时,针对集群系统进行比较简单的扩展即可满足需求,且不会降低服务质量。
(4)高可用性
(5)透明性
(6)可管理性
(7)可编辑性

集群常见分类

  1. 负载均衡集群,简称LBC或者LB
  2. 高可用性集群,简称HAC
  3. 高性能计算集群,简称HPC
  4. 网格计算集群

常见集群软硬件产品

互联网企业常用的开源集群软件有:Nginx,LVS,Haproxy,keepalived,heartbeat
互联网企业常用的商业集群硬件有:F5,Netscaler,radware,A10,工作模式相当于Haproxy的工作模式。

快速实践Nginx负载均衡环境准备

准备三台虚拟机,一台做负载均衡,两台做Web服务器

安装Nginx

(1)安装依赖软件包

[root@localhost ~]# yum -y install openssl openssl-devel pcre pcre-devel
[root@localhost ~]# rpm -qa openssl openssl-devel pcre pcre-devel

(2)安装Nginx软件包

[root@localhost ~]# wget http://nginx.org/download/nginx-1.10.2.tar.gz
[root@localhost ~]# tar xf nginx-1.10.2.tar.gz -C /usr/src/
[root@localhost ~]# cd /usr/src/nginx-1.10.2/
[root@localhost nginx-1.10.2]# useradd -M -s /sbin/nologin nginx
[root@localhost 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
[root@localhost nginx]# ln -s /usr/local/nginx/sbin/* /usr/local/sbin/

配置用于测试的Web服务

   egrep -v "#|^$" nginx.conf.default > nginx.conf
    [root@localhost 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;
        server {
            listen       80;
            server_name  bbs.yunjisuan.com;
            location / {
                root   html/bbs;
                index  index.html index.htm;
        }
        server {
            listen       80;
            server_name  www.yunjisuan.com;
            location / {
                root   html/www;
                index  index.html index.htm;
            }        
    }
}

实现一个简单的负载均衡

下面进行一个简单地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 192.168.200.135:80 weight=1;
    server 192.168.200.129:80 weight=1;
}
    server {
        listen 80;
        server_name www.yunjisuan.com;
        location / {
        proxy_pass http://www_server_pools;
        }
     }
}

Nginx负载均衡核心组件

Nginx upstream模块

Nginx的负载均衡功能依赖于ngx_http_upsteam_module模块,所支持的代理方式包括proxy_pass,fastcgi_pass,memcached_pass等,新版Nginx软件支持的方式有所增加。本文主要讲解proxy_pass代理方式。
ngx_http_upstream_module模块允许Nginx定义一组或多组节点服务器组,使用时可以通过proxy_pass代理方式把网站的请求发送到事先定义好的对应Upstream组的名字上,具体写法为“proxy_pass
http://
www_server_pools”,其中www_server_pools就是一个Upstream节点服务器组名字。ngx_http_upstream_module模块官方地址为:http://nginx.org/en/docs/http/ngx_http_upstream_module.html

基本的upstream配置

upstream www_server_pools {

#       upstream是关键字必须有,后面的www_server_pools为一个Upstream集群组的名字,可以自己起名,调用时就用这个名字

server 192.168.0.223:80 weight=5;
server 192.168.0.224:80 weight=10;
server 192.168.0.225:80 weight=15;


#       server关键字是固定的,后面可以接域名(门户会用)或IP。如果不指定端口,默认是80端口。weight代表权重,数值越大被分配的请求越多,结尾有分号,别忘了。

}

较完善的upstream配置

upstream blog_server_pool {

server 192.168.0.223;   #这行标签和下行是等价的
server 192.168.0.224:80 weight=1 max_fails=1 fail_timeout=10s;       #这行标签和上一行是等价的,此行多余的部分就是默认配置,不写也可以。

server 192.168.0.225:80 weight=1 max_fails=2 fail_timeout=20s backup;

#   server最后面可以加很多参数,具体参数作用看下文的表格

}

使用域名及socket的upstream配置

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;

}

upstream模块相关说明

在这里插入图片描述

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; #热备机器设置

}

upstream模块调度算法

范例1:基本的upstream配置案例

upstream www_server_pools {

#       upstream是关键字必须有,后面的www_server_pools为一个Upstream集群组的名字,可以自己起名,调用时就用这个名字

server 192.168.0.223:80 weight=5;
server 192.168.0.224:80 weight=10;
server 192.168.0.225:80 weight=15;


#       server关键字是固定的,后面可以接域名(门户会用)或IP。如果不指定端口,默认是80端口。weight代表权重,数值越大被分配的请求越多,结尾有分号,别忘了。

}

范例2:较完整的upstream配置案例

upstream blog_server_pool {

server 192.168.0.223;   #这行标签和下行是等价的
server 192.168.0.224:80 weight=1 max_fails=1 fail_timeout=10s;       #这行标签和上一行是等价的,此行多余的部分就是默认配置,不写也可以。

server 192.168.0.225:80 weight=1 max_fails=2 fail_timeout=20s backup;

#   server最后面可以加很多参数,具体参数作用看下文的表格

}

范例3:使用域名及socket的upstream配置案例

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;

}

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

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

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

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

upstream yunjisuan_lb{

server 192.168.0.223;
server 192.168.0.224;
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算法(nginx默认没有一致性hash)
一致性hash算法一般用于代理后端业务为缓存服务(如Squid,Memcached)的场景,通过将用户请求的URI或者指定字符串进行计算,然后调度到后端的服务器上,此后任何用户查找同一个URI或者指定字符串都会被调度到这一台服务器上,因此后端的每个节点缓存的内容都是不同的,一致性hash算法可以解决后端某个或几个节点宕机后,缓存的数据动荡最小,一致性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;

}

}

常用的有轮询(rr)权重轮询(wrr)最小连接数(least_conn)
会话保持:ip_hash session共享(在服务器端) Cookie(在客户端)

反向代理多虚拟主机节点服务器企业案例

在代理向后端服务器发送的http请求头中加入host字段信息后,若后端服务器配置有多个虚拟主机,它就可以识别代理的是哪个虚拟主机。这是节点服务器多虚拟主机时的关键配置。整个Nginx代理配置为:

[root@lb01 nginx]# cat /usr/local/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 {

    server 192.168.0.223:80 weight=1;

    server 192.168.0.224:80 weight=1;

    }
    server {
        listen       80;
        server_name  www.yunjisuan.com;
        location / {
        proxy_pass http://www_server_pools;
        proxy_set_header host $host;    #在代理向后端服务器发送的http请求头中加入host字段信息,用于当后端服务器配置有多个虚拟主机时,可以识别代理的是哪个虚拟主机。这是节点服务器多虚拟主机时的关键配置。
        }
    }
}

经过反向代理后的节点服务器记录用户IP企业案例

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

解决上述问题的整个Nginx代理配置为:
[root@lb01 nginx]# cat /usr/local/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 {

    server 192.168.0.223:80 weight=1;

    server 192.168.0.224:80 weight=1;

    }
    server {
        listen       80;
        server_name  www.yunjisuan.com;
        location / {
        proxy_pass http://www_server_pools;
        proxy_set_header host $host;
        proxy_set_header X-Forwarded-For $remote_addr;
        #在代理向后端服务器发送的http请求头中加入X-Forwarded-For字段信息,用于后端服务器程序,日志等接收记录真实用户的IP,而不是代理服务器的IP
        }
    }
}

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

[root@web01 ~]# cat /usr/local/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;
    log_format main '$remote_addr-$remote_user[$time_local]"$request"'
    '$status $body_bytes_sent "$http_referer"'
    '"$http_user_agent""$http_x_forwarded_for"';
    #就是这里的“$http_x_forwarded_for”参数,如果希望在第一行显示,可以替换掉第一行的$remote_addr变量。
    server {
        listen       80;
        server_name  bbs.yunjisuan.com;
        location / {
            root   html/bbs;
            index  index.html index.htm;
        }
    access_log logs/access_bbs.log 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;
    }
}

#注意:这里是客户端Web01的配置

与反向代理配置相关的更多参数说明

相信同学们对这些参数有了一定了解了,由于参数众多,最好把这些参数放到一个配置文件里,然后用include方式包含到虚拟主机配置里,效果如下:

[root@lb01 conf]# cat /usr/local/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 {

    server 192.168.0.223:80 weight=1;

    server 192.168.0.224:80 weight=1;

    }
    server {
        listen       80;
        server_name  www.yunjisuan.com;
        location / {
        proxy_pass http://www_server_pools;
        include proxy.conf;         #这就是包含的配置,具体配置内容见下文
        }
    }
}

[root@lb01 conf]# cat 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中的目录地址实现代理转发

根据URL中的目录地址实现代理转发的说明

案例背景:
通过Nginx实现动静分离,即通过Nginx反向代理配置规则实现让动态资源和静态资源及其他业务分别由不同的服务器解析,以解决网站性能,安全,用户体验等重要问题。

下图为企业常见的动静分离集群架构图,此架构图适合网站前端只使用同一个域名提供服务的场景,例如,用户访问的域名是www.yunjisuan.com,然后,当用户请求www.yunjisuan.com/upload/xx地址时候,代理会分配请求到上传服务器池处理数据;当用户请求www.yunjisuan.com/static/xx地址的时候,代理会分配请求到静态服务器池请求数据;当用户请求www.yunjisuan.com/xx地址的时候,即不包含上述指定的目录地址路径时,代理会分配请求到默认的动态服务器池请求数据(注意:上面的xx表示任意路径)。

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值