负载均衡

要理解负载均衡,必须先搞清楚正向代理和反向代理,请见米扑博客:正向代理、反向代理、透明代理的图文详解

简而言之:

1)正向代理,代理的是用户。

2)反向代理,代理的是服务器

当一台服务器在单位时间内的访问量越大时,服务器压力就越大,大到超过自身承受能力时,服务器就会崩溃。

为了避免服务器崩溃,让用户有更好的体验,我们通过多台服务器做负载均衡的方式来分担服务器压力。

我们可以建立很多很多服务器,组成一个服务器集群,当用户访问网站时,先访问一个中间服务器,在让这个中间服务器在服务器集群中选择一个压力较小的服务器,然后将该访问请求引入该服务器。如此以来,用户的每次访问,都会保证服务器集群中的每个服务器压力趋于平衡,分担了服务器压力,避免了服务器崩溃的情况。

负载均衡的原理是用反向代理实现的。

 

Nginx的负载均衡方案有四种:

1、轮询

轮询即Round Robin,根据Nginx配置文件中的顺序,依次把客户端的Web请求分发到不同的后端服务器。

http{
  upstream mimvp.com {
    server <<dns entry or IP Address(optional with port)>>;
    server <<another dns entry or IP Address(optional with port)>>;
  }
  ....
  server{
     listen 80;
     ...
     location / {
      proxy_pass http://mimvp.com;
     }  
  }

上面只有1个DNS入口被插入到upstream节,即mimvp.com,同样也在后面的proxy_pass节重新提到。

 

2、最少连接

Web请求会被转发到连接数最少的服务器上。

http{
  upstream mimvp.com {
    least_conn;
    server <<dns entry or IP Address(optional with port)>>;
    server <<another dns entry or IP Address(optional with port)>>;
  }
  ....
  server{
     listen 80;
     ...
     location / {
      proxy_pass http://mimvp.com;
     }  
  }

上面的例子只是在upstream节添加了 least_conn 配置,其它的配置同轮询配置。

 

3、IP地址哈希

前述的两种负载均衡方案中,同一客户端连续的Web请求可能会被分发到不同的后端服务器进行处理,因此如果涉及到会话Session,那么会话会比较复杂。

常见的是基于数据库的会话持久化,要克服上面的难题,可以使用基于IP地址哈希的负载均衡方案。

这样的话,同一客户端连续的Web请求都会被分发到同一服务器进行处理

http{
  upstream mimvp.com {
    ip_hash;
    server <<dns entry or IP Address(optional with port)>>;
    server <<another dns entry or IP Address(optional with port)>>;
  }
  ....
  server{
     listen 80;
     ...
     location / {
      proxy_pass http://mimvp.com;
     }  
  }

上面的例子只是在upstream节添加了 ip_hash 配置,其它的配置同轮询配置。

 

4、基于权重的负载均衡

基于权重的负载均衡即Weighted Load Balancing,这种方式下,我们可以配置Nginx把请求更多地分发到高配置的后端服务器上,把相对较少的请求分发到低配服务器。

http{
  upstream mimvp.com {
    server <<dns entry or IP Address(optional with port)>> weight=2;
    server <<another dns entry or IP Address(optional with port)>>;
  }
  ....
  server{
     listen 80;
     ...
     location / {
      proxy_pass http://mimvp.com;
     }
  }

上面的例子在服务器地址和端口后weight=2的配置,这意味着,每接收到3个请求,前2个请求会被分发到第一个服务器,第3个请求会分发到第二个服务器,其它的配置同轮询配置。

还要说明一点,基于权重的负载均衡和基于IP地址哈希的负载均衡可以组合在一起使用

 

5、按响应时间分配请求fair) 

按后端服务器的响应时间来分配请求,响应时间短的优先分配。

upstream backserver {
    server server1;
    server server2;
    fair;
}

 

6、按访问url的hash结果分配请求url_hash

按访问url的hash结果来分配请求,使每个url定向到同一个后端服务器,后端服务器为缓存时比较有效。

upstream backserver {
    server squid1:3128;
    server squid2:3128;
    hash $request_uri;
    hash_method crc32;
}

每个设备的状态设置为:

1)down 表示单前的server暂时不参与负载 

2)weight 默认为1.weight越大,负载的权重就越大。 

3)max_fails:允许请求失败的次数默认为1.当超过最大次数时,返回proxy_next_upstream模块定义的错误 

4)fail_timeout:max_fails次失败后,暂停的时间。 

5)backup: 其它所有的非backup机器down或者忙的时候,请求backup机器。所以这台机器压力会最轻。

配置实例:

#user  nobody;
worker_processes  4;
events {
    worker_connections  1024;					# 最大并发数
}

http {
    # 待选服务器列表
    upstream mimvp.com {
        ip_hash;								# ip_hash指令,将同一用户引入同一服务器
        server 126.18.82.8 fail_timeout=60s;
        server 172.32.12.182;
   	}

    server {
            listen 80;	 						# 监听端口
            location / {       					# 根目录下
                proxy_pass http://mimvp.com;	# 选择哪个服务器列表
            }
	}
}

 

 

CentOS + Nginx 负载均衡配置实例

现在nginx到处都可以见到,经常会看到宕机后的网页会显示nginx的字样,例如:

米扑代理: https://proxy.mimvp.com

这也说明nginx由于高性能、使用配置简单、开源这些特点被越来越多的用户所接受,所使用。

 

nginx负载均衡的理解

nginx是一个轻量级的、高性能的webserver,主要可以干下面两件事:

  • 作为http服务器(和apache的效果一样)
  • 作为反向代理服务器实现负载均衡(对外网为Web服务器,对内网为Web请求客户端)

第一种作为http服务器

结合php-fpm进程,对发来的请求进行处理,nginx本身并不会解析php,他只是作为一个服务器,接受客户端发来的请求,如果是php请求,则交给php进程处理,并将php处理完成之后的结果发送给客户端。这个很简单,安装好nginx  +  php-fpm之后配置好各自的配置文件,启动就可以实现。

nginx+php-fpm 运行原理:

Nginx不支持对外部程序的直接调用或者解析,所有的外部程序(包括PHP)必须通过FastCGI接口来调用。FastCGI接口在Linux下是socket(这个socket可以是文件socket,也可以是ip socket)。

为了调用CGI程序,还需要一个FastCGI的wrapper(wrapper可以理解为用于启动另一个程序的程序),这个wrapper绑定在某个固定socket上,如端口或者文件socket。

当Nginx将CGI请求发送给这个socket的时候,通过FastCGI接口,wrapper接收到请求,然后派生出一个新的线程(例如php-cgi解释线程),这个线程调用解释器或者外部程序处理脚本并读取返回数据;

接着,wrapper再将返回的数据通过FastCGI接口,沿着固定的socket传递给Nginx;

最后,Nginx将返回的数据发送给客户端。

这就是Nginx+FastCGI的整个运作过程,如图下图所示。

nginx-load-balancing-01

上面这段话解释了nginx + fastcgi的运行机制,在nginx配置文件中会对请求进行匹配,并作做出相应的处理,比如说直接返回错误文件(这里和上面说的有点区别,我估计是nginx内部对html等这些静态文件可以做类似上图的解析),使用php进程对php请求进行处理(这里的php进程可以是多个php-cgi)。

 

第二种是用反向代理事项负载均衡

这个其实其实很简单,说起来就是自己定义一组server,对请求进行匹配,并将请求转给server中的任意一个处理,来减轻每个server的压力,先看看网上对反向向代理的定义:

反向代理(Reverse Proxy)方式是指在服务器端,以代理服务器来接受internet上的连接请求,然后将请求转发给内部网络上的后台处理服务器,并将从服务器上得到的结果返回给internet上请求连接的客户端,此时代理服务器对外就表现为一个反向代理服务器(只转发请求,不做数据处理)。

nginx-load-balancing-02

反向代理是与正向代理(或者叫代理) 相反的,代理(即指正向代理)大家定听过吧,为了更方便的访问B资源,通过A资源(代理服务器)间接的访问B资源,特点就是正向代理(代理,如使用米扑代理ip就是典型的正向代理)用户知道自己最终要访问的网站是什么,但是反向代理用户是不知道代理服务器后边做了什么处理的,反向代理中服务真正的处理服务器放在内网,对外网而言只可以访问反向代理服务器,这也大大提高了安全性。

 

安装软件

nginx安装很简单

1、安装nginx需要的环境

pcre(作用rewrite)、zlib(作用压缩)、ssl,这个也可以自己下载编译安装

yum -y install zlib;

yum –y install pcre;

yum –y install openssl;

 

2、下载安装nginx-*.tar.gz

tar –zxvf nginx-1.7.9.tar.gz –C ./;

cd nginx-1.7.9;

./congigure --prefix=/usr/local/nginx;

make && make install;

 

3、配置

这里配置的时候只需要修改http{}之间的内容就行了,修改的第一个地方就是设置服务器组,在http节点之间添加

upstream myServer{
        server www.myapp2.com:80;            
# 这里是你自己要做负载均衡的服务器地址1
        server www.myapp1.com:8080;         # 这里是要参与负载均衡的地址2
    }

nginx中的upstream支持下面几种方式:

轮询,默认按照时间顺序对所有服务器一个一个的访问,如果有服务器宕机,会自动剔除;weight,服务器的访问几率和weight成正比,这个可以在服务器性能配置不均的时候进行配置;ip_hash,对每个请求的ip进行hash计算,并按照一定的规则分配对应的服务器;

fair,按照每台服务器的响应时间(rt)来分配请求,rt晓得优先分配;

url_hash,按照访问url的hash值来分配请求。

我这里使用了默认的轮训方式

将请求指向myServer

location / {
         proxy_pass   http://myServer;
     }

完整的配制文件如下(删除注释):

 

worker_processes  1;
events {
    worker_connections  1024;
}
http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;
    upstream myServer{
       server www.myapp1.com:80;
       server www.myapp2.com:8080;
    }
    server {
        listen       80;
        server_name  my22;
        location / {
            proxy_pass   http://myServer;
        }
    }
}

 

设置反向代理后端作为负载均衡的两个服务器

可以看到上一步骤有两个服务器地址,www.myapp1.com:80和www.myapp2.com:8080

上面的nginx 是安装在虚拟机上面的;这两个服务器是安装在本机win8系统中的,使用apache的virtualhost,设置了两个域名,这两个域名下的代码是互相独立的,设置也很简单:

1、设置apache配置文件

我使用的是xampp集成环境,要修改的地方有两个,在httpd.conf中监听端口的地方添加

Listen 8080

也就是说这个地方监听了两个端口

Listen 80
Listen 8080

看看下面这个句是否打开,没有打开的话,打开,打开如下面所示

# Virtual hosts
Include conf/extra/httpd-vhosts.conf

在httpd-vhosts.conf中添加下面的内容,

<VirtualHost *:80>
    ServerName www.myapp1.com #对应的域名,负载均衡的服务器地址
    DocumentRoot E:\soft\xampp\htdocs\www.myapp1.com #代码文件夹
</VirtualHost>
<VirtualHost *:8080>
    ServerName www.myapp2.com
    DocumentRoot E:\soft\xampp\htdocs\www.myapp2.com
</VirtualHost>

修改windows的hosts文件,追加下面的内容

127.0.0.1        www.myapp1.com
127.0.0.1        www.myapp2.com

修改linux的/etc/hosts文件,追加下面的内容

192.168.1.12        www.myapp1.com #这里前面的地址对应我win8本机的ip地址
192.168.1.12        www.myapp2.com

我在www.myapp1.com:80中放了一个文件                      

             index.php【E:\soft\xampp\htdocs\www.myapp1.com\index.php】

www.myapp2.com:8080中也放了一个文件

             index.php【E:\soft\xampp\htdocs\www.myapp2.com\index.php】

文件中的内容基本相同,只是I'm the myapp2这个地方有区别,一个是myapp1,另一个是myapp2。

如果你可以在win8浏览器中输入www.myapp1.com:80和www.myapp2.com:8080看到不同的效果

并且在centos下面看到下面的结果(自己美化了下)说明配置成功了

[root@bogon nginx]# curl www.myapp1.com:80
I'm the myapp1<br>【view】1
[root@bogon nginx]# curl www.myapp2.com:8080
I'm the myapp2<br>【view】1
<?php
session_save_path("./");
session_start();
header("Content-type:text/html;charset=utf-8");
if(isset($_SESSION['view'])){
    $_SESSION['view'] = $_SESSION['view'] + 1;
}else{
    $_SESSION['view'] = 1;
}
echo "I'm the myapp2<br>";
echo "【view】{$_SESSION['view']}";

 

看看效果

等所有都ok之后可硬通过浏览器访问看看效果

忘了说了,nginx代理服务器的地址为http://192.168.1.113,

浏览器输入http://192.168.1.113/index.php之后,不停的刷新,你会发现,会在

I'm the myapp2、I'm the myapp1

这两个页面之间来回交换,view会没刷新两下增加一次,这也证明了前面所说的默认是轮训的方式,但这里又有一个比较常见的问题了,当用户访问网站时,未做处理的情况下,session会保存在不同的服务器上(我这里用两个不同的文件夹模拟两台服务器),session数据可能出现多套,这个问题怎么解决呢,其实也很简单,见上文Nginx的负载均衡方案第三中方案,配制IP地址哈希一致性(ip_hash;

 

 

参考推荐

Nginx 反向代理及示例

正向代理、反向代理、透明代理的图文详解

后台服务器开发总结

Apache 和 Nginx 对比

Apache、Nginx、Tomcat 区别