> Linux集群 > 负载均衡SLB >

nginx负载均衡设置

废话少说。直接需求,公司网站由于访问量巨大,现将访问量平摊到两台同样配置的服务器上,由于公司的程序是php的,就决定使用nginx来实现负载均衡:

  下面是nginx的完整配置:

 

Java代码 复制代码 收藏代码
  1. user  www www;   
  2.   
  3. worker_processes 8;   
  4.   
  5. error_log  /data1/logs/nginx_error.log  crit;   
  6.   
  7. pid        /usr/local/webserver/nginx/nginx.pid;   
  8.   
  9. #Specifies the value for maximum file descriptors that can be opened by this process.    
  10. worker_rlimit_nofile 65535;   
  11.   
  12. events    
  13. {   
  14.   use epoll;   
  15.   worker_connections 65535;   
  16. }   
  17.   
  18. http    
  19. {   
  20.   include       mime.types;   
  21.   default_type  application/octet-stream;   
  22.   
  23.   charset  utf-8;   
  24.          
  25.   server_names_hash_bucket_size 128;   
  26.   client_header_buffer_size 32k;   
  27.   large_client_header_buffers 4 32k;   
  28.   client_max_body_size 8m;   
  29.          
  30.   sendfile on;   
  31.   tcp_nopush     on;   
  32.   
  33.   keepalive_timeout 60;   
  34.   
  35.   tcp_nodelay on;   
  36.   
  37.   fastcgi_connect_timeout 300;   
  38.   fastcgi_send_timeout 300;   
  39.   fastcgi_read_timeout 300;   
  40.   fastcgi_buffer_size 64k;   
  41.   fastcgi_buffers 4 64k;   
  42.   fastcgi_busy_buffers_size 128k;   
  43.   fastcgi_temp_file_write_size 128k;   
  44.   
  45.   gzip on;   
  46.   gzip_min_length  1k;   
  47.   gzip_buffers     4 16k;   
  48.   gzip_http_version 1.0;   
  49.   gzip_comp_level 2;   
  50.   gzip_types       text/plain application/x-javascript text/css application/xml;   
  51.   gzip_vary on;   
  52.   
  53.   #limit_zone  crawler  $binary_remote_addr  10m;   
  54.   
  55.   <STRONG>upstream mysvr {   
  56.      server 192.168.1.104:8088;   
  57.      server 192.168.1.104:8080;   
  58.   }</STRONG>   
  59.   
  60.   
  61.   
  62.   server   
  63.   {   
  64.     listen       8080;   
  65.     server_name  192.168.1.104;   
  66.     index index.html index.htm index.php;   
  67.     root  /data0/htdocs/mobile;   
  68.   
  69.     #limit_conn   crawler  20;       
  70.                                 
  71.     location ~ .*\.(php|php5)?$   
  72.     {         
  73.       #fastcgi_pass  unix:/tmp/php-cgi.sock;   
  74.       fastcgi_pass  127.0.0.1:9000;   
  75.       fastcgi_index index.php;   
  76.       include fcgi.conf;   
  77.     }   
  78.        
  79.     location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$   
  80.     {   
  81.       expires      30d;   
  82.     }   
  83.   
  84.     location ~ .*\.(js|css)?$   
  85.     {   
  86.       expires      1h;   
  87.     }       
  88.   
  89.   
  90.     log_format  mobilelogs  '$remote_addr - $remote_user [$time_local] "$request" '  
  91.               '$status $body_bytes_sent "$http_referer" '  
  92.               '"$http_user_agent" $http_x_forwarded_for';   
  93.     access_log  /data1/logs/mobileaccess.log  mobilelogs;   
  94.       }   
  95.   
  96.   server   
  97.   {   
  98.     listen       8088;   
  99.     server_name  192.168.1.104;   
  100. #   index aa.html;    
  101.    index index.html index.htm index.php;   
  102.     root  /data0/htdocs/www;   
  103.   
  104.   
  105.     location ~ .*\.(php|php5)?$   
  106.     {         
  107.       #fastcgi_pass  unix:/tmp/php-cgi.sock;   
  108.       fastcgi_pass  127.0.0.1:9000;   
  109.       fastcgi_index index.php;   
  110.       include fcgi.conf;   
  111.     }   
  112.   
  113.     error_page 400 404 /error.html;   
  114.   
  115.     log_format  wwwlogs  '$remote_addr - $remote_user [$time_local] "$request" '  
  116.                '$status $body_bytes_sent "$http_referer" '  
  117.                '"$http_user_agent" $http_x_forwarded_for';   
  118.     access_log  /data1/logs/wwwlogs.log  wwwlogs;   
  119.   }   
  120.   
  121.   server   
  122.   {   
  123.     listen  80;   
  124.     server_name  192.168.1.104;   
  125.   
  126.     location / {   
  127.    <STRONG>     proxy_pass http://mysvr;</STRONG>   
  128.   
  129.     }   
  130.   
  131.        #以下是一些反向代理的配置可删除.   
  132.     
  133.           proxy_redirect off;   
  134.     
  135.           #后端的Web服务器可以通过X-Forwarded-For获取用户真实IP   
  136.           proxy_set_header Host $host;   
  137.           proxy_set_header X-Real-IP $remote_addr;   
  138.           proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;   
  139.           client_max_body_size 10m;    #允许客户端请求的最大单文件字节数   
  140.           client_body_buffer_size 128k;  #缓冲区代理缓冲用户端请求的最大字节数,   
  141.           proxy_connect_timeout 90;  #nginx跟后端服务器连接超时时间(代理连接超时)   
  142.           proxy_send_timeout 90;        #后端服务器数据回传时间(代理发送超时)   
  143.           proxy_read_timeout 90;         #连接成功后,后端服务器响应时间(代理接收超时)   
  144.           proxy_buffer_size 4k;             #设置代理服务器(nginx)保存用户头信息的缓冲区大小   
  145.           proxy_buffers 4 32k;               #proxy_buffers缓冲区,网页平均在32k以下的话,这样设置   
  146.           proxy_busy_buffers_size 64k;    #高负荷下缓冲大小(proxy_buffers*2)   
  147.           proxy_temp_file_write_size 64k;  #设定缓存文件夹大小,大于这个值,将从upstream服务器传   
  148.     
  149.   
  150.   }   
  151. }  

 

 

 

本机80端口接受请求,转发到本机8080和8088端口:

    主要核心配置:

 

定义代理服务器该代理服务器由两个后端组成:

 

Java代码 复制代码 收藏代码
  1. upstream mysvr {   
  2.    server 192.168.1.104:8088 weight=2;   
  3.    server 192.168.1.104:8080 weight=3;   
  4. }  

upstream设备上的状态设置:


    down 表示单前的server暂时不参与负载
    weight  默认为1.weight越大,负载的权重就越大。
    max_fails :允许请求失败的次数默认为1.当超过最大次数时,返回proxy_next_upstream 模块定义的错误
    fail_timeout:max_fails 次失败后,暂停的时间。
    backup: 其它所有的非backup机器down或者忙的时候,请求backup机器。所以这台机器压力会最轻。

 

 

 所有到本机80的请求全部转发到上述代理上:

Java代码 复制代码 收藏代码
  1. server   
  2. {   
  3.   listen  80;   
  4.   server_name  192.168.1.104;   
  5.   
  6.   location / {   
  7.       proxy_pass http://mysvr;   
  8.   }   
  9.   
  10.      #以下是一些反向代理的配置可删除.   
  11.   
  12.         proxy_redirect off;   
  13.   
  14.         #后端的Web服务器可以通过X-Forwarded-For获取用户真实IP   
  15.         proxy_set_header Host $host;   
  16.         proxy_set_header X-Real-IP $remote_addr;   
  17.         proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;   
  18.         client_max_body_size 10m;    #允许客户端请求的最大单文件字节数   
  19.         client_body_buffer_size 128k;  #缓冲区代理缓冲用户端请求的最大字节数,   
  20.         proxy_connect_timeout 90;  #nginx跟后端服务器连接超时时间(代理连接超时)   
  21.         proxy_send_timeout 90;        #后端服务器数据回传时间(代理发送超时)   
  22.         proxy_read_timeout 90;         #连接成功后,后端服务器响应时间(代理接收超时)   
  23.         proxy_buffer_size 4k;             #设置代理服务器(nginx)保存用户头信息的缓冲区大小   
  24.         proxy_buffers 4 32k;               #proxy_buffers缓冲区,网页平均在32k以下的话,这样设置   
  25.         proxy_busy_buffers_size 64k;    #高负荷下缓冲大小(proxy_buffers*2)   
  26.         proxy_temp_file_write_size 64k;  #设定缓存文件夹大小,大于这个值,将从upstream服务器传   

nginx 的 upstream目前支持 4 种方式的分配
1)、轮询(默认)
      每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务器down掉,能自动剔除。
2)、weight
      指定轮询几率,weight和访问比率成正比,用于后端服务器性能不均的情况。
2)、ip_hash
      每个请求按访问ip的hash结果分配,这样每个访客固定访问一个后端服务器,可以解决session的问题。 
3)、fair(第三方)
      按后端服务器的响应时间来分配请求,响应时间短的优先分配。 
4)、url_hash(第三方)

 

 

负载均衡容易配置,但session共享成为一个负载固有的问题,以下是来自于互联网的资料:

 

1、不用session,通过cookie等方式绕过session

      貌似这种方式还是会存在问题,假如客户端禁用cookie怎么办。

 

2、应用服务器自行实现共享

    如单点登录,采用中央认证服务器;或者memcache来存放后端服务器需要使用的公共数据。我曾经就有程序采用本地ehcache+memcache来缓存数据,其中ehcache缓存一些与他机无关的数据,memcache缓存一些公共数据,但这样往往也容易出现问题。

 

nginx自身提供的session共享方案:

3、ip_hash方式解决session共享

        nginx中的ip_hash技术能够将某个ip的请求定向到同一台后端,这样一来这个ip下的某个客户端和某个后端就能建立起稳固的session,ip_hash是在upstream配置中定义的, 配置方式样例:

Java代码 复制代码 收藏代码
  1. upstream backend {   
  2.   server 127.0.0.1:8080 ;   
  3.   server 127.0.0.1:9090 ;   
  4.    ip_hash;   
  5. }  

 ip_hash是容易理解的,但是因为仅仅能用ip这个因子来分配后端,因此ip_hash是有缺陷的,不能在一些情况下使用:

     1/ nginx不是最前端的服务器。ip_hash要求nginx一定是最前端的服务器,否则nginx得不到正确ip,就不能根据ip作hash。譬如使用的是squid为最前端,那么nginx取ip时只能得到squid的服务器ip地址,用这个地址来作分流是肯定错乱的。

      2/ nginx的后端还有其它方式的负载均衡。假如nginx后端又有其它负载均衡,将请求又通过另外的方式分流了,那么某个客户端的请求肯定不能定位到同一台session应用服务器上。这么算起来,nginx后端只能直接指向应用服务器,或者再搭一个squid,然后指向应用服务器。最好的办法是用 location作一次分流,将需要session的部分请求通过ip_hash分流,剩下的走其它后端去。

4) upstream_hash(这种方式没有尝试过)

          为了解决ip_hash的一些问题,可以使用upstream_hash这个第三方模块,这个模块多数情况下是用作url_hash的,但是并不妨碍将它用来做session共享:

          假如前端是squid,他会将ip加入x_forwarded_for这个http_header里,用upstream_hash可以用这个头做因子,将请求定向到指定的后端:

          可见这篇文档:http://www.sudone.com/nginx/nginx_url_hash.html

          在文档中是使用$request_uri做因子,稍微改一下:

             hash   $http_x_forwarded_for;

          这样就改成了利用x_forwarded_for这个头作因子,在nginx新版本中可支持读取cookie值,所以也可以改成:

            hash   $cookie_jsessionid;

         假如在php中配置的session为无cookie方式,配合nginx自己的一个userid_module模块就可以用nginx自发一个cookie,可参见userid模块的英文文档:

                     http://wiki.nginx.org/NginxHttpUserIdModule

         另可用姚伟斌编写的模块upstream_jvm_route:http://code.google.com/p/nginx-upstream-jvm-route/

 

 

 

其实我比较倾向于第2中和第3中方案来实现session共享。

(责任编辑:IT)