nginx用法

内容纲要

一 概念

Nginx 是一个高性能的 HTTP 服务器和反向代理服务器,核心作用是高效处理网络请求、转发流量、提供静态资源服务。它最常出现在以下场景中:

  1. 反向代理
    这是 Nginx 最核心的用途之一。客户端请求先到 Nginx,再由它转发给后端的应用服务器(如 Tomcat、Node.js、Python、Java 服务),然后把结果返回给客户端。这样做的好处是隐藏后端真实地址、统一入口、方便做负载均衡和 HTTPS 卸载。

  2. 负载均衡
    当后端有多台服务器时,Nginx 可以把请求按轮询、加权、IP 哈希等策略分发到不同机器上,提升整体吞吐量和可用性。常见于 Web 集群、微服务网关前置层。

  3. 静态资源服务
    Nginx 处理静态文件(HTML、CSS、JS、图片、视频)的效率非常高,常用来直接托管前端打包后的文件,或者作为 CDN 边缘节点。相比让应用服务器处理静态文件,Nginx 更省资源、响应更快。

  4. HTTPS termination(SSL 卸载)
    证书配置在 Nginx 上,由它负责加解密,后端应用只处理明文 HTTP。这样简化了后端配置,也集中管理了证书。

  5. 缓存与压缩
    Nginx 可以缓存后端响应,减少后端压力;也可以对返回内容做 gzip/brotli 压缩,节省带宽。

  6. 限流、防盗链、访问控制
    通过 limit_req、limit_conn 做请求频率和连接数限制;通过 valid_referers 防盗链;通过 allow/deny 做 IP 白名单黑名单。

  7. 动静分离
    把静态请求和动态请求分开处理:静态走 Nginx 本地或专用静态服务器,动态转发给后端应用。这是很经典的架构模式。

典型使用场景举例:

网站入口网关:所有流量先经过 Nginx,再分发到后端服务

前后端分离项目:Nginx 托管前端 dist 文件,同时代理 /api 到后端

微服务 API 网关前置:配合 Kong、Traefik 或直接由 Nginx 做路由

高并发静态站点:直接作为 Web 服务器提供页面和资源

内网服务对外暴露:通过反向代理 + HTTPS 统一出口

简单说,Nginx 在现代架构里通常扮演流量入口 + 静态服务器 + 反向代理 + 负载均衡器这几个角色,是 Web 基础设施中非常常见的一层。

二 配置文件命令解读

1 server {listen 443 ssl http2;}

这里的关键是:listen 443 ssl http2; 里的 ssl 和 http2 都是加在这个监听端口上的"能力开关",不是协议名本身。
所以 listen 443 ssl http2; = 在 443 端口上,提供"加密 + HTTP/2"的服务。

先拆开看这条指令的结构:
443 —— 端口号
ssl —— 告诉 Nginx:这个端口上的连接要用 TLS/SSL 加密来处理
http2 —— 告诉 Nginx:这个端口支持 HTTP/2 协议

  1. ssl 是什么意思?

443 端口是 HTTPS 的默认端口,但端口号本身并不自动带来加密。你完全可以让 443 端口跑明文 HTTP。
ssl 这个参数的作用是:让 Nginx 在这个监听端口上启用 TLS 层。启用后,Nginx 会:
在建立连接时先做 TLS 握手(交换证书、协商密钥)之后所有数据都在加密通道里传输使用同一个 server 块里配置的 ssl_certificate 和 ssl_certificate_key
所以 ssl 是给这个端口"套上加密层"的开关。没有它,就算你写了 ssl_certificate,Nginx 也不会在这个端口上用证书。

一个直观的对比:

listen 443;          # 443 端口,但走明文 HTTP
listen 443 ssl;      # 443 端口,走 TLS 加密(即 HTTPS)
  1. http2 是什么意思?

http2 是让这个端口支持 HTTP/2 协议。HTTP/2 是 HTTP/1.1 的升级版,主要改进:
多路复用:一个 TCP 连接上可以并行传多个请求,不用排队
头部压缩:减少重复的请求头开销
二进制分帧:传输效率更高
服务端推送(Nginx 支持有限)
在 Nginx 里,HTTP/2 是基于 TLS 之上运行的(浏览器基本只支持加密的 HTTP/2,即 h2)。所以通常写成 listen 443 ssl http2;,先有 ssl 再有 http2。

  1. 这两个参数合起来的效果

listen 443 ssl http2;
可以翻译成一句话:
监听 443 端口;进来的连接先经过 TLS 加密(ssl);加密通道里跑的是 HTTP/2 协议(http2)。

数据流向大致是:

客户端
  │  ① TCP 连接到 443
  ▼
Nginx 443 端口
  │  ② TLS 握手(因为开了 ssl)
  ▼
加密通道
  │  ③ 在通道里用 HTTP/2 解析请求(因为开了 http2)
  ▼
交给对应的 server / location 处理
  1. 几个容易混淆的点

ssl 和 http2 都是写在 listen 后面的参数,不是独立的指令。
如果你写 listen 443 ssl; 而没有 http2,那这个端口就是 HTTPS + HTTP/1.1。
较新版本的 Nginx(1.25.1+)推荐把 HTTP/2 单独写成 http2 on; 指令,而不是放在 listen 后面。两种写法目前都还能用:

  1. 新旧写法
    旧写法(仍然兼容)
    listen 443 ssl http2;

新写法(Nginx 1.25.1+ 推荐)
listen 443 ssl;
http2 on;
http2 不能单独用在明文端口上(listen 80 http2; 在浏览器里基本没用),因为主流浏览器只支持基于 TLS 的 HTTP/2。

2 server name

server_name 到底是什么?server_name 不是变量,而是虚拟主机的匹配规则。

它的作用是:当有请求到达这个端口时,Nginx 会看请求头里的 Host 字段(也就是用户访问的域名),然后拿它去和各个 server 块里的 server_name 做比对,决定用哪个 server 块来处理这个请求。

server {
    listen 443 ssl http2;
    server_name example.com www.example.com;
    ...
}

意思是:如果用户访问的是 example.com 或 www.example.com,就用我这个 server 块来处理。
所以 server_name 更像是这个虚拟主机的"域名标签"或"匹配条件",而不是一个可以被后面引用的变量。

它和变量最大的区别:
变量(比如 $host、$remote_addr)是可以在配置里被引用、参与计算的。
server_name 只是一个声明,告诉 Nginx "我负责这些域名",后面不能写 $server_name 去取它的值来当普通变量用(虽然 Nginx 内部有个 $server_name 变量,但那是另一回事,取的是匹配到的名字,不是让你在这里赋值)。

  1. 那"括号"是指什么?

看到的 { } 是 Nginx 配置的块(block)语法,不是域名的一部分。

server {
    ...
}

这一对花括号包起来的部分,叫做一个 server 块,也就是一个"虚拟主机"的配置。花括号的作用是划定作用范围:

写在 server { } 里面的指令,只对这个虚拟主机生效。
写在 http { } 里面的,对所有虚拟主机生效。
写在 location { } 里面的,只对匹配到的路径生效。

所以花括号是配置的分组边界,跟域名没有关系。域名是写在 server_name 后面的那串字符。

  1. 用个类比理解

可以把 Nginx 想象成一栋写字楼(http 块):
楼里有很多间办公室,每间就是一个 server { } 块(虚拟主机)。
每间办公室门口挂个牌子,写着"我负责接待 example.com 和 www.example.com 的访客"——这个牌子就是 server_name。
访客(请求)进楼后,前台看他要找哪个域名,就把他领到对应牌子的办公室。
花括号就是这间办公室的四面墙,划定了"这间屋里的事只在这间屋里算数"。

  1. 补充几个实际要点

server_name 可以写多个域名,用空格隔开,表示这个 server 块同时负责这几个域名。
可以写通配符:server_name *.example.com;
可以写正则:server_name ~^www\d+.example.com$;
如果所有 server_name 都没匹配上,Nginx 会用这个端口上的默认 server(第一个出现的,或者用 default_server 标记的那个)来处理。
server_name 后面不写分号以外的符号,多个域名之间只空格,不加逗号。

server_name example.com www.example.com;   # 正确
server_name example.com, www.example.com;  # 错误,逗号会被当成域名的一部分

一句话总结:
server_name 是虚拟主机的域名匹配规则,不是变量;{ } 是配置块的范围边界,不是括号。
两者都不是"域就是括号"这种关系——域名写在 server_name 后面,花括号只是把一组配置圈起来。

配置文件示例

# =========================================================
# Nginx 主配置文件示例
# 路径通常为 /etc/nginx/nginx.conf
# =========================================================

# 运行 Nginx 的用户和用户组
# 一般用 www-data(Ubuntu/Debian)或 nginx(CentOS/RHEL)
user  www-data;

# 工作进程数
# auto 表示自动根据 CPU 核心数设置,通常等于 CPU 核数
worker_processes  auto;

# 每个 worker 可打开的文件描述符数量
# 高并发场景需要调大,需同时调整系统 ulimit
worker_rlimit_nofile 65535;

# 错误日志路径和级别
# 级别可选:debug | info | notice | warn | error | crit | alert | emerg
error_log  /var/log/nginx/error.log warn;

# PID 文件路径
pid        /var/run/nginx.pid;

# =========================================================
# events 块:连接处理相关配置
# =========================================================
events {
    # 每个 worker 允许的最大并发连接数
    worker_connections  10240;

    # 使用 epoll 事件模型(Linux 下性能最好)
    use epoll;

    # 一个 worker 同时接受多个新连接
    multi_accept on;
}

# =========================================================
# http 块:所有 HTTP 相关配置
# =========================================================
http {
    # ---------- 基础配置 ----------

    # 引入 MIME 类型映射,告诉浏览器文件类型
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    # 日志格式定义
    # $remote_addr    客户端 IP
    # $remote_user    客户端用户(一般为空)
    # $time_local     本地时间
    # $request        请求行
    # $status         响应状态码
    # $body_bytes_sent 响应体字节数
    # $http_referer   来源页面
    # $http_user_agent 客户端 UA
    # $http_x_forwarded_for 经过代理后的真实 IP 链
    # $request_time   请求处理总时间
    # $upstream_response_time 后端响应时间
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for" '
                      'rt=$request_time urt=$upstream_response_time';

    # 访问日志路径和使用的格式
    access_log  /var/log/nginx/access.log  main;

    # 开启 sendfile,零拷贝提升静态文件传输效率
    sendfile        on;

    # 配合 sendfile 使用,减少网络报文数量
    tcp_nopush      on;

    # 不缓存小包,降低延迟
    tcp_nodelay     on;

    # 长连接超时时间,单位秒
    keepalive_timeout  65;

    # 客户端请求头超时时间
    client_header_timeout 15;

    # 客户端请求体超时时间
    client_body_timeout 15;

    # 发送响应超时时间
    send_timeout 15;

    # 隐藏 Nginx 版本号,提升安全性
    server_tokens off;

    # 客户端请求体最大大小(影响上传文件大小)
    client_max_body_size 50m;

    # 请求头缓冲区大小
    client_header_buffer_size 4k;

    # 大请求头缓冲区
    large_client_header_buffers 4 16k;

    # ---------- 文件缓存 ----------

    # 打开文件缓存,减少磁盘 IO
    open_file_cache max=10000 inactive=30s;
    open_file_cache_valid 60s;
    open_file_cache_min_uses 2;
    open_file_cache_errors on;

    # ---------- Gzip 压缩 ----------

    # 开启 gzip 压缩,减少传输体积
    gzip on;

    # 最小压缩长度,小于该值不压缩
    gzip_min_length 1k;

    # 压缩缓冲区
    gzip_buffers 4 16k;

    # 压缩级别 1-9,越高越耗 CPU
    gzip_comp_level 5;

    # 需要压缩的 MIME 类型
    gzip_types text/plain text/css text/xml
               application/json application/javascript
               application/xml application/xml+rss
               image/svg+xml;

    # 是否在响应头中添加 Vary: Accept-Encoding
    gzip_vary on;

    # 对代理请求也启用压缩
    gzip_proxied any;

    # 禁用 IE6 的 gzip
    gzip_disable "MSIE [1-6]\.";

    # ---------- 限流配置 ----------

    # 定义限流区域:按客户端 IP 限制请求频率
    # zone=req_limit:10m  表示区域名和共享内存大小
    # rate=10r/s          表示每秒最多 10 个请求
    limit_req_zone $binary_remote_addr zone=req_limit:10m rate=10r/s;

    # 定义连接数限制区域:按 IP 限制并发连接数
    limit_conn_zone $binary_remote_addr zone=conn_limit:10m;

    # ---------- 负载均衡配置 ----------

    # 定义后端服务器组,组名 backend_servers
    upstream backend_servers {
        # 负载均衡策略,默认轮询
        # 可选:least_conn(最少连接)、ip_hash(按 IP 哈希)
        least_conn;

        # 后端服务器列表
        # weight=1     权重,越大分配请求越多
        # max_fails=3  最大失败次数
        # fail_timeout=30s 失败后暂停时间
        server 127.0.0.1:8080 weight=1 max_fails=3 fail_timeout=30s;
        server 127.0.0.1:8081 weight=1 max_fails=3 fail_timeout=30s;

        # 备用服务器,主服务器全部不可用时启用
        # server 127.0.0.1:8082 backup;

        # 长连接保持,减少握手开销
        keepalive 32;
    }

    # ---------- 代理通用配置 ----------

    # 代理请求头,传递真实客户端信息
    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;

    # 代理连接超时
    proxy_connect_timeout 30s;

    # 代理读取超时
    proxy_read_timeout 60s;

    # 代理发送超时
    proxy_send_timeout 60s;

    # 开启代理缓冲
    proxy_buffering on;
    proxy_buffer_size 8k;
    proxy_buffers 8 8k;
    proxy_busy_buffers_size 16k;

    # 后端返回错误时,尝试下一台服务器
    proxy_next_upstream error timeout http_502 http_503 http_504;

    # =========================================================
    # 虚拟主机 1:HTTP 跳转到 HTTPS
    # =========================================================
    server {
        listen 80;
        server_name example.com www.example.com;

        # 所有 HTTP 请求永久重定向到 HTTPS
        return 301 https://$host$request_uri;
    }

    # =========================================================
    # 虚拟主机 2:HTTPS 主站
    # =========================================================

    server {
        # 监听 443 端口,开启 SSL【Secure Sockets Layer中文:(安全套接字层)】 和 HTTP/2
        # Hyper Text Transfer Protocol Secure(超文本传输安全协议)
        listen 443 ssl http2;
        server_name example.com www.example.com;

        # ---------- SSL 证书配置 ----------
        ssl_certificate     /etc/nginx/ssl/example.com.crt;
        ssl_certificate_key /etc/nginx/ssl/example.com.key;

        # SSL 协议版本,禁用不安全的旧版本
        ssl_protocols TLSv1.2 TLSv1.3;

        # 加密套件
        ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;

        # 优先使用服务端加密套件
        ssl_prefer_server_ciphers on;

        # SSL 会话缓存,提升握手效率
        ssl_session_cache shared:SSL:10m;
        ssl_session_timeout 10m;

        # 开启 HSTS,强制浏览器使用 HTTPS
        add_header Strict-Transport-Security "max-age=31536000" always;

        # 防止点击劫持
        add_header X-Frame-Options SAMEORIGIN always;

        # 禁止 MIME 类型嗅探
        add_header X-Content-Type-Options nosniff always;

        # ---------- 限流应用 ----------
        # 应用请求频率限制,burst=20 允许突发 20 个请求
        # nodelay 表示突发请求立即处理,不排队
        limit_req zone=req_limit burst=20 nodelay;

        # 限制单 IP 并发连接数
        limit_conn conn_limit 20;

        # ---------- 根路径:静态前端 ----------
        location / {
            # 前端打包后的静态文件目录
            root /var/www/frontend/dist;
            index index.html;

            # 尝试找文件,找不到则回退到 index.html
            # 适用于 Vue/React 等 SPA 前端路由
            try_files $uri $uri/ /index.html;
        }

        # ---------- 静态资源缓存 ----------
        location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
            root /var/www/frontend/dist;

            # 浏览器缓存 30 天
            expires 30d;

            # 添加缓存控制头
            add_header Cache-Control "public, immutable";

            # 关闭访问日志,减少日志量
            access_log off;
        }

        # ---------- API 反向代理 ----------
        location /api/ {
            # 转发到后端服务器组
            proxy_pass http://backend_servers/;

            # 传递真实客户端信息
            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;

            # 支持 WebSocket
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "upgrade";

            # 不缓存 API 响应
            proxy_buffering off;
        }

        # ---------- 后端管理接口,限制 IP ----------
        location /admin/ {
            # 只允许指定网段访问
            allow 192.168.1.0/24;
            allow 10.0.0.0/8;

            # 其他全部拒绝
            deny all;

            proxy_pass http://backend_servers/admin/;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        }

        # ---------- 健康检查接口 ----------
        location /health {
            access_log off;
            return 200 "OK\n";
            add_header Content-Type text/plain;
        }

        # ---------- 禁止访问隐藏文件 ----------
        location ~ /\. {
            deny all;
        }
    }

    # =========================================================
    # 虚拟主机 3:静态资源站点(可选)
    # =========================================================
    server {
        listen 80;
        server_name static.example.com;

        root /var/www/static;
        index index.html;

        # 开启目录浏览(按需开启,生产慎用)
        # autoindex on;

        location / {
            try_files $uri $uri/ =404;
        }

        # 图片、视频等大文件缓存
        location ~* \.(mp4|webm|ogg|mp3|wav|flac|aac)$ {
            expires 7d;
            add_header Cache-Control "public";
        }
    }
}

发表评论

您的邮箱地址不会被公开。 必填项已用 * 标注

滚动至顶部