Nginx 是一个高性能的 HTTP 和反向代理服务器,也是一个 IMAP/POP3/SMTP 代理服务器。以其高并发、低内存消耗、稳定性著称,被广泛应用于现代 Web 架构中。


目录


1. Nginx 基础概念

1.1 什么是 Nginx

Nginx (“engine x”) 是一个开源的高性能 HTTP 和反向代理服务器,由俄罗斯程序员 Igor Sysoev 开发,2004 年首次公开发布。

1.2 Nginx 的优点

  • 高并发能力强:单机支持 10 万+ 并发连接
  • 内存消耗低:10k 并发连接仅占 ~2.5MB 内存
  • 稳定性高:热部署、不断机重载配置
  • 功能丰富:反向代理、负载均衡、静态处理、SSL/TLS 等
  • 模块化设计:扩展灵活

1.3 Nginx 应用场景

  1. 静态资源服务器:直接提供 HTML/CSS/JS/图片等静态文件
  2. 反向代理:将请求转发给后端应用服务器
  3. 负载均衡:将流量分发到多个后端服务器
  4. API 网关:统一入口、路由、认证、限流
  5. SSL 终端:处理 HTTPS 加密解密
  6. 静态资源缓存:减轻后端压力

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 (最低)

完整匹配顺序:

  1. 先找精确匹配 =,找到立即用它
  2. 找前缀匹配,找出最长前缀匹配,如果有 ^~ 就用它,否则继续
  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 工具自动切割,操作步骤如下:

操作步骤

  1. 创建 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

  1. 测试配置是否正确

手动模拟执行一次,测试配置有没有问题,不会真的切割:

sudo logrotate -f /etc/logrotate.d/nginx

#查看结果
ls /opt/lt/nginx/logs

如果没有报错说明配置正确。

  1. 手动执行(可选)

如果你想现在就执行切割,可以直接运行:

logrotate /etc/logrotate.d/nginx
  1. 确认自动运行

方法一 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 安全配置

  1. 隐藏版本号:防止攻击者针对性攻击,server_tokens off;
  2. 禁止直接 IP 访问:防止别人把域名解析到你的 IP,污染搜索引擎:
# 默认 server,不匹配任何域名的请求都走到这里,直接返回 444 关闭连接
server {
    listen 80 default_server;
    server_name _;
    return 444;
}
  1. 禁止访问隐藏文件和点开头的文件(比如 .git、.env):
# 匹配点开头的任何文件,直接拒绝
location ~ /\. {
    deny all;          # 403 拒绝
    access_log off;    # 不记日志,省空间
    log_not_found off; # 404 也不记日志,不污染错误日志
}
  1. 设置合理的请求大小限制:防止用户上传超大文件占满带宽和磁盘:
# 限制最大请求体 10MB,一般上传头像文件够了,不够可以调大
client_max_body_size 10m;
  1. 使用非 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

常见原因:

  1. 端口被占用:端口已经被别的程序占用了,换端口或者关掉占用程序
  2. 配置语法错误:刚才说了,先 nginx -t 检查
  3. 权限不够:证书或者静态文件权限不对,Nginx 读不了
  4. 路径不存在:配置里写的目录不存在,创建对应目录

9. Nginx 常用命令

命令作用
nginx -v显示 Nginx 版本号
nginx -V显示版本号和编译时的参数、启用了哪些模块
nginx -t测试配置文件语法是否正确,不实际启动
nginx -s reload热重载配置,不重启服务加载新配置,不中断业务
nginx -s reopen重新打开日志文件,切割日志后用
nginx -s stop快速停止,立刻关闭所有连接,不处理正在处理的请求
nginx -s quit优雅停止,处理完当前连接再退出,平滑升级用
systemctl start nginxsystemd 方式启动 Nginx 服务
systemctl stop nginxsystemd 方式停止 Nginx 服务
systemctl reload nginxsystemd 方式重载配置
systemctl status nginx查看 Nginx 当前运行状态

10. 常见问题排查

10.1 502 Bad Gateway

可能原因:

  • 后端服务没有启动,Nginx 连不上
  • 后端服务处理太慢,超时了
  • 后端连接数被打满了,新连接连不上
  • proxy_pass 地址写错了,端口不对或者 IP 不对

排查:

  • curl 后端地址 测试后端能不能直接访问
  • 查看 Nginx error.log 里面有具体错误信息
  • 调大 proxy_connect_timeoutproxy_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 用户有没有读权限
  • 检查 rootindex 配置对不对,文件存在吗
  • 检查配置文件里有没有 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 架构中必不可少的组件,在生产环境部署中需要关注:

  1. 性能优化:合理设置 worker 进程数、连接数、内核参数,发挥最大性能
  2. 安全性:隐藏版本、限制访问、HTTPS、最小权限原则
  3. 可维护性:拆分配置文件、日志切割、状态监控
  4. 高可用:配合 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
    }
}

⚠️ 注意:interfacevirtual_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 验证高可用

  1. 查看 VIP:主节点执行 ip addr,能看到你的 VIP 已经绑定到网卡了,从节点现在没有,正常。

  2. 测试访问:访问 VIP,能正常打开你的网站,说明正常。

  3. 模拟故障:把主节点 Nginx 停掉

    systemctl stop nginx
    

    等待 2-5 秒,再看 VIP,现在 VIP 已经漂移到从节点了,访问 VIP 网站依然正常,说明切换成功!

  4. 恢复:把主节点 Nginx 启动起来,过一会 VIP 会自动切回主节点,因为主节点优先级更高。

12.4 Keepalived 配置参数说明

参数作用注意
state MASTER/BACKUP角色主节点写 MASTER,从节点 BACKUP
interfaceVIP 绑定到哪个网卡一定要改成你服务器实际网卡名字
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) ,主节点的数据会自动同步到所有从节点。

  • 主节点:负责处理写请求,也可以处理读请求
  • 从节点:默认只读,数据完全来自主节点自动同步
  • 一主可以多从

主从复制作用

  1. 读写分离:主节点写,从节点读,分摊压力,提高并发能力
  2. 数据容灾:主节点挂了,从节点有完整数据,可以手动切换
  3. 扩容:加从节点就能扩展读能力

部署架构示例

角色内网 IP端口
主节点192.168.1.106379
从节点192.168.1.116379

详细配置步骤

主节点配置

修改 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 就是配置成功了!

测试:主节点写一条数据,从节点能读到就是同步成功。

主从复制原理

  1. 全量同步:从节点第一次连接主节点,主节点把全量内存数据生成 RDB 文件发给从节点,从节点加载进内存
  2. 增量同步:全量完成后,主节点把这期间新增的写命令同步给从节点,从节点执行,保持一致
  3. 持续同步:之后主节点每收到一个写命令,就同步给从节点,一直保持一致

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: 可以,改不同端口就行,测试没问题,生产环境建议分开到不同机器。