Nginx:安装、配置、模块扩展与代理详解

Nginx 是一款高性能的 Web 服务器和反向代理服务器,同时也可用作邮件代理服务器和通用的 TCP/UDP 代理服务器。它由伊戈尔·赛索耶夫(Igor Sysoev)于 2004 年发布,旨在解决当时流行的 Apache 服务器在高并发场景下的性能瓶颈(即 C10K 问题——单机处理 1 万个并发连接)。

核心特点

  • 高并发、低内存占用:采用异步、非阻塞的事件驱动模型,一个主进程管理多个工作进程,每个工作进程可以处理成千上万个连接。因此,在相同硬件下,Nginx 能支撑比同步阻塞模型高得多的并发量,且内存消耗很低(通常几 MB 到几十 MB)。
  • 丰富的模块化设计:Nginx 的核心功能精简,其他功能(Gzip 压缩、SSL/TLS、代理、缓存、访问控制、日志等)通过静态编译的模块实现。官方和第三方社区提供了大量扩展模块。Nginx 1.9.11 起还支持动态模块(.so),可用 load_module 在启动时加载。
  • 灵活的配置:配置语法简单、清晰、灵活,支持复杂的规则(如正则表达式)、变量、嵌套块和条件逻辑。
  • 支持热更新和热部署:可以在不停止服务器的情况下,平滑地重新加载配置文件(nginx -s reload)或无缝升级 Nginx 二进制文件。

常见用途

  • Web 服务器:直接提供静态文件服务(HTML、CSS、JS、图片、视频等),通常作为前端服务器使用。
  • 反向代理服务器:将客户端的请求转发给后端的应用服务器(Tomcat、Gunicorn、Node.js、PHP-FPM 等),并将响应返回给客户端。
  • 动静分离:通常将 Nginx 作为前端,优先处理静态请求(直接返回本地文件),而将动态请求(如 .php.jsp)通过反向代理或 FastCGI 协议传递给后端的动态处理程序。
  • 缓存服务器:Nginx 可以缓存从后端服务器获得的响应。当相同请求再次到来时,可以直接从缓存中返回响应,极大地降低后端服务器负载和响应时间。
  • 安全防护和访问控制:限制请求速率(限流),基于 IP、用户名、密码、地理位置、请求方法进行访问控制,管理证书和加密解密等。

安装

安装 nginx

通过 brew 安装:brew install nginx

brew search nginx
brew install nginx
brew uninstall nginx
brew update
brew info nginx
brew list
# 资源下载慢,可以设置代理。比如:
export https_proxy=http://127.0.0.1:7897
export http_proxy=http://127.0.0.1:7897

添加扩展模块(echo-nginx-module)

核心思路:版本一致的源码重新编译。 --add-module 是静态编译,会生成新的 nginx 可执行文件;--add-dynamic-module 配合 make modules 只生成 .so,再用 load_module 加载,不必替换 Homebrew 已安装的 nginx。下文按动态模块说明。

  • 准备工作:电脑有编译工具 xcode-select

    xcode-select -v
    nginx -V
    
  • 下载源码:Nginx 源码(版本必须与当前安装的一致)、echo-nginx-module 源码。

    cd ~/Downloads
    
    wget https://nginx.org/download/nginx-1.31.1.tar.gz
    tar -xzvf nginx-1.31.1.tar.gz
    
    git clone https://github.com/openresty/echo-nginx-module.git
    
  • 执行配置文件:进入 Nginx 源码目录,执行 configure 文件。动态模块必须用 --add-dynamic-module(不是 --add-module),并保留 nginx -V 里的 --with-compat

    cd ~/Downloads/nginx-1.31.1
    ./configure [nginx -V 输出的所有参数] --add-dynamic-module=[echo-nginx-module源码路径]
    
    nginx -V
    
    nginx version: nginx/1.31.1
    built by clang 17.0.0 (clang-1700.6.4.2)
    built with OpenSSL 3.6.2 7 Apr 2026
    TLS SNI support enabled
    configure arguments: --prefix=/opt/homebrew/Cellar/nginx/1.31.1 --sbin-path=/opt/homebrew/Cellar/nginx/1.31.1/bin/nginx --with-cc-opt='-I/opt/homebrew/opt/pcre2/include -I/opt/homebrew/opt/openssl@3/include' --with-ld-opt='-L/opt/homebrew/opt/pcre2/lib -L/opt/homebrew/opt/openssl@3/lib' --conf-path=/opt/homebrew/etc/nginx/nginx.conf --pid-path=/opt/homebrew/var/run/nginx.pid --lock-path=/opt/homebrew/var/run/nginx.lock --http-client-body-temp-path=/opt/homebrew/var/run/nginx/client_body_temp --http-proxy-temp-path=/opt/homebrew/var/run/nginx/proxy_temp --http-fastcgi-temp-path=/opt/homebrew/var/run/nginx/fastcgi_temp --http-uwsgi-temp-path=/opt/homebrew/var/run/nginx/uwsgi_temp --http-scgi-temp-path=/opt/homebrew/var/run/nginx/scgi_temp --http-log-path=/opt/homebrew/var/log/nginx/access.log --error-log-path=/opt/homebrew/var/log/nginx/error.log --with-compat --with-debug --with-http_addition_module --with-http_auth_request_module --with-http_dav_module --with-http_degradation_module --with-http_flv_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_mp4_module --with-http_random_index_module --with-http_realip_module --with-http_secure_link_module --with-http_slice_module --with-http_ssl_module --with-http_stub_status_module --with-http_sub_module --with-http_v2_module --with-http_v3_module --with-ipv6 --with-mail --with-mail_ssl_module --with-pcre --with-pcre-jit --with-stream --with-stream_realip_module --with-stream_ssl_module --with-stream_ssl_preread_module
    

    注意:用 brew install nginx 安装,目录下没有 ./configure 程序。需要在官网下载安装包,或者直接下载源码。

  • 编译模块

    • make:编译整个 Nginx,生成可执行文件。不会安装,只在源码目录生成文件。静态编译模块时用这个。
    • make install:将编译好的文件安装到系统目录。
    • make modules只编译动态模块(.so 文件),不编译主程序。编译后,会在 objs/ 目录生成 ngx_http_echo_module.so
    make modules
    
  • 修改 nginx 配置文件:/opt/homebrew/bin/nginx 是可执行文件,不能当目录用。把 .so 复制到单独的模块目录,例如 /opt/homebrew/etc/nginx/modules,在 nginx.confmain 上下文eventshttp 之前)添加:

    mkdir -p /opt/homebrew/etc/nginx/modules
    cp objs/ngx_http_echo_module.so /opt/homebrew/etc/nginx/modules/
    
    load_module /opt/homebrew/etc/nginx/modules/ngx_http_echo_module.so;
    
  • 验证并测试

    nginx -t
    nginx -s reload
    

关键文件与目录

通过 Homebrew 安装的 Nginx,Apple Silicon 上文件统一存放在 /opt/homebrew 目录下;Intel Mac 对应前缀为 /usr/local(下文以 Apple Silicon 为例)。

  • 可执行文件/opt/homebrew/bin/nginx。通过 which nginx 查看。
  • 主配置文件/opt/homebrew/etc/nginx/nginx.conf。通过 nginx -t 命令可测试并确认该文件路径。
  • 网站根目录:默认为 html,相对路径(相对于 --prefix)。通过 nginx.confroot 指定,Homebrew 推荐规范路径为 /opt/homebrew/var/www
  • 访问日志:未在配置中显式指定时,默认路径为 logs/access.log,相对路径(相对于 --prefix)。通过 nginx.confhttpaccess_log 指定。Homebrew 推荐规范路径为 /opt/homebrew/var/log/nginx/access.log
  • 错误日志:未在配置中显式指定时,默认路径为 logs/error.log,相对路径(相对于 --prefix)。通过 nginx.conf 的主上下文、httpservererror_log 指定(不能写在 events 块里)。Homebrew 推荐规范路径为 /opt/homebrew/var/log/nginx/error.log
  • 包含站点配置:默认在 http 块末尾有 include servers/*;,表示会加载 /opt/homebrew/etc/nginx/servers/ 目录下的所有 .conf 文件。Homebrew 推荐规范路径为 /opt/homebrew/etc/nginx/servers

注意nginx.conf 中的相对路径,是相对于 --prefix

彻底卸载

  • 停止 nginx 服务:nginx -s stop
  • 卸载 nginx:brew uninstall nginx
  • 彻底结束所有 nginx 进程

    sudo pkill -9 nginx
    
    ps aux | grep nginx
    sudo kill -9 [PID]
    
  • 手动删除残留文件(关键)

    sudo rm -rf /opt/homebrew/etc/nginx
    sudo rm -rf /opt/homebrew/var/log/nginx
    sudo rm -rf /opt/homebrew/var/www
    
    rm -f ~/Library/LaunchAgents/homebrew.mxcl.nginx.plist
    sudo rm -f /Library/LaunchDaemons/homebrew.mxcl.nginx.plist
    

常用命令

Nginx 命令

nginx             # 启动 Nginx
                  # 会按 --pid-path 创建 pid 文件,Homebrew 一般为 /opt/homebrew/var/run/nginx.pid
nginx -s reload   # 重新加载配置(平滑热加载,不中断服务)
                  # 前提:主进程已在运行,且 pid 文件存在
nginx -s reopen   # 重新打开日志文件(用于日志切割,不是重启)
nginx -s stop     # 快速停止
                  # 停止后会删除 pid 文件
nginx -s quit     # 优雅退出(处理完当前请求再退出)
nginx -V          # 查看版本和编译参数(含配置文件、pid 等路径)
nginx -v          # 查看版本
nginx -c filename # 指定配置文件
nginx -h          # 帮助
nginx -t          # 测试配置是否有语法错误

brew services 命令

brew services start nginx    # 启动 Nginx 服务
brew services stop nginx     # 停止 Nginx 服务
brew services restart nginx  # 重启 Nginx 服务

配置文件

Nginx 的主配置文件是 nginx.conf,由三部分组成:全局块、events 块、http 块

http 块配置 HTTP 相关的所有功能,是 Nginx 最核心、最复杂的部分,包含 http 全局块和多个 server 块,每个 server 块又包含 server 全局块和多个 location 块。

nginx.conf
├── 全局块
├── events 块
└── http 块
    ├── http 全局块
    └── server 块 (可以有多个)
        ├── server 全局块
        └── location 块 (可以有多个)
#user  nobody;
worker_processes  1;

#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;
}

http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;

    server {
        listen       8080;
        server_name  localhost;
        location / {
            root   html;
            index  index.html index.htm;
        }
        error_page  404              /404.html;
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }

    server {
        listen       443 ssl;
        server_name  localhost;

        ssl_certificate      cert.pem;
        ssl_certificate_key  cert.key;

        ssl_session_cache    shared:SSL:1m;
        ssl_session_timeout  5m;

        ssl_ciphers  HIGH:!aNULL:!MD5;
        ssl_prefer_server_ciphers  on;

        location / {
            root   html;
            index  index.html index.htm;
        }
    }
    include servers/*;
}

全局块

配置影响 Nginx 整体运行的指令,通常放在配置文件的最开头,主要配置工作进程数、用户、错误日志、PID 文件。

常见配置项

  • user:指定 Nginx 工作进程运行的用户。
  • worker_processes:指定工作进程数,通常设为 CPU 核心数。
  • error_log:定义错误日志文件路径和级别。
  • pid:指定 Nginx 主进程 ID 存放文件。
  • worker_rlimit_nofile:设置单个工作进程的最大文件打开数。
  • daemon:是否以守护进程方式运行。
  • master_process:是否启用主进程。
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
worker_rlimit_nofile 65535;

events 块

配置 Nginx 服务器与用户的连接方式,影响网络 I/O 模型,主要配置最大连接数、事件驱动模型。

常见配置项

  • worker_connections:每个工作进程的最大并发连接数。
  • use:指定事件驱动模型(如 epoll、kqueue)。
  • multi_accept:是否允许一次接受多个网络连接。
  • accept_mutex:是否开启连接互斥锁。
events {
    use kqueue;
    worker_connections 4096;
    multi_accept on;
}

http 全局块

对所有虚拟主机(server 块)生效的通用配置,主要配置 MIME 类型、日志、压缩。

常见配置项

  • include:引入其他配置文件。
  • default_type:默认 MIME 类型。
  • log_format:定义日志格式。
  • access_log:定义访问日志路径。
  • sendfile:启用高效文件传输。
  • tcp_nopush:在 sendfile 启用时优化数据包。
  • tcp_nodelay:禁用 Nagle 算法(实时性更好)。
  • keepalive_timeout:保持连接超时时间。
  • client_max_body_size:客户端请求体最大大小。
  • gzip:启用压缩。
  • upstream:定义后端服务器组(用于负载均衡)。
http {
    include       /opt/homebrew/etc/nginx/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  /opt/homebrew/var/log/nginx/access.log  main;

    sendfile        on;
    tcp_nopush      on;
    keepalive_timeout  65;
    client_max_body_size 20M;

    gzip  on;

    # 引入所有 server 块配置
    include /opt/homebrew/etc/nginx/servers/*;
}

server 块

定义一个虚拟主机,可以配置独立的域名、端口、访问规则等。一个 http 块中可以包含多个 server 块。

server 全局块

server 全局块最常见的两个配置项是虚拟主机的监听和名称。

  • listen:监听的端口和协议。
  • server_name:服务器域名(支持通配符和正则)。
  • root:网站根目录。
  • index:默认首页文件。
  • access_log:该虚拟主机的访问日志(可覆盖 http 全局)。
  • error_page:自定义错误页面。
  • ssl_certificate:SSL 证书路径。
  • ssl_certificate_key:SSL 证书私钥路径。

listen 指令配置语法:

listen 127.0.0.1:8000;  # 监听 127.0.0.1 的 8000 端口
listen 127.0.0.1;       # 监听 127.0.0.1 的 80 端口(不指定端口,默认 80)
listen 8000;            # 监听所有 IP 的 8000 端口
listen *:8000;          # 和上面效果一样
listen localhost:8000;  # 按名称解析 localhost,通常是 127.0.0.1,双栈环境下还可能包含 ::1

server_name 使用通配符 * 时,星号只能出现在名称的开头或结尾,并且必须紧贴 .www.*.example.comw*.example.com 这类写法无效。也可用 .example.com 同时匹配精确名 example.com 和通配符 *.example.com

server_name myserver.* *.myserver.com;

Nginx 按以下优先级匹配 server_name(不是按配置文件里谁写在前面):

  1. 精确匹配。
  2. 最长的前置通配符(如 *.example.com)。
  3. 最长的后置通配符(如 mail.*)。
  4. 按配置书写顺序,第一个命中的正则表达式。

同一优先级下:通配符取最长的那条;正则取配置文件中最先出现的那条。都未匹配时,使用该 listen 上带 default_serverserver,若未指定则使用该端口上第一个 server

server {
    listen       80;
    server_name  example.com www.example.com;
    root         /var/www/example;
    index        index.html index.php;

    access_log   /var/log/nginx/example.access.log main;
    error_page   404 /404.html;

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

location 块

配置特定 URL 路径的请求处理规则。可以嵌套在 server 块中,用于实现路由、反向代理、重定向等。

location 语法:

location [修饰符] URI {
    ...
}

其中,URI 变量是待匹配的请求字符串,可以是不含正则表达式的字符串,如 /myserver.php;也可以是包含正则表达式的字符串,如 \.php$

修饰符说明

  • 无:前缀匹配,匹配以指定路径开头的 URL。
  • =:精确匹配,优先级最高。
  • ~:正则匹配(区分大小写)。
  • ~*:正则匹配(不区分大小写)。
  • ^~:如果该前缀是最长前缀匹配,则停止后续正则匹配。

匹配顺序

  1. = 精确匹配,命中即停。
  2. 收集所有前缀匹配,记住最长的那条;若它带 ^~,命中即停,不再看正则。
  3. 按配置书写顺序检查 ~~*,首次命中即用。
  4. 正则都未命中,则使用步骤 2 记住的最长前缀。
server {
    listen 8080;
    server_name localhost;

    # 精确匹配(优先级最高)
    location = / {
        root /var/www/html;
        index welcome.html;
        return 200 "【精确匹配 = /】欢迎页\n";
    }

    # ^~ 前缀匹配(高优先级,匹配后停止正则检查)
    location ^~ /static/ {
        root /var/www/;
        expires 1y;
        access_log off;
        return 200 "【^~ 停止正则】静态资源目录:$uri\n";
    }

    # 正则匹配(区分大小写)
    location ~ \.php$ {
        fastcgi_pass 127.0.0.1:9000;
        include fastcgi_params;
        return 200 "【正则 ~ (区分大小写)】PHP 请求:$uri\n";
    }

    # ~* 正则匹配(不区分大小写)
    location ~* \.(jpg|jpeg|png|gif|css|js)$ {
        expires 30d;
        add_header Cache-Control "public";
        root /var/www/;
        return 200 "【正则 ~* (不区分大小写)】静态资源:$uri\n";
    }
    location ~* \.html$ {
        return 200 "【正则 ~* (不区分大小写)】HTML 文件:$uri\n";
    }

    # 无修饰符 - 前缀匹配(按最长匹配优先)
    location /api/ {
        proxy_pass http://localhost:3000;
        return 200 "【无修饰符 - 前缀匹配】API 请求:$uri\n";
    }
    location /images {
        root /var/www/;
        try_files $uri /default.png;
        return 200 "【无修饰符 - 前缀匹配】图片目录:$uri\n";
    }
    location / {
        root /var/www/html;
        index index.html index.htm;
        return 200 "【无修饰符 - 兜底前缀匹配】默认处理:$uri\n";
    }
}

常见配置项

  • root:指定该 location 的根目录。
  • alias:将请求的 URL 路径映射到文件系统上的另一个位置(路径别名)。
  • rewrite:根据正则表达式修改请求的 URI(URL 路径部分),实现 URL 重写和重定向。不加 flag 参数的情况下,默认继续执行后续指令(try_filesproxy_pass)。
  • try_files:按顺序检查文件或目录是否存在,返回第一个找到的,否则执行最后一个回退操作。
  • proxy_pass:反向代理到后端服务器。
  • return:直接向客户端返回响应,不再继续处理后面的配置。返回状态码 + 可选消息文本,或者返回重定向。
  • expires:设置缓存过期时间。
  • deny、allow:访问控制。

alias 注意事项

  • 路径末尾最好加 /,否则容易出问题,推荐使用绝对路径
  • 不能用在 location 块中配合正则匹配(除非使用 location ~ 并捕获分组)。
  • 同时存在 aliasrootalias 生效,root 被忽略。
  • 同时存在 aliasproxy_passproxy_pass 生效,alias 被忽略。

执行顺序(同一 location 内,按 Nginx 处理阶段,不是按「谁优先级更高」):

  • rewrite 模块指令setifrewritereturnbreak)在 rewrite 阶段按配置书写顺序执行。return 一旦执行,请求立即结束;rewrite 若带 last,会重新走 location 匹配。
  • try_files:在 rewrite 之后的 try_files 阶段执行。如果找到,内部跳转到该文件(或命名 location),后续的 proxy_pass 不会执行。
  • proxy_pass:内容处理阶段。当 location 中没有 try_files 或其他内容处理器时,请求会被转发到后端服务器。
server {
    listen 8080;
    server_name localhost;

    location /images/ {
        root /var/www/;
        try_files $uri =404;
    }

    location /admin/ {
        root /var/www/admin/;
        index index.html;
    }

    location /static/ {
        alias /var/www/static-files/;
        expires 30d;
    }

    location ~ ^/users/(.+)/avatar\.jpg$ {
        alias /var/avatars/$1.jpg;
    }

    location /old/ {
        rewrite ^/old/(.*)$ /new/$1;  # 重写 URL
        root /var/www/;
        try_files $uri =404;
    }

    location / {
        root /var/www/html;
        try_files $uri $uri/ =404;
    }

    location /docs/ {
        root /var/www/;
        try_files $uri $uri/ /docs/404.html;
    }

    location /api/ {
        proxy_pass http://localhost:3000/;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

set 指令

定义或修改一个 Nginx 变量的值。

set $变量名 变量值;
server {
    listen 8080;

    set $name "User";
    set $greeting "Hello, $name!";
    set $log_info "$remote_addr - $request_time";

    location /test {
        set $custom_header "X-Request-ID: $request_id";
        add_header X-Custom $custom_header;

        return 200 "Name: $name, Greeting: $greeting";
    }
}

if 指令

根据条件判断,决定是否执行块内的配置指令。

if (条件) {
    # 满足条件时执行的指令
}

条件写法

  • 变量:变量值为空或 0 时为假,非空或非 0 时为真。
  • 变量 = "值":字符串相等比较。
  • 变量 != "值":字符串不相等比较。
  • 变量 ~ 正则:区分大小写正则匹配。
  • 变量 ~* 正则:不区分大小写正则匹配。
  • 变量 !~ 正则:区分大小写正则不匹配。
  • 变量 !~* 正则:不区分大小写正则不匹配。
  • -f 文件路径:文件存在。
  • !-f 文件路径:文件不存在。
  • -d 目录路径:目录存在。
  • !-d 目录路径:目录不存在。
  • -e 文件或目录:文件或目录存在。
  • !-e 文件或目录:文件或目录不存在。
  • -x 文件:文件存在且可执行。
  • !-x 文件:文件不存在或不可执行。
server {
    listen 8080;

    location / {
        if ($http_user_agent ~* "curl") {
            return 200 "Hello from curl!\n";
        }
        return 200 "Hello from browser!\n";
    }

    location /api/ {
        if ($request_method = DELETE) {
            return 405 "Method Not Allowed";
        }
        proxy_pass http://localhost:3000;
    }

    location /download/ {
        set $file_path "/var/www/downloads/$uri";
        if (-f $file_path) {
            break;  # 文件存在,停止 rewrite 阶段后续指令
        }
        return 404 "File not found";
    }

    location /admin/ {
        if ($remote_addr = 192.168.1.100) {
            return 403 "Access Denied";
        }
        proxy_pass http://admin-backend;
    }
}

常见内置变量

  • $hostname:主机名。
  • $scheme:请求协议(http 或 https)。
  • $host:请求中的 Host 字段。
  • $uri:请求中的当前 URI(规范化后的路径,不含参数)。
  • $args:URL 参数部分。
  • $status:HTTP 响应状态码。
  • $remote_addr:客户端 IP 地址。
  • $remote_port:客户端端口号。
  • $request_uri:完整的请求 URI(含参数)。
  • $request_method:请求方法(GET、POST、DELETE 等)。
  • $request_filename:请求对应的文件路径(rootalias 后的完整物理路径)。
  • $request_time:请求处理时间(秒,从客户端读取到响应发送完成)。
  • $request_id:唯一请求标识符(16 字节随机数,用于日志追踪)。
  • $http_user_agent:浏览器 User-Agent。
  • $http_referer:来源页面 URL。
  • $http_cookie:请求中的 Cookie 字符串。
  • $server_name:匹配到的 server_name 值。
  • $server_addr:服务器 IP 地址。
  • $server_port:服务器监听端口。

正向代理和反向代理

正向代理和反向代理的核心区别在于:代理的对象不同

  • 正向代理:代理的是客户端(帮客户端发出请求)。
  • 反向代理:代理的是服务器(帮服务器接收请求)。

正向代理

正向代理是位于客户端和目标服务器之间的代理服务器。客户端明确知道要访问的目标服务器,但将请求发给代理服务器(被代理服务器拦截),由代理服务器转发给目标服务器并返回响应。

客户端 A ──┐
客户端 B ──┼──→ 正向代理服务器 ──→ 目标服务器(如 Google)
客户端 C ──┘

典型场景

  • 科学上网:通过代理服务器访问被屏蔽的国外网站
  • 公司内网:员工通过公司统一代理访问外网。
  • 隐藏客户端 IP:目标服务器只能看到代理服务器 IP,看不到真实客户端 IP。
  • 绕过访问限制:突破 IP 封锁、地域限制。
  • 访问控制:公司限制员工只能访问特定网站。
  • 缓存加速:代理服务器缓存常用资源,减少重复请求。

反向代理

反向代理位于服务器端,客户端不知道也不关心背后是哪个服务器。客户端请求反向代理,由反向代理决定将请求转发给哪个后端服务器。

客户端 ──→ 反向代理服务器(如 Nginx) ──┬──→ 后端服务器 1(Web)
                                    ├──→ 后端服务器 2(API)
                                    └──→ 后端服务器 3(数据库)

典型场景

  • 负载均衡:将请求分发到多个后端服务器。
  • 高可用:某台服务器宕机时,自动切换。
  • 动静分离:静态资源由 Nginx 直接返回,动态请求代理到后端。
  • SSL 终结:在代理层统一处理 HTTPS 证书,后端用 HTTP。
  • 缓存加速:代理服务器缓存后端响应,减少后端压力。
  • 安全防护:隐藏真实后端服务器 IP,防护 DDoS。
  • 统一入口:多个微服务统一通过 API 网关访问。

配置示例

从配置语法上看,正向代理和反向代理都用 proxy_pass 指令。但它们的配置方式、使用场景、Nginx 的处理逻辑有本质不同。

正向代理配置(仅覆盖 HTTP;HTTPS 的 CONNECT 隧道需要第三方模块,如 ngx_http_proxy_connect_module):

server {
    listen 8888;
    # 正向代理必须配置 DNS 解析器
    resolver 8.8.8.8;
    location / {
        proxy_pass http://$http_host$request_uri;
    }
}

反向代理配置

server {
    listen 80;
    server_name api.example.com;
    location / {
        proxy_pass http://backend-servers;
        proxy_set_header Host $host;
    }
}

upstream backend-servers {
    server 192.168.1.10:8080;
    server 192.168.1.11:8080;
}

设置代理器(Mac)

Mac 设置代理:较新系统为「系统设置 → 网络 → 对应网络的详细信息 → 代理」;较旧系统为「系统偏好设置 → 网络 → 高级 → 代理」。在「网页代理(HTTP)」「安全网页代理(HTTPS)」中填入代理服务器的 IP 和端口号。

image-20211201202840435

常见问题

重启 nginx 报错

执行命令:nginx -s reload 时,报错:

nginx: [error] invalid PID number "" in "/opt/homebrew/var/run/nginx.pid"
nginx: [error] open() "/opt/homebrew/var/run/nginx.pid" failed (2: No such file or directory)

原因: 没有有效的 nginx.pid 文件。常见原因:尚未启动 nginx,或 nginx.pid 被误删。路径以 nginx -V 中的 --pid-path 为准(Intel Homebrew 多为 /usr/local/var/run/nginx.pid)。

解决: 先确认进程是否在运行。未启动则执行 nginxbrew services start nginx 生成 pid 文件;已启动但 pid 丢失,可停掉残留进程后重新启动。

启动 nginx 报错

nginx

nginx: [emerg] bind() to 0.0.0.0:8080 failed (48: Address already in use)
nginx: [emerg] bind() to 0.0.0.0:8080 failed (48: Address already in use)
nginx: [emerg] bind() to 0.0.0.0:8080 failed (48: Address already in use)
nginx: [emerg] bind() to 0.0.0.0:8080 failed (48: Address already in use)
nginx: [emerg] bind() to 0.0.0.0:8080 failed (48: Address already in use)
nginx: [emerg] still could not bind()

原因: 常见有两种:系统中其他进程占用了端口,或 nginx 已经启动。

解决: lsof -i:8080 找出占用端口的进程。如果是其他进程占用了,可以用 kill -9 [进程id] 关闭该进程,或者为 nginx 指定其他端口。如果已是 nginx 占用该端口,说明服务已在运行,用 nginx -s reload 重载配置即可,不要再执行一次 nginx 启动。

参考资料

Nginx 中文文档

© lizhao all right reserved,powered by Gitbook文件修订时间: 2026-09-02 21:54:10

results matching ""

    No results matching ""