nignx性能优化
-
启用文件发送(sendfile)
打开sendfile指令将省去copy数据到缓存buffer,而直接从一个文件copy数据到另一个文件,为防止一个连接占居所有的worker进程,可以设置限制一个sendfile的最大数据传输量
location /mp3 { sendfile on; sendfile_max_chunk 1m; ... }
-
启用tcp_nopush
启用tcp_nopush选项与sendfile on结合,可以使nginx在通过sendfile获取数据后发送http响应头在一个包中
location /mp3 { sendfile on; tcp_nopush on; ... }
-
启用tcp_nodelay
tcp_nodelay选项允许重写Nagle算法,该算法原本是解决在慢速网络中传输小的数据包的问题,该算法会把小包的数据集成为大包数据并有200ms的发送延迟。现在当请求大的静态文件时,数据可以立即发送而忽略包的大波。默认tcp_nodelay被设置为on,意味着关闭Nagle算法,常常仅用于保持活动连接
location /mp3 { tcp_nodelay on; keepalive_timeout 65; ... }
-
优化Backlog队列
nginx处理接收的连接请求速度的一个重要因素就是backlog队列。一般是当一个连接建立时,它会放在监听队列里。在正常的压力下,这个队列有可能有很少的连接,也可能为空,但是在高负载情况下,队列可能会成倍的增长,导致不好的性能,连接可能会被扔掉
可以调节操作系统的net.core.somaxconn的值,默认为128,来增加处理的峰值。如 sudo sysctl -w net.core.somaxconn=4096,然后设置nginx的backlog的值,如
server { listen 80 backlog 4096; # The rest of server configuration }
反向代理
通常用于负载均衡,显示来自不同网站的内容或是传输请求到不同的服务器去处理
-
传递请求到代理服务器
- proxy_pass 传递一个请求给一个http代理服务器
- fastcgi_pass 传递一个请求到fastcgi服务器
- uwsgi_pass 传递一个请求到uwsgi服务器
- scgi_pass 传递一个请求到scgi服务器
- memcached_pass 传递一个请求到memcached服务器
-
传输请求头
nginx默认只在代理请求中重定义两个头信息Host=$proxy_host和Connection=close,可以使用proxy_set_header指令来修改或设置其他的头信息,该指令可以放在location,server或http上下文或块中,为了阻止头字段传给代理服务器,可以将其设置为空,如下所示:
location /some/path/ { proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header Accept-Encoding ""; proxy_pass http://localhost:8000; }
-
配置缓存buffers
默认情况下,nginx缓存来自代理服务器的响应,响应存储在内部buffer中直到所有的响应都收到才发送给客户端。开启buffer缓存,nginx允许代理服务器快速处理响应,同时nginx尽可能长时间的存储响应数据让客户端下载他们。
负责开启和关闭缓存命令是proxy_buffering,默认情况下是on,打开缓存的。而proxy_buffers指令则控制缓存的数量及大小,来自代理服务器的第一部分响应数据是存储在一个独立的缓存上的,其大小是通过proxy_buffer_size指令设置的,这部分通常包含一个比较小的响应报头,并且可以更小比存放响应其余部分的缓存。
location /some/path/ { proxy_buffers 16 4k; proxy_buffer_size 2k; #proxy_buffering off; proxy_pass http://localhost:8000; }
负载均衡
HTTP负载均衡
http { upstream backend { server backend1.example.com weight=5; server backend2.example.com; server 192.0.0.1 backup; } }
NGINX支持4种负载均衡方法:
-
轮循方法
默认情况下,nginx使用轮循法根据权重分发请求到相应的服务器,可以通过server指令的weight参数指定权重,默认权重为1:
upstream backend { server backend1.example.com weight=5; server backend2.example.com; server 192.0.0.1 backup; }
- 最少连接方法:
-
> 一个请求会被分发到根据权重的最少连接的服务器上
```
upstream backend {
least_conn;
server backend1.example.com;
server backend2.example.com;
}
```
- ip哈希方法
> 一个请求被分发到哪个服务器决定于客户端的IP地址,根据IP地址来计算其哈希值,来自相同IP地址的请求会被分发到相同的服务器上
```
upstream backend {
ip_hash;
server backend1.example.com;
server backend2.example.com;
}
```
> 如果一个服务器需要临时删除,则给其后添加down参数,以便保留当前客户端IP的哈希值,则请求会被自动发送到下一个服务器进行处理:
```
upstream backend {
server backend1.example.com;
server backend2.example.com;
server backend3.example.com down;
}
```
- 通用散列法
> 其请求分发决定于用户自定义的hash key,可以是文本,变量,或是它们的组合,比如IP地址和端口号,或是URI
- 最小次数访求
> 对于每个请求,NGINX选择具有最低平均等待时间和数量最少的活动连接的服务器处理,而最低的平均等待时间是基于以下参数来计算的
1. header - 从服务器收到第一个字节的时间
2. last_byte - 从服务器收到所有响应的时间
```shell
upstream backend {
least_time header;
server backend1.example.com;
server backend2.example.com;
}
```
# NGINX日志切分方式
#### 定时任务切分
> 所谓的定时任务切分,是指通过定时任务(比如crontab),发送信号给nginx,让其重新打开文件。发送USR1 信号会让nginx主动重新打开日志文件:
```shell
$ mv access.log access.log.0
$ kill -USR1 `cat master.nginx.pid`
$ sleep 1
$ gzip access.log.0 # do something with access.log.0
```
#### 自切分
> 自切分是指让nginx自身实现日志切分功能,不依赖crontab等东西。 其主要原理是依赖access_log的强大功能---- 可以用变量定义请求的log路径。
> 但每打印一个请求log就得打开文件,写日志,关闭文件,性能效率比较差,所以借助于open_file_cache指令,即存打开的文件,只有满足一定条件的时候才会重新去check当前fd对应的文件是否合法,是否需要重新打开。
```shell
#提取nginx变量
if ($time_iso8601 ~ "^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})"){
set $year $1;
set $month $2;
set $day $3;
set $hour $4;
set $minutes $5;
set $seconds $6;
}
#配置access_log ;以 hour 为界
access_log logs/access.log.$year$month$day$hour;
#配置open_log_file_cache
open_log_file_cache max=10 inactive=60s valid=1m min_uses=2;
```