1. Nginx 简介
1.1 什么是 Nginx?
Nginx(发音为”Engine-X“)是一个高性能的开源 Web 服务器,同时也可作为:
代理服务器;
负载均衡器;
HTTP 缓存服务器;
邮件代理服务器
由俄罗斯工程师 lgor Sysoev 于 2004 年发布,现已称为全球最流行的 Web 服务器之一,支撑着许多高流量网站(如 Netflix、GitHub、WordPress.com等)。
1.2 核心特点
特性 | 说明 |
---|---|
高性能 | 采用 事件驱动(Event-Driven)和异步非阻塞I/O 架构,单机可轻松支持数万并发连接; |
低资源消耗 | 相比传统服务器(如Apache),内存和CPU占用更低; |
模块化设计 | 支持通过模块扩展功能(如HTTP/2、gzip、SSL等); |
热部署 | 支持不重启服务更新配置或升级版本; |
高可靠性 | 广泛用于企业级应用,稳定性极高。 |
1.3 主要功能
(1)Web 服务器
-
直接托管静态网站(HTML、CSS、JS、图片等);
-
支持 FastCGI(如PHP-FPM)运行动态内容;
(2)反向代理
-
隐藏后端服务器,提升安全性;
-
实现负载均衡(轮询、IP Hash、最少连接等算法);
(3)负载均衡
-
将网络流量分配到后端多个服务器上,提高应用的可用性、可靠性和性能;
-
主要负载均衡几种算法:
-
轮询(Round Robin) - 默认方法,按顺序将请求分配给服务器;
-
加权轮询(Weighted Round Robin) - 根据服务器权重分配请求;
-
最少连接(Least Connections) - 将请求发送到当前连接数最少的服务器;
-
加权最少连接(Weighted Least Connections) - 考虑权重的least_conn;
-
IP哈希(IP Hash) - 基于客户端IP地址分配请求,保证同一IP总是访问同一服务器;
-
通用哈希(Generic Hash) - 基于任意关键字(如URL、参数等)进行哈希分配。
-
(4)HTTP 缓存
-
缓存动态内容,减轻后端压力;
(5)HTTPS 终端
-
集中管理 SSL/TLS 证书(如Let's Encrypt)。
1.4 Nginx vs Apache
对比项 | Nginx | Apache HTTPD |
---|---|---|
架构 | 事件驱动、异步非阻塞 | 多线程/多进程 |
并发能力 | 极高(适合高并发) | 较低(依赖 prefork) |
静态文件性能 | 更快(零拷贝优化) | 较慢 |
动态内容 | 需配合 FastCGI | 原生支持(如 mod_php) |
配置方式 | 简洁直观 | .htaccess 复杂 |
1.5 应用场景
Nginx 的 Web服务、反向代理、负载均衡及前端业务数据缓存这几项功能是国内使用 Nginx 的主要场景, 特别是Web服务和反向代理及负载均衡
-
Web服务
Nginx本身是一个静态资源服务器; 当只有静态资源时, 使用 Nginx 做服务器; 当然nginx也可结合其它服务实现动静分离(如Apache、PHP-FPM、tomcat等);
-
FTP服务
通常会提供一个上传的功能, 其它应用若需要静态资源就可从该静态服务器中获取;
-
反向代理
反向代理(Reverse Proxy)方式是指代理服务器来接收 Inter 上的连接请求, 然后将请求转发到内部服务器, 并将从服务器上得到的结果返回给 Inter 上请求连接的客户端, 此时代理服务器对外就表现为一个反向代理服务器;
-
负载均衡
负载均衡是 Nginx 常用的一个功能, 是将请求分摊到多个操作单元上进行执行, 从而共同完成工作任务;
-
前端业务数据缓存
在 Web 缓存服务方面, nginx可通过自身的 proxy_cache 模块实现类 Squid 等专业缓存软件的功能;
1.6 Web 服务选择
在实际工作中, 需要根据业务需求来选择合适的业务服务软件, 有关Web服务,有以下建议
-
静态业务 : 若是高并发场景, 尽量采用 Nginx或Lighttpd, 首选 Nginx;
-
动态业务 : 理论上采用 Nginx和Apache 均可, 建议选择Nginx, 为了避免相同业务的服务软件多样化, 增加额外维护成本; 动态业务可以由nginx做前端代理, 再根据页面元素的类型或目录, 转发到后端对应的服务器进行处理;
-
既有静态又有动态业务 : 采用 Nginx
-
若并发量不是很大, 又对Apache很熟悉, 采用Apache也是可以的, Apache2.4版本也很强大, 并发连接数也有所增加;
-
总体来说, 在满足需求的前提下, 首选最擅长的软件, 若发现更好的软件, 可在掌握之后逐步替换, 虽然动态和静态业务都倾向于Nginx, 但前提是熟练掌握nginx;
切记, 在工作中不要盲目选择软件, 可能最终会导致自己无法控制的就按, 从而给企业带来灾难性的损失
2. Nginx 部署
2.1 Nginx 源码部署
2.1.1 源码部署
配置epel yum仓库
$ wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-8.repo
安装依赖包
$ yum -y install pcre-devel openssl-devel gcc gcc-c++ make
下载源码包安装
# -*- 官网下载分为三类:
# (Mainline version/Stable version/Legacy version)
# 主线版本/稳定版本/历史版本, 使用稳定版
$ wget -P /usr/local/src http://nginx.org/download/nginx-1.24.0.tar.gz
# -*- 创建运行用户
$ groupadd -r nginx
$ useradd -r -s /sbin/nologin -M nginx
# -*- 解压cd /usr/local/src
$ tar xf nginx-1.24.0.tar.gz -C /usr/local/src
# -*- 预配置、编译、安装cd nginx-1.24.0
$ ./configure --user=nginx --group=nginx --prefix=/usr/local/nginx/ --with-http_stub_status_module --with-http_ssl_module
$ make && make install
# -*- 环境变量中添加 nginx 命令
# 可以做软连接
$ ln -s /usr/local/nginx/sbin/nginx /usr/local/sbin/
# 也可以修改 /etc/profile 或 ~/.bash_profifle 修改 PATH 变量
PATH=/usr/local/nginx/sbin/nginx:$PATH
2.1.2 重新编译添加模块
Step 1,查看 nginx 配置参数
# -*- 作用
# 1. 检查所有模块是否已安装;
# 2. 将 configure arguments 后的参数复制并保存,重新编译时还需将这些模块添加;
$ nginx -V
nginx version: nginx/1.24.0
built by gcc 4.8.5 20150623 (Red Hat 4.8.5-44) (GCC)
built with OpenSSL 1.0.2k-fips 26 Jan 2017
TLS SNI support enabled
configure arguments: --prefix=/usr/local/nginx --user=nginx --group=nginx --with-http_stub_status_module --with-http_ssl_module
Step 2,清除历史编译
# -*- 进入 Nginx 源码包目录下,执行以下指令清除历史编译;
$ cd /usr/local/src/nginx-1.24.0
$ make clean
rm -rf Makefile objs
Step 3,添加所需模块
-
可通过 ./configure --help 查看需要的参数;
-
也可访问 nginx官网 查看;
Step 4,预配置并编译
# -*- 预配置进行添加新的模块
$ ./configure --user=nginx --group=nginx \
--prefix=/usr/local/nginx/ \
--with-http_stub_status_module \
--with-http_ssl_module \
--with-http_gzip_static_module
# -*- 编译,因为已经安装过 nginx,这里只需 make 无需 make install
$ make
Step 5,停止并备份nginx可执行文件
# -*- 停止 Nginx
$ nginx -s stop
# -*- 备份 nginx 可执行文件
$ cp /usr/local/nginx/sbin/nginx /tmp/
Step 6,覆盖可执行程序
$ cd /usr/local/src/nginx-1.24.0/objs
$ cp nginx /usr/local/nginx/sbin/
Step 7,查看 nginx 参数
$ nginx -V
2.1.3 开机启动
配置开机启动文件路径为:
/usr/lib/systemd/system/
/lib/systemd/system
$ cd /usr/lib/systemd/system
$ vim nginx.service
[Unit]
Description=nginx server daemon
After=network.target
[Service]
Type=forking
ExecStart=/usr/local/sbin/nginx
ExecReload=/usr/local/sbin/nginx -s reload
ExecStop=/usr/local/sbin/nginx -s quit
PrivateTmp=true
[Install]
WantedBy=multi-user.target
[Unit]
-
Description: 描述服务
-
After: 描述服务类别
[Service] 服务运行参数设置
-
Type=forking: 后台运行形式
-
ExecStart: 服务的具体运行命令
-
ExecReload: 重启命令
-
ExecStop: 停止命令
-
PrivateTmp=True: 表示给服务分配独立的临时空间
-
启动、重启、停止要使用绝对路径
[Install]
-
运行级别下服务安装的相关设置, 可设置为多用户, 即系统运行级别为3
2.1.4 防火墙配置
关闭防火墙
$ systemctl disable firewalld --now
临时添加策略
# -*- 添加 httpd 服务
$ firewall-cmd --add-service=http
# -*- 添加指定端口
$ firewall-cmd --add-port=66/tcp --add-port=88/tcp
永久添加策略
# -*- 添加 httpd 服务
$ firewall-cmd --permanent --add-service=http
$ firewall-cmd --reload
# -*- 添加指定端口
$ firewall-cmd --permanent --add-port=66/tcp --add-port=88/tcp
$ firewall-cmd --reload
2.2 Nginx yum部署
Step 1,安装必要组件
$ yum -y install yum-utils
Step 2,创建nginx的yum仓库
# -*- $releasever 需要更改为系统的版本号
$ vim /etc/yum.repos.d/nginx.repo
[nginx-stable]
name=nginx stable repo
baseurl=http://nginx.org/packages/centos/$releasever/$basearch/
gpgcheck=1
enabled=1
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true
[nginx-mainline]
name=nginx mainline repo
baseurl=http://nginx.org/packages/mainline/centos/$releasever/$basearch/
gpgcheck=1
enabled=0
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true
Step 3,安装nginx
# -*- 默认使用稳定版本,若想使用主线版本执行下面命令,否则直接执行安装
$ yum-config-manager --enable nginx-mainline
# -*- 安装
$ yum -y install nginx
2.3 目录结构
├── nginx.conf # 主配置文件 ├── conf.d/ # 通用配置片段 │ ├── gzip.conf # 压缩配置 │ ├── security.conf # 安全配置 │ └── proxy_defaults.conf # 代理默认设置 ├── sites-available/ # 可用站点配置 │ ├── example.com.conf │ └── api.example.com.conf ├── sites-enabled/ # 启用的站点(符号链接) ├── modules/ # 动态模块 ├── ssl/ # SSL证书 └── snippets/ # 可复用配置片段
3. 配置文件
Nginx 使用纯文本格式的配置文件,通常位于
/etc/nginx
目录下,主配置文件为nginx.conf
;Nginx 的配置采用模块化的层级结构,具有清晰的语法规则。
3.1 配置文件结构
基本结构
-
Nginx 配置文件由指令和块组成:
-
指令:由名称和参数组成,以分号(;)结尾
-
块:用大括号({})包裹的一组指令,也称为上下文(context)
-
主要配置块
# -*- 全局上下文(main context)
user nginx;
worker_processes auto;
events {
# 事件处理配置
}
http {
# HTTP 服务器配置
server {
# 虚拟主机配置
location {
# URL 路径配置
}
}
}
文件组织建议
-
主配置文件:
/etc/nginx/nginx.conf
-
额外配置:
/etc/nginx/nginx.d/ 目录
-
虚拟主机:
/etc/nginx/sites-available/ 和 /etc/nginx/sites-enabled/
-
日志文件:
/var/log/nginx
3.2 核心配置
-
全局配置
user nginx; # 运行 nginx 的用户和组; worker_processes auto; # 工作进程数(通常设置为 CPU 核心数); error_log /var/log/nginx/error.log warn; # 错误日志路径及级别; pid /run/nginx.pid; # 存储主进程 PID 的文件;
-
events 块
events { worker_connections 1024; # 每个 worker 进程的最大连接数; use epoll; # 事件处理模型(Linux 推荐 epoll); multi_accept on; # 允许同时接收多个连接; }
-
http 块
http { include mime.type; # 包含 MIME 类型定义文件; default_type application/octet-stream; # 默认 MIMIE 类型; log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log /var/log/nginx/access.log main; # 访问日志配置; sendfile on; # 启用高效文件传输模式; tcp_nopush on; # 优化网络数据包发送; keepalive_timeout 65; # 保持连接的超时时间; }
3.3 server 块配置
-
基本虚拟主机
server { listen 80; # 监听端口; server_name example.com; # 域名 root /var/www/html; # 网站根目录; index index.html index.htm; # 默认首页文件; location / { try_files $uri $uri/ =404; # $uri 尝试直接匹配请求的 URI 对应的文件; # $uri/ 若上一步失败,尝试将该 URI 作为目录处理; # =404 若前两步都失败,返回 404 错误; # =404 也可替换成其它类型,如后端应用服务器; } }
-
常用指令
-
listen:监听端口(可加IP地址)
-
server_name:域名(支持通配符和正则)
-
root:网站根目录
-
index:默认首页文件
-
error_page:自定义错误页面
-
3.4 location 块配置
Nginx 的
location
指令是配置服务器如何处理不同 URI 请求的核心部分;根据请求的 URI 定义不同的处理规则。
3.4.1 基本语法
location [修饰符] 匹配模式 {
# 配置指令
}
3.4.2 匹配修饰符
Nginx 提供了几种不同的匹配修饰符:
-
无修饰符--前缀匹配
location /images/ { # 匹配以 /images/ 开头的所有 URI }
-
=
精准匹配location = /exact/match { # 只匹配 /exact/match 这个精准 URI }
-
~
区分大小写的正则匹配location ~ \.php$ { # 匹配以 .php 结尾的 URI,区分大小写 }
-
~*
不区分大小写的正则匹配location ~* \.(jpg|jpeg|png|gif)$ { # 匹配图片文件扩展名,不区分大小写 }
- **^~ 优先前缀匹配**
location ^~ /static/ { # 匹配以 /static/ 开头的 URI,且优先于正则匹配 }
3.4.3 匹配优先级
-
精准匹配(
=
) 最高优先级,找到后立即停止搜索; -
优先前缀匹配(
^~
) 检查所有非正则的前缀匹配,选择最长的匹配; 若找到^~
匹配则停止搜索; -
正则匹配(
~ 或 ~*
) 按配置文件中的顺序检查正则匹配; 第一个匹配的正则表达式会被使用; -
普通前缀匹配 若没有上述匹配,使用最长的前缀匹配。
3.4.4 匹配测试
配置文件
server {
listen 80;
server_name location.tzhry.com;
root /var/www/html/location;
location / {
return 401;
}
location = / {
return 402;
}
location = /images/ {
return 501;
}
location /documents/ {
return 403;
}
location ^~ /images/ {
return 404;
}
location ~* \.(gif|jpg|jpeg)$ {
return 500;
}
}
访问匹配结果
# -*- 重新加载 nginx 配置文件
$ nginx -t && systemctl reload nginx
# -*- 访问测试
$ curl -s -o /dev/null -w "%{http_code}\n" location.tzhry.com
402 # 匹配 =
$ curl -s -o /dev/null -w "%{http_code}\n" location.tzhry.com/
402 # 匹配 =
$ curl -s -o /dev/null -w "%{http_code}\n" location.tzhry.com/123
401 # 匹配不到, 默认匹配 /
$ curl -s -o /dev/null -w "%{http_code}\n" location.tzhry.com/documents/
403 # 匹配字符串
$ curl -s -o /dev/null -w "%{http_code}\n" location.tzhry.com/images/
501 # 优先匹配 =
$ curl -s -o /dev/null -w "%{http_code}\n" location.tzhry.com/images/t.png
404 # 配置^~, 停止匹配
$ curl -s -o /dev/null -w "%{http_code}\n" location.tzhry.com/documents/images/t.jpg
500 # 匹配 ~*
3.4.5 常用配置示例
1. 静态文件处理
location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
expires 30d;
access_log off;
add_header Cache-Control "public";
root /var/www/static;
}
2. PHP 处理
location ~ \.php$ {
try_files $uri =404;
fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
3. 重定向规则
location /old/ {
return 301 /new/;
}
location = /special-page {
rewrite ^ /new-special-page permanent;
}
4. 代理设置
location /api/ {
proxy_pass http://backend-server;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
3.4.6 高级配置
1. 嵌套 location
location / {
# 主配置
location /images/ {
# 专门处理/images/下的请求
}
location ~ \.php$ {
# 处理PHP文件
}
}
2. try_files 指令
location / {
try_files $uri $uri/ /index.php?$query_string;
}
3. location (@)
location / {
try_files $uri @fallback;
}
location @fallback {
proxy_pass http://backend;
}
3.5 基础配置示例
-
静态网站
server { listen 80; server_name example.com; root /var/www/example; index index.html; location / { try_files $uri $uri/ =404; } }
-
反向代理
server { listen 80; server_name example.com; location / { proxy_pass http://localhost:3000; proxy_set_header Host $host; proxy_set_header X-Real_IP $remote_addr; } }
3.6 规范配置文件(重点)
-
配合使用 extra 目录的子配置文件,采用模块化设计思想,便于维护和管理;
核心目录结构
├── nginx.conf # 主配置文件 ├── conf.d/ # 标准配置片段(兼容默认习惯) ├── extra/ # 扩展子配置文件目录(自定义) │ ├── gzip.conf # 压缩配置 │ ├── security.conf # 安全相关配置 │ ├── proxy.conf # 反向代理通用配置 │ ├── php-fpm.conf # PHP处理配置 │ ├── ssl/ # SSL证书配置目录 │ │ └── example.com.conf │ └── vhosts/ # 虚拟主机配置目录 │ ├── static.conf # 静态站点配置 │ └── api.conf # API服务配置 └── snippets/ # Nginx官方推荐配置片段目录
主配置文件(nginx.conf)规范
# -*- 全局块
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
# -*- 动态加载模块(如有需要)
# load_module modules/ngx_http_geoip_module.so;
events {
worker_connections 1024;
multi_accept on;
}
http {
# -*- 基础配置
include /etc/nginx/mime.types;
default_type application/octet-stream;
charset utf-8;
# -*- 日志格式
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
# -*- 引入扩展配置
include /etc/nginx/extra/gzip.conf; # Gzip压缩配置
include /etc/nginx/extra/security.conf; # 安全头配置
include /etc/nginx/extra/proxy.conf; # 反向代理通用配置
# -*- 虚拟主机配置(通过extra目录管理)
include /etc/nginx/extra/vhosts/*.conf; # 静态站点
include /etc/nginx/extra/ssl/*.conf; # HTTPS站点
}
子配置文件规范示例
-
Gzip 配置(extra/gzip.conf)
# -*- 压缩配置 gzip on; gzip_vary on; gzip_proxied any; gzip_comp_level 6; gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript; gzip_min_length 1024;
-
安全配置(extra/security.conf)
# -*- 安全头 add_header X-Frame-Options "SAMEORIGIN"; add_header X-Content-Type-Options "nosniff"; add_header X-XSS-Protection "1; mode=block"; add_header Referrer-Policy "strict-origin-when-cross-origin"; # -*- 禁用服务器标记 server_tokens off; # -*- 限制HTTP方法 if ($request_method !~ ^(GET|HEAD|POST)$ ) { return 405; }
-
虚拟主机配置(extra/vhosts/static.conf)
server { listen 80; server_name tzhry.com; root /var/www/static; index index.html; # 静态资源缓存 location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ { expires 365d; access_log off; add_header Cache-Control "public"; } # 禁止访问隐藏文件 location ~ /\. { deny all; access_log off; log_not_found off; } # 错误页面 error_page 404 /404.html; }
-
HTTPS配置(extra/ssl/tzhry.com.conf)
server { listen 443 ssl http2; server_name tzhry.com; # SSL证书路径 ssl_certificate /etc/nginx/extra/ssl/tzhry.com/fullchain.pem; ssl_certificate_key /etc/nginx/extra/ssl/tzhry.com/privkey.pem; # SSL优化配置 include /etc/nginx/snippets/ssl-params.conf; # 官方推荐SSL配置片段 # 强制HTTPS跳转(如需) if ($scheme != "https") { return 301 https://$host$request_uri; } # 其他业务逻辑... }
4. 虚拟主机
4.1 概念
虚拟主机(Virtual Host)是指 在单一服务器上托管多个网站 的技术,每个网站有独立的域名和配置,但对用户透明,看起来像是运行在不同的服务器上;
节省服务器资源,降低运维成本;
这个独立的站点在配置里由一定格式的标签段标记, 对于 Apache 来说, 一个虚拟主机的标签段通常被包含在 VirtualHost{...} 内;而 Nginx 则使用一个 Server{...} 标签来标识一个虚拟主机, 一个Web服务里可有多个虚拟主机标签对, 即同时可支持多个虚拟主机站点。
4.2 类型
三种虚拟主机类型均可独立使用, 也可混合使用, 重点是基于域名的虚拟主机。
基于域名的虚拟主机
通过不同的域名区分不同的虚拟主机,基于域名的虚拟主机是企业应用最多的类型,几乎所有对外提供服务的网站都是使用基于域名的虚拟主机, 如www.baidu.com;
基于端口的虚拟主机
通过不同的端口区分不同的虚拟主机,此类虚拟主机对应的企业应用主要为公司内部的网站;如一些不希望直接对外提供用户访问的网站后台等,访问基于端口的虚拟主机地址里要带端口号,如http://www.baidu.com:8080;
基于 IP 的虚拟主机
通过不同的IP区分不同的虚拟主机,此类虚拟主机对应的企业应用很少,一般不同业务需要使用多IP的场景都会在负载均衡器上进行 VIP 绑定,而不是在 Web 上通过绑定 IP 区分不同的虚拟主机。
4.3 基于域名虚拟主机
Step 1,修改主配置文件
user nginx;
worker_processes auto;
error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;
pid logs/nginx.pid;
events {
worker_connections 1024;
use epoll;
}
http {
include mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log logs/access.log main;
gzip on;
sendfile on;
tcp_nopush on;
keepalive_timeout 65;
types_hash_max_size 2048;
# 引入扩展配置
include extra/*.conf;
# 通过 extra 目录管理引入虚拟主机配置
include extra/vhosts/*.conf;
}
Step 2,创建对应 extra 目录
$ mkdir -p /usr/local/nginx/conf/extra/vhosts
Step 3,创建基于域名虚拟主机配置文件
$ vim /usr/local/nginx/conf/extra/vhosts/domain.conf
server {
listen 80;
server_name domain1.tzhry.com;
location / {
root html/domain1;
index index.html index.htm;
}
error_page 404 /404.html;
location = /40x.html {
root html;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
server {
listen 80;
server_name domain2.tzhry.com;
location / {
root html/domain2;
index index.html index.htm;
}
error_page 404 /404.html;
location = /40x.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}
Step 4,创建对应目录及测试文件
$ cd /usr/local/nginx/html
$ mkdir domain{1,2}
$ echo "<h1>This is Domain--1</h1>" > domain1/index.htm
$ echo "<h1>This is Domain--2</h1>" > domain2/index.html
Step 5,修改hosts文件映射
$ echo -e "10.99.156.4 www.domain1.com www.domain2.com" >> /etc/hosts
Step 6,检测配置文件并重启nginx
# -*- 检测配置
$ nginx -t
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful
# -*- 重启服务
$ sudo systemctl restart nginx
Step 7,访问测试
$ curl www.domain1.com
<h1>This is Domain--1</h1>
$ curl www.domain2.com
<h1>This is Domain--2</h1>
4.4 基于端口虚拟主机
Step 1,创建基于端口虚拟主机配置文件
$ vim /usr/local/nginx/conf/extra/vhosts/port.conf
server {
listen 66;
server_name 10.99.156.4;
location / {
root html/port1;
index index.html index.htm;
}
error_page 404 /404.html;
location = /40x.html{
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}
server {
listen 88;
server_name 10.99.156.4;
location /{
root html/port2;
index index.html index.htm;
}
error_page 404 /404.html;
location = /40x.html {
root html;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html{
root html;
}
}
Step 2,创建访问目录及文件
$ mkdir -p /usr/local/nginx/html/port{1,2}
$ echo -e "<h1>This is Port--66</h1>" > /usr/local/nginx/html/port/1/index.html
$ echo -e "<h1>This is Port--88</h1>" > /usr/local/nginx/html/port/2/index.htm
Step 3,检测配置文件并重启nginx
# -*- 检测配置
$ nginx -t
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful
# -*- 重启服务
$ systemctl restart nginx
Step 4,访问测试
$ curl 10.99.156.4:66
<h1>This is Port--66</h1>
$ curl 10.99.156.4:88
<h1>This is Port--88</h1>
4.5 基于IP虚拟主机
Step 1,实验中配置虚拟网卡
# -*- 临时配置虚拟网卡
$ sudo ifconfig ens32:1 10.99.156.110/24 up
# -*- ubuntu 永久配置
$ sudo vim /etc/network/interfaces
auto lo
iface lo inet loopback
auto ens32
iface ens32 inet static
address 10.99.156.4
gateway 10.99.156.2
netmask 255.255.255.0
auto ens32:1
iface ens32:1 inet static
address 10.99.156.110
gateway 10.99.156.2
netmask 255.255.255.0
$ sudo /etc/init.d/networking restart
# -*- CentOS 永久配置
$ vim /etc/sysconfig/network-scripts/ifcfg-ens32:1
TYPE=Ethernet
PROXY_METHOD=none
BROWSER_ONLY=no
BOOTPROTO=static
DEFROUTE=yes
IPV4_FAILURE_FATAL=no
NAME=ens32:1
UUID=3cf40564-4688-4493-af7d-ab2a6a6cd55c
DEVICE=ens32:1
ONBOOT=yes
IPADDR=10.99.156.110
NETMASK=255.255.255.0
GATEWAY=10.99.156.2
DNS1=8.8.8.8
DNS2=114.114.114.114
$ sudo systemctl restart netwok
# 重启网卡要是不生效的话, 需要重启服务器
Step 2,创建基于端口虚拟主机配置文件
$ vim /usr/local/nginx/conf/extra/vhosts/ip.conf
server {
listen 80;
server_name 10.99.156.4;
location / {
root html/ip_4;
index index.html index.htm;
}
error_page 404 /404.html;
location = /40x.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}
server {
listen 80;
server_name 10.99.156.110;
location /{
root html/ip_110;
index index.html index.htm;
}
error_page 404 /404.html;
location = /40x.html {
root html;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html{
root html;
}
}
Step 3,创建访问目录及文件
# -*- 创建项目目录
$ mkdir -pv /usr/local/nginx/html/ip_{4,110}
mkdir: created directory '/usr/local/nginx/html/ip'
mkdir: created directory '/usr/local/nginx/html/ip/4'
mkdir: created directory '/usr/local/nginx/html/ip/110'
# -*- 创建index文件
$ sh -c 'echo "<h1>This is 156.4</h1>" > /usr/local/nginx/html/ip_4/index.html'
$ echo "<h1>This is 156.110</h1>" |sudo tee /usr/local/nginx/html/ip_110/index.htm
<h1>This is 156.110</h1>
Step 4,检查配置文件并重启nginx服务
$ sudo nginx -t
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful
$ sudo systemctl restart nginx
Step 5,访问测试
$ curl 10.99.156.4
<h1>This is 156.4</h1>
$ curl 10.99.156.110
<h1>This is 156.110</h1>
5. 常用功能配置
5.1 压缩功能
5.1.1 Gzip 压缩
Gzip 压缩是 Nginx 提供的一项重要功能,能显著减少传输的数据量,提高网站性能。
Gzip 压缩工作原理
-
压缩流程
-
客户端发送带有
Accept-Encoding: gzip
的请求头; -
Nginx 检查配置决定是否压缩响应;
-
对符合条件的响应进行实时压缩;
-
返回带有
Content-Encoding: gzip
头的压缩内容; -
客户端解压并渲染内容。
-
-
压缩算法比较
算法 压缩率 CPU 消耗 Nginx 支持 gzip 中等 中等 是(默认) deflate 较低 低 是 br(Bortli) 最高 高 需要模块 zstd 很高 中 需要模块
基础配置指令
-
启用基本压缩
http { # 启用gzip压缩; gzip on; # 指定压缩类型; gzip_types text/plain text/css application/json; # 压缩级别(1-9); gzip_comp_level 6; }
-
完整配置参数
指令 默认值 说明 gzip off 压缩功能开关 gzip_comp_level 1 压缩级别(1~9) gzip_min_length 20 最小压缩文件大小(字节) gzip_types text/html 压缩的 MIME 类型 gzip_buffers 32 4k/8k 压缩缓冲区(数量 大小) gzip_proxied off 代理请求压缩策略 gzip_vary off 是否添加 Vary 头 gzip_disable - 禁用压缩的 UA 正则 gzip_http_version 1.1 最小 HTTP 版本
高级配置
-
智能压缩策略
http { gzip on; gzip_min_length 1024; # 只压缩大于1KB的文件 gzip_comp_level 5; # 平衡压缩率和CPU消耗 # 根据文件类型动态调整 location ~* \.(html|css|js)$ { gzip_comp_level 6; } location ~* \.(json|xml)$ { gzip_comp_level 3; } }
-
静态资源预压缩
http { gzip_static on; # 优先使用预生成的.gz文件 gzip_vary on; # 告知代理服务器有压缩版本 # 生成预压缩文件的命令示例: # find /var/www -type f -name "*.css" -exec gzip -k9 {} \; }
-
代理环境特殊处理
server { location / { proxy_pass http://backend; # 防止重复压缩 proxy_set_header Accept-Encoding ""; gzip_proxied any; # 解压后端已压缩内容 gunzip on; } }
性能优化建议
-
静态资源:6-9 级(可预压缩);
-
动态内容:3-5 级(平均 CPU 和压缩率);
-
API 响应:1-3 级(低延迟优先)。
问题排查
-
验证压缩是否生效
$ curl -I -H "Accept-Encoding: gzip" http://example.com/style.css # 检查返回头中是否有: Content-Encoding: gzip
-
CPU 使用率过高
gzip_comp_level 3; # 降低压缩级别 gzip_min_length 1024; # 增大最小压缩阈值
-
某些文件未压缩
-
检查文件类型是否在
gzip_types
中; -
确认文件大小是否超过
gzip_min_lenght
; -
检查
gzip_disable
规则。
-
-
代理服务器返回未压缩内容
proxy_set_header Accept-Encoding ""; gzip_proxied any;
5.5.2 Brotli 压缩
Brotli 是 Google 开发的一种现代压缩算法,相比 Gzip 能提供更高的压缩率(通常可提升 15~25%),特别适合文本内容的压缩。
Brotli 与 Gzip 的主要区别
-
压缩率:Brotli 通常比 Gzip 高 15-25%;
-
CPU 消耗:Brotli 压缩时 CPU 消耗略高于 Gzip;
-
浏览器支持:现代浏览器(Chrome、Firefox、Edgae、Safari等)都支持;
-
HTTP 支持:Brotli 仅支持 HTTPS 连接,需要 HTTPS 连接才能获得最佳支持。
安装 Brotli 模块
-
官方模块安装(推荐)
# 对于Debian/Ubuntu sudo apt-get install libnginx-mod-brotli # 对于CentOS/RHEL sudo yum install nginx-module-brotli
-
源码编译安装
# -*- 克隆 ngx_brotli 仓库 $ git clone https://github.com/google/ngx_brotli.git $ cd ngx_brotli $ git submodule update --init # 初始化子模块 # 注意:若 git submodule 失败(如国内网络问题),可手动下载 Brotli 子模块并放入 deps/brotli 目录; # -*- 安装 cmake,需要 cmake 3版本以上 $ yum -y install epel-release $ yum -y install cmake3 $ ln -s /usr/bin/cmake3 /usr/bin/cmake # -*- 编译 Nginx 时添加模块 $ cd deps/brotli $ mkdir out && cd out $ cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF .. $ make $ make install # 安装到系统库路径(如 /usr/local/lib) $ ldconfig # 更新库缓存 # -*- 重新编译 Nginx $ nginx -s stop $ cd /usr/local/src/nginx-1.24.0 $ make clean $ ./configure --user=nginx --group=nginx \ --prefix=/usr/local/nginx/ \ --add-module=/usr/local/src/ngx_brotli/ \ --with-http_stub_status_module \ --with-http_ssl_module \ --with-http_gzip_static_module $ make $ cp /usr/local/nginx/sbin/nginx /tmp $ cp objs/nginx /usr/local/nginx/sbin/ $ nginx -V nginx version: nginx/1.24.0 built by gcc 4.8.5 20150623 (Red Hat 4.8.5-44) (GCC) built with OpenSSL 1.0.2k-fips 26 Jan 2017 TLS SNI support enabled configure arguments: --user=nginx --group=nginx --prefix=/usr/local/nginx/ --add-module=/usr/local/src/ngx_brotli/ --with-http_stub_status_module --with-http_ssl_module --with-http_gzip_static_module
启动基本 Brotli 压缩
http {
# 启用Brotli压缩
brotli on;
# 压缩级别(1-11,6是推荐值)
brotli_comp_level 6;
# 最小压缩文件大小
brotli_min_length 256;
# 指定压缩的MIME类型
brotli_types
text/plain
text/css
text/xml
text/javascript
application/javascript
application/json
application/xml
application/xml+rss
application/atom+xml
image/svg+xml
font/ttf
font/otf
font/woff
font/woff2;
brotli_static on; # 启用预压缩文件支持;
}
配置参数解释
指令 | 默认值 | 说明 |
---|---|---|
brotli | off | Brotli 压缩开关 |
brotli_comp_level | 6 | 压缩级别(1-11) |
brotli_min_length | 256 | 最小压缩文件大小(字节) |
brotli_types | text/html | 压缩的 MIME 类型 |
brotli_buffers | 32 4k/8k | 压缩缓冲区 |
brotli_window | 512k | 滑动窗口大小 |
brotli_static | off | 预压缩文件支持 |
性能优化建议
-
静态资源:使用级别 9-11 预压缩;
-
动态内容:使用级别 4-6 实时压缩;
-
API 响应:使用级别 3-5 平衡性能;
5.2 状态信息功能
Step 1,首选确认编译时是否加载了此模块
$ which nginx
/usr/local/sbin/nginx
$ nginx -V
nginx version: nginx/1.24.0
built by gcc 4.8.5 20150623 (Red Hat 4.8.5-44) (GCC)
built with OpenSSL 1.0.2k-fips 26 Jan 2017
TLS SNI support enabled
configure arguments: --user=nginx --group=nginx --prefix=/usr/local/nginx --add-module=/usr/local/src/ngx_brotli/ --with-http_stub_status_module --with-http_ssl_module
# -*- 说明
--with-http_stub_status_module 为状态信息模块
Step 2,设定信息模块配置
-
状态信息模块配置方式和搭建虚拟网站类似,需要占用一个域名来访问
; -
需要重启 Nginx 服务
$ vim /usr/local/nginx/conf/extra/status.conf server { listen 80; server_name status.tzhry.com; location / { stub_status on; # 开启状态信息功能; access_log off; # 不记录访问日志; } }
Step 3,检查配置并重启服务
# -*- 检查配置
$ nginx -t
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful
# -*- 重启服务
$ systemctl restart nginx
Step 4,添加 hosts 映射
# -*- 上面实验已经添加过 10.99.156.4 映射;
$ sed -i '/10.99.156.4/s/$/ status.tzhry.com/' /etc/hosts
# 若是新的服务器进行操作,使用 echo 命令
$ echo "10.99.156.4 status.tzhry.com" >> /etc/hosts
Step 5,访问查看结果
$ curl status.tzhry.com
Active connections: 1
server accepts handled requests
9 9 16
Reading: 0 Writing: 1 Waiting: 0
# -*- 说明
Active connections: # Nginx 正在处理的活动连接数;
server: # Nginx 启动到现在共处理了多少个连接;
accepts: # Nginx 启动到现在共成功创建多少次握手;
请求丢失数 = 握手数 - 连接数 # 可看出本次状态显示没有丢失请求;
handle requests: # 共处理了多少次请求;
Reading: # Nginx 读取到客户端的 Header 信息数;
Writing: # Nginx 返回客户端的 Header 信息数;
Waiting: # Nginx 已经处理完正在等候下一次请求指令的驻留连接,
# 在开启 keep-alive 的情况下,这个值等于:active - (reading + writing);
# -*- 注意,为了安全,这个状态信息要防止外部用户查看。
5.3 增加错误日志
-
常见的日志级别:
-
debug、info、notice、warn、error、crit、alter、emerg;
-
-
生产场景一般是 warn、error、crit 三个级别之一,注意不要配置 info 等较低级别,会带来巨大磁盘 I/O 消耗;
-
error_log 的默认值为:
default: error_log logs/error.log error;
$ vim /usr/local/nginx/conf/nginx.conf
user nginx;
worker_processes auto;
error_log logs/error.log; # 默认 error 级别;
#error_log logs/error.log notice; # 可指定日志级别;
#error_log logs/error.log info;
... ...
5.4 访问目录功能
Step 1,创建配置文件
$ vim /usr/local/nginx/conf/extra/folder.conf
server {
listen 80 default_server;
server_name folder.tzhry.com;
location / {
# 开启目录浏览功能;
autoindex on;
# 详细文件大小统计,显示MB,GB单位;
autoindex_exact_size off;
# 服务器本地时区显示文件修改日期;
autoindex_localtime on;
# 指定实际目录的绝对路径;
root /media/cdrom;
}
}
Step 2,创建目录及文件
$ mkdir -pv /media/cdrom
# 可挂载镜像文件,也可上传文件到上面的目录中;
# -*- 挂载镜像文件
$ ls /usr/local/src
CentOS-7-x86_64-DVD-2009.iso
$ mount -t iso9660 CentOS-7-x86_64-DVD-2009.iso /media/cdrom/
Step 3,重启nginx
$ nginx -t
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful
$ systemctl restart nginx
Step 4,访问测试
$ curl folder.tzhry.com |sed 's/<[^>]*>//g'
EFI/ 27-Oct-2020 00:25 -
LiveOS/ 27-Oct-2020 00:25 -
Packages/ 04-Nov-2020 19:30 -
images/ 27-Oct-2020 00:26 -
isolinux/ 03-Nov-2020 00:17 -
repodata/ 04-Nov-2020 19:35 -
CentOS_BuildTag 30-Oct-2020 05:14 14
EULA 30-Aug-2017 22:33 227
GPL 10-Dec-2015 06:35 18K
RPM-GPG-KEY-CentOS-7 10-Dec-2015 06:35 1690
RPM-GPG-KEY-CentOS-Testing-7 10-Dec-2015 06:35 1690
TRANS.TBL 04-Nov-2020 19:36 2883
5.5 日志轮询切割
默认情况下,Nginx 会将所有的访问日志生成到一个指定的访问日志文件 access.log 里,这样的话时间长了就会导致日志文件很大,不利于日志的分析和处理;因此有必要对 Nginx 日志按天或按小时进行切割,将其分割成不同的文件保存。
5.5.1 使用 logrotate(推荐)
logrotate 是 Linux 系统自带的日志管理工具,配置简单可靠;
Step 1,创建 logrotate 配置文件 /etc/logrotate.d/nginx
$ vim /etc/logrotate.d/nginx
/usr/local/nginx/logs/*.log {
daily
missingok
rotate 14
dateext
dateformat -%Y-%m-%d
compress
delaycompress
notifempty
create 0640 nginx nginx
sharedscripts
postrotate
if [ -f /usr/local/nginx/logs/nginx.pid ]; then
kill -USR1 `cat /usr/local/nginx/logs/nginx.pid`
fi
endscript
}
# postrotate
# ... ...
# endscript
# 这部分内容为 通知 Nginx 重新打开日志;
Step 2,测试配置
# -*- 模拟运行,不实际执行
$ logrotate -d /etc/logrotate.d/nginx
# -*- 强制立即运行
$ logrotate -vf /etc/logrotate/nginx
Step 3,结合 cron自动切割
$ crontab -e
01 00 * * * /usr/sbin/logrotate -f /etc/logrotate.d/nginx
Step 4,调试技巧
-
查看执行记录
$ cat /var/lib/logrotate/logrotate.status
-
检查 cron 任务
$ grep 'logrotate' /etc/cron*
5.5.2 脚本 + cron
脚本配合 crontab 定时任务实现
Step 1,编写脚本
$ vim /usr/local/nginx/sbin/cut_log.sh
#!/bin/bash
DateFormat=$(date +%F)
BaseDir="/usr/local/nginx"
NginxLogDir="$BaseDir/logs"
LogName="access"
[ -d $NginxLogDir ] && cd $NginxLogDir || exit 1
[ -f ${LogName}.log ] || exit 2
/bin/mv ${LogName}.log ${DateFormat}_${LogName}.log
$Basedir/sbin/nginx -s reload
Step 2,配置定时任务
$ cat >> /var/spool/cron/root << EOF
> 00 00 * * * /bin/bash /opt/shell/cut_nginx_log.sh >/dev/null 2>&1
> EOF
5.5.3 nginx的 time_iso8601 变量
Nginx 内置的
time_iso8601
变量可以用于实现更灵活的日志切割方案,无需依赖外部工具(如 logrotate);这种方式直接在 Nginx 配置中实现日志按时间分割,更加高效和可靠。
基本原理
-
time_iso8601 变量提供 ISO 8601 格式的时间戳(如 2024-01-01T12:00:00+00:00);
-
通过正则表达式提取其中的 年、月、日等信息,然后动态生成日志文件名。
配置方法
-
1. 基本配置
$ vim /usr/local/nginx/conf/nginx.conf ... ... http { # 定义日志格式 log_format main '$remote_addr - $remote_user [$time_iso8601] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; # 设置时间变量 map $time_iso8601 $logdate { '~^(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})' "${year}${month}${day}"; default 'nodate'; } server { listen 80; server_name example.com; # 使用动态日志文件名 access_log /var/log/nginx/access-${logdate}.log main; error_log /var/log/nginx/error-${logdate}.log; # 其他服务器配置... } ... ...
-
2. 高级配置(按小时分割)
$ vim /usr/local/nginx/conf/nginx.conf ... ... http { # 提取年月日小时 map $time_iso8601 $loghour { '~^(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})T(?<hour>\d{2})' "${year}${month}${day}${hour}"; default 'nodate'; } server { # ... access_log /var/log/nginx/access-${loghour}.log main; # ... } } ... ...
-
3. 完整日期格式配置
$ vim /usr/local/nginx/conf/nginx.conf ... ... map $time_iso8601 $logdate { '~^(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})' "${year}-${month}-${day}"; default 'nodate'; } server { access_log /var/log/nginx/access-${logdate}.log main; } ... ...
机制说明
-
map 指令 创建一个新变量 $logdate,通过正则表达式从 $time_iso8601 提取日期部分;
-
正则表达式 ~^(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2}) 匹配并捕获年月日;
-
~^
:正则表达式开始标记(~
是特定语言中的模式修饰符,^
表示匹配字符串开头) -
(?<year>\d{4})
:命名捕获组year
,匹配 4 位数字(年份) -
-
:匹配字面量连字符-
-
(?<month>\d{2})
:命名捕获组month
,匹配 2 位数字(月份) -
-
:匹配字面量连字符-
-
(?<day>\d{2})
:命名捕获组day
,匹配 2 位数字(日))
-
-
变量引用 在 access_log 指令中使用 ${logdate} 动态生成日志文件名。
优势与特点
-
无外部依赖:不依赖 logrotate 或 cron;
-
及时生效:新日志文件自动创建,无需重载配置;
-
更精准控制:可以按小时、日、月等任意时间粒度分割;
-
无服务中断:不需要向 Nginx 发送信号。
维护过程
-
日志清理:仍需设置定期清理旧日志的 cron 任务
$ crontab -e # 删除 30 天前的日志 0 1 * * * find /usr/local/nginx/logs -name "*.log" -mtime +30 -exec rm -f {} \;
-
文件权限:确保 Nginx 工作进程有权限创建新日志文件
-
监控磁盘:高流量站点仍需监控日志磁盘使用情况
注意事项
-
每个新时间周期(如新的一天)会自动创建新文件,但不会压缩或删除旧文件;
-
对于非常高频的日志写入,文件系统性能可能成为瓶颈;
-
某些旧版本 Nginx 可能会对变量支持不完全。
5.5.4 三种方案对比
特性 | logrotate | time_iso8601 | 脚本 |
---|---|---|---|
实现方式 | 外部工具 | 内置功能 | 编写脚本 |
切割粒度 | 通常按天/周/日 | 灵活(可精确到毫秒) | 灵活(可精确到秒) |
是否需要信号通知 | 是(USR1信号) | 否 | 是 |
旧日志处理 | 内置压缩和删除 | 需额外清理脚本 | 需自行实现 |
适用场景 | 大多数通用场景 | 高精度需求环境 | 大多数通用场景 |
性能影响 | 定时 I/O 压力 | 持续文件创建开销 | 切割时瞬时 I/O 压力 |
调试难度 | 中等(依赖 logrotate 状态) | 较难(Nginx 内部处理) | 较容易(日志明确) |
5.6 实现 HTTPS 功能
HTTPS 是通过 SSL/TLS 加密的 HTTP 协议,能够保护网站数据传输的安全。
5.6.1 获取 SSL 证书
方式1:从证书颁发机构(CA)获取
-
推荐使用 Let's Encrypt 免费证书
# -*- 安装 cerbot $ apt install certbot python3-certbot-nginx # certbot:Let's Encrypt 的官方客户端; # python3-certbot-nginx:Certbot 的 Nginx 插件,用于自动配置 SSL; # -*- 获取证书(将 example.com 替换为自己的域名) $ certbot --nginx --nginx-server-root=/usr/local/nginx/conf \ --nginx-ctl=/usr/local/nginx/sbin/nginx \ -d example.com -d www.tzhry.com # --nginx-server-root Nginx 配置目录(默认 /etc/nginx) # --nginx-ctl Nginx 可执行文件路径(默认 /usr/sbin/nginx) # -d 指定域名(可多个)
方式2:自签名证书(仅用于测试)
# -*- 生成私钥
$ openssl genrsa -out server.key 2048
# -*- 生成证书签名请求(CSR)
$ openssl req -new -key server.key -out server.csr
# -*- 生成自签名证书(有效期 365 天)
$ openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt
5.6.2 nginx 配置
基本配置
$ vim /usr/local/nginx/conf/extra/ssl.conf
server {
listen 443 ssl;
server_name tzhry.com www.tzhry.com;
ssl_certificate /path/to/server.crt;
ssl_certificate_key /path/to/server.key;
... ...
}
增强安全性配置
$ vim /usr/local/nginx/conf/extra/ssl.conf
server {
listen 443 ssl http2;
server_name tzhry.com www.tzhry.com;
ssl_certificate /path/to/server.crt;
ssl_certificate_key /path/to/server.key;
# 启用会话缓存
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
# 安全协议和加密套件
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256';
ssl_prefer_server_ciphers on;
# 启用 HSTS
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload";
... ...
}
5.6.3 http 重定向到 HTTPS
$ vim /usr/local/nginx/conf/extra/www.conf
server {
listen 80;
server_name tzhry.com www.tzhry.com;
return 301 https://$server_name$request_uri;
}
5.6.4 证书自动续费
-
Let's Encrypt 证书有效期为 90 天,设置自动续期
# -*- 测试续期 $ certbot renew --dry-run # -*- 设置定时任务(每周检查续期) $ crontab -e # 添加以下内容 0 0 * * * /usr/bin/certbot renew --quiet && /bin/systemctl reload nginx
5.6.5 高级配置
OCSP Stapling
-
OCSP(Online Certificate Status Protocol),在线证书状态协议;
-
OCSP Stapling 允许 Web 服务器(如 Nginx)定期从证书颁发机构(CA)获取 OCSP 响应,并在 TLS 握手过程中将该响应“装订”(Staple)到服务器发送的证书中;
-
传统 OCSP 客户端直接向 CA 的 OCSP 服务器查询证书状态,OCSP Stapling 是由服务器代为查询并缓存响应,在握手时提供给客户端;
-
工作原理
-
Web 服务器定期向 CA 的 OCSP 服务器查询其证书的状态;
-
CA 返回一个带有时间戳的签名响应;
-
服务器缓存此响应(通常有效期为几天);
-
当客户端连接时,服务器在 TLS 握手期间提供此缓存的 OCSP 响应;
-
客户端验证响应的签名和时间有效性。
-
-
优势
-
提高性能:减少客户端直接查询 OCSP 服务器的延迟;
-
增强隐私:客户端无需向第三方暴露其访问的网站;
-
提高可靠性:减少对 CA OCSP 服务器可用性的依赖;
-
解决防火墙问题:某些网络可能组织 OCSP 查询。
-
ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /path/to/chain.pem;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;
多域名配置
server {
listen 443 ssl;
server_name www.tzhry.com;
ssl_certificate /path/to/www.tzhry.com.crt;
ssl_certificate_key /path/to/www.tzhry.com.key;
... ...
}
server {
listen 443 ssl;
server_name another.tzhr.com;
ssl_certificate /path/to/another.tzhry.com.crt;
ssl_certificate_key /path/to/another.tzhry.com.key;
... ...
}
5.6.6 验证
# -*- 检查 nginx 配置语法
$ nginx -t
# -*- 重载 nginx 配置
$ systemctl reload nginx
# -*- 测试 HTTPS 连接
$ openssl s_client -connect www.tzhry.com:443 -servername www.tzhry.com
5.6.7 常见问题
-
证书不受信任 确保使用受信任的 CA 颁发的证书,或导入自签名证书到客户端;
-
混合内容警告 确保所有资源(图片、JS、CSS)都通过 HTTPS 加载;
-
协议或加密套件不匹配 调整 ssl_protocols 和 ssl_ciphers 配置;
-
证书过期 设置自动续期或手动更新证书。
5.7 访问控制与限流
5.7.1 IP 访问控制
1. 基本原理
-
基于客户端 IP 地址进行访问过滤,使用 allow 和 deny 指令实现黑白名单控制;
2. 配置语法
location /secure/ {
allow 192.168.1.100; # 允许单个IP
allow 10.0.0.0/8; # 允许整个网段
deny all; # 拒绝其他所有访问
}
3. 特性说明
-
执行顺序:规则从上到下依次匹配,匹配即停止;
-
作用范围:可在 http/server/location 块中使用;
-
变量支持:可以
geo 或 map 模块
结合实现动态 IP 列表。
4. 高级用法
# 使用 geo 模块定义IP组
geo $trusted_ip {
default 0;
192.168.1.0/24 1;
10.1.0.0/16 1;
}
server {
location /admin/ {
if ($trusted_ip = 0) {
return 403;
}
}
}
5. 适用场景
-
内部管理系统限制访问 IP;
-
屏蔽恶意 IP 地址;
-
区分内外网访问限制;
5.7.2 HTTP 基础认证
在实际工具中企业要求为网站设置访问账号和密码权限,这样操作后,只有拥有账号密码的用户才能访问网站内容;
这种使用账号密码才可以访问网站的功能主要应用在企业内部人员访问的低智上;例如,企业网站后台、MySQL 客户端 phpmyadmin、企业内部的 CRM、WIKI 网站平台。
1. 基本原理
auth_basic
,基于 RFC 2617 的标准认证方式,需要用户输入用户名和密码。
2. 配置过程
-
创建密码文件
# -*- 使用htpasswd工具(Apache工具包) $ htpasswd -c /etc/nginx/.htpasswd username # -*- 或使用openssl $ openssl passwd -apr1 >> /etc/nginx/.htpasswd
-
Nginx 配置
location /private/ { auth_basic "Restricted Area"; auth_basic_user_file /etc/nginx/.htpasswd; # 可结合IP限制 allow 192.168.1.0/24; deny all; } # auth_basic:验证的基本信息选项(后面跟的双引号是验证窗口的名称); # auth_basic_user_file:验证的用户文件(后面跟账号密码文件的绝对路径);
3. 安全增强
# 限制认证失败次数
limit_req zone=auth_limit burst=3;
# 使用安全头部
add_header WWW-Authenticate 'Basic realm="Restricted"';
add_header Cache-Control 'no-store';
4. 适用场景
-
简单的 Web 管理界面保护;
-
临时性的资源访问控制;
-
配合 IP 限制实现双重认证。
5.7.3 请求速率限制
1. limit_req 模块 - 限制请求速率
-
基本配置
limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s; location /api/ { limit_req zone=api burst=20 nodelay; proxy_pass http://api_backent; } # -*- 参数说明 # limit_req_zone --- 定义限制区域; # $binary_remote_addr --- 基于客户端 IP 进行限制; # zone=api:10m --- 创建名为 api 的共享内存区,大小 10MB; # rate=10r/s --- 限制每秒 10 个请求(也可用“5r/m”表示每分钟5个); # limit_req --- 应用限制; # burst=20 --- 允许突发 20 个请求; # nodelay --- 不延迟处理突发请求,直接拒绝超限请求。
2. limit_conn 模块 - 限制并发连接数
http {
limit_conn_zone $binary_remote_addr zone=addr:10m;
server {
location /download/ {
limit_conn addr 5;
# 每个 IP 最多 5 个并发连接;
}
}
}
3. 高级配置示例
-
白名单设置
geo $limit { default 1; 10.0.0.0/8 0; 192.168.0.0/24 0; } map $limit $limit_key { 0 ""; 1 $binary_remote_addr; } limit_req_zone $limit_key zone=api:10m rate=10r/s;
-
不同位置不同限制
http { limit_req_zone $binary_remote_addr zone=api_limit:10m rate=5r/s; limit_req_zone $binary_remote_addr zone=static_limit:10m rate=20r/s; server { location /api/ { limit_req zone=api_limit burst=10; } location /static/ { limit_req zone=static_limit burst=30; } } }
4. 错误响应自定义
在 Nginx 的请求速率限制中,当客户端超过限制时,默认会返回 503 Service Temporarily Unavailable 错误,可以自定义这些错误响应,包括状态码和页面内容。
-
自定义错误状态码
limit_req_status 和 limit_conn_status
# -*- 这两个指令用于自定义超过限制时返回的 HTTP 状态码: http { # 设置请求速率限制返回429状态码(Too Many Requests) limit_req_status 429; # 设置连接数限制返回429状态码 limit_conn_status 429; limit_req_zone $binary_remote_addr zone=mylimit:10m rate=10r/s; server { location /api/ { limit_req zone=mylimit burst=20; # ... } } }
常用状态码
-
429 Too Many Requests
(推荐用于速率限制); -
503 ServiceTemporarily Unavailable
(Nginx 默认); -
403 Forbidden
-
-
自定义错误页面
http { limit_req_status 429; server { error_page 429 /custom_429.html; location = /custom_429.html { root /usr/share/nginx/html; internal; } location /api/ { limit_req zone=mylimit burst=20; # ... } } }
-
返回 JSON 格式错误(适用于 API)
# -*- 对于 API 服务,希望返回 JSON 格式的错误信息; http { limit_req_status 429; server { location /api/ { limit_req zone=mylimit burst=20; error_page 429 @ratelimit; # ... } location @ratelimit { default_type application/json; return 429 '{"error": "Too many requests", "code": 429, "message": "Rate limit exceeded. Please try again later."}'; } } }
5. 日志记录
-
可以在日志中添加速率限制状态
log_format main '$remote_addr - $remote_user [$time_local] ' '"$request" $status $body_bytes_sent ' '"$http_referer" "$http_user_agent" ' 'Rate: $limit_req_status Conn: $limit_conn_status';
注意事项
-
共享内存区大小计算:1MB 大约可存储 16000 个 IP 地址的状态;
-
生产环境中应根据实际负载测试调整 burst 和 rate 值;
-
对于代理服务器,可能需要使用
$http_x_forwarded_for
代替$binary_remote_addr
; -
限制过于严格可能影响正常用户,建议配合监控调整。
5.7.4 下载限速
Nginx 可通过 limit_rate 和 limit_rate_after 指令来实现下载速度限制;
这对于控制带宽使用非常有用。
1. 基本下载限速配置
server {
listen 80;
server_name example.com;
location /download/ {
# 限制下载速度为50KB/s (50千字节/秒)
limit_rate 50k;
# 文件路径设置
root /var/www/downloads;
}
}
2. 分段限速(延迟限速)
# -*- 允许用户先快速下载一部分,然后开始限速;
location /download/ {
# 前500KB不限速,之后限制为20KB/s
limit_rate_after 500k;
limit_rate 20k;
root /var/www/downloads;
}
3. 根据条件动态限速
-
根据文件类型限速
location ~* \.(mp4|avi)$ { limit_rate 100k; # 视频文件限速100KB/s } location ~* \.(zip|rar|tar\.gz)$ { limit_rate 200k; # 压缩文件限速200KB/s }
-
根据用户 IP 限速
geo $limit_speed { default 100k; # 默认限速100KB/s 192.168.1.0/24 500k; # 内网用户限速500KB/s 10.0.0.1 0; # 特定IP不限速 } server { location /download/ { limit_rate $limit_speed; root /var/www/downloads; } }
4. 限速与连接数限制结合
http {
limit_conn_zone $binary_remote_addr zone=downloader:10m;
server {
location /download/ {
# 每个IP最多2个并发下载连接
limit_conn downloader 2;
# 每个连接限速100KB/s
limit_rate 100k;
root /var/www/downloads;
}
}
}
5. 限制与请求速率限制结合
http {
limit_req_zone $binary_remote_addr zone=download_req:10m rate=5r/s;
server {
location /download/ {
# 每秒最多 5 个下载请求
limit_req zone=download_req burst=10;
# 限速 50KB/s
limit_rate 50k;
root /var/www/downloads;
}
}
}
6. 临时取消限速(通过 cookie 或参数)
location /download/ {
# 默认限速50KB/s
limit_rate 50k;
# 如果有premium=1参数或cookie,则不限速
if ($arg_premium = "1") {
set $limit_rate 0;
}
if ($http_cookie ~* "premium=1") {
set $limit_rate 0;
}
root /var/www/downloads;
}
7. 限速单位说明
-
k
或K
表示千字节(KB/s); -
m
或M
表示兆字节(MB/s); -
不加单位表示
字节/秒
; -
0
表示不限速。
8. 注意事项
-
限速是基于每个连接的,若有多个并发连接,总带宽会成倍增加;
-
实际速度可能会有轻微波动,受网络条件影响;
-
对于大文件下载,建议结合
limit_rate_after
使用,提供更好的用户体验; -
限速设置会影响服务器性能测试结果;
-
在生产环境中应用前,应在测试环境验证限速效果。
5.8 更改日志为 json 格式
将 Nginx 日志转换为 JSON 格式可以更方便地与日志分析工具(如 ELK、Splunk等)集成,并提供更结构化的日志数据。
1. 定义 JSON 日志格式
# -*- 在 Nginx 配置文件中 http 块中添加/修改以下日志格式定义;
log_format json_advanced escape=json
'{'
'"timestamp":"$time_iso8601",'
'"host":"$host",'
'"server_ip":"$server_addr",'
'"client_ip":"$remote_addr",'
'"xff":"$http_x_forwarded_for",'
'"user":"$remote_user",'
'"method":"$request_method",'
'"path":"$request_uri",'
'"query":"$query_string",'
'"status":$status,'
'"size":$body_bytes_sent,'
'"request_time":$request_time,'
'"upstream_time":"$upstream_response_time",'
'"upstream_addr":"$upstream_addr",'
'"http_referer":"$http_referer",'
'"http_user_agent":"$http_user_agent",'
'"protocol":"$server_protocol",'
'"request_length":$request_length,'
'"bytes_sent":$bytes_sent,'
'"connection":$connection,'
'"connection_requests":$connection_requests,'
'"ssl_protocol":"$ssl_protocol",'
'"ssl_cipher":"$ssl_cipher"'
'}';
2. 应用 JSON 日志格式
# -*- 在 server 或 location 块中使用这个日志格式;
server {
access_log /var/log/nginx/access.log json_advanced;
... ...
}
3. 重新加载 Nginx 配置
$ nginx -t && systemctl reload nginx
4. 注意事项
-
escape=json 参数会自动转义 JSON 特殊字符;
-
对于空值字段,Nginx 会输出
-
,在 JSON 中可能需要后续处理; -
大量日志字段可能会影响性能,建议只记录必要的字段;
-
可以使用
map
指令对某些字段进行预处理。
5. 性能优化建议
对于高流量网站,可以考虑:
-
减少日志字段数量;
-
使用缓冲写入
access_log /var/log/nginx/access.log json_advanced buffer=32k flush=5m;
-
将日志直接发送到日志收集系统,避免磁盘 I/O 瓶颈。
5.9 nginx rewrite
Nginx 的 rewrite 功能是 URL 重写和重定向的核心机制;
允许修改客户端请求的 URI,实现 URL 的美化、重定向或条件转发;
需要 PCRE 软件支持,即通过 Perl 兼容正则表达式语法进行规则匹配,默认参数编译时,Nginx 就会安装支持 rewrite 模块,但也必须要有 PCRE 软件支持。
5.9.1 基本语法
# -*- rewrite 指令的基本语法如下:
rewrite regex replacement [flag];
# regex: 正则表达式,用于匹配请求的 URI;
# replacement: 替换字符串,匹配成功后将被替换的字符串;
# flag: 标志位,控制重写行为;
5.9.2 regex 常用正则表达说明
字符 | 描述 |
---|---|
\ | 将后面接着的字符标记为一个特殊字符或一个原义字符或一个向后引用;<br />例如:"\n" 匹配一个换行符,序列"\" 和 "$" 则匹配 "$"。 |
^ | 匹配输入字符串的起始位置,若设置了 RegExp 对象的 Multiline 属性,^ 也匹配 "\n" 或 "\r" 之后的位置。 |
$ | 匹配输入字符的结束位置,若设置了 RegExp 对象的 Multiline 属性,$ 也匹配 "\n" 或 "\r" 之前的位置。 |
* | 匹配前面的字符零次或多次;<br />例如:ol* 能匹配 "o" 及 "oll",等价于{o,}。 |
+ | 匹配前面的字符一次或多次;<br />例如:ol+ 能匹配 "o" 及 "ol",但不能匹配"o",+等价于 {1,}。 |
? | 匹配前面的字符零次或一次;<br />例如:do(es)? 可以匹配 "do" 或 "does",? 等价于 {0,1};<br />当该字符仅仅跟在任何一个其它限制符 (*, +, ?, {n}, {n,}, {n,m}) 后面时,匹配模式是 非贪婪模式,非贪婪模式会尽可能少的匹配所搜索的字符串;<br />默认是 贪婪模式,会尽可能多的匹配所搜索的字符串;<br />例如:字符串"ooooo","o+?" 将匹配单个 "o",而 "o+" 将匹配所有的 "o"。 |
. | 匹配除 "\n" 之外的任何单个字符,要匹配包括 "\n" 在内的任何字符,请使用 "[.\n]" 模式。 |
(pattern) | 匹配括号内的 pattern,并可以在后面获取对应的匹配,常用 $0..$9 属性获取小括号中的匹配内容;要匹配圆括号字符需使用 "\(" 或 "\)"。 |
5.9.3 常用 flag 标志
1. last
-
停止当前处理
rewrite
指令集; -
用重写后的 URI 重新搜索 location 块;
-
类似于 Apache 的 [L] 标记。
2. break
-
停止处理当前
rewrite
指令集; -
不重新搜索 location 块。
3. redirect
-
返回 302 临时重定向;
-
浏览器地址栏会显示跳转后的 URL。
4. permanent
-
返回 301 永久重定向;
-
浏览器地址栏会显示跳转后的 URL。
5.9.4 rewrite 使用场景
1. 基本重写
rewrite ^/oldpage$ /newpage permanent;
# 将 /oldpage 永久重定向到 /newpage
2. 捕获组使用
rewrite ^/user/(.*)$ /profile.php?user=$1 last;
# 将 /user/john 重写为 /profile.php?user=john
3. 文件存在性检查
if (-f $request_filename) {
break;
}
if (-d $request_filename) {
break;
}
rewrite ^/(.*)$ /index.php?q=$1 last;
4. 域名重定向
server {
listen 80;
server_name olddomain.com;
rewrite ^(.*)$ http://newdomain.com$1 permanent;
}
5. 强制 HTTPS
if ($scheme != "https") {
rewrite ^ https://$host$uri permanent;
}
6. 移除 index.php
rewrite ^/(.*)/index\.php$ /$1 permanent;
7. 伪静态化
rewrite ^/product/([0-9]+)/?$ /product.php?id=$1 last;
8. 目录访问添加斜杠
rewrite ^([^.]*[^/])$ $1/ permanent;
9. 防止盗链
location ~* \.(jpg|gif|png)$ { # 不区分大小写匹配所有jpg/gif/png文件;
valid_referers
none # 允许直接访问(无Referer);
blocked # 允许Referer被防火墙修改过的请求;
www.example.com # 允许来自自己域的请求;
example.com; # 同上,无www前缀;
if ($invalid_referer) { # 若 Referer 不合法
rewrite ^/ http://www.example.com/403.jpg;
# 重定向到 403 提示图;
}
}
10. 实现不通过域名的 URL 跳转
-
实现访问 mail.tzhry.com 时跳转到 www.tzhry.com/mail/mail_test.html
# 外部跳转时,使用这种方法可以让浏览器地址变为跳转后的地址; # 另外,要实现设置 http://www.tzhry.com/mail/mail_test.html 有 # 输出结果,不然会出现 401 等权限错误;配置如下 server { listen 80; server_name mail.tzhry.com; location / { root /var/www/html/mailcom; index index.html index.htm; } if ( $http_host ~* "^(.*)\.tzhry\.com$" ) { set $domain $1; rewrite ^(.*) http://www.tzhry.com/$domain/mail_test.html break; } }
5.9.5 注意事项
-
正则表达式性能:复杂的正则表达式会影响性能,尽量简单;
-
rewrite 顺序:Nginx 按顺序处理 rewrite 规则,一旦匹配就不再继续;
-
if 的陷阱:Nginx 的 if 有诸多限制,尽量避免在 if 中使用 rewrite;
-
循环重定向:不当的 rewrite 规则可能导致无限重定向循环;
-
location 优先级:rewrite 后可能进入不同的 location 块,需注意优先级;
5.9.6 企业应用场景
-
可以调整用户浏览的 URL,使其看起来更规范,合乎开发及产品人员的需求;
-
让搜索引擎收录网站内容、让用户体验更好,企业会将动态 URL 地址伪装成静态地址提供服务;
-
网站换新域名后,让旧域名的访问跳转到新的域名上;
-
根据特殊变量、目录、客户端的信息进行 URL 跳转等。
6. 反向代理
6.1 概念与原理
1. 反向代理本质
-
定义 Nginx 作为客户端与后端服务器之间的中介,接收客户端请求并转发到后端服务器,隐藏真实服务器信息。
-
与正向代理的区别
-
正向代理:代理客户端,隐藏客户端身份(如 VPN);
-
反向代理:代理服务端,隐藏后端服务器架构(如负载均衡)。
-
2. 核心功能
-
请求转发;
-
负载均衡;
-
SSL 终止;
-
缓存加速;
-
安全防护。
3. 工作流程
-
客户端发送请求到 Nginx;
-
Nginx 解析请求并匹配 location 规则;
-
根据配置转发到后端服务器(proxy_pass);
-
后端服务器处理完成后返回请求结果给 Nginx;
-
Nginx 处理响应并返回给客户端。
6.2 核心配置
1. 基础代理配置
server {
listen 80;
server_name tzhry.com;
location / {
# 核心指令;
proxy_pass http://backend_server:8080;
# 传递原始域名;
proxy_set_header Host $host;
# 传递真实客户端 IP;
proxy_set_header X-Real-IP $remote_addr;
# 代理链;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# 原始协议(http/https);
proxy_set_header X-Forwarded-Proto $scheme;
}
}
2. 关键指令解析
proxy_pass
-
作用:定义后端服务器地址;
-
URL 格式:
-
http://backend:port:直接转发请求;
-
http://backend:port/:重写 URI(移除当前路径前缀)。
-
-
变量支持:
proxy_pass http://$host$request_uri; # 动态代理目标;
proxy_set_header
-
常用头设置
# 保留客户端原始域名; proxy_set_header Host $host; # 客户端真实 IP; proxy_set_header X-Real-IP $remote_addr; # 代理链 IP 列表; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # 原始协议(http/https); proxy_set_header X-Forwarded-Proto $scheme;
3. 连接与超时控制
# 连接后端服务器的超时时间;
proxy_connect_timeout 60s;
# 发送请求到后端的超时时间;
proxy_send_timeout 60s;
# 读取后端响应的超时时间;
proxy_read_timeout 60s;
# 使用 HTTP/1.1 协议(支持 keepalive);
proxy_http_version 1.1;
# 清除 Connection 头;
proxy_set_header Connection "";
4. 缓冲与缓存
# 启用响应缓冲;
proxy_buffering on;
# 单个缓冲区大小;
proxy_buffer_size 4k;
# 缓冲区数量和大小(总数 128k =8*16k);
proxy_buffers 8 16k;
# 忙碌时缓冲区大小;
proxy_busy_buffers_size 32k;
# 临时文件最大尺寸;
proxy_max_temp_file_size 1024m;
# 临时文件存储路径;
proxy_temp_path /var/cache/nginx/tmp;
6.3 高级配置
1. URL重写与路径处理
location /api/ {
rewrite ^/api/(.*) /$1 break; # 移除 /api 前缀
proxy_pass http://backend_server; # 转发到后端
}
2. WebSocket 代理
location /ws/ {
proxy_pass http://backend;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade; # 协议升级头
proxy_set_header Connection "upgrade"; # 保持长连接
proxy_read_timeout 86400s; # 超时时间(WebSocket 需长连接)
}
3. 动态负载均衡
upstream backend {
server 10.0.0.1:8080 weight=3; # 权重轮询
server 10.0.0.2:8080;
server 10.0.0.3:8080 backup; # 备用服务器
# 负载均衡算法
# ip_hash; # IP 哈希
# least_conn; # 最少连接数
keepalive 32; # 连接池大小
}
server {
location / {
proxy_pass http://backend;
}
}
4. SSL 终止(HTTPS 卸载)
server {
listen 443 ssl;
server_name tzhry.com;
ssl_certificate /etc/nginx/ssl/example.com.crt;
ssl_certificate_key /etc/nginx/ssl/example.com.key;
location / {
proxy_pass http://backend;
proxy_set_header X-Forwarded-Proto https; # 告知后端使用 HTTPS
}
}
6.4 性能优化
1. 连接池优化
upstream backend {
server backend.tzhry.com;
keepalive 32; # 保持的连接数
keepalive_timeout 60s; # 连接保持时间
}
server {
location / {
proxy_pass http://backend;
proxy_http_version 1.1;
proxy_set_header Connection "";
}
}
2. 静态资源缓存
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=my_cache:10m inactive=60m;
server {
location ~* \.(jpg|css|js)$ {
proxy_cache my_cache; # 启用缓存区
proxy_cache_valid 200 302 12h; # 缓存有效期
proxy_cache_use_stale error timeout; # 后端故障时使用旧缓存
proxy_pass http://backend;
}
}
3. 压缩传输
gzip on;
gzip_types text/plain text/css application/json;
gzip_min_length 1024; # 最小压缩大小
proxy_set_header Accept-Encoding ""; # 避免后端重复压缩
6.5 安全加固
1. IP 访问控制
location /admin/ {
allow 192.168.1.0/24;
deny all; # 黑名单/白名单
proxy_pass http://backend;
}
2. 隐藏敏感头信息
proxy_hide_header X-Powered-By; # 隐藏后端框架信息
proxy_hide_header Server; # 隐藏服务器标识
3. 防止 DDoS 攻击
limit_req_zone $binary_remote_addr zone=one:10m rate=10r/s;
location / {
limit_req zone=one burst=20; # 限流配置
proxy_pass http://backend;
}
6.6 常见问题排查
1. 502 Bad Gateway
-
原因:后端服务器不可用或网络不同;
-
解决
# 检查后端服务状态 curl -I http://backend:port # 查看 Nginx 错误日志 tail -f /var/log/nginx/error.log
2. 504 Gateway Timeout
-
原因:后端处理超时;
-
解决
proxy_read_timeout 300s; # 增加超时时间
3. 请求头丢失
-
解决:确保配置 proxy_set_header;
proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr;
4. 大文件上传失败
-
解决
client_max_body_size 100M; # 允许大文件上传 proxy_request_buffering off; # 禁用请求缓冲(适用于流式上传)
7. 负载均衡
7.1 概述
7.1.1 介绍
负载均衡是将网络流量分发到各个服务器的技术,目的是优化资源使用、最大化吞吐量、减少响应时间,并避免任何单一资源过载;
负载均衡集群提供了一种廉价、有效、透明的方法,扩展网络设备和服务器负载、带宽和吞吐量,同时加强了网络数据处理能力,提高网络的灵活性和可用性。
Nginx 作为负载均衡器的优势:
-
高性能,事件驱动的架构;
-
支持多种负载均衡算法;
-
可作为七层(应用层)和四层(传输层)负载均衡器;
-
配置简单灵活;
-
支持健康检查;
-
开源且社区活跃。
7.1.2 四层与七层
四层负载均衡(L4)
-
工作层次:传输层(TCP/UDP),基于 IP 和端口分发流量;
-
特点:
-
高性能:仅解析IP和端口,转发效率高,适合高并发场景(如数据库、实时通信等);
-
功能简单:不支持 HTTP 协议解析,无法根据 URL 或 Header 路由;
-
配置模块:通过 stream 模块实现,需与 http 模块同级配置。
-
-
示例配置
stream { upstream si_backend { server 10.99.156.5:3306; server 10.99.156.6:3306; } server { listen 3306; proxy_pass si_backend; } }
七层负载均衡(L7)
-
工作层次:应用层(HTTP/HTTPS),可解析请求内容(如URL、Header、Cookie);
-
特点:
-
功能丰富:支持会话保持、URL路由、SSL卸载、缓存等高级功能;
-
性能开销:需要解析 HTTP 协议,处理速度略低于四层;
-
配置模块:通过 http 模块中的 upstream 和 proxy_pass 实现。
-
-
示例配置:
http { upstream qi_backend { server 10.99.156.5:80 weight=3; server 10.99.156.6:80; } server { listen 80; location / { proxy_pass http://qi_backend; } } }
核心对比
维度 | 四层(L4) | 七层(L7) |
---|---|---|
协议支持 | TCP/UDP | HTTP/HTTPS |
分发依据 | IP + 端口 | URL/Header/Cookie 等应用层信息 |
性能 | 高(低解析开销) | 中(需解析 HTTP) |
使用场景 | 数据库、游戏、视频流 | Web应用、API服务、移动端 |
典型算法 | 轮询、最少连接、IP哈希 | 加权轮询、URL哈希、响应时间 |
选择
-
需要高性能、低延迟的 TCP/UDP 服务(如MySQL 集群)就选 四层;
-
需基于内容路由或高级 HTTP 功能(如电商网站的会话保持)就选 七层。
7.2 负载均衡配置
7.2.1 基本配置
http {
upstream backend {
server backend1.tzhry.com;
server backend2.tzhry.com;
server backend3.tzhry.com;
}
server {
listen 80;
location / {
proxy_pass http://backend;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
}
7.2.2 四层负载均衡
# -*- 四层为 TCP/UDP
stream {
upstream backend {
server backend1.tzhry.com:12345;
server backend2.tzhry.com:12345;
}
server {
listen 12345;
proxy_pass backend;
}
}
7.3 负载均衡算法
7.3.1 轮询(Round Robin)
-
默认算法,请求按时间顺序逐一分配到不同的后端服务器。
upstream backend { server backend1.tzhry.com; server backend2.tzhry.com; }
7.3.2 加权轮询(Weighted Round Robin)
-
根据服务器权重分配请求,权重越高分配的请求越多。
upstream backend { server backend1.tzhry.com weight=5; server backend2.tzhry.com weight=1; }
7.3.3 IP哈希(IP Hash)
-
基于客户端 IP 地址的哈希值分配请求,可保持会话。
upstream backend { ip_hash; server backend1.tzhry.com; server backend2.tzhry.com; }
7.3.4 最少连接(Least Connections)
-
将请求分配给当前连接数最少得服务器。
upstream backend { least_conn; server backend1.tzhry.com; server backend2.tzhry.com; }
7.3.5 基于响应时间(Fair)
-
按后端服务器的响应时间来分配请求,响应时间短的优先分配(需要第三方模块)。
upstream backend { fair; server backend1.tzhry.com; server backend2.tzhry.com; }
7.3.6 URL哈希(URL Hash)
-
基于请求 URL 的哈希值分配请求(需要第三方模块)。
upstream backend { hash $request_uri; server backend1.tzhry.com; server backend2.tzhry.com; }
7.4 健康检查
7.4.1 被动健康检查(默认)
工作原理
-
在请求转发过程中自动检测后端状态;
-
当连接失败、超时或返回错误码时自动标记。
upstream backend { server backend1.tzhry.com max_fails=3 fail_timeout=30s; server backend2.tzhry.com max_fails=3 fail_timeout=30s; }
-
max_fails
:允许失败的次数; -
fail_timeout
:失败后暂停服务的时间。
-
7.4.2 主动检查
Nginx Plus(商业版)提供的特性。
工作原理
-
主动发送探测请求到后端服务;
-
独立于客户端请求的定期检测。
http { match status_ok { status 200-399; header Content-Type ~ "text/plain"; body !~ "maintenance"; } upstream backend { zone backend 64k; server backend1.tzhry.com:8080; server backend2.tzhry.com:8080; health_check interval=5s fails=3 passes=2 uri=/health match=status_ok port=8080; } }
配置解析
-
match 指令块 这部分定义了名为
status_ok
的健康检查匹配条件,只有后端服务器的响应满足下面所有条件时,Nginx 才会认为该服务器是健康的:-
status 200-399:要求 HTTP 响应状态码在 200 到 399 之间(表示成功的响应);
-
header Content-Type ~ "text/plain":要求响应头中的 Content-Type 包含 "text/plain";
-
body !~ "maintenance":要求响应体内容中不包含 "maintenance" 字符串。
-
-
upstream 指令块 这部分定义了一个名为
backend
的上游服务器组:-
zone backend 64k:在共享内存中分配 64k 的空间用于存储上游组的配置和运行状态;
-
server backend1.tzhry.com:定义第一个后端服务器;
-
server backend2.tzhry.com:定义第二个后端服务器;
健康检查参数
-
interval=5s:每 5s 执行一次健康检查;
-
fails=3:连续 3 次检查失败后标记服务器为不健康;
-
passes=2:连续 2 次检查成功后标记服务器为健康;
-
uri=/health:健康检查请求的 URI 路径;
-
match=status_ok:使用前面定义的
status_ok
匹配条件; -
port=8080:健康检查请求发送到 8080 端口。
-
工作流程
-
Nginx 每 5 秒向每个后端服务器的 ***:8080/health 发送健康检查请求;
-
检查响应是否符合
status_ok
定义的条件:-
状态码在 200~399 之间;
-
Content-Type 头包含 "text/plain";
-
响应体不包含 "maintenance"。
-
-
若连续 3 次检查失败,将该服务器标记为不健康,停止向其发送请求;
-
若服务器之前不健康,需连续 2 次检查成功才会重新标记为健康;
-
健康状态的变化会实时影响负载均衡决策。
7.5 会话保持
在负载均衡环境中,会话保持(Session Persistence)是确保用户请求能够持续分配到同一后端服务器的重要机制。
7.5.1 IP Hash 方法
原理
-
基于 客户端IP 地址的哈希值分配请求,同一 IP 的客户端总是被分配到同一台后端服务器。
配置示例
upstream backend {
ip_hash;
server backend1.tzhry.com;
server backend2.tzhry.com;
}
特点
-
优点
-
配置简单,无需额外模块;
-
适用于客户端 IP 固定的场景(如企业内网);
-
-
缺点
-
同一局域网的多用户可能共享公网IP,导致请求集中到同一服务器;
-
移动设备切换网络时 P 变化会导致会话丢失;
-
服务器增减时哈希会重新分配,部分会话会丢失。
-
适用场景
-
客户端 IP 固定不变的内部系统;
-
不需要严格会话一致性的简单应用。
7.5.2 Cookie 方法
原理
-
Nginx 在第一个响应中插入包含服务器标识的 Cookie,后续请求根据该 Cookie 分配到对应服务器。
配置示例
upstream backend {
server backend1.tzhry.com;
server backend2.tzhry.com;
sticky cookie srv_id expires=1h domain=.tzhry.com path=/;
}
参数说明
-
srv_id
:Cookie 名称; -
expires
:Cookie 有效期; -
domain
:Cookie 作用域; -
path
:Cookie 作用路径。
特点
-
优点
-
客户端 IP 变化不影响会话保持;
-
比 IP Hash 更精确的会话保持;
-
支持 Cookie 参数定制。
-
-
缺点
-
需要客户端支持 Cookie;
-
首次请求没有 Cookie 时仍使用轮询分配;
-
需要 Nginx 商业版或第三方模块(如 nginx-sticky-module)。
-
适用场景
-
面向公众的 Web 应用;
-
需要精确会话控制的场景。
7.5.3 Sticky Route 方法
原理
-
基于自定义变量(如 URL 参数或特定 Cookie)分配请求,需要应用服务器配合设置路由标识。
配置示例
upstream backend {
server backend1.tzhry.com route=a;
server backend2.tzhry.com route=b;
sticky route $cookie_route $arg_route;
}
参数说明
-
route=a
:将 backend1 标记为路由 "a"; -
route=b
:将 backend2 标记为路由 "b";这些标识符可以是任意字符串,用于后续的粘性路由;
-
sticky route 指令
:基于特定变量值将客户端请求持久化到特定后端服务器; -
$cookie_route
:检查名为 "route" 的 cookie 值; -
$arg_route
:检查 URL 参数中的 "route" 值(如?route=a
)。
工作流程
-
应用在响应中设置路由标识(如 Cookie 或 URL 参数);
-
Nginx 根据该标识分配后续请求;
-
标识不存在时使用默认负载均衡算法。
特点
-
优点
-
灵活性高,可基于各种条件路由;
-
不依赖客户端 IP;
-
应用可主动控制路由。
-
-
缺点
-
需要应用服务器配合实现;
-
配置相对复杂;
-
需要 Nginx 商业版支持。
-
适用场景
-
需要自定义路由逻辑的复杂应用;
-
多租户 SaaS 系统;
-
A/B 测试等需要定向路由的场景。
7.5.4 三种方式对比
特性 | IP Hash | Sticky Cookie | Sticky Route |
---|---|---|---|
依赖条件 | 客户端IP | Cookie 支持 | 自定义标识 |
配置复杂度 | 简单 | 中等 | 复杂 |
客户端适应性 | 差(IP变化) | 好 | 好 |
服务器增减影响 | 部分会话丢失 | 无影响 | 无影响 |
Nginx 版本要求 | 开源版支持 | 商业版/第三方模块 | 商业版 |
典型应用场景 | 内网系统 | 公众 Web 应用 | 复杂路由需求 |
7.5.5 生产建议
-
严格会话需求:优先考虑 Sticky Cookie 方式,确保会话一致性;
-
高可用要求:配合健康检查使用,避免请求被分配到故障服务器;
-
性能考虑:会话保持会降低负载均衡的随机性,可能影响均衡效果;
-
扩展性:在需要增加服务器时,评估会话保持方法对扩展的影响;
-
备选方案:考虑使用外部会话存储(如 Redis)替代服务器绑定方案。
7.6 高级配置
7.6.1 服务器备份
Nginx 负载均衡功能支持将部分服务器标记为备份服务器(backend server),当主服务器不可用时,备份服务器会被启用;
这是一种高可用性的重要配置方式。
配置示例
upstream backend {
server backend1.tzhry.com; # 主服务器;
server backend2.tzhry.com; # 主服务器;
server backend3.tzhyr.com backup; # 备份服务器;
}
工作特点
-
正常情况下,流量只会被分配到非备份的主服务器;
-
当所有主服务器不可用时,才会启用备份服务器;
-
一旦有主服务器恢复可用,流量会自动切回主服务器。
高级配置
# -*- 权重分配
upstream backend {
server backend1.tzhry.com weight=5;
server backend2.tzhry.com weight=3;
server backup1.tzhry.com backup weight=1;
}
# -*- 慢启动配置(Nginx Plus)
upstream backend {
server backend1.tzhry.com slow_start=30s;
server backup1.tzhry.com backup slow_start=60s;
}
# -*- 最大连接数限制
upstream backend {
server backend1.tzhry.com max_conns=100;
server backup1.tzhry.com backup max_conns=50;
}
7.6.2 服务器下线
服务器下线
-
服务器下线是指将某台服务器从负载均衡池中移除,使其不再接收任何请求;
-
适用于服务器需要长期维护或彻底移除的场景。
upstream backend { server backend1.tzhry.com; server backend2.tzhry.com; # server backend3.tzhry.com; # 服务器下线; }
平滑下线
-
平滑下线是指将某台服务器标记为不可用,但允许其继续处理已接收的请求,直到所有请求处理完后彻底下线;
-
适用于需要临时维护或避免中断现有请求的场景。
upstream backend { server backend1.tzhry.com; server backend2.tzhry.com down; server backend3.tzhry.com; }
方式对比
特性 | 服务器下线 | 平滑下线 |
---|---|---|
适用场景 | 长期维护或彻底移除服务器 | 临时维护或避免中断现有请求 |
是否接收新请求 | 否 | 否 |
是否处理现有请求 | 立即停止 | 继续处理,直到所有请求完成 |
配置修改 | 移除或注释服务器配置 | 添加 down 标记 |
操作复杂度 | 简单 | 较简单 |
7.6.3 长连接配置
Nginx 与后端服务器之间的长连接配置是提升系统性能的关键环节,合理配置可以显著较少 TCP 连接建立和关闭的开销,提高吞吐量。
upstream 模块中长连接配置
upstream backend {
server backend1.tzhry.com;
server backend2.tzhry.com;
# 每个 worker 进程保持的空闲长连接数(核心参数)
keepalive 32;
# 长连接空闲超时时间(默认 60s)
keepalive_timeoute 60s;
# 单个长连接上允许的最大请求数(默认 1000)
keepalive_requests 1000;
}
proxy模块相关配置
server {
location / {
proxy_pass http://backend;
# 必须使用HTTP/1.1协议才能支持长连接
proxy_http_version 1.1;
# 清空Connection头(关键配置)
proxy_set_header Connection "";
# 其他建议配置
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
配置参数详解
-
keepalive(关键参数)
-
作用:每个 worker 进程与后端服务器保持的最大空闲连接数;
-
推荐值:
-
一般场景:
CPU 核心数 * 2 + 1
; -
高并发场景:根据实际压力测试调整,通常 50~100。
-
-
计算示例:4核CPU服务器 →
4 * 2 + 1 = 9
。
-
-
keepalive_timeout
-
作用:空闲连接保持时间,超时后关闭;
-
默认值:60s;
-
优化建议:
-
根据业务特点设置,突发流量大的场景可适当延长;
-
不宜设置过长,避免占用过多服务器资源。
-
-
-
keepalive_requests
-
作用:单个长连接处理的最大请求数;
-
默认值:1000;
-
调优建议:
-
高并发场景可提高到 5000~10000;
-
设置过高可能导致连接不均匀。
-
-
7.6.4 缓冲区配置
缓冲区配置是 Nginx 负载均衡性能优化的关键环节,合理的缓冲区设置可以显著提高吞吐量并降低后端服务器压力。
核心缓冲区配置指令
-
代理缓冲区基本配置
location / { proxy_pass http://backend; # 启用响应缓冲 proxy_buffering on; # 初始响应头缓冲区大小 proxy_buffer_size 4k; # 响应正文缓冲区数量和大小(数量 大小) proxy_buffers 8 16k; # 忙碌时缓冲区大小(如大响应头) proxy_busy_buffers_size 32k; # 临时文件写入阈值 proxy_temp_file_write_size 64k; }
-
缓冲区相关参数详解
指令 默认值 说明 proxy_buffering on 是否启用响应缓冲 proxy_buffer_size 4k/8k 存储响应头的缓冲区大小 proxy_buffers 8 4k/8k 响应正文缓冲区(数量 大小) proxy_busy_buffers_size 8k/16k 忙碌时缓冲区大小限制 proxy_max_temp_file_size 1024m 临时文件最大大小 proxy_temp_file_write_size 8k/16k 每次写入临时文件的数据量 proxy_temp_path - 临时文件存储路径
生产环境推荐配置
-
常规 Web 应用配置
location / { proxy_pass http://backend; proxy_buffering on; proxy_buffer_size 8k; proxy_buffers 16 8k; proxy_busy_buffers_size 16k; # 禁用临时文件(全内存缓冲) proxy_max_temp_file_size 0; }
-
大文件传输配置
location /download/ { proxy_pass http://backend; proxy_buffering on; proxy_buffer_size 16k; proxy_buffers 32 16k; proxy_busy_buffers_size 32k; # 启用临时文件 proxy_max_temp_file_size 2g; proxy_temp_file_write_size 128k; proxy_temp_path /var/nginx/temp 1 2; }
缓冲区调优
-
内存与磁盘平衡策略
http { # 根据响应大小自动调整缓冲策略 proxy_buffers 32 8k; # 小文件全内存缓冲 proxy_max_temp_file_size 1g; # 大文件使用磁盘缓冲 # 临时文件路径优化(SSD存储) proxy_temp_path /ssd/nginx_temp levels=1:2 keys_zone=temp:10m inactive=1d; }
-
动态内容优化
location /api/ { proxy_pass http://backend; # 禁用缓冲以获得实时响应 proxy_buffering off; proxy_request_buffering off; # 保持长连接 proxy_http_version 1.1; proxy_set_header Connection ""; }
常见问题解决方案
-
内存消耗过高 现象:Nginx 进程占用内存持续增长; 解决方案:
# 减少缓冲区数量和大小 proxy_buffers 8 8k; proxy_buffer_size 4k; # 限制最大临时文件大小 proxy_max_temp_file_size 256m;
-
响应延迟 现象:客户端收到响应时间边长; 解决方案:
# 减小busy缓冲区大小 proxy_busy_buffers_size 8k; # 或考虑禁用缓冲 proxy_buffering off;
-
临时文件过多 现象:磁盘空间被临时文件占满 解决方案:
# 设置自动清理 proxy_temp_path /var/nginx/temp levels=1:2 inactive=7d; # 限制临时文件总大小 proxy_max_temp_file_size 2g;
7.7 性能优化
7.7.1 调整 worker 进程数
Worker 进程是 Nginx 处理请求的核心执行单元,合理配置 worker 进程数量及相关参数对负载均衡性能至关重要。
基本配置指令
# /etc/nginx/nginx.conf 主配置段
user nginx;
worker_processes auto; # Worker进程数量
worker_cpu_affinity auto; # CPU亲和性
worker_rlimit_nofile 65535; # 每个worker能打开的文件描述符上限
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 4096; # 每个worker的最大连接数
use epoll; # 事件模型(Linux推荐)
multi_accept on; # 允许接受所有新连接
}
http {
# 其他HTTP配置...
}
核心参数详解
-
worker_processes
-
作用:定义 worker 进程数量;
-
推荐值:
-
auto
:自动匹配 CPU 核心数(推荐); -
数字:CPU 物理核心数(非超线程核心);
-
测试命令:
grep processor /proc/cpuinfo |wc -l
。
-
-
-
worker_connections
-
作用:单个 worker 能处理的并发连接数;
-
计算公式:
最大并发数 = worker_processes * worker_connections
-
推荐值:
-
一般场景:2048~4096;
-
高并发场景:8192~16384(需调整系统限制)。
-
-
-
worker_rlimit_nofile
-
作用:解除 worker 进程的文件描述符限制;
-
设置原则:
-
应 ≥ worker_connections * 2;
-
需同步调整系统限制:
ulimit -n 65535
。
-
-
生产环境调优方案
-
CPU 密集型场景(如 SSL/TLS 加解密)
worker_processes 8; # 匹配物理CPU核心数 worker_cpu_affinity 00000001 00000010 00000100 00001000 00010000 00100000 01000000 10000000; events { worker_connections 2048; # 适当降低连接数 }
-
I/O 密集型场景(如静态文件服务)
worker_processes auto; worker_cpu_affinity auto; events { worker_connections 8192; # 提高连接数 use epoll; }
-
混合型负载均衡场景
worker_processes 12; # 物理核心数×1.5 worker_rlimit_nofile 131072; # 128k文件描述符 events { worker_connections 16384; accept_mutex on; # 避免惊群效应 accept_mutex_delay 100ms; }
7.7.2 启用 epoll(Linux)
epoll 是 Linux 系统上高效的事件通知机制,特别适合高并发的负载均衡场景。
epoll 基础配置
-
启用 epoll 事件模型
events { use epoll; # 显式指定epoll模型 worker_connections 65536; # 每个worker最大连接数 multi_accept on; # 一次性接受所有新连接 }
-
内核参数检查
# 确认系统支持 epoll $ grep -i epoll /usr/include/linux/eventpoll.h # 查看当前使用的事件模型 $ strace -p `cat /var/run/nginx.pid` 2>&1 | grep epoll
epoll 调优
-
主配置文件优化
events { use epoll; # epoll专属参数 epoll_events 512; # 每次处理的最大事件数(默认512) # 连接处理优化 accept_mutex on; # 避免惊群效应(Nginx 1.11.3+默认off) accept_mutex_delay 100ms; # 互斥锁延迟 # 高性能配置 worker_aio_requests 128; # 每个worker的未完成AI/O操作数 }
-
负载均衡配置
http { upstream backend { server 10.0.0.1:80; server 10.0.0.2:80; # epoll相关优化 keepalive 64; # 长连接数 keepalive_timeout 75s; # 保持时间 } server { listen 80 reuseport; # Linux 3.9+内核支持SO_REUSEPORT location / { proxy_pass http://backend; # epoll网络优化 tcp_nodelay on; # 禁用Nagle算法 tcp_nopush on; # 启用TCP_CORK } } }
-
系统内核参数优化
# /etc/sysctl.conf 追加以下内容 # epoll事件队列大小 fs.epoll.max_user_watches = 1048576 # 网络连接优化 net.core.netdev_max_backlog = 32768 net.core.somaxconn = 32768 net.ipv4.tcp_max_syn_backlog = 8192 # TCP内存调整 net.ipv4.tcp_mem = 94500000 915000000 927000000 net.ipv4.tcp_wmem = 4096 16384 4194304 net.ipv4.tcp_rmem = 4096 87380 4194304 # 生效配置 sysctl -p
常见问题解决方案
-
epoll_wait 频繁返回 EINTR
-
现象:日志中出现大量系统调用中断;
-
解决方案:
events { use epoll; worker_connections 32768; # 适当降低连接数 epoll_events 256; # 减少单次处理事件数 }
-
-
高延迟下的 epoll 性能下降
-
优化方案:
# 调整TCP栈参数 $ echo "net.ipv4.tcp_slow_start_after_idle = 0" >> /etc/sysctl.conf $ echo "net.ipv4.tcp_tw_reuse = 1" >> /etc/sysctl.conf $ sysctl -p
-
-
epoll 的惊群问题
-
解决方案:
events { accept_mutex on; # 启用互斥锁 accept_mutex_delay 50ms; # 优化延迟 # Linux 3.9+内核替代方案 listen 80 reuseport; # 使用SO_REUSEPORT }
-
7.7.5 Gzip 压缩
gzip on;
gzip_types text/plain text/css application/json application/javascript;
7.8 完整配置示例
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;
events {
worker_connections 10240;
multi_accept on;
use epoll;
}
http {
log_format upstream_time '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'rt=$request_time uct="$upstream_connect_time" '
'uht="$upstream_header_time" urt="$upstream_response_time"';
access_log /var/log/nginx/access.log upstream_time;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
include /etc/nginx/mime.types;
default_type application/octet-stream;
gzip on;
gzip_types text/plain text/css application/json application/javascript;
upstream backend {
least_conn;
server backend1.tzhry.com weight=5 max_fails=3 fail_timeout=30s;
server backend2.tzhry.com weight=3 max_fails=3 fail_timeout=30s;
server backup.tzhry.com backup;
keepalive 32;
}
server {
listen 80;
server_name tzhry.com;
location / {
proxy_pass http://backend;
proxy_http_version 1.1;
proxy_set_header Connection "";
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_buffers 16 8k;
proxy_buffer_size 4k;
proxy_busy_buffers_size 16k;
}
location /health_check {
access_log off;
return 200 "OK";
}
}
}
8. 企业级优化
8.1 架构优化
8.1.1 多进程模型优化
worker_processes auto; # 自动匹配 CPU 核心数;
worker_cpu_affinity auto; # 自动绑定 CPU 核心数(1.9.10+);
worker_rlimit_nofile 65535; # 每个 worker 的文件描述符限制;
8.1.2 事件驱动模型
events {
worker_connections 8192; # 每个 worker 的最大连接数;
use epoll; # Linux 高性能事件模型;
multi_accept on; # 一次性接受所有新连接;
accept_mutex off; # 新版内核建议关闭(4.5+);
}
8.2 性能调优
8.2.1 网络传输优化
http {
sendfile on; # 启用零拷贝技术(跳过用户空间,减少数据拷贝次数,提高性能);
tcp_nopush on; # 配合 sendfile 使用;
tcp_nodelay on; # 禁用 Nagle 算法;
keepalive_timeout 65; # 长连接超时;
keepalive_requests 1000; # 单个连接最大请求数;
tcp_fastopen on; # TCP 快速打开(内核 3.7+);
}
8.2.2 缓冲区优化
http {
client_body_buffer_size 16k;
client_header_buffer_size 4k;
client_max_body_size 10m;
large_client_header_buffers 4 16k;
# 代理缓冲区
proxy_buffers 16 8k;
proxy_buffer_size 8k;
}
8.3 安全加固
8.3.1 基础安全配置
server_tokens off; # 隐藏Nginx版本
more_clear_headers 'Server'; # 完全移除Server头
# 安全头部
add_header X-Frame-Options SAMEORIGIN;
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
add_header Referrer-Policy "strict-origin";
8.3.2 访问控制
# IP白名单
allow 192.168.1.0/24;
allow 10.0.0.1;
deny all;
# 速率限制
limit_req_zone $binary_remote_addr zone=api_limit:10m rate=100r/s;
8.4 负载均衡优化
8.4.1 上游服务器配置
upstream backend {
zone backend 64k; # 共享内存区(Nginx Plus)
server 10.0.0.1:80 weight=5;
server 10.0.0.2:80 weight=3;
# 健康检查(Plus版)
health_check interval=5s fails=3 passes=2 uri=/health;
# 长连接优化
keepalive 32;
keepalive_timeout 60s;
}
8.4.2 高级负载策略
# 最少连接算法
least_conn;
# IP哈希会话保持
ip_hash;
# 响应时间动态调整(Nginx Plus)
fair;
8.5 缓存加速
8.5.1 代理缓存
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=my_cache:10m inactive=60m
use_temp_path=off max_size=1g;
location / {
proxy_cache my_cache;
proxy_cache_valid 200 302 10m;
proxy_cache_valid 404 1m;
proxy_cache_use_stale error timeout updating;
}
8.5.2 静态资源优化
location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
expires 365d;
access_log off;
add_header Cache-Control "public";
# 启用预压缩
gzip_static on;
brotli_static on;
}
8.6 日志优化
8.6.1 自定义日志格式
log_format main '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'$request_time $upstream_response_time';
8.6.2 日志切割与轮转
# logrotate配置示例
/var/log/nginx/*.log {
daily
missingok
rotate 30
compress
delaycompress
notifempty
create 640 nginx adm
sharedscripts
postrotate
[ -f /var/run/nginx.pid ] && kill -USR1 `cat /var/run/nginx.pid`
endscript
}
8.7 内核参数优化
8.7.1 sysctl.conf 优化
# 文件描述符
fs.file-max = 2097152
# 网络栈优化
net.core.somaxconn = 32768
net.ipv4.tcp_max_syn_backlog = 8192
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_fin_timeout = 30
# TCP内存
net.ipv4.tcp_mem = 94500000 915000000 927000000
net.ipv4.tcp_wmem = 4096 16384 4194304
net.ipv4.tcp_rmem = 4096 87380 4194304
8.8 监控与维护
8.8.1 状态监控(Nginx Plus)
location /nginx_status {
stub_status;
allow 127.0.0.1;
deny all;
}
8.8.2 性能分析工具
# 实时监控
top -p $(pgrep -d',' nginx)
# 连接状态
ss -ant | awk '{print $6}' | sort | uniq -c
# 性能分析
perf top -p $(cat /var/run/nginx.pid)
9. nginx 优化总结
-
gzip 压缩优化;
-
expires 缓存优化;
-
网络 I/O 事件模型优化;
-
隐藏软件名和版本号;
-
防盗链优化;
-
禁止恶意域名解析;
-
禁止通过 IP 地址访问网站;
-
HTTP 请求方法优化;
-
防 DDOS 攻击,单 IP 并发连接的控制与连接速率控制;
-
严格设置 Web 站点目录的权限;
-
将 nginx 进程以及站点运行于监牢模式;
-
通过 robot 协议及 HTTP_USER_AGENT 防爬虫优化;
-
配置错误页面根据错误代码指定网页反馈给用户;
-
nginx 日志相关优化;
-
限制上传到资源目录的程序被访问,防止木马入侵系统破坏文件;
-
FastCGI 参数 buffer 和 cache 以及超时等的优化;
-
php.ini 和 php-fpm.conf 配置文件优化;
-
有关 Web 服务的 Linux 内核方面深度优化(网络连接、I/O、内存等);
-
Nginx 加密传输优化(SSL);
-
Web 服务器磁盘挂载以及网络文件系统优化。