Nginx 详细文档与生产环境部署
目录
Nginx 是一个高性能的 HTTP 和反向代理服务器,也是一个 IMAP/POP3/SMTP 代理服务器。以其高并发、低内存消耗、稳定性著称,被广泛应用于现代 Web 架构中。
目录
- 1. Nginx 基础概念
- 2. Nginx 核心架构
- 3. Nginx 安装
- 4. Nginx 目录结构与配置
- 5. Nginx 核心配置
- 6. Nginx 常用功能配置
- 7. Nginx 日志配置
- 8. 生产环境部署最佳实践
- 9. Nginx 常用命令
- 10. 常见问题排查
- 11. 完整配置示例
1. Nginx 基础概念
1.1 什么是 Nginx
Nginx (“engine x”) 是一个开源的高性能 HTTP 和反向代理服务器,由俄罗斯程序员 Igor Sysoev 开发,2004 年首次公开发布。
1.2 Nginx 的优点
- 高并发能力强:单机支持 10 万+ 并发连接
- 内存消耗低:10k 并发连接仅占 ~2.5MB 内存
- 稳定性高:热部署、不断机重载配置
- 功能丰富:反向代理、负载均衡、静态处理、SSL/TLS 等
- 模块化设计:扩展灵活
1.3 Nginx 应用场景
- 静态资源服务器:直接提供 HTML/CSS/JS/图片等静态文件
- 反向代理:将请求转发给后端应用服务器
- 负载均衡:将流量分发到多个后端服务器
- API 网关:统一入口、路由、认证、限流
- SSL 终端:处理 HTTPS 加密解密
- 静态资源缓存:减轻后端压力
2. Nginx 核心架构
2.1 进程模型
Nginx 采用 主进程 + 多个工作进程 模型:
- 主进程 (Master Process) :读取配置、管理工作进程、接收信号,不处理业务
- 工作进程 (Worker Process) :真正处理请求,数量一般设置为 CPU 核心数
2.2 事件驱动模型
- 采用异步非阻塞事件驱动
- 每个 worker 进程单线程但能处理数千并发
- 基于 epoll (Linux) / kqueue (BSD) / IOCP (Windows) 实现
3. Nginx 安装
3.1 yum 安装 (CentOS/RHEL)
# 安装 EPEL 软件源扩展,CentOS 默认源没有 nginx 包,需要先添加 epel 源
sudo yum install -y epel-release
# 使用 yum 从 epel 源安装 nginx
sudo yum install -y nginx
# 启动 nginx 服务
sudo systemctl start nginx
# 设置 nginx 开机自动启动,系统重启后 nginx 会自己起来
sudo systemctl enable nginx
# 查看 nginx 版本号,验证是否安装成功
nginx -v
3.2 apt 安装 (Ubuntu/Debian)
# 更新本地软件包索引,获取最新版本信息
sudo apt update
# 通过 apt 安装 nginx
sudo apt install -y nginx
# 启动服务
sudo systemctl start nginx
# 开机自启
sudo systemctl enable nginx
3.3 源码编译安装
# 1. 安装编译依赖:
# gcc/g++ 是编译工具
# make 是构建工具
# pcre-devel 支持正则表达式,rewrite 模块需要
# zlib-devel 支持 gzip 压缩
# openssl-devel 支持 SSL/TLS 加密,HTTPS 需要
yum install -y gcc gcc-c++ make pcre-devel zlib-devel openssl-devel
# 2. 下载源码包 (从 https://nginx.org/en/download.html 获取最新版)
wget https://nginx.org/download/nginx-1.26.0.tar.gz
# 解压源码包到当前目录
tar -zxf nginx-1.26.0.tar.gz
# 进入源码目录
cd nginx-1.26.0
# 3. 编译配置,指定各种安装路径和启用模块:
./configure \
--prefix=/usr/local/nginx \ # Nginx 安装的根目录
--sbin-path=/usr/local/nginx/sbin/nginx \ # Nginx 可执行文件路径
--conf-path=/etc/nginx/nginx.conf \ # 主配置文件路径
--error-log-path=/var/log/nginx/error.log \# 错误日志默认路径
--http-log-path=/var/log/nginx/access.log \# 访问日志默认路径
--pid-path=/var/run/nginx.pid \ # PID 文件路径,存储主进程 ID
--lock-path=/var/lock/nginx.lock \ # 锁文件路径,防止重复启动
--with-http_ssl_module \ # 启用 HTTPS 支持,必须开启
--with-http_v2_module \ # 启用 HTTP/2 支持,现代浏览器推荐
--with-http_gzip_static_module \ # 启用预压缩 gzip 文件支持
--with-stream \ # 启用 TCP/UDP 反向代理支持
--with-stream_ssl_module # 启用 stream 的 SSL 支持
# 4. 编译源码,然后安装到指定路径
make && make install
# 5. 添加软链接到系统 PATH,这样任意目录都能直接使用 nginx 命令
ln -s /usr/local/nginx/sbin/nginx /usr/sbin/nginx
3.4 Docker 安装
# 启动一个 nginx 容器:
# -d 后台运行
# --name 给容器起个名字
# -p 端口映射:宿主机端口:容器内端口
# -v 卷挂载:把宿主机目录挂载到容器内,方便修改配置和查看日志
docker run -d \
--name nginx \
-p 80:80 \
-p 443:443 \
-v /your-path/conf:/etc/nginx \
-v /your-path/html:/usr/share/nginx/html \
-v /your-path/logs:/var/log/nginx \
nginx:stable
4. Nginx 目录结构与配置
4.1 默认目录结构
| 路径 | 说明 |
|---|---|
/etc/nginx/nginx.conf | 主配置文件,全局配置都在这里 |
/etc/nginx/conf.d/ | 虚拟主机配置目录,一般每个站点一个配置文件 |
/usr/share/nginx/html/ | 默认静态文件根目录,放静态网页文件 |
/var/log/nginx/ | 默认日志存放目录,access.log 和 error.log 在这里 |
4.2 配置文件结构
Nginx 配置文件由多个块(block)组成,层级结构如下:
全局块 # 全局配置,影响整个 Nginx
events 块 # 事件模型相关配置,影响网络连接
http 块 # HTTP 相关配置,所有 HTTP 服务共享
upstream 块 # 负载均衡后端服务器列表配置
server 块 # 一个虚拟主机站点配置
location 块 # 匹配特定 URL 的配置
4.3 主要指令说明
-
# :注释符号,后面的内容不会被执行 - 指令名 参数值; :Nginx 配置的基本格式,必须以分号
;结尾 -
{} :块定义符号,一对大括号包裹多个相关指令,形成一个块
5. Nginx 核心配置
5.1 全局块
位于配置文件最顶部,对整个 Nginx 生效:
# 指定 Nginx 工作进程运行的用户和用户组
# 使用普通用户而不是 root 是为了安全,如果出问题权限也有限制
user nginx nginx;
# 指定工作进程(worker process)的数量
# 一般设置为等于 CPU 核心数,可以充分利用多核,auto 自动检测
worker_processes auto;
# PID 文件存放路径,Nginx 启动后把主进程的 ID 写入这个文件
# 方便后续管理,比如 nginx -s reload 会读取这里找进程 ID
pid /var/run/nginx.pid;
# 指定错误日志存放路径和日志级别
# 日志级别从低到高:debug > info > notice > warn > error > crit
# 级别越低记录越详细,日志越大,生产环境一般设为 warn 足够
error_log /var/log/nginx/error.log warn;
5.2 events 块
events 块主要配置网络连接模型相关参数:
events {
# 指定使用的事件驱动模型,Linux 下推荐用 epoll,性能最好
# 其他可选:select/poll/epoll/kqueue 等,不同系统默认不同
use epoll;
# 指定每个 worker 进程最多同时维护多少个并发连接
# 注意:这是每个 worker 的限制,总连接数 = worker_processes * worker_connections
# 一般设置 10240 足够应对大多数场景,流量大可以开更大
worker_connections 10240;
# 是否允许多个 worker 进程同时接受新进来的连接
# 开启后性能更好,一般建议打开
multi_accept on;
}
5.3 http 块
http 块配置所有 HTTP 服务的公共参数:
http {
# 引入 mime.types 文件,这个文件定义了文件扩展名对应 Content-Type
# 浏览器根据 Content-Type 判断如何处理文件
include mime.types;
# 如果找不到对应的 mime 类型,默认用这个值
# application/octet-stream 表示让浏览器当作二进制下载
default_type application/octet-stream;
# 是否开启 sendfile 零拷贝传输模式
# sendfile 直接在内核空间完成文件发送,不拷贝到用户空间,大大提高静态文件传输效率
sendfile on;
# 开启 tcp_nopush,必须配合 sendfile on 使用
# 作用:让数据包尽量累积到足够大再发送,减少网络包次数,提高网络利用率
tcp_nopush on;
# 开启 tcp_nodelay,用于 keepalive 连接
# 作用:延迟小,小数据包也会尽快发送,交互更及时
tcp_nodelay on;
# keepalive 链接超时时间,单位秒
# 客户端保持连接多长时间空闲后断开,节省资源
keepalive_timeout 65;
# 是否开启 gzip 压缩,开启后传输更小,节省带宽,提高加载速度
gzip on;
# 把 /etc/nginx/conf.d/ 目录下所有 .conf 结尾的文件都包含进来
# 这样每个站点单独写一个配置文件,不用都写到 nginx.conf,结构更清晰
include /etc/nginx/conf.d/*.conf;
}
5.4 server 块
每个 server 块对应一个虚拟主机,也就是一个站点:
server {
# 监听 80 端口(IPv4),HTTP 默认端口就是 80
listen 80;
# 监听 80 端口(IPv6),兼容 IPv6 访问
listen [::]:80;
# 指定这个虚拟主机对应的域名,可以写多个,空格分隔
# 访问时如果域名匹配这个配置,Nginx 就用这个 server 处理请求
server_name example.com www.example.com;
# 指定这个站点静态文件的根目录,Nginx 会从这里找文件
root /var/www/example.com;
# 指定默认首页,访问目录时默认返回这个文件,可以写多个,按顺序找
index index.html index.htm;
# 指定访问日志存放路径,main 是前面定义的日志格式名称
access_log /var/log/nginx/example.com.access.log main;
# 指定这个站点的错误日志存放路径
error_log /var/log/nginx/example.com.error.log;
}
5.5 location 块
location 块用于根据请求的 URI(URL 路径)匹配不同规则,做不同处理:
语法:
location [匹配符] uri { ... }
匹配符说明:
| 符号 | 含义 | 优先级 |
|---|---|---|
= | 精确匹配:必须完全相等才匹配 | 1 (最高) |
^~ | 前缀匹配:URI 以这个前缀开头就匹配,匹配成功后不再搜索正则 | 2 |
~ | 正则匹配:区分大小写 | 3 |
~* | 正则匹配:不区分大小写,比如 .PNG 和 .png 都能匹配 | 3 |
| 无 | 普通前缀匹配:没有特殊符号,按前缀匹配,最长前缀命中 | 4 (最低) |
完整匹配顺序:
- 先找精确匹配
=,找到立即用它 - 找前缀匹配,找出最长前缀匹配,如果有
^~就用它,否则继续 - 按顺序匹配正则,第一个匹配到的就用它
- 如果正则没匹配到,就用之前找到的最长普通前缀匹配
示例:
# 精确匹配首页 /,只有访问根路径才命中
location = / {
# 静态文件根目录
root /var/www/html;
# 默认首页
index index.html;
}
# 不区分大小写匹配以这些扩展名结尾的文件,命中所有静态图片、样式、脚本
location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
# 设置缓存过期时间为 7 天,浏览器下次访问直接读缓存
expires 7d;
# 开启 gzip 压缩这些静态文件
gzip on;
}
# 前缀匹配所有以 /api/ 开头的路径,比如 /api/user、/api/list 都会命中
location /api/ {
# 转发请求给后端地址,末尾 / 表示保留 /api/ 后面的部分传给后端
proxy_pass http://127.0.0.1:8080/;
}
6. Nginx 常用功能配置
6.1 静态网站部署
部署一个纯静态网站:
server {
# 监听 80 端口 HTTP
listen 80;
# 站点域名,改成你自己的
server_name your-domain.com;
# 静态文件放在哪个目录
root /var/www/your-site;
# 默认首页
index index.html;
# 不显示 Nginx 版本号在响应头,防止攻击者知道版本去挖漏洞,安全考虑关闭
server_tokens off;
# 访问日志路径
access_log /var/log/nginx/your-site.access.log;
# 错误日志路径
error_log /var/log/nginx/your-site.error.log;
}
6.2 反向代理
把前端请求转发给后端应用服务:
location / {
# 后端服务地址,就是 Nginx 把请求转发到这里
proxy_pass http://127.0.0.1:8080;
# 设置转发给后端的 Host 请求头,值为 Nginx 收到的原 Host
# 让后端知道是哪个域名收到的请求
proxy_set_header Host $host;
# 设置 X-Real-IP 头,告诉后端真实的客户端 IP
proxy_set_header X-Real-IP $remote_addr;
# 设置 X-Forwarded-For 头,记录整条请求链路的 IP
# 格式:客户端IP, 第一层代理IP, 第二层代理IP...
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# 设置 X-Forwarded-Proto 头,告诉后端原请求是 HTTP 还是 HTTPS
# 后端如果需要跳转的时候能用对协议
proxy_set_header X-Forwarded-Proto $scheme;
# 连接后端的超时时间,单位秒
# 如果超过这个时间连不上后端,就返回 502
proxy_connect_timeout 60s;
# 从后端读取响应的超时时间,连接连上了但一直收不到数据超时
proxy_read_timeout 60s;
# 向后端发送请求的超时时间,发送不完超时
proxy_send_timeout 60s;
}
6.3 负载均衡
把请求分发到多个后端服务器,提高可用性和吞吐量:
http {
# upstream 定义一组后端服务器,起个名字叫 backend
upstream backend {
# 每一行一个后端服务器,格式:ip:端口
server 192.168.1.101:8080; # 第一台后端
server 192.168.1.102:8080; # 第二台后端
server 192.168.1.103:8080; # 第三台后端
}
server {
listen 80;
server_name example.com;
location / {
# 反向代理到 upstream 定义的后端组,名字要对应
proxy_pass http://backend;
}
}
}
负载均衡策略
Nginx 支持多种负载均衡调度策略:
| 策略 | 说明 | 配置示例 |
|---|---|---|
| 轮询 (默认) | 按顺序一个一个轮流分发请求,每个后端按顺序接请求 | upstream { server s1; server s2; } |
| weight 加权轮询 | 权重越高,分配到的请求越多,可以根据机器性能分配比例 | server s1 weight=5; server s2 weight=1; |
| ip_hash | 根据客户端 IP 的哈希值分配,同一个 IP 总是分到同一个后端 可以保持会话,用户登录状态存在后端内存时需要用 | ip_hash; |
| least_conn | 把请求分给当前活跃连接数最少的后端,更智能的负载均衡 比起轮询,能更好地适配性能不同的后端机器,减少过载 | least_conn; |
| fair | 根据后端响应时间分配,响应快的后端多分(需要第三方模块) | fair; |
least_conn 完整配置示例
完整的配置,每一行都带注释:
http {
# upstream 定义后端服务器组
upstream backend {
# ========== 关键配置 ==========
# 使用 least_conn 负载均衡策略
# 作用:把新请求分给当前"活跃连接数最少"的后端服务器
# 比默认轮询更智能,适合后端机器性能不一致,或者请求耗时差异大的场景
least_conn;
# ========== 后端服务器列表 ==========
# 每一行一个后端,格式:ip:端口
# 可以加 weight 权重,如果机器性能不同,可以设置不同权重
server 192.168.1.101:8080 weight=2; # 性能好的机器权重设高一点,分更多请求
server 192.168.1.102:8080 weight=1;
server 192.168.1.103:8080 weight=1;
}
# 前端 server 配置
server {
listen 80;
server_name example.com;
location / {
# 反向代理到 upstream 定义的后端组
proxy_pass http://backend;
# 你可以继续加各种反向代理配置
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
}
💡 提示:
least_conn是 Nginx 官方内置模块,不需要重新编译,直接就能用- 可以配合 weight 权重一起用,兼顾机器性能和连接数均衡
什么时候用 least_conn?
- 你的后端机器性能不一样,有的配置好有的差 → 用 least_conn 会自动把更多请求分给空闲的机器
- 请求耗时差异大,有的请求快有的慢 → least_conn 比轮询更均衡
- 如果所有机器配置差不多,请求也差不多,轮询就够用了
后端服务器额外参数说明:
| 参数 | 作用 |
|---|---|
weight=number | 设置权重,默认是 1 |
fail_timeout=time | 如果失败了,隔离后端这个时间,过了再试,默认 10 秒 |
max_fails=number | 失败多少次之后把后端标记为不可用,默认 1 次 |
backup | 标记为备机,只有所有主节点宕机了才会启用它 |
down | 标记为永久下线,不会分配请求 |
6.4 动静分离
把静态请求(HTML/CSS/JS/图片)直接交给 Nginx 处理,动态请求(PHP/Java API)转发给后端:
# 匹配静态文件后缀,直接由 Nginx 处理返回
location ~* \.(html|css|js|jpg|png|gif)$ {
# 缓存 30 天,浏览器缓存可以减少回源,加快访问
expires 30d;
# 静态文件存放在这个目录
root /data/static;
}
# 其他请求都是动态,转发给后端
location / {
proxy_pass http://tomcat_backend;
}
6.5 Gzip 压缩
开启 Gzip 压缩可以减小传输体积,节省带宽,加快页面加载速度:
# 是否开启 gzip,on 开启 off 关闭
gzip on;
# 只有大于这个长度的文件才压缩,单位可以用 k/m,太小的文件压缩了也没好处
gzip_min_length 1k;
# 设置 gzip 压缩使用多少个缓冲区,单位 16k,4 个就是 64k
gzip_buffers 4 16k;
# 压缩兼容 HTTP 版本,只对 1.1 版本才压缩
gzip_http_version 1.1;
# 压缩级别,1-9,级别越高压缩率越高越慢越占 CPU,一般 4-6 就够了
gzip_comp_level 6;
# 指定哪些类型的内容需要压缩,文本类的压缩率很高,二进制已经压缩过不用压
gzip_types text/plain text/css text/xml application/json application/javascript application/xml+rss text/javascript;
# 是否开启 Vary: Accept-Encoding 响应头,告诉缓存同一个 URL 可能有不同编码
gzip_vary on;
# IE6 及以下不支持 gzip,所以禁用,兼容性更好
gzip_disable "MSIE [1-6]\.";
6.6 HTTPS 配置
配置 HTTPS,需要先申请 SSL 证书,推荐使用 Let’s Encrypt 免费证书,自动续期很方便。申请步骤(CentOS/Ubuntu 通用):
# 安装 certbot 工具
# CentOS
sudo yum install -y certbot python2-certbot-nginx
# 或 Ubuntu
sudo apt install -y certbot python3-certbot-nginx
# 自动申请证书并配置 Nginx,按照提示操作就行
certbot --nginx -d example.com -d www.example.com
证书会自动续期,不用管。证书默认放在 /etc/letsencrypt/live/你的域名/ 目录下。
配置 Nginx:
server {
# 监听 443 端口,HTTPS 默认端口,ssl 表示开启 SSL 处理
# http2 表示开启 HTTP/2 协议,性能更好
listen 443 ssl http2;
# 域名
server_name example.com;
# SSL 证书文件路径,公钥
# 证书一般从 CA 机构申请得到,比如 Let's Encrypt
ssl_certificate /etc/nginx/ssl/example.com.crt;
# SSL 证书私钥路径,自己保存,不能泄露
ssl_certificate_key /etc/nginx/ssl/example.com.key;
# 支持的 SSL 协议版本,只开 TLSv1.2 和 TLSv1.3,旧的不安全协议关掉
ssl_protocols TLSv1.2 TLSv1.3;
# 指定加密套件,优先使用安全强度高的
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384;
# 是否优先使用服务器端的加密套件偏好,开启
ssl_prefer_server_ciphers on;
# 设置 SSL session 缓存大小和过期时间,缓存会话可以避免重复握手,提高性能
ssl_session_cache shared:SSL:10m;
# SSL 会话过期时间,10 分钟后过期
ssl_session_timeout 10m;
# 静态文件根目录
root /var/www/example.com;
# 默认首页
index index.html;
}
6.7 HTTP 跳转 HTTPS
把所有 HTTP 请求都 301 跳转到 HTTPS:
server {
# HTTP 还是监听 80 端口
listen 80;
# 域名和 HTTPS 的一致
server_name example.com www.example.com;
# 返回 301 永久重定向,把请求跳转到 https://域名+原请求路径
return 301 https://$server_name$request_uri;
}
6.8 跨域配置
配置允许跨域请求,解决浏览器跨域限制:
location /api/ {
# 允许哪个源跨域访问,* 表示允许所有源,生产环境建议改成你的域名更安全
add_header Access-Control-Allow-Origin *;
# 允许哪些 HTTP 方法跨域
add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS, PUT, DELETE';
# 允许哪些请求头跨域,列出常见的自定义头
add_header Access-Control-Allow-Headers 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization';
# OPTIONS 预检请求,浏览器会先发一个预检询问是否允许跨域
# 预检请求直接返回 204 不需要处理业务
if ($request_method = OPTIONS) {
return 204;
}
# 实际请求转发给后端
proxy_pass http://backend;
}
6.9 缓存配置
给静态资源设置长缓存,优化用户访问速度:
# 匹配常见静态资源扩展名
location ~* \.(jpg|jpeg|png|gif|ico|css|js|svg|woff|ttf)$ {
# 设置缓存过期时间为 365 天,也就是一年,一般静态资源不常变
expires 365d;
# 添加 Cache-Control 响应头,告诉浏览器是公共缓存,可以存在CDN,内容不变更
add_header Cache-Control "public, immutable";
# 添加 Vary 头,告诉缓存服务器根据 Accept-Encoding 区分不同版本
add_header Vary Accept-Encoding;
}
7. Nginx 日志配置
7.1 访问日志
访问日志记录所有客户端请求信息,方便排查问题和统计:
# 先定义日志格式,名字叫 main,放在 http 块里
# 各个变量含义:
# $remote_addr 客户端 IP 地址
# $remote_user 客户端用户名,一般用于认证,大多为空
# [$time_local] 本地时间格式
# "$request" 完整的请求行:GET /index.html HTTP/1.1
# $status 响应状态码,200/404/500 等
# $body_bytes_sent 响应发送给客户端的字节数
# "$http_referer" 来源页面,从哪个链接点击过来的
# "$http_user_agent" 客户端浏览器信息
# "$http_x_forwarded_for" 经过代理后记录真实客户端 IP
# $request_time 请求处理时间,单位秒,日志排查性能问题用
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for" $request_time';
# 使用上面定义的 main 格式写访问日志到这个文件
access_log /var/log/nginx/access.log main;
7.2 错误日志
错误日志记录 Nginx 运行中的错误和警告,排查问题必须看:
# 错误日志路径和级别,级别:debug < info < notice < warn < error < crit
# 生产环境一般 warn 级别就够了,只记录警告和错误
error_log /var/log/nginx/error.log warn;
日志级别优先级:debug > info > notice > warn > error > crit
设置为某个级别后,大于等于这个级别的日志都会记录。
7.3 日志分割
Nginx 默认不会自动切割日志,时间长了单个日志文件会越来越大,不好管理还占满磁盘。推荐使用 Linux 系统自带的 logrotate 工具自动切割,操作步骤如下:
操作步骤
- 创建 logrotate 配置文件
用 root 权限创建 /etc/logrotate.d/nginx:
复制粘贴下面配置(每一行都有详细注释):
sudo cat > /etc/logrotate.d/nginx << 'EOF'
# Nginx 日志自动切割 + 每日打包配置
# 作用:每天自动切割日志,并将 access.log 和 error.log 打包成 年月日.tar.gz
# 要切割的日志文件路径(匹配所有 .log 日志)
/opt/lt/nginx/logs/*.log {
# 每天 0 点 自动执行一次日志切割
daily
# 日志文件不存在时不报错
missingok
# 保留 30 份历史日志(超过自动删除)
rotate 30
# 延迟压缩:本次不压缩,留给脚本打包使用
delaycompress
# 空文件不切割
notifempty
# 切割后新建日志文件,权限 0644 root:root
create 0644 root root
# 所有日志文件只执行一次后续脚本
sharedscripts
# 切割完成后执行的脚本
postrotate
# 通知 Docker 内 Nginx 重新加载日志文件(不中断服务)
docker exec nginx kill -USR1 1 > /dev/null 2>&1 || true;
# 执行打包脚本:将今天的日志打包成 年月日.tar.gz
/opt/lt/nginx/pack-logs.sh;
endscript
}
EOF
二、最终完整版:打包脚本(每天自动打包)
sudo cat > /opt/lt/nginx/pack-logs.sh << 'EOF'
#!/bin/bash
# 每天自动将 Nginx 切割后的 access.log.1 + error.log.1 打包
# 输出文件名:2025xxxx.tar.gz(年月日)
# 获取今天日期:年月日
TODAY=$(date +%Y%m%d)
# 进入日志目录
cd /opt/lt/nginx/logs
# 只打包今天切割出来的日志(不存在也不报错)
tar -czf "${TODAY}.tar.gz" access.log.1 error.log.1 2>/dev/null
# 打包完成后删除已打包的文件
rm -f access.log.1 error.log.1 2>/dev/null
EOF
# 加执行权限(必须)
chmod +x /opt/lt/nginx/pack-logs.sh
保存退出 :wq
- 测试配置是否正确
手动模拟执行一次,测试配置有没有问题,不会真的切割:
sudo logrotate -f /etc/logrotate.d/nginx
#查看结果
ls /opt/lt/nginx/logs
如果没有报错说明配置正确。
- 手动执行(可选)
如果你想现在就执行切割,可以直接运行:
logrotate /etc/logrotate.d/nginx
- 确认自动运行
方法一 logrotate 已经由系统 cron 定时任务自动执行,一般每天会自动跑一次,不需要额外配置。检查:
ls -l /etc/cron.daily/logrotate
能看到文件存在就 OK 了。
方法二
# 编辑定时任务(自动用默认编辑器打开)
crontab -e
第一步:添加定时任务(核心命令)
# 编辑定时任务(自动用默认编辑器打开)
crontab -e
执行后会进入编辑界面,直接粘贴以下内容(不用改任何东西,适配你之前的配置路径):
# 每天23:59强制执行Nginx日志切割+打包(文件名:年月日.tar.gz)
59 23 * * * /usr/sbin/logrotate -f /etc/logrotate.d/nginx
粘贴完成后:
- 按
Esc键退出编辑模式 - 输入
:wq回车(保存并退出)
第二步:验证定时任务是否添加成功
# 查看已配置的定时任务
crontab -l
✅ 成功标志:能看到刚添加的 59 23 * * * /usr/sbin/logrotate -f /etc/logrotate.d/nginx 这一行。
第三步(可选):测试定时任务是否能正常执行
# 手动执行一次定时任务里的命令,验证日志打包是否正常
/usr/sbin/logrotate -f /etc/logrotate.d/nginx
# 查看打包结果
ls /opt/lt/nginx/logs/*.tar.gz
能看到 2025xxxx.tar.gz(今日日期)的压缩包,说明执行成功
手动脚本切割(不推荐,了解即可)
如果不想用 logrotate,也可以自己写 shell 脚本切割:
#!/bin/bash
# 日志存放目录
LOG_PATH="/var/log/nginx"
# 昨天日期作为文件名
YESTERDAY=$(date -d "yesterday" +%Y%m%d)
# 切割 access.log
mv ${LOG_PATH}/access.log ${LOG_PATH}/access_${YESTERDAY}.log
# 切割 error.log
mv ${LOG_PATH}/error.log ${LOG_PATH}/error_${YESTERDAY}.log
# 向 Nginx 发送信号,让它重新打开新的日志文件
kill -USR1 $(cat /var/run/nginx.pid)
# 删除 30 天前的旧日志
find ${LOG_PATH} -name "*.log" -mtime +30 -delete
# 压缩超过 1 天的旧日志
find ${LOG_PATH} -name "*.log" -mtime +1 -gzip
保存成 nginx-log-cut.sh,添加执行权限,然后加到 cron 每天执行:
chmod +x nginx-log-cut.sh
crontab -e
# 添加一行,每天凌晨 1 点执行
0 1 * * * /path/to/nginx-log-cut.sh
⚠️ 推荐还是用系统自带的 logrotate,更稳定可靠,不需要自己维护脚本。
验证切割是否生效
一天之后,到 /var/log/nginx/ 目录查看,能看到类似这样的文件就是成功了:
access.log
access_20260406.log.gz
access_20260405.log.gz
...
error.log
error_20260406.log.gz
...
自动切割、自动压缩、自动删除旧日志,不会占满磁盘。
8. 生产环境部署最佳实践
8.1 系统优化
Linux 默认的内核参数比较保守,高并发场景需要调整。
调整打开文件句柄限制:
Nginx 需要处理大量连接,每个连接都是一个文件句柄,默认限制太小会出 “too many open files” 错误。
编辑 /etc/security/limits.conf 添加:
# 给 nginx 用户设置打开文件数软限制 65535
nginx soft nofile 65535
# 硬限制 65535,不能超过这个数
nginx hard nofile 65535
# 给所有用户也设置一下
* soft nofile 65535
* hard nofile 65535
调整内核网络参数 (/etc/sysctl.conf):
# 允许复用 TIME-WAIT 状态的 sockets,快速回收重用,减少 TIME-WAIT 数量
net.ipv4.tcp_tw_reuse = 1
# 开启 TCP TIME-WAIT 快速回收,高并发下建议开启
net.ipv4.tcp_tw_recycle = 1
# 调整 TCP 半连接队列长度,增大可以容纳更多并发连接
net.core.somaxconn = 10240
# 网络设备接收数据包排队最大数量,流量突增不容易丢包
net.core.netdev_max_backlog = 10240
# TCP SYN 队列最大长度
net.ipv4.tcp_max_syn_backlog = 10240
# 允许系统使用的端口范围,开大一点,高并发下有足够端口可用
net.ipv4.ip_local_port_range = 1024 65535
# 开启 BBR 拥塞控制算法(Linux 内核 4.9+ 支持),带宽利用率更高,延迟更低
net.core.default_qdisc=fq
net.ipv4.tcp_congestion_control=bbr
让配置生效:
sysctl -p
8.2 Nginx 配置优化
# worker 进程数设置为 auto,自动等于 CPU 核心数,充分利用多核
worker_processes auto;
# 每个 worker 最大打开文件数,和系统 limits 对应开大
worker_rlimit_nofile 65535;
events {
# 每个 worker 最大连接数开大
worker_connections 10240;
# Linux 用 epoll 模型性能最好
use epoll;
# 允许多个 worker 同时接受新连接,提高并发性能
multi_accept on;
}
http {
# 开启零拷贝 sendfile,提高静态文件传输效率
sendfile on;
# 开启 tcp_nopush,优化网络包发送
tcp_nopush on;
# 开启 tcp_nodelay,小数据包及时发送
tcp_nodelay on;
# keepalive 超时 65 秒,保持长连接减少握手开销
keepalive_timeout 65;
# 一个 keepalive 连接最多处理 100 个请求就释放,防止长时间占用
keepalive_requests 100;
# 不显示版本号,安全考虑
server_tokens off;
# 开启 gzip 压缩,减少传输体积
gzip on;
}
8.3 安全配置
- 隐藏版本号:防止攻击者针对性攻击,
server_tokens off; - 禁止直接 IP 访问:防止别人把域名解析到你的 IP,污染搜索引擎:
# 默认 server,不匹配任何域名的请求都走到这里,直接返回 444 关闭连接
server {
listen 80 default_server;
server_name _;
return 444;
}
- 禁止访问隐藏文件和点开头的文件(比如 .git、.env):
# 匹配点开头的任何文件,直接拒绝
location ~ /\. {
deny all; # 403 拒绝
access_log off; # 不记日志,省空间
log_not_found off; # 404 也不记日志,不污染错误日志
}
- 设置合理的请求大小限制:防止用户上传超大文件占满带宽和磁盘:
# 限制最大请求体 10MB,一般上传头像文件够了,不够可以调大
client_max_body_size 10m;
- 使用非 root 用户运行 Nginx,默认已经是,权限更小,被攻破后危害也小。
8.4 HTTPS 优化
- 使用 Let’s Encrypt 免费证书,配合 certbot 自动续期,不用手动管
- 只开启 TLS 1.2+,禁用老旧不安全 SSLv3/TLS1.0/TLS1.1
- 开启 HTTP/2,多路复用性能更好
- 开启 OCSP Stapling,减少客户端查询证书吊销状态时间,可以添加:
ssl_stapling on; ssl_stapling_verify on; - 配置 HSTS 强制浏览器一直用 HTTPS 访问:
# HSTS 头,max-age 单位秒,一年,includeSubDomains 子域名也生效
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
8.5 监控与维护
一定要配置日志切割,不然哪天日志占满整个磁盘,系统就挂了
开启 Nginx 状态监控,方便查看连接数等指标:
# 开启状态页面,只允许本地访问,外网不要开 location /nginx_status { stub_status on; # 开启状态输出 access_log off; # 不记访问日志 allow 127.0.0.1; # 只允许本地访问 deny all; # 其他都拒绝 }访问返回说明:
Active connections: 2 当前活跃连接数 server accepts handled requests 1632 1632 2326 总共接受了 1632 连接,成功握手 1632,总共处理了 2326 请求 Reading: 0 Writing: 1 Waiting: 1 Reading 正在读取请求头的连接数 Writing 正在给客户端发送响应的连接数 Waiting 空闲等待请求的连接数,keepalive 住的连接修改配置后一定要先检查语法:
nginx -t如果输出
test is successful说明语法正确,才能重载。有错它会提示哪里错了,先改好再继续。重载配置用热加载,不重启不中断业务:
nginx -s reload # 或者用 systemd systemctl reload nginx不会中断正在处理的请求,用户无感知。
Nginx 启动失败排查
如果启动失败,先看错误日志:
# 查看错误日志
tail -n 50 /var/log/nginx/error.log
常见原因:
- 端口被占用:端口已经被别的程序占用了,换端口或者关掉占用程序
- 配置语法错误:刚才说了,先
nginx -t检查 - 权限不够:证书或者静态文件权限不对,Nginx 读不了
- 路径不存在:配置里写的目录不存在,创建对应目录
9. Nginx 常用命令
| 命令 | 作用 |
|---|---|
nginx -v | 显示 Nginx 版本号 |
nginx -V | 显示版本号和编译时的参数、启用了哪些模块 |
nginx -t | 测试配置文件语法是否正确,不实际启动 |
nginx -s reload | 热重载配置,不重启服务加载新配置,不中断业务 |
nginx -s reopen | 重新打开日志文件,切割日志后用 |
nginx -s stop | 快速停止,立刻关闭所有连接,不处理正在处理的请求 |
nginx -s quit | 优雅停止,处理完当前连接再退出,平滑升级用 |
systemctl start nginx | systemd 方式启动 Nginx 服务 |
systemctl stop nginx | systemd 方式停止 Nginx 服务 |
systemctl reload nginx | systemd 方式重载配置 |
systemctl status nginx | 查看 Nginx 当前运行状态 |
10. 常见问题排查
10.1 502 Bad Gateway
可能原因:
- 后端服务没有启动,Nginx 连不上
- 后端服务处理太慢,超时了
- 后端连接数被打满了,新连接连不上
proxy_pass地址写错了,端口不对或者 IP 不对
排查:
curl 后端地址测试后端能不能直接访问- 查看 Nginx
error.log里面有具体错误信息 - 调大
proxy_connect_timeout和proxy_read_timeout
10.2 504 Gateway Timeout
原因:
- 后端处理时间超过了 Nginx 设置的
proxy_read_timeout - 后端负载太高,响应太慢
解决:
- 适当调大
proxy_read_timeout,比如改成 120s - 优化后端程序接口响应速度,加快处理
10.3 413 Request Entity Too Large
原因:
- 上传文件大小超过了 Nginx
client_max_body_size限制
解决: 在 http 块或者 server 块或者 location 块添加:
# 允许最大 100MB 上传,根据需求调整
client_max_body_size 100m;
10.4 403 Forbidden
可能原因:
- 文件权限不够,Nginx 运行用户没有读取文件权限
- 目录权限不对,Nginx 进不去目录
- 找不到配置的
index默认首页文件 - IP 被规则
deny all;拒绝了
排查:
- 检查文件/目录权限:
ls -l 文件路径,看看 Nginx 用户有没有读权限 - 检查
root和index配置对不对,文件存在吗 - 检查配置文件里有没有
deny当前 IP 的规则
11. 完整配置示例
以下是一个生产环境可用的完整 nginx.conf:
# 指定运行 Nginx worker 的用户和用户组
user nginx;
# worker 进程数量自动匹配 CPU 核心数
worker_processes auto;
# 每个 worker 最大打开文件数限制
worker_rlimit_nofile 65535;
# PID 文件路径,存主进程 ID
pid /run/nginx.pid;
# 错误日志路径和级别
error_log /var/log/nginx/error.log warn;
# events 块,事件模型配置
events {
# Linux 用 epoll 事件模型性能最好
use epoll;
# 每个 worker 最大并发连接数
worker_connections 10240;
# 允许多 worker 同时接受新连接,开启提高并发
multi_accept on;
}
# http 块,所有 HTTP 服务公共配置
http {
# 引入 mime 类型映射表
include mime.types;
# 默认 mime 类型,找不到就是二进制下载
default_type application/octet-stream;
# 定义访问日志格式,名字叫 main
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for" $request_time';
# 开启 sendfile 零拷贝,加速静态文件传输
sendfile on;
# 开启 tcp_nopush,优化网络传输
tcp_nopush on;
# 开启 tcp_nodelay,小数据包及时发送
tcp_nodelay on;
# keepalive 超时时间,单位秒
keepalive_timeout 65;
# 一个连接最多处理 100 个请求释放
keepalive_requests 100;
# 不显示 Nginx 版本,安全优化
server_tokens off;
# 开启 gzip 压缩
gzip on;
# 大于 1k 才压缩
gzip_min_length 1k;
# 缓冲大小
gzip_buffers 4 16k;
# 压缩级别,1-9,6 是平衡速度和压缩率
gzip_comp_level 6;
# 不管是不是经过代理,都压缩
gzip_proxied any;
# 只压缩文本类型,这些压缩率高
gzip_types
text/plain
text/css
text/xml
text/javascript
application/json
application/javascript
application/x-javascript
image/svg+xml;
# 把 conf.d 目录下所有站点配置包含进来
include /etc/nginx/conf.d/*.conf;
}
一个典型的站点配置 /etc/nginx/conf.d/example.com.conf:
# HTTP 服务,所有请求跳转到 HTTPS
server {
listen 80;
server_name example.com www.example.com;
# 301 跳转到 HTTPS,保留域名和路径
return 301 https://$host$request_uri;
}
# HTTPS 服务
server {
# 监听 443 端口,开启 SSL 和 HTTP/2
listen 443 ssl http2;
# 域名
server_name example.com www.example.com;
# 静态文件根目录
root /var/www/example.com;
# 默认首页
index index.html index.htm;
# SSL 证书路径,公钥证书链
ssl_certificate /etc/nginx/ssl/example.com/fullchain.pem;
# SSL 私钥路径
ssl_certificate_key /etc/nginx/ssl/example.com/privkey.pem;
# 只支持 TLS 1.2 和 1.3,老旧不安全协议禁用
ssl_protocols TLSv1.2 TLSv1.3;
# 加密套件选择安全强度高的
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384;
# 优先用服务端加密套件偏好
ssl_prefer_server_ciphers on;
# SSL 会话缓存,大小 10MB,共享给所有 worker
ssl_session_cache shared:SSL:10m;
# HSTS 强制 HTTPS,一年有效期,包含子域名
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
# 禁止访问 .开头的隐藏文件,比如 .git .env
location ~ /\. {
deny all; # 全部拒绝 403
access_log off; # 不记日志
log_not_found off; # 不记 404 日志
}
# 静态资源匹配,设置长缓存
location ~* \.(jpg|jpeg|png|gif|ico|css|js|svg|woff|woff2|ttf)$ {
# 缓存一年,静态资源版本号更新后自动变
expires 365d;
# 公共缓存,内容不可变
add_header Cache-Control "public, immutable";
# 不记访问日志,省空间
access_log off;
}
# API 接口前缀,转发给后端应用
location /api/ {
# 后端地址,末尾 / 保证路径正确
proxy_pass http://127.0.0.1:8080/;
# 传递各种头给后端,后端能拿到真实信息
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 X-Forwarded-Proto $scheme;
# 超时设置,60 秒
proxy_connect_timeout 60s;
proxy_read_timeout 60s;
# 允许最大 10MB 请求体,API 上传够用
client_max_body_size 10m;
}
# 访问日志用 main 格式
access_log /var/log/nginx/example.com.access.log main;
# 错误日志
error_log /var/log/nginx/example.com.error.log warn;
}
总结
Nginx 是现代 Web 架构中必不可少的组件,在生产环境部署中需要关注:
- 性能优化:合理设置 worker 进程数、连接数、内核参数,发挥最大性能
- 安全性:隐藏版本、限制访问、HTTPS、最小权限原则
- 可维护性:拆分配置文件、日志切割、状态监控
- 高可用:配合 Keepalived 可以实现多机故障自动切换
按照本文的逐行注释配置和最佳实践,可以搭建一个稳定、高性能、安全的生产级 Nginx 服务。
新手常见问题快速检查表
| 问题 | 解决方法 |
|---|---|
| 修改配置不生效 | 检查语法 nginx -t,然后一定要 nginx -s reload |
| 访问显示 403 | 检查文件权限、检查 index 文件存在、检查有没有 deny 规则 |
| 上传大文件报错 413 | 添加 client_max_body_size 100m; |
| 日志越来越大 | 按照 7.3 配置 logrotate 自动切割 |
| 报 “too many open files” | 调整 /etc/security/limits.conf 打开文件数限制 |
| 启动失败 | 看错误日志 tail /var/log/nginx/error.log |
收藏这篇文档,下次搭环境直接抄作业就行👍
12. Nginx 多机主从+Keepalived 高可用部署
12.1 为什么需要 Nginx 高可用
如果你的整个网站只有一台 Nginx 服务器,这台机器或者 Nginx 进程挂了,整个网站就无法访问了,这叫单点故障。
解决方案:两台 Nginx 服务器(一主一从),配合 Keepalived 维护一个共享的虚拟 IP(VIP) :
- 默认 VIP 在主节点,主节点提供服务
- 主节点 Nginx 或者机器挂了,Keepalived 自动把 VIP 漂移到从节点
- 从节点开始提供服务,整个过程几秒完成,用户几乎无感知
12.2 架构说明
| 角色 | 内网 IP |
|---|---|
| Nginx 主节点 | 192.168.1.10 |
| Nginx 从节点 | 192.168.1.11 |
| 虚拟 IP (VIP) | 192.168.1.100(对外提供服务) |
用户访问域名 → DNS 解析到 VIP → 访问当前持有 VIP 的 Nginx → Nginx 转发给后端
12.3 详细配置步骤
12.3.1 环境准备
- 两台 CentOS/Ubuntu 服务器,内网互通
- 两台都已经安装好 Nginx,站点配置完全一致(这样切换不影响访问)
12.3.2 安装 Keepalived
CentOS:
# 安装 Keepalived
sudo yum install -y keepalived
# 设置开机自启
sudo systemctl enable keepalived
Ubuntu:
sudo apt install -y keepalived
sudo systemctl enable keepalived
配置文件位置:/etc/keepalived/keepalived.conf
12.3.3 主节点 Keepalived 配置
编辑 /etc/keepalived/keepalived.conf:
# 全局配置
global_defs {
# 路由器标识,主从不一样就行
router_id nginx_master
}
# 自定义检测 Nginx 状态的脚本
# Nginx 死了就降优先级,触发切换
vrrp_script check_nginx {
script "/etc/keepalived/check_nginx.sh" # 检测脚本路径
interval 2 # 每 2 秒检测一次
weight -20 # 检测失败,优先级减 20
fall 2 # 连续失败 2 次才认为失败
rise 2 # 连续成功 2 次才认为恢复
}
# VRRP 实例配置
vrrp_instance VI_1 {
state MASTER # 角色:主节点是 MASTER,从节点是 BACKUP
interface eth0 # 你的网卡名称,用 ip addr 查看,一般是 eth0 或 ens33
virtual_router_id 51 # 主从这个 ID 必须一样
priority 100 # 优先级,主节点要比从节点高,比如主 100,从 90
advert_int 1 # 心跳间隔,1 秒
# 认证密码,主从必须一样
authentication {
auth_type PASS
auth_pass 123456
}
# 绑定我们的检测脚本
track_script {
check_nginx
}
# 定义虚拟 IP,主从配置必须完全一样
virtual_ipaddress {
192.168.1.100/24 dev eth0
}
}
⚠️ 注意:
interface和virtual_ipaddress里的网卡名称,要改成你自己服务器实际的网卡名称,用ip addr命令查看。
接下来创建 Nginx 检测脚本 /etc/keepalived/check_nginx.sh:
#!/bin/bash
# 检测 Nginx 进程是否存在
# 如果不存在,尝试启动一次,还是不行就返回 1,触发 Keepalived 切换
# 统计 Nginx 进程数量
nginx_count=$(ps -C nginx --no-header | wc -l)
if [ $nginx_count -eq 0 ]; then
# Nginx 没起来,尝试启动
systemctl start nginx
sleep 3
nginx_count=$(ps -C nginx --no-header | wc -l)
if [ $nginx_count -eq 0 ]; then
# 启动失败,返回非零,让 Keepalived 切换
exit 1
fi
fi
# 正常返回 0
exit 0
给脚本加执行权限:
sudo chmod +x /etc/keepalived/check_nginx.sh
12.3.4 从节点 Keepalived 配置
从节点配置和主节点几乎一样,只改三个地方:
global_defs {
router_id nginx_backup # 这里改成不一样的 ID
}
vrrp_script check_nginx {
script "/etc/keepalived/check_nginx.sh"
interval 2
weight -20
fall 2
rise 2
}
vrrp_instance VI_1 {
state BACKUP # 角色改成 BACKUP
interface eth0 # 改成你自己的网卡
virtual_router_id 51 # ID 必须和主节点一样
priority 90 # 优先级比主节点低,比如 90
advert_int 1
authentication {
auth_type PASS
auth_pass 123456 # 密码必须和主节点一样
}
track_script {
check_nginx
}
virtual_ipaddress {
192.168.1.100/24 dev eth0 # VIP 必须和主节点完全一样
}
}
从节点同样需要创建检测脚本 /etc/keepalived/check_nginx.sh,和主节点内容一样,然后加执行权限:
chmod +x /etc/keepalived/check_nginx.sh
12.3.5 启动服务
先启动主节点 Keepalived,再启动从节点:
主节点:
systemctl start keepalived
从节点:
systemctl start keepalived
查看状态:
systemctl status keepalived
显示 active (running) 就是成功。
12.3.6 验证高可用
查看 VIP:主节点执行
ip addr,能看到你的 VIP 已经绑定到网卡了,从节点现在没有,正常。测试访问:访问 VIP,能正常打开你的网站,说明正常。
模拟故障:把主节点 Nginx 停掉
systemctl stop nginx等待 2-5 秒,再看 VIP,现在 VIP 已经漂移到从节点了,访问 VIP 网站依然正常,说明切换成功!
恢复:把主节点 Nginx 启动起来,过一会 VIP 会自动切回主节点,因为主节点优先级更高。
12.4 Keepalived 配置参数说明
| 参数 | 作用 | 注意 |
|---|---|---|
state MASTER/BACKUP | 角色 | 主节点写 MASTER,从节点 BACKUP |
interface | VIP 绑定到哪个网卡 | 一定要改成你服务器实际网卡名字 |
virtual_router_id | 虚拟路由 ID | 同一个 VIP 主从必须一样 |
priority | 优先级 | 数字越大优先级越高,主节点 > 从节点 |
virtual_ipaddress | 虚拟 IP | 主从必须完全一致 |
12.5 常见问题
Q: 配置完了 VIP 不出现怎么办? A: 1. 检查网卡名称对不对 2. 检查防火墙,开放 VRRP 协议:
# CentOS firewalld
firewall-cmd --add-protocol vrrp --permanent
firewall-cmd --reload
Q: 检测脚本不生效?
A: 检查脚本路径对不对,有没有加执行权限 chmod +x,脚本里命令路径对不对。
Q: 能支持一主多从吗?
A: 可以,多个从节点,优先级依次降低,配置和第一个从节点差不多,改一下 router_id 和优先级就行。
附录:Redis 主从复制部署
什么是主从复制
Redis 主从复制,就是一个 主节点 (master) 多个 从节点 (slave) ,主节点的数据会自动同步到所有从节点。
- 主节点:负责处理写请求,也可以处理读请求
- 从节点:默认只读,数据完全来自主节点自动同步
- 一主可以多从
主从复制作用
- 读写分离:主节点写,从节点读,分摊压力,提高并发能力
- 数据容灾:主节点挂了,从节点有完整数据,可以手动切换
- 扩容:加从节点就能扩展读能力
部署架构示例
| 角色 | 内网 IP | 端口 |
|---|---|---|
| 主节点 | 192.168.1.10 | 6379 |
| 从节点 | 192.168.1.11 | 6379 |
详细配置步骤
主节点配置
修改 redis.conf:
# 绑定网卡,允许内网连接,改成 0.0.0.0 允许所有
bind 0.0.0.0
# 端口
port 6379
# 数据存放目录
dir /var/lib/redis
# 日志文件路径
logfile /var/log/redis/redis-server.log
# (可选)设置主节点密码,从节点需要配置
# requirepass your_master_password_here
# 保护模式开着安全
protected-mode yes
# 后台运行
daemonize yes
主节点默认就是主节点,不需要额外配置。改完重启:
systemctl restart redis
从节点配置
修改从节点 redis.conf,关键就是几行:
# 基础配置和主节点一样
bind 0.0.0.0
port 6379
dir /var/lib/redis
logfile /var/log/redis/redis-server.log
protected-mode yes
daemonize yes
# ---------------- 关键配置 ----------------
# 指定主节点 IP 和端口
# Redis 5.0+ 推荐用 replicaof,旧版本用 slaveof 都可以
replicaof 192.168.1.10 6379
# 旧版本写法兼容
# slaveof 192.168.1.10 6379
# 如果主节点设置了密码,这里必须配置主节点密码
# masterauth your_master_password
# 从节点只读,推荐开启,保证数据一致性
slave-read-only yes
改完重启从节点:
systemctl restart redis
验证配置成功
redis-cli
# 查看复制信息
127.0.0.1:6379> info replication
主节点输出应该包含:
role:master
connected_slaves:1
slave0:ip=192.168.1.11,port=6379,state=online
从节点输出应该包含:
role:slave
master_host:192.168.1.10
master_port:6379
master_link_status:up
看到 master_link_status:up 就是配置成功了!
测试:主节点写一条数据,从节点能读到就是同步成功。
主从复制原理
- 全量同步:从节点第一次连接主节点,主节点把全量内存数据生成 RDB 文件发给从节点,从节点加载进内存
- 增量同步:全量完成后,主节点把这期间新增的写命令同步给从节点,从节点执行,保持一致
- 持续同步:之后主节点每收到一个写命令,就同步给从节点,一直保持一致
Redis 有增量缓冲区
repl_backlog,断线重连后只同步断线期间的数据,不用全量重新同步,效率很高。
常见问题
Q: 从节点能不能写?
A: 默认 slave-read-only yes,不能写。如果关掉也能写,但写了不会同步回主节点,主节点覆盖,数据会丢,绝对不推荐。
Q: 主节点有密码,从节点连不上怎么办?
A: 从节点一定要配置 masterauth 主节点密码,才能认证成功连接。
Q: 主节点挂了,怎么把从节点提升成新主节点? A: 在要提升的从节点执行:
127.0.0.1:6379> slaveof no one
这个从节点就变成主节点了,其他从节点再执行 slaveof 新主节点IP 端口 就行。
Q: 一台机器能跑多个节点吗? A: 可以,改不同端口就行,测试没问题,生产环境建议分开到不同机器。