Nginx 优化
隐藏版本号
配置文件隐藏版本号
http {
...
# 隐藏版本信息
server_tokens off;
...
}隐藏服务名及版本号
修改源代码在nginx的安装包中src/core/nginx.h文件,然后进行编译安装。
修改源码包配置
注意:需要将配置文件中的server_tokens off;去掉,否则回不生效。
#define NGINX_VERSION "1.12.2" # 修改版本号
#define NGINX_VER "nginx/"NGINX_VERSION # 修改软件名称源码包编译
如果服务已经编译运行的情况下可以用平滑升级方式只编译不安装。
make编译- 编译后会在源码包内有个objs目录,里面有个nginx可执行文件
- 备份旧nginx执行文件
- 复制新的nginx可执行文件
- 不影响业务情况下可停止服务并重新启动
降权启动
worker进程降权
# 在nginx.conf中指定普通用户
user www;master进程降权
创建程序用户
useradd -Ms /sbin/nologin www修改nginx的启动端口
Linux系统1-1024为root用户使用端口,普通用户无权使用。
server {
listen 8080;
server_name localhost;
location / {
root html;
index index.html;
}
}修改服务目录归属
chown -R www:www /usr/local/nginx/设置systemd服务启动用户
文件位置/usr/lib/systemd/system/nginx.service,指定User和Group为www。
[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启动服务
systemctl daemon-reload
systemctl restart nginxNginx站点目录及文件URL访问控制
Web2.0时代,绝大多数网站都是以用户为中心多的,例如:bbs,blog,sns产品,这几个产品都有一个共同特点,就是不但允许用户发布内容到服务器,还允许用户发图片甚至上传附件到服务器上,由于为用户开了上传功能,因此给服务器带来了很大的安全风险。虽然很多程序在上传前会着一定的控制,例如:文件大小,类型等,但是,一不小心就会被黑客钻了控制,上传了木马程序。
面将利用Nginx配置禁止访问上传资源目录下的PHP,Shell,Perl,Python程序文件,这样禁止用户上传木马文件,从而加强了网站的安全。
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;
}文件上传大小限制
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模型。
events {
use epoll; # Linux推荐使用epoll
multi_accept on; # 一次接受所有新连接
accept_mutex on; # 启用互斥锁
}Nginx 文件打开数
nginx进程打开的最多文件数目,理论值应该是最多打开文件数(ulimit -n)与nginx进程数相除,但是nginx分配请求并不是那么均匀,所以最好与ulimit -n的值保持一致。
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的设置才能生效。
events {
# 4 worker 进程 × 4096 连接 = 16384 最大并发连接
worker_connections 16384;
}最大并发连接数
这个值还受到操作系统对单个进程打开文件描述符(File Descriptor)数量的限制(即ulimit -n)。因此,worker_connections的值不能超过文件描述符的限制。你需要确保worker_connections <= ulimit -n。
通用基础配置
# 最大客户端并发数 = 4 worker_processes × 1024 worker_connections
user www;
worker_processes auto; # 自动匹配CPU核心数
events {
worker_connections 8192;
multi_accept on; # 同时接受多个新连接
use epoll; # Linux高性能事件模型
}
http {
# 其他配置...
}反向代理
# 最大客户端并发数 = 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 个连接
高并发
# 需配合系统调优
# 最大客户端并发数 = 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;
}压力测试工具
# 使用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 段加入对特定内容的过期参数
# 静态文件缓存
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 日志切割
#!/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" -deleteNginx 连接超时
在企业网站中,为了避免同一个客户长时间占用连接,造成资源浪费,可以设置相应的 连接超时参数,实现控制连接访问时间。
keepalived_timeout:设置连接保持超时时间,一般可只设置该参数,默认为65 秒,可根据网站的情况设置,或者关闭,可在http 段、server 段、或者location 段设置。client_header_timeout:指定等待客户端发送请求头的超时时间。如果服务端长时间未获取请求头会返回408报错client_body_timeout:设置请求体读超时时间。如果客户端上传请求主题若出现超时,会返回408 报错
http {
...
keepalive_timeout 60;
client_header_timeout 20;
client_body_timeout 20;
...
}| 参数 | 默认值 | 含义 | 生产建议值 | 适用场景 |
|---|---|---|---|---|
client_header_timeout | 60s | 客户端发送请求头的超时时间,超时返回 408 (Request Time-out)。 | 20s–30s | 公网服务、移动端用户,可防止慢速攻击。 |
client_body_timeout | 60s | 客户端发送请求体的超时时间(如 POST 数据),超时返回 408。 | 20s–30s(大文件上传可设 60s) | 表单提交、文件上传,需配合 client_max_body_size 使用。 |
keepalive_timeout | 75s | 长连接保持时间,减少 TCP 握手开销。 | 15s–30s | 高并发 HTTP 服务,减少连接重建。 |
send_timeout | 60s | 响应数据发送超时时间(非请求超时),超时关闭连接。 | 10s–30s | 慢速客户端或高延迟网络(如 CDN 回源)。 |
client_max_body_size | 1M | 客户端请求体的最大大小(如文件上传)。 | 10M–100M(按需调整) | 文件上传、API 接收大数据,避免 413 (Request Entity Too Large) 错误。 |
proxy_read_timeout | 60s | Nginx 从后端服务器读取响应的超时时间。 | 30s–120s(长任务需延长) | 反向代理场景(如 Tomcat、Node.js),避免 504 (Gateway Time-out)。 |
proxy_connect_timeout | 60s | Nginx 连接后端服务器的超时时间。 | 5s–15s | 后端服务健康检查或内网高可用场景。 |
Nginx 设置cpu亲和
在高并发场景,需要启动更多的nginx 进程以保证快速影响,以处理用户的请求,避免 造成阻塞。修改配置文件的worker_processes 参数,一般设置为CPU 的个数或者核数的2 倍 设置Nginx运行进程个数,nginx运行进程个数一般我们设置cpu的核心一致或者核心数x2
查看CPU数
grep processor /proc/cpuinfo
# 使用 top 命令 #按1,可以查看cup的核心
nproc
lscpu | grep "CPU:"Nginx 配置CPU
worker_processes 1; 默认Nginx的多个进程可能更多的跑在一颗CPU 上,可以分配不同的进程给不同的CPU 处 理,充分利用硬件多核多CPU。在一台4核物理服务器,可以进行下面的配置,将进程进行分配。
# 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句柄数优化
内核修改
# 临时生效
ulimit -n 65535
# 永久生效 (/etc/security/limits.conf)
* soft nofile 65535
* hard nofile 65535内核参数优化
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 -pNginx 高效传输
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和文件的开始部分放在一个文件里发布,其积极的作用是减少网络报文段的数量。
缓冲区优化
client_body_buffer_size 16k;
client_header_buffer_size 4k;
client_max_body_size 50m;
large_client_header_buffers 4 16k;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 实现防盗链功能
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文件。
User-agent: [爬虫名称]
Disallow: [禁止访问的路径]
Allow: [允许访问的路径]
Crawl-delay: [抓取延迟秒数]
Sitemap: [网站地图位置]示例
可参考网站:https://www.sohu.com/robots.txt
# 禁止所有爬虫访问后台和临时文件
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.xmlNginx 配置Robots
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;
}阻止下载协议
if ($http_user_agent ~* LWP:Simple | BBBike | wget) {
return 403;
}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;
}