Nginx

来自tomtalk
跳转至: 导航搜索

最佳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管理:

  1. 默认启动方式

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

  1. 带上配置文件:

sudo /usr/local/web/nginx.0.8.15/sbin/nginx -c /usr/local/web/nginx.0.8.15/conf/nginx.conf


  1. 带测试配置文件启动方法

sudo /usr/local/web/nginx.0.8.15/sbin/nginx -t

  1. 从容停止

sudo kill -QUIT `cat /usr/local/web/nginx.0.8.15/nginx.pid`

  1. 快速停止

sudo kill -INT `cat /usr/local/web/nginx.0.8.15/nginx.pid`

  1. 平滑重启

sudo kill -HUP `cat /usr/local/web/nginx.0.8.15/nginx.pid`

平滑升级你的Nginx

Nginx方便地帮助我们实现了平滑升级。其原理简单概括,就是:

  1. 在不停掉老进程的情况下,启动新进程。
  2. 老进程负责处理仍然没有处理完的请求,但不再接受处理请求。
  3. 新进程接受新请求。
  4. 老进程处理完所有请求,关闭所有连接后,停止。

这样就很方便地实现了平滑升级。一般有两种情况下需要升级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;
    charset     utf-8;
    server_name go.tomtalk.com;
    root        "/home/github_projects/memorize_site";
 
    location /api {
        proxy_pass http://192.168.1.57:3001;
        proxy_http_version 1.1;
        proxy_set_header Connection "";
    }
 
    location / {
        proxy_pass http://192.168.1.57:3000;
        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;
    }
}

代理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;
      }
    }
}