读书人

nginx负载均衡设立

发布时间: 2012-10-07 17:28:51 作者: rapoo

nginx负载均衡设置

?

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

? 下面是nginx的完整配置:

?

user  www www;worker_processes 8;error_log  /data1/logs/nginx_error.log  crit;pid        /usr/local/webserver/nginx/nginx.pid;#Specifies the value for maximum file descriptors that can be opened by this process. worker_rlimit_nofile 65535;events {  use epoll;  worker_connections 65535;}http {  include       mime.types;  default_type  application/octet-stream;  charset  utf-8;        server_names_hash_bucket_size 128;  client_header_buffer_size 32k;  large_client_header_buffers 4 32k;  client_max_body_size 8m;        sendfile on;  tcp_nopush     on;  keepalive_timeout 60;  tcp_nodelay on;  fastcgi_connect_timeout 300;  fastcgi_send_timeout 300;  fastcgi_read_timeout 300;  fastcgi_buffer_size 64k;  fastcgi_buffers 4 64k;  fastcgi_busy_buffers_size 128k;  fastcgi_temp_file_write_size 128k;  gzip on;  gzip_min_length  1k;  gzip_buffers     4 16k;  gzip_http_version 1.0;  gzip_comp_level 2;  gzip_types       text/plain application/x-javascript text/css application/xml;  gzip_vary on;  #limit_zone  crawler  $binary_remote_addr  10m;  upstream mysvr {     server 192.168.1.104:8088;     server 192.168.1.104:8080;  }  server  {    listen       8080;    server_name  192.168.1.104;    index index.html index.htm index.php;    root  /data0/htdocs/mobile;    #limit_conn   crawler  20;                                     location ~ .*\.(php|php5)?$    {            #fastcgi_pass  unix:/tmp/php-cgi.sock;      fastcgi_pass  127.0.0.1:9000;      fastcgi_index index.php;      include fcgi.conf;    }        location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$    {      expires      30d;    }    location ~ .*\.(js|css)?$    {      expires      1h;    }        log_format  mobilelogs  '$remote_addr - $remote_user [$time_local] "$request" '              '$status $body_bytes_sent "$http_referer" '              '"$http_user_agent" $http_x_forwarded_for';    access_log  /data1/logs/mobileaccess.log  mobilelogs;      }  server  {    listen       8088;    server_name  192.168.1.104;#   index aa.html;    index index.html index.htm index.php;    root  /data0/htdocs/www;    location ~ .*\.(php|php5)?$    {            #fastcgi_pass  unix:/tmp/php-cgi.sock;      fastcgi_pass  127.0.0.1:9000;      fastcgi_index index.php;      include fcgi.conf;    }    error_page 400 404 /error.html;    log_format  wwwlogs  '$remote_addr - $remote_user [$time_local] "$request" '               '$status $body_bytes_sent "$http_referer" '               '"$http_user_agent" $http_x_forwarded_for';    access_log  /data1/logs/wwwlogs.log  wwwlogs;  }  server  {    listen  80;    server_name  192.168.1.104;    location / {        proxy_pass http://mysvr;    }       #以下是一些反向代理的配置可删除.           proxy_redirect off;           #后端的Web服务器可以通过X-Forwarded-For获取用户真实IP          proxy_set_header Host $host;          proxy_set_header X-Real-IP $remote_addr;          proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;          client_max_body_size 10m;    #允许客户端请求的最大单文件字节数          client_body_buffer_size 128k;  #缓冲区代理缓冲用户端请求的最大字节数,          proxy_connect_timeout 90;  #nginx跟后端服务器连接超时时间(代理连接超时)          proxy_send_timeout 90;        #后端服务器数据回传时间(代理发送超时)          proxy_read_timeout 90;         #连接成功后,后端服务器响应时间(代理接收超时)          proxy_buffer_size 4k;             #设置代理服务器(nginx)保存用户头信息的缓冲区大小          proxy_buffers 4 32k;               #proxy_buffers缓冲区,网页平均在32k以下的话,这样设置          proxy_busy_buffers_size 64k;    #高负荷下缓冲大小(proxy_buffers*2)          proxy_temp_file_write_size 64k;  #设定缓存文件夹大小,大于这个值,将从upstream服务器传   }}

?

?

?

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

??? 主要核心配置:

?

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

?

  upstream mysvr {     server 192.168.1.104:8088 weight=2;     server 192.168.1.104:8080 weight=3;  }

upstream设备上的状态设置:


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

?

?

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

  server  {    listen  80;    server_name  192.168.1.104;    location / {        proxy_pass http://mysvr;    }       #以下是一些反向代理的配置可删除.           proxy_redirect off;           #后端的Web服务器可以通过X-Forwarded-For获取用户真实IP          proxy_set_header Host $host;          proxy_set_header X-Real-IP $remote_addr;          proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;          client_max_body_size 10m;    #允许客户端请求的最大单文件字节数          client_body_buffer_size 128k;  #缓冲区代理缓冲用户端请求的最大字节数,          proxy_connect_timeout 90;  #nginx跟后端服务器连接超时时间(代理连接超时)          proxy_send_timeout 90;        #后端服务器数据回传时间(代理发送超时)          proxy_read_timeout 90;         #连接成功后,后端服务器响应时间(代理接收超时)          proxy_buffer_size 4k;             #设置代理服务器(nginx)保存用户头信息的缓冲区大小          proxy_buffers 4 32k;               #proxy_buffers缓冲区,网页平均在32k以下的话,这样设置          proxy_busy_buffers_size 64k;    #高负荷下缓冲大小(proxy_buffers*2)          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配置中定义的, 配置方式样例:

upstream backend {  server 127.0.0.1:8080 ;  server 127.0.0.1:9090 ;   ip_hash;}

?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共享。

?

?

?

?

?

读书人网 >操作系统

热点推荐