Nginx
目录
最佳Nginx日志分析工具GoAccess
1、下载 GoAccess 解压编译安装
#需要安装 GeoIP, ncurses, glib2 yum -y install glib2 glib2-devel ncurses ncurses-devel GeoIP GeoIP-devel wget http://downloads.sourceforge.net/project/goaccess/0.5/goaccess-0.5.tar.gz tar zxvf goaccess-0.5.tar.gz cd goaccess-0.5 ./configure --enable-geoip --enable-utf8 make && make install make clean #GeoIP数据 wget http://geolite.maxmind.com/download/geoip/database/GeoLiteCountry/GeoIP.dat.gz gunzip GeoIP.dat.gz
2、~/.accessrc配置文件
color_scheme 0 date_format %d/%b/%Y:%T %z log_format %h - - [%d] "%r" %s %b "%R" "%u"
3、使用
goaccess -f access_20140430.log #输出为文件 goaccess -f access_20140430.log > report.html
Linux下 Nginx的安装和简单管理
Nginx安装前,您需要准备以下包:
1. Perl库:pcre-7.9.tar.gz
2. Nginx安装包:nginx-0.8.15.tar.gz
您的Linux是否已经安装了gcc等,还没有的话,先用yum安装一下,编译啥的都需要靠这些: yum install gcc gcc-c++ gcc-g77 autoconf automake zlib* fiex* libxml* ncurses-devel libmcrypt* libtool-ltdl-devel* libevent 安装pcre包 sudo tar -zvxf pcre-7.9.tar.gz cd pcre-7.9 sudo ./configure --prefix=/usr/local/web/lib/pcre sudo make sudo make install 安装Nginx包,安装路径/usr/local/web/nginx.0.8.15 sudo tar zxvf nginx-0.8.15.tar.gz cd nginx-0.8.15 sudo ./configure --user=nfsnobody --group=nfsnobody --prefix=/usr/local/web/nginx.0.8.15 --with-http_stub_status_module --without-http-cache sudo make sudo make install 创建日志目录,www目录: sudo mkdir -p /usr/local/web/nginx.0.8.15/logs #日志文件夹 sudo chmod +w /usr/local/web/nginx.0.8.15/logs sudo chown -R nfsnobody:nfsnobody /usr/local/web/nginx.0.8.15/logs sudo mkdir /usr/local/web/www #日志文件夹 sudo chown -R nfsnobody:nfsnobody /usr/local/web/www
拷贝我们已经准备好的配置文件,没有就不需要拷贝 sudo rm -f /usr/local/web/nginx.0.8.15/conf/nginx.conf sudo cp nginx.conf /usr/local/web/nginx.0.8.15/conf/nginx.conf #配置文件 sudo cp fcgi.conf /usr/local/web/nginx.0.8.15/conf/fcgi.conf 启动Nginx sudo /usr/local/web/nginx.0.8.15/sbin/nginx 查看Nginx是否启动,查看Nginx进程和用ip在浏览器中访问一下: ps –ef | grep nginx 如果已经开启防火墙,那么在防火墙中添加80端口: iptables -I INPUT -p tcp --dport 80 -j ACCEPT service iptables save service restart Nginx管理:
- 默认启动方式
sudo /usr/local/web/nginx.0.8.15/sbin/nginx sudo /usr/local/web/nginx.0.8.15/sbin/nginx -s stop sudo /usr/local/web/nginx.0.8.15/sbin/nginx -s reload
- 带上配置文件:
sudo /usr/local/web/nginx.0.8.15/sbin/nginx -c /usr/local/web/nginx.0.8.15/conf/nginx.conf
- 带测试配置文件启动方法
sudo /usr/local/web/nginx.0.8.15/sbin/nginx -t
- 从容停止
sudo kill -QUIT `cat /usr/local/web/nginx.0.8.15/nginx.pid`
- 快速停止
sudo kill -INT `cat /usr/local/web/nginx.0.8.15/nginx.pid`
- 平滑重启
sudo kill -HUP `cat /usr/local/web/nginx.0.8.15/nginx.pid`
平滑升级你的Nginx
Nginx方便地帮助我们实现了平滑升级。其原理简单概括,就是:
- 在不停掉老进程的情况下,启动新进程。
- 老进程负责处理仍然没有处理完的请求,但不再接受处理请求。
- 新进程接受新请求。
- 老进程处理完所有请求,关闭所有连接后,停止。
这样就很方便地实现了平滑升级。一般有两种情况下需要升级Nginx,一种是确实要升级Nginx的版本,另一种是要为Nginx添加新的模块。
具体的操作也很简单,如下:
查看当前版本
在存放Nginx的可执行文件的目录下输入:
./nginx -V
下载新的Nginx版本并编译
wget nginx-1.0.11.tar.gz
tar zxvf nginx-1.0.11.tar.gz
cd nginx-1.0.11
./configure --add-module=/customized_module_0 --add-module=/customized_module_1
make
注意不要进行make install
备份老版本的可执行文件
cd /usr/local/nginx/sbin
sudo cp nginx nginx.old
修改配置文件
如果有必要的话,进行配置文件的修改。
拷贝新的可执行文件
sudo cp /home/michael/tmp/nginx-1.0.11/objs/nginx /usr/local/nginx/sbin/
升级
cd /home/michael/tmp/nginx-1.0.11
make upgrade
清理多余文件
rm -rf /home/michael/tmp/nginx-1.0.11
查看Nginx版本
cd /usr/local/nginx/sbin
./nginx -V
nginx转发
公司网站采用 nginx + apache + tomcat + db + nfs 的架构,即前端 nginx 进行 upstream 转发,交给后端的 apache 和 tomcat 进行处理,两个一静一动,各司其职。db 采用主从读写分离,各后端服务器 mount 挂载 nfs 上的某图片路径,用于共享运营上传上来的图片信息。
今天客服反映说很多公司的图片都看不到了,但是单独指定IP的话可以访问。
指定单独的IP可以访问,但是走 nginx 就不行,可以基本判定 nfs 没有问题,于是排查 nginx 错误,在 nfs 上查到的 nginx 转发图片的配置为:
location ~ /p/ { expires -1; rewrite ^/p/(.*) /picture/c/$1 break; }
查看 nginx 错误日志,tail -f ng_err.log | grep '421965.jpg' 报如下错误,/opt/data/picture/c/logo/0/421/421965.jpg 现在发现,在 nginx 所做的转发是拦截 /p 的请求转发至 /picture/c , 而进入 /opt/data/picture 目录看,发现 logo 和 c 是同级文件夹,并且 c 下根本就不存在 logo 文件夹,判断了问题所在,提出了以下两种解决方法
1. 通知研发在代码层修改,将图片存取路径改为正确的,经反馈该代码代价太大,只好采取第二种方法了。
2. 修改 nginx 配置,将 rewrite ^/p/(.*) /picture/c/$1 break; 改为 rewrite ^/p/(.*) /picture/$1 break;
在此测试,找到了图片,问题解决。
Nginx 优化
via CSDN博客推荐文章 by gaoming655 on 3/8/12
一般来说nginx 配置文件中对优化比较有作用的为以下几项:
worker_processes 8;
nginx 进程数,建议按照cpu 数目来指定,一般为它的倍数。
worker_cpu_affinity 00000001 00000010 00000100 00001000 00010000 00100000 01000000 10000000;
为每个进程分配cpu,上例中将8 个进程分配到8 个cpu,当然可以写多个,或者将一 个进程分配到多个cpu。
worker_rlimit_nofile 102400;
这个指令是指当一个nginx 进程打开的最多文件描述符数目,理论值应该是最多打开文 件数(ulimit -n)与nginx 进程数相除,但是nginx 分配请求并不是那么均匀,所以最好与ulimit -n 的值保持一致。
use epoll;
使用epoll 的I/O 模型
worker_connections 102400;
每个进程允许的最多连接数, 理论上每台nginx 服务器的最大连接数为worker_processes*worker_connections。
keepalive_timeout 60;
keepalive 超时时间。
client_header_buffer_size 4k;
客户端请求头部的缓冲区大小,这个可以根据你的系统分页大小来设置,一般一个请求 头的大小不会超过1k,不过由于一般系统分页都要大于1k,所以这里设置为分页大小。分页大小可以用命令getconf PAGESIZE 取得。
open_file_cache max=102400 inactive=20s;
这个将为打开文件指定缓存,默认是没有启用的,max 指定缓存数量,建议和打开文件数一致,inactive 是指经过多长时间文件没被请求后删除缓存。
open_file_cache_valid 30s;
这个是指多长时间检查一次缓存的有效信息。
open_file_cache_min_uses 1;
open_file_cache 指令中的inactive 参数时间内文件的最少使用次数,如果超过这个数字,文件描述符一直是在缓存中打开的,如上例,如果有一个文件在inactive 时间内一次没被使用,它将被移除。
关于内核参数的优化:
net.ipv4.tcp_max_tw_buckets = 6000
timewait 的数量,默认是180000。
net.ipv4.ip_local_port_range = 1024 65000
允许系统打开的端口范围。
net.ipv4.tcp_tw_recycle = 1
启用timewait 快速回收。
net.ipv4.tcp_tw_reuse = 1
开启重用。允许将TIME-WAIT sockets 重新用于新的TCP 连接。
net.ipv4.tcp_syncookies = 1
开启SYN Cookies,当出现SYN 等待队列溢出时,启用cookies 来处理。
net.core.somaxconn = 262144
web 应用中listen 函数的backlog 默认会给我们内核参数的net.core.somaxconn 限制到128,而nginx 定义的NGX_LISTEN_BACKLOG 默认为511,所以有必要调整这个值。
net.core.netdev_max_backlog = 262144
每个网络接口接收数据包的速率比内核处理这些包的速率快时,允许送到队列的数据包的最大数目。
net.ipv4.tcp_max_orphans = 262144
系统中最多有多少个TCP 套接字不被关联到任何一个用户文件句柄上。如果超过这个数字,孤儿连接将即刻被复位并打印出警告信息。这个限制仅仅是为了防止简单的DoS 攻击,不能过分依靠它或者人为地减小这个值,更应该增加这个值(如果增加了内存之后)。
net.ipv4.tcp_max_syn_backlog = 262144
记录的那些尚未收到客户端确认信息的连接请求的最大值。对于有128M 内存的系统而言,缺省值是1024,小内存的系统则是128。
net.ipv4.tcp_timestamps = 0
时间戳可以避免序列号的卷绕。一个1Gbps 的链路肯定会遇到以前用过的序列号。时间戳能够让内核接受这种“异常”的数据包。这里需要将其关掉。
net.ipv4.tcp_synack_retries = 1
为了打开对端的连接,内核需要发送一个SYN 并附带一个回应前面一个SYN 的ACK。也就是所谓三次握手中的第二次握手。这个设置决定了内核放弃连接之前发送SYN+ACK 包的数量。
net.ipv4.tcp_syn_retries = 1
在内核放弃建立连接之前发送SYN 包的数量。
net.ipv4.tcp_fin_timeout = 1
如果套接字由本端要求关闭,这个参数决定了它保持在FIN-WAIT-2 状态的时间。对端可以出错并永远不关闭连接,甚至意外当机。缺省值是60 秒。2.2 内核的通常值是180 秒,3你可以按这个设置,但要记住的是,即使你的机器是一个轻载的WEB 服务器,也有因为大量的死套接字而内存溢出的风险,FIN- WAIT-2 的危险性比FIN-WAIT-1 要小,因为它最多只能吃掉1.5K 内存,但是它们的生存期长些。
net.ipv4.tcp_keepalive_time = 30
当keepalive 起用的时候,TCP 发送keepalive 消息的频度。缺省是2 小时。
关于FastCGI 的几个指令:
fastcgi_cache_path /usr/local/nginx/fastcgi_cache levels=1:2 keys_zone=TEST:10minactive=5m;
这个指令为FastCGI 缓存指定一个路径,目录结构等级,关键字区域存储时间和非活动删除时间。
fastcgi_connect_timeout 300;
指定连接到后端FastCGI 的超时时间。
fastcgi_send_timeout 300;
向FastCGI 传送请求的超时时间,这个值是指已经完成两次握手后向FastCGI 传送请求的超时时间。
fastcgi_read_timeout 300;
接收FastCGI 应答的超时时间,这个值是指已经完成两次握手后接收FastCGI 应答的超时时间。
fastcgi_buffer_size 4k;
指定读取FastCGI 应答第一部分需要用多大的缓冲区,一般第一部分应答不会超过1k,由于页面大小为4k,所以这里设置为4k。
fastcgi_buffers 8 4k;
指定本地需要用多少和多大的缓冲区来缓冲FastCGI 的应答。
fastcgi_busy_buffers_size 8k;
这个指令我也不知道是做什么用,只知道默认值是fastcgi_buffers 的两倍。
fastcgi_temp_file_write_size 8k;
在写入fastcgi_temp_path 时将用多大的数据块,默认值是fastcgi_buffers 的两倍。
fastcgi_cache TEST
开启FastCGI 缓存并且为其制定一个名称。个人感觉开启缓存非常有用,可以有效降低CPU 负载,并且防止502 错误。
fastcgi_cache_valid 200 302 1h; fastcgi_cache_valid 301 1d; fastcgi_cache_valid any 1m;
为指定的应答代码指定缓存时间,如上例中将200,302 应答缓存一小时,301 应答缓存1 天,其他为1 分钟。
fastcgi_cache_min_uses 1;
缓存在fastcgi_cache_path 指令inactive 参数值时间内的最少使用次数,如上例,如果在5 分钟内某文件1 次也没有被使用,那么这个文件将被移除。
fastcgi_cache_use_stale error timeout invalid_header http_500;
不知道这个参数的作用,猜想应该是让nginx 知道哪些类型的缓存是没用的。以上为nginx 中FastCGI 相关参数,另外,FastCGI 自身也有一些配置需要进行优化,如果你使用php-fpm 来管理FastCGI,可以修改配置文件中的以下值:
<value name="max_children">60</value>
同时处理的并发请求数,即它将开启最多60 个子线程来处理并发连接。
<value name="rlimit_files">102400</value>
最多打开文件数。
<value name="max_requests">204800</value>
每个进程在重置之前能够执行的最多请求数。
Nginx监控
需要注意的是,Nginx默认安装不包含状态模块stub_status,所以,在编译Nginx的时候,需要添加以下参数:
--with-http_stub_status_module
一旦包含stub_status模块后,我们就可以在配置文件nginx.conf中开启状态页面:
location /nginx-status { stub_status on; access_log off; }
Nginx的状态页面是: http://www.domain.com/nginx-status
建议将示例中的nginx-status修改为其它字符串。
access log_format
log_format que360 '$remote_addr - $remote_user [$time_local] ' '$http_host "$request_method $http_host$request_uri $server_protocol" $status $body_bytes_sent $request_time ' '"$http_referer" "$http_user_agent"';
$remote_addr 记录客户端IP地址 $http_x_forwarded_for 记录客户端IP地址 $remote_user 记录客户端用户名称 $request 记录请求的URL和HTTP协议 $http_host 域名 $status 记录请求状态 $body_bytes_sent 发送给客户端的字节数,不包括响应头的大小; 该变量与Apache模块mod_log_config里的“%B”参数兼容。 $bytes_sent 发送给客户端的总字节数。 $connection 连接的序列号。 $connection_requests 当前通过一个连接获得的请求数量。 $msec 日志写入时间。单位为秒,精度是毫秒。 $pipe 如果请求是通过HTTP流水线(pipelined)发送,pipe值为“p”,否则为“.”。 $http_referer 记录从哪个页面链接访问过来的 $http_user_agent 记录客户端浏览器相关信息 $request_length 请求的长度(包括请求行,请求头和请求正文)。 $request_time 请求处理时间,单位为秒,精度毫秒; 从读入客户端的第一个字节开始,直到把最后一个字符发送给客户端后进行日志写入为止。 $time_iso8601 ISO8601标准格式下的本地时间。 $time_local 通用日志格式下的本地时间。
反向代理
server { listen 80; listen 443 ssl http2; server_name oauthv2.local.com; root "/home/github_projects/oauth/public"; index index.html index.htm index.php; charset utf-8; #仅用这一行就能实现反向代理功能 location / { proxy_pass http://192.168.1.54:8080; } location = /favicon.ico { access_log off; log_not_found off; } location = /robots.txt { access_log off; log_not_found off; } access_log off; error_log /var/log/nginx/oauth.local.com-error.log error; sendfile off; client_max_body_size 100m; location ~ /\.ht { deny all; } ssl_certificate /etc/nginx/ssl/oauth.local.com.crt; ssl_certificate_key /etc/nginx/ssl/oauth.local.com.key; }
代理ws://
http { include mime.types; default_type application/octet-stream; sendfile on; keepalive_timeout 65; gzip on; map $http_upgrade $connection_upgrade { default upgrade; '' close; } server { listen 80; server_name ourapp.com; location / { proxy_pass http://127.0.0.1:100; proxy_http_version 1.1; 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; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $connection_upgrade; } } }