在国内,已经有 新浪博客、新浪播客、网易新闻、六间房、56.com、Discuz!、水木社区、豆瓣、YUPOO、海内、迅雷在线 等多家网站使用 Nginx 作为Web服务器或反向代理服务器。
我观察了国内清一色的CDN网站,基本都是用了nginx作为它们的web服务器。nginx的优点如下:
1、高并发连接:官方测试能够支撑5万并发连接,在实际生产环境中跑到2~3万并发连接数。
2、内存消耗少:在3万并发连接下,开启的10个Nginx进程才消耗150M内存(15M*10=150M)。
3、配置文件非常简单:风格跟程序一样通俗易懂。
4、成本低廉:Nginx为开源软件,可以免费使用。而购买F5 BIG-IP、NetScaler等硬件负载均衡交换机则需要十多万至几十万人民币。
5、支持Rewrite重写规则:能够根据域名、URL的不同,将HTTP请求分到不同的后端服务器群组。
6、内置的健康检查功能:如果 Nginx Proxy后端的某台Web服务器宕机了,不会影响前端访问。
7、节省带宽:支持GZIP压缩,可以添加浏览器本地缓存的Header头。
8、稳定性高:用于反向代理,宕机的概率微乎其微。
9、对网络的依赖性非常之低,理论上ping得通就能正常使用。
本文将介绍如何利用nginx配置简单的web负载均衡。文中所用的平台是64bit的FreeBSD 8.1。
部分内容参考了张宴的相关文章。
安装
cd /usr/ports/www/nginx
make install clean
配置nginx.conf文件
#user nobody;
worker_processes 4;
#error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;
#pid logs/nginx.pid;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
#log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
#access_log logs/access.log main;
sendfile on;
#tcp_nopush on;
#keepalive_timeout 0;
keepalive_timeout 65;
#gzip on;
upstream webserver {
server 192.168.21.45 weight=1;
server 192.168.4.45 weight=1;
}
server {
listen 80;
server_name localhost;
#charset koi8-r;
#access_log logs/host.access.log main;
location / {
proxy_pass http://webserver;
proxy_redirect off;
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;
proxy_send_timeout 90;
proxy_read_timeout 90;
proxy_buffer_size 4 32k;
proxy_temp_file_write_size 64k;
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/local/www/nginx-dist;
}
# proxy the PHP scripts to Apache listening on 127.0.0.1:80
#
#location ~ .php$ {
# proxy_pass http://127.0.0.1;
#}
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
#location ~ .php$ {
# root html;
# fastcgi_pass 127.0.0.1:9000;
# fastcgi_index index.php;
# fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
# include fastcgi_params;
#}
# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /.ht {
# deny all;
#}
}
another virtual host using mix of IP-, name-, and port-based configuration
#
#server {
listen 8000;
listen somename:8080;
server_name somename alias another.alias;
location / {
root html;
index index.html index.htm;
}
#}
HTTPS server
#
#server {
listen 443;
server_name localhost;
ssl on;
ssl_certificate cert.pem;
ssl_certificate_key cert.key;
ssl_session_timeout 5m;
ssl_protocols SSLv2 SSLv3 TLSv1;
ssl_ciphers ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP;
ssl_prefer_server_ciphers on;
location / {
root html;
index index.html index.htm;
}
#}
}
重点语法讲解
worker_processes 4; #这个与服务器的核数等同即可
upstream #这个里面的weight值越大,服务器所要承担的压力也越大;如果采用ip_hash模块时,就不能分配weight了,不然Nginx启动时会报错
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
#以上配置是让后端的web服务器可以通过X-Forwarded-For获取客户端的真实IP
#允许客户端请求的最大的单个文件字节数
client_max_body_size 10m;
#缓冲区代理缓冲用户端请求的最大字节数 可以理解为先保存到本地再传给用户
client_body_buffer_size 128k;
#跟后端服务器连接的超时时间_发起握手等候响应超时时间
proxy_connect_timeout 90;
#连接成功后_等候后端服务器响应时间_其实已经进入后端的排队之中等候处理
proxy_read_timeout 90;
#后端服务器数据回传时间_就是在规定时间之内后端服务器必须传完所有的数据
proxy_send_timeout 90;
#代理请求缓存区_这个缓存区间会保存用户的头信息以供Nginx进行规则处理,一般只要能保存下头信息即可
proxy_buffer_size 8k;
#同上 告诉Nginx保存单个用的几个Buffer 最大用多大空间
proxy_buffers 4 32k;
#如果系统很忙的时候可以申请更大的proxy_buffers 官方推荐*2
proxy_busy_buffers_size 64k;
#proxy缓存临时文件的大小
proxy_temp_file_write_size 64k;
Nginx如何解决session的问题
Nginx负载均衡器采用ip_hash来代替默认的rr方式,即可以将某客户端IP的请求通过哈希算法定位到同一台后端web服务器上,这样避免了session丢失,解决了session问题。
但ip_hash指令无法保证后端服务器的负载均衡,可能有些后端服务器接收的请求多,有些后端服务器接收的请求少;这样失去了负载均衡的意义。
我们的解决方案是将用户的登录session信息写进后端的Mysql数据库,这个在后面的PHPCMS系统中也实现了,效果也不错;后来我提出了折衷方案,如果Nginx并发连接数(即Nginx负载均衡器的NginxStatus的active connections)>2000,即采用将session写进MySQL数据库的方法;如果并发数小的话,ip_hash效果也是相当好的。