Skip to content

Nginx 优化

隐藏版本号

配置文件隐藏版本号

nginx
http {
    ...
    # 隐藏版本信息
    server_tokens off;
    ...
}

隐藏服务名及版本号

修改源代码在nginx的安装包中src/core/nginx.h文件,然后进行编译安装。

修改源码包配置

注意:需要将配置文件中的server_tokens off;去掉,否则回不生效。

c
#define NGINX_VERSION 	"1.12.2"				# 修改版本号
#define	NGINX_VER		"nginx/"NGINX_VERSION 	# 修改软件名称

源码包编译

如果服务已经编译运行的情况下可以用平滑升级方式只编译不安装。

  1. make编译
  2. 编译后会在源码包内有个objs目录,里面有个nginx可执行文件
  3. 备份旧nginx执行文件
  4. 复制新的nginx可执行文件
  5. 不影响业务情况下可停止服务并重新启动

降权启动

worker进程降权

nginx
# 在nginx.conf中指定普通用户
user www;

master进程降权

创建程序用户

bash
useradd -Ms /sbin/nologin www

修改nginx的启动端口

Linux系统1-1024为root用户使用端口,普通用户无权使用。

nginx
server {
    listen 8080;
    server_name localhost;
    location / {
        root html;
        index index.html;
    }
}

修改服务目录归属

bash
chown -R www:www /usr/local/nginx/

设置systemd服务启动用户

文件位置/usr/lib/systemd/system/nginx.service,指定UserGroup为www。

ini
[Unit]
Description=The nginx HTTP and reverse proxy server
After=network.target remote-fs.target nss-lookup.target

[Service]
Type=forking
PIDFile=/usr/local/nginx/logs/nginx.pid
ExecStartPre=/usr/local/nginx/sbin/nginx -t -q
ExecStart=/usr/local/nginx/sbin/nginx
ExecReload=/usr/local/nginx/sbin/nginx -s reload
ExecStop=/usr/local/nginx/sbin/nginx -s quit
TimeoutStopSec=5
KillSignal=SIGQUIT
Restart=on-failure
RestartSec=10s
PrivateTmp=true
User=www
Group=www

[Install]
WantedBy=multi-user.target

启动服务

bash
systemctl daemon-reload
systemctl restart nginx

Nginx站点目录及文件URL访问控制

Web2.0时代,绝大多数网站都是以用户为中心多的,例如:bbs,blog,sns产品,这几个产品都有一个共同特点,就是不但允许用户发布内容到服务器,还允许用户发图片甚至上传附件到服务器上,由于为用户开了上传功能,因此给服务器带来了很大的安全风险。虽然很多程序在上传前会着一定的控制,例如:文件大小,类型等,但是,一不小心就会被黑客钻了控制,上传了木马程序。

面将利用Nginx配置禁止访问上传资源目录下的PHP,Shell,Perl,Python程序文件,这样禁止用户上传木马文件,从而加强了网站的安全。

nginx
location ~ ^/images/.*\.(php|php5|sh|pl|py)$ {
	deny all;
}
location ~ ^/static/.*\.(php|php5|sh|pl|py)$ {
	deny all;
}
location ~* ^/data/(attachment|avatar)/.*\.(php|php5)$ {
	deny all;
}
#对上述目录的限制必须写在Nginx处理PHP服务配置的前面,如下
location ~ .*\.(php|php5)${
    fastcgi_pass 127.0.0.1:9000;
    fastcgi_index index.php;
    include fcgi.conf;
}

文件上传大小限制

nginx
client_max_body_size 10m;
# 可以存放在:hettp,server,location下进行限制
# 具体大小根据公司的业务做调整,如果不清楚就先设置为8m把,一般情况下,HTTP的post方法在提交数据时才 会携带请求主体信

事件模型优化

Nginx的连接处理机制在不同的操作系统会采用不同的I/O模型,在Linux下,Nginx使用epoll的I/O多路复用模型,在Freebsd中使用kqueue的I/O多路复用模型,在Solaris中使用/dev/poll方式的I/O多路复用模型,在Windows中使用的是icop,等等。

要根据系统类型选择不同的事件处理模型,可供使用的选择有“use[kqueue|rtsig|epoll|/dev/poll|select|poll];”。因为教学使用的是Linux,因此将Nginx的事件处理模型调整为epoll模型。

nginx
events {
    use epoll;  		# Linux推荐使用epoll
    multi_accept on;  	# 一次接受所有新连接
    accept_mutex on;  	# 启用互斥锁
}

Nginx 文件打开数

nginx进程打开的最多文件数目,理论值应该是最多打开文件数(ulimit -n)与nginx进程数相除,但是nginx分配请求并不是那么均匀,所以最好与ulimit -n的值保持一致。

nginx
worker_rlimit_nofile 65535;

Nginx 连接数

worker_ connections也是个事件模块指令,用于定义Nginx每个进程的最大连接数,默认是1024.最大客户端连接数由worker_ processes和worker_ connections决定, 即Max_client= worker_processes *worker_ connections. 进程的最大连接数受Linux系统进程的最大打开文件数限制,在执行操作系统命令"ulimit -HSn 65535"或配置相应文件后,worker_ connect ions的设置才能生效。

nginx
events {
    # 4 worker 进程 × 4096 连接 = 16384 最大并发连接
    worker_connections 16384;
}

最大并发连接数

这个值还受到操作系统对单个进程打开文件描述符(File Descriptor)数量的限制(即ulimit -n)。因此,worker_connections的值不能超过文件描述符的限制。你需要确保worker_connections <= ulimit -n

通用基础配置

nginx
# 最大客户端并发数 = 4 worker_processes × 1024 worker_connections
user www;
worker_processes auto;  # 自动匹配CPU核心数

events {
    worker_connections 8192;
    multi_accept on;    # 同时接受多个新连接
    use epoll;          # Linux高性能事件模型
}

http {
    # 其他配置...
}

反向代理

nginx
# 最大客户端并发数 = 4 worker_processes * 1024 worker_connections / 2
worker_processes auto;
worker_rlimit_nofile 100000;  # > worker_connections × worker_processes

events {
    worker_connections 4096;
    multi_accept on;
    use epoll;
}

原因‌:一个客户端连接可能触发另一个到上游服务器的连接(如 PHP-FPM),占用 2 个连接

高并发

nginx
# 需配合系统调优
# 最大客户端并发数 = 4 worker_processes * 1024 worker_connections
worker_processes auto;
worker_rlimit_nofile 100000;  # > worker_connections × worker_processes

events {
    worker_connections 8192;
    multi_accept on;
    use epoll;
}

压力测试工具

bash
# 使用ab测试(示例测试1000并发)
ab -n 10000 -c 1000 http://example.com/

不同场景建议值

服务器配置推荐 worker_connections计算逻辑与资源适配说明
1核1GB内存512~1024- worker_processes = 1(单核)5 - 系统 FD 限制约 1 万(1GB 内存)6 - 取 1024/2 = 512 并发客户端,预留资源避免 OOM
2核4GB内存2048~4096- worker_processes = 2(双核)5 - FD 限制约 4 万(4GB 内存 ≈ 4×1 万)6 - 取 4096/2 = 2048 并发,适配中小型流量
4核8GB内存4096~8192- worker_processes = 4(四核)5 - FD 限制约 8 万(内存充足) - 支持 8192/2 = 4096 并发,满足 API/电商需求 47
8核16GB+内存8192~16384- worker_processes = 8(八核) - FD 需调至 >16 万(sysctl -w fs.file-max=200000)7 - 支持 8K~16K 连接,应对高并发场景

Nginx 静态文件缓存

当Nginx 将网页数据返回给客户端后,可设置缓存的时间,以方便在日后进行相同内容的请求时直接返回,以避免重复请求,加快了访问速度,一般针对静态网页进行设置,对动态网页不用设置缓存时间。可在Windows 客户端中使用fiddler 查看网页缓存时间。

设置方法:可修改配置文件,在http 段、或server 段、或者location 段加入对特定内容的过期参数

nginx
# 静态文件缓存
location ~ \.(css|js|gif|jpg|jpeg|png|bmp|ico)$ {
	# 启用缓存
    proxy_cache static_cache;
    proxy_cache_valid 200 304 1h;   # 成功响应缓存1小时
    proxy_cache_valid 404 1m;       # 404缓存1分钟
    expires 3h;  					# 浏览器缓存3小时
}

Nginx 日志切割

shell
#!/bin/bash
# nginx_log_backup.sh

# Nginx进程PID
NGINX_PID="/usr/local/nginx/logs/nginx.pid"
# 备份目录
NGINX_BACKUP="/var/log/nginx"
# 源日志文件
NGINX_SRC_LOG="/usr/local/nginx/logs/access.log"
# 目标日志文件
NGINX_DST_LOG="$NGINX_BACKUP/test.com-access-$(date -d '-1 day' +%Y%m%d).log"
# 保留天数
KEEP_DAYS=30
# 程序用户
NGINX_USER="www"

if [ ! -f $NGINX_PID ];then 
	echo "Nginx Not Start"
	exit 1
fi
[ ! -e $NGINX_BACKUP ] || mkdir -p "$NGINX_BACKUP"
# 备份日志
mv $NGINX_SRC_LOG $NGINX_DST_LOG
# 创建空文件
touch $NGINX_SRC_LOG
# 修改权限归属
chown $NGINX_USER:$NGINX_USER $NGINX_SRC_LOG
chmod 640 $NGINX_SRC_LOG
# 信号通知Nginx重新打开日志文件
kill -USR1 $(cat $NGINX_PID)
# 压缩
gzip $NGINX_DST_LOG
# 删除历史文件
find $NGINX_BACKUP -mtime +$KEEP_DAYS -name "*.log.gz" -delete

Nginx 连接超时

在企业网站中,为了避免同一个客户长时间占用连接,造成资源浪费,可以设置相应的 连接超时参数,实现控制连接访问时间。

keepalived_timeout:设置连接保持超时时间,一般可只设置该参数,默认为65 秒,可根据网站的情况设置,或者关闭,可在http 段、server 段、或者location 段设置。client_header_timeout:指定等待客户端发送请求头的超时时间。如果服务端长时间未获取请求头会返回408报错client_body_timeout:设置请求体读超时时间。如果客户端上传请求主题若出现超时,会返回408 报错

bash
http {
	...
	keepalive_timeout 60;
	client_header_timeout 20;
	client_body_timeout 20;
	...
}
参数默认值含义生产建议值适用场景
client_header_timeout60s客户端发送请求头的超时时间,超时返回 408 (Request Time-out)20s–30s公网服务、移动端用户,可防止慢速攻击。
client_body_timeout60s客户端发送请求体的超时时间(如 POST 数据),超时返回 40820s–30s(大文件上传可设 60s表单提交、文件上传,需配合 client_max_body_size 使用。
keepalive_timeout75s长连接保持时间,减少 TCP 握手开销。15s–30s高并发 HTTP 服务,减少连接重建。
send_timeout60s响应数据发送超时时间(非请求超时),超时关闭连接。10s–30s慢速客户端或高延迟网络(如 CDN 回源)。
client_max_body_size1M客户端请求体的最大大小(如文件上传)。10M–100M(按需调整)文件上传、API 接收大数据,避免 413 (Request Entity Too Large) 错误。
proxy_read_timeout60sNginx 从后端服务器读取响应的超时时间。30s–120s(长任务需延长)反向代理场景(如 Tomcat、Node.js),避免 504 (Gateway Time-out)
proxy_connect_timeout60sNginx 连接后端服务器的超时时间。5s–15s后端服务健康检查或内网高可用场景。

Nginx 设置cpu亲和

在高并发场景,需要启动更多的nginx 进程以保证快速影响,以处理用户的请求,避免 造成阻塞。修改配置文件的worker_processes 参数,一般设置为CPU 的个数或者核数的2 倍 设置Nginx运行进程个数,nginx运行进程个数一般我们设置cpu的核心一致或者核心数x2

查看CPU数

bash
grep processor /proc/cpuinfo
# 使用 top 命令 #按1,可以查看cup的核心
nproc
lscpu | grep "CPU:"

Nginx 配置CPU

worker_processes 1; 默认Nginx的多个进程可能更多的跑在一颗CPU 上,可以分配不同的进程给不同的CPU 处 理,充分利用硬件多核多CPU。在一台4核物理服务器,可以进行下面的配置,将进程进行分配。

nginx
# CPU数
worker_processes 4;
## 或
worker_processes auto;

# CPU绑定
worker_cpu_affinity 0001 0010 0100 1000
## 或(个别系统不生效)
worker_cpu_affinity 1010 0101;
## 或
worker_cpu_affinity auto;

# 检测
ps -eo pid,args,psr | grep nginx

句柄数优化

内核修改

bash
# 临时生效
ulimit -n 65535

# 永久生效 (/etc/security/limits.conf)
* soft nofile 65535
* hard nofile 65535

内核参数优化

bash
cat >> /etc/sysctl.conf << EOF
# 调节系统同时发起的tcp连接数
net.core.somaxconn = 50000
# tcp连接快速回收
net.ipv4.tcp_tw_recycle = 1
# tcp连接重用
net.ipv4.tcp_tw_reuse = 1
# 不抵御洪水攻击
net.ipv4.tcp_syncookies = 0
# 该参数用于设定系统中最多允许存在多少TCP套接字不被关联到任何一个用户文件句柄上,主要目的为防止Ddos攻击
net.ipv4.tcp_max_orphans = 262144
EOF

# 应用配置
sysctl -p

Nginx 高效传输

nginx
http {
    sendfile on;  # 启用零拷贝传输
    tcp_nopush on;  # 合并数据包
    tcp_nodelay on;  # 禁用Nagle算法
    
    # 直接IO配置(适合大文件)
    directio 4m;
    directio_alignment 512;
    
    # 异步IO配置
    aio threads;
    aio_write on;
}
  • sendfile on:开启高效文件传输模式,sendfile指令指定nginx是否调用sendfile函数来传输,输出文件,当nginx是一个静态文件服务器的时候,开启sendfile配置项能大大提高nginx的性能。

  • tcp_nopush on:在sendfile开启模式才有效,防止网络阻塞,积极的减少网络报文段的数量(将响应头和响应体两部分一起发送,而不一个接一个的发送。)激活或禁用Linux上的TCP_CORKsocket选项,此选项仅仅当开启sendfile时才生效,激活这个tcp_ nopush参数可以允许把http response header和文件的开始部分放在一个文件里发布,其积极的作用是减少网络报文段的数量。

缓冲区优化

nginx
client_body_buffer_size 16k;
client_header_buffer_size 4k;
client_max_body_size 50m;
large_client_header_buffers 4 16k;

Nginx 压缩输出

nginx
http{ 
    # 开启gzip 压缩输出
    gzip on;
    # 用于设置允许压缩的页面最小字节数
    gzip_min_length 1k;
    # 表示申请4 个单位为16k 的内存作为压缩结果流缓存,默认值是申请与原始数据大小相同的内存空间来储存gzip 压缩结果
    gzip_buffers 4 16k;
    # 设置识别http 协议版本,默认是1.1
    gzip_http_version 1.1;
    # gzip 压缩比,1-9 等级
    gzip_comp_level 2;
    # 压缩类型,是就对哪些网页文档启用压缩功能
    gzip_types text/plain text/javascript application/x-javascrip t text/css text/xml application/xml application/xml+rss;
    # 选项可以让前端的缓存服务器经过gzip 压缩的页面
    gzip_vary on;
}

Nginx 实现防盗链功能

nginx
location ~* \.(jpg|gif|png|swf)$ {
    valid_referers none blocked *.amber.com amber.com;
    if ($invalid_referer) {
        rewrite ^/ http://www.amber.com/error.jpg;
        #return 403;
    }
}
  • valid_referers:设置信任网站

  • none:浏览器中referer 为空的情况,就直接在浏览器访问图片

  • blocked referrer:不为空的情况,但是值被代理或防火墙删除了,这些值不以http://或https😕/开头

Nginx 防爬虫优化

Robots 协议基本语法

基本指令

Robots协议(也称为爬虫协议,机器人协议等)的全称是“网络爬虫排除标准”(Robots ExclusionProtocol),网站通过Robots协议告诉搜索引擎哪些页面可以抓取,哪些页面不能抓取。我理解的是robots.txt是通过代码控制搜索引擎蜘蛛索引的一个手段,以便减轻网站服务器的带宽使用率,从而让网站的空间更稳定,同时也可以提高网站其他页面的索引效率,提高网站收录。我们只需要创建一个robots.txt文本文件,然后在文档内设置好代码,告诉搜索引擎我网站的哪些文件你不能访问。然后上传到网站根目录下面,因为当搜索引擎蜘蛛在索引一个网站时,会先爬行查看网站根目录下是否有robots.txt文件。

tex
User-agent: [爬虫名称]
Disallow: [禁止访问的路径]
Allow: [允许访问的路径]
Crawl-delay: [抓取延迟秒数]
Sitemap: [网站地图位置]

示例

可参考网站:https://www.sohu.com/robots.txt

tex
# 禁止所有爬虫访问后台和临时文件
User-agent: *
Disallow: /admin/
Disallow: /tmp/
Disallow: /cgi-bin/

# 特别允许Googlebot访问某些目录
User-agent: Googlebot
Allow: /special-offers/
Allow: /promotions/

# 设置爬取延迟
Crawl-delay: 5

# 网站地图
Sitemap: https://example.com/sitemap.xml
Sitemap: https://example.com/image-sitemap.xml

Nginx 配置Robots

nginx
location = /robots.txt {
    root /var/www/example.com;
    try_files $uri =404;
    access_log off;
    log_not_found off;
    # 爬虫限速
    if ($http_user_agent ~* (Googlebot|Bingbot)) {
        limit_req zone=crawlers burst=5 nodelay;
    }
}
# 防止暴力破解
http {
    limit_req_zone $binary_remote_addr zone=auth:10m rate=1r/s;
}

阻止下载协议

nginx
if ($http_user_agent ~* LWP:Simple | BBBike | wget) {
	return 403;
}

Nginx 阻止爬虫代理网站

nginx
if ($http_user_agent ~* "qihoobot|Baiduspider|Googlebot|Modile|Googlebot-Image|Mediapartners-Google|Adsbot-Google|Yahoo! SSlurp China|YoudaoBot|Sosospider|Sogou spider|Sogou web spider|MSNBot") {
 return 403;
}