一聚教程网:一个值得你收藏的教程网站

热门教程

Nginx实现网站多机负载均衡配置方法

时间:2022-06-30 18:49:07 编辑:袖梨 来源:一聚教程网


Nginx的高并发特性就不用多说了,单机静态并发能承受大压力测试,但并不代表在搭载后端的情况下依然保持高并发,因为后端动态处理才是并发瓶颈。nginx作者初衷是为邮件提供多机反向代理,而这特性也正好能用在其他网络服务上,因为这是nginx原生基础服务,比apache等其他服务器需提供外部插件的实现形式显得更快捷高效。

传统负载均衡的方法是在后端服务器前设置一台前端服务器负责总调度,这是最简单的方式,当前端搭载的是nginx负责单点均衡,后端服务可以是任意web服务,譬如apache,tomcat,甚至IIS等,因为此处nginx只起到转发和缓存作用,我们用nginx的upstream功能,相应nginx.conf配置信息如下,假设服务器1绑定域名server1, 服务器2绑定域名server2,如此这般。

 代码如下 复制代码

upstream www.111com.net {
server server1:80;
server server2:80;
server server3:80;
}

server {
listen 80;
server_name www.111com.net;
location / {
proxy_pass  http://www.111com.net;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}

如果你的站点没有CDN等云端加速服务,不管nginx的并发多高,前端单点均衡总有一个极限,当我们需要增加系统容量是否能直接增加前端服务器来解决问题呢?答案是可以的,但我们又会面临一系列新问题。当我们新增了前端服务器,那域名绑定如何解决?有的站点直接通过多级域名解决,譬如很多邮件服务就通过设置m1.mail.example.com, m2.mail.example.com, m3.mail.example.com等直接域名跳转解决,封闭式服务提议这样做,但开发式服务不管从用户体验还是SEO角度出发统一域名路径还是必须的,但统一域名路径还是会产生一些问题,普通域名商的DNS设置只支持DNS域名轮询和线路选择,不能提供更高级的DNS功能,当然有人说公司资金充足的话,直接配F5等负载均衡设备就可以了,为什么还要折腾nginx呢,然网易新浪腾讯这些大公司也有在用,其实大公司更需要提高效率,成本等同的情况下能进一步提高效率,何乐而不为呢,况且很好地配置负载均衡设备的复杂度并不比配置nginx低。nginx还有另一个重要特性颇受青睐,就是可用性,当upstream下游节点nginx服务失效后,它能自动切换到其它可用节点,这是很多前端服务所不具备的。下面我们以单一域名DNS轮询策略为例来部署多机负载均衡的架构,先看以下示意图:

upstreamstruct


多机负载均衡示意图


我们给每台前端都配上上面的upstream配置,按道理说设好DNS这一过程就完成了,但当你运行动态程序时,会出现一些诡异现象,当你在浏览器登录系统,过一会刷新一下,便变成登出状态,这是因为DNS轮询中域名指向的IP是会定期发生变化的,那就是说在server1上保存了登录session,但server2此session却不存在,但若然后端程序有统一登录认证统一Session管理,这个问题不存在,但对于系统架构来说频繁切换后端服务器对缓存策略也会带来麻烦,那有没办法让同一IP登录客户端对应上特定的服务器呢?答案是肯定的,nginx的威力就在这里,让我们对上面upstream配置稍作修改:

 代码如下 复制代码

upstream www.111com.net {
ip_hash;
server server1:80;
server server2:80;
server server3:80;
}

是的,只是稍作修改,增加ip_hash一项就可以了,这是nginx的一个内置模块,自动计算出来源ip的hash值,并根据此值指向到服务器列表中的特定服务器,这样只要客户端IP不变,就始终会指向同一后端服务器。这下满意了吧,什么?还不满意,你还希望通过特定区域的IP指向特定服务器,疑惑根据特定登录用户的uid来指向到特定服务器?没问题,nginx一切就绪,除了ip_hash,还有一个自定义hash功能,譬如针对url参数的hash配置:

 代码如下 复制代码
upstream www.111com.net {
hash   $request_uri;
hash_again 100; #hash有效保持次数,nginx会把每次hash结构缓存下来
server server1:80;
server server2:80;
server server3:80;
}

#注:用hash模块后每个server backend配置后面的权重参数weight和max_fails不再生效

要启用此hash插件必须重新编译源码,而且需要memcache支持,插件地址:http://wiki.nginx.org/HttpUpstreamRequestHashModule

此外还有其他upstream的负载均衡策略,譬如fair闲时分配,consistent_hash一致性哈希,详情上官网查询。

下面来给出一个完整的配置例子,包括后端PHP配置。

 代码如下 复制代码

upstream example.com {
 ip_hash;
 server 192.168.0.1:8081 weight=3;
 server 192.168.0.2:8081 max_fails=3 fail_timeout=30s;
}
server {
 listen 80;
 server_name example.com;
 location / {
    proxy_pass  http://example.com;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
   }
}
# for server 192.168.0.1 setting
server
 {
  listen    8081;
  server_name 192.168.0.1;
  index index.html index.htm index.php;
  root  /home/www/;

  location ~ .*.(php|php5)?$
   {
    fastcgi_pass  unix:/tmp/php-cgi.sock;
    fastcgi_index index.php;
    include fcgi.conf;
   }

  log_format  t1.bigpu.cn  '$proxy_add_x_forwarded_for - [$time_local] $request '
             '$status $body_bytes_sent $http_referer '
             '$http_user_agent $http_x_forwarded_for';
  access_log  /home/wwwlogs/www1.log  ex1.example.com;
 }

# for server 192.168.0.2 setting
server
 {
  listen    8081;
  server_name 192.168.0.2;
  index index.html index.htm index.php;
  root  /home/www/;

  location ~ .*.(php|php5)?$
   {
    fastcgi_pass  unix:/tmp/php-cgi.sock;
    fastcgi_index index.php;
    include fcgi.conf;
   }

  log_format  t2.bigpu.cn  '$proxy_add_x_forwarded_for - [$time_local] $request '
             '$status $body_bytes_sent $http_referer '
             '$http_user_agent $http_x_forwarded_for';
  access_log  /home/wwwlogs/www2.log  ex2.example.com;
 }

热门栏目