nginx做负载均衡

1.nginx的安装
下载地址
http://sysoev.ru/en/
文件
nginx-0.6.35.tar.gz

为了确保能在 Nginx 中使用正则表达式进行更灵活的配置,安装之前需要确定系统是否安装有 PCRE(Perl Compatible Regular Expressions)包。
rpm -q pcre

本机系统显示:

[sillycat@dev1 tmp]$ rpm -q pcre 

pcre-4.5-3.2.RHEL4



不知道版本会不会过低,等等再说

tar zxvf nginx-0.6.35.tar.gz 

cd nginx-0.6.35 


./configure --with-http_stub_status_module --prefix=/usr/local/nginx



make
make install
安装成功后 /usr/local/nginx 目录下有四个子目录分别是:
conf、html、logs、sbin 。
其中 Nginx 的配置文件存放于 conf/nginx.conf,Nginx 只有一个程序文件位于 sbin 目录下的 nginx 文件。
确保系统的 80 端口没被其他程序占用,
运行 sbin/nginx 命令来启动 Nginx,打开浏览器访问此机器的 IP,
如果浏览器出现 Welcome to nginx! 则表示 Nginx 已经安装并运行成功。

本机发现不行,需要修改配置文件中的

conf/nginx.conf 

 server { 

 listen 80; 

 server_name www.kiko.com;


原来server_name是localhost只监听了本机

程序运行参数

Nginx 安装后只有一个程序文件,本身并不提供各种管理程序,它是使用参数和系统信号机制对 Nginx 进程本身进行控制的。 Nginx 的参数包括有如下几个:
-c <path_to_config>:使用指定的配置文件而不是 conf 目录下的 nginx.conf 。
-t:测试配置文件是否正确,在运行时需要重新加载配置的时候,此命令非常重要,用来检测所修改的配置文件是否有语法错误。
-v:显示 nginx 版本号。
-V:显示 nginx 的版本号以及编译环境信息以及编译时的参数。
例如我们要测试某个配置文件是否书写正确,我们可以使用以下命令

sbin/nginx – t – c conf/nginx.conf



nginx启动脚本

通过信号对 Nginx 进行控制

Nginx 支持下表中的信号:

信号名 作用描述
TERM, INT 快速关闭程序,中止当前正在处理的请求
QUIT 处理完当前请求后,关闭程序
HUP 重新加载配置,并开启新的工作进程,关闭就的进程,此操作不会中断请求
USR1 重新打开日志文件,用于切换日志,例如每天生成一个新的日志文件
USR2 平滑升级可执行程序
WINCH 从容关闭工作进程

有两种方式来通过这些信号去控制 Nginx,第一是通过 logs 目录下的 nginx.pid 查看当前运行的 Nginx 的进程 ID,通过 kill – XXX <pid> 来控制 Nginx,其中 XXX 就是上表中列出的信号名。如果您的系统中只有一个 Nginx 进程,那您也可以通过 killall 命令来完成,例如运行 killall – s HUP nginx 来让 Nginx 重新加载配置。

nginx是超级稳定的服务器,一般不会因为超载问题而需要重启,重启的目的一般都是修改配置文件后需要加载一下。

最开始的时候,我是用最直接的重启方式
killall -9

如果机器比较慢,kill进程时一瞬间杀不完,再执行一次即可。这种重启方式不是特别安全,如果配置有误,则会重启失败,需要重新修改配置文件然后再启动,期间会消耗一点时间。不过对于目前普遍还是不怎么严格的http界而言,这点时间还不至于产生太大损失,只要不是在关键时刻搞出来就好。如果希望沿用这种重启办法,我提议还是先好好测试吧。
后来我在nginx.net上看到了一种更奇妙的重启
kill -HUP $pid($pid就是nginx master进程的进程号)
我一般这样用
kill -HUP `cat /data/nginx/logs/nginx.pid`
这种方式的好处是实现“平滑重启”,在ps -aux中可以看到,nginx首先启动新进程,旧的进程仍然提供服务,在一段时间后,旧的进程服务结束就自动关闭,剩下新进程继续服务。但是这种方式也是有缺点的,如果配置文件有误,或者资源冲突,则重启失效,但nginx并没有任何的提示!这就会时常发现改动的配置文件没有生效,又比较难找到问题。

所以,最后杂和了一下问题,弄了一个nginx.sh,这个版本的nginx.sh还是没有解决kill -HUP的资源冲突的问题,但解决了配置文件的问题。资源冲突的比如80端口被占用、日志文件目录没有创建这种的。
参考网上的做法,用如下脚本控制:

#!/bin/sh 

BASE_DIR='/usr/local/' 

${BASE_DIR}nginx/sbin/nginx -t -c ${BASE_DIR}nginx/conf/nginx.conf >& ${BASE_DIR}nginx/logs/nginx.start 

info=`cat ${BASE_DIR}nginx/logs/nginx.start` 

if [ `echo $info | grep -c "syntax is ok" ` -eq 1 ]; then 

if [ `ps aux|grep "nginx"|grep -c "master"` == 1 ]; then 

kill -HUP `cat ${BASE_DIR}nginx/logs/nginx.pid` 

echo "ok" 

else 

killall -9 nginx 

sleep 1 

${BASE_DIR}nginx/sbin/nginx 

fi 

else 

echo "######## error: ########" 

cat ${BASE_DIR}nginx/logs/nginx.start 

fi



2.nginx负载均衡配置

user nobody; #work user 

worker_processes 1; #work process number, acording to you cpu number 


#error_log logs/error.log; 

#error_log logs/error.log notice; 

#error_log logs/error.log info; 


#pid logs/nginx.pid; 



events { 

 use epoll; #linux best event mode 

 worker_connections 1024; # most connects of one work process 

} 



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; # log file name 


 sendfile on; 

 #tcp_nopush on; 


 #keepalive_timeout 0; 

 keepalive_timeout 65; 


 #gzip on; 


 upstream itsm { 

 ip_hash; 

 server localhost:8081; 

 server localhost:8082; 

 } 


 server { 

 listen 80; 

 server_name www.kiko.com; 


 charset utf-8; 


 access_log logs/host.access.log main; 


 location /nginxstatus { 

 stub_status on; #nginx status watch 

 access_log off; 

 } 


 location / { 

 proxy_pass http://itsm; 

 proxy_set_header X-Real-IP $remote_addr; 

 } 


 #location / { 

 # root html; 

 # index index.html index.htm; 

 #} 


 #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 html; 

 } 

 } 


}



3.Nginx状态监控

上面是一个实际网站的配置实例,其中灰色文字为配置说明。上述配置中,首先我们定义了一个 location ~ ^/nginxstatus/,这样通过
http://www.kiko.com/nginxstatus
就可以监控到 Nginx 的运行信息,显示的内容如下:

Active connections: 70 

server accepts handled requests 

14553819 14553819 19239266 

Reading: 0 Writing: 3 Waiting: 67


NginxStatus 显示的内容意思如下:

active connections – 当前 Nginx 正处理的活动连接数。
server accepts handled requests -- 总共处理了 14553819 个连接 , 成功创建 14553819 次握手 ( 证明中间没有失败的 ), 总共处理了 19239266 个请求 ( 平均每次握手处理了 1.3 个数据请求 )。
reading -- nginx 读取到客户端的 Header 信息数。
writing -- nginx 返回给客户端的 Header 信息数。
waiting -- 开启 keep-alive 的情况下,这个值等于 active - (reading + writing),意思就是 Nginx 已经处理完正在等候下一次请求指令的驻留连接。

4.问题
这个ip_hash模块是采用IP段来做负载均衡的,IP的前三位来做的hash,也就是说

192.168.1.2 --> server1 

192.168.1.12 --> server1 

192.168.1.13 --> server1


源文件

ngx_http_upstream_ip_hash_module.c



iphp->addr[0] = p[0]; 

 iphp->addr[1] = p[1]; 

 iphp->addr[2] = p[2];


好像确实只取了前三位,我C语言不好。看的不是很明白其算法。