浅谈Nginx

🔍 1. 什么是 Nginx?

详细解析:

Nginx(发音为"engine-x")是一个高性能的开源 Web 服务器 ,同时也作为反向代理服务器负载均衡器HTTP 缓存使用。

核心特性:

  • 事件驱动架构:采用异步非阻塞 I/O 模型,能够高效处理大量并发连接

  • 模块化设计:通过模块扩展功能,支持自定义开发

  • 低内存消耗:特别是在处理静态文件时表现优异

  • 高稳定性:能够长时间运行而不需要重启

支持的协议:

  • HTTP/1.0、HTTP/1.1、HTTP/2

  • HTTPS(SSL/TLS)

  • SMTP、POP3、IMAP(作为邮件代理)

  • WebSocket

  • gRPC

应用场景:

  • 静态内容服务

  • 动态内容反向代理

  • API 网关

  • 负载均衡

  • 内容缓存

  • SSL 终端


🧩 2. Nginx 的特性

详细解析:

2.1 反向代理 / L7 负载均衡器

bash 复制代码
upstream backend {
    server 10.0.0.1:8080 weight=3;
    server 10.0.0.2:8080 weight=2;
    server 10.0.0.3:8080 backup;
}

server {
    location / {
        proxy_pass http://backend;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

负载均衡算法:

  • 轮询(默认)

  • 最少连接(least_conn)

  • IP 哈希(ip_hash)

  • 加权轮询

2.2 嵌入式 Perl 解释器

  • 允许在配置文件中嵌入 Perl 代码

  • 支持复杂的请求处理逻辑

  • 逐渐被 Lua 模块(OpenResty)替代

2.3 动态二进制升级

bash

复制代码
# 无需停止服务即可升级
nginx -s upgrade

优势:

  • 零停机时间更新

  • 保持现有连接不中断

  • 回滚机制

2.4 URL 重写与 PCRE 支持

bash 复制代码
location /products {
    rewrite ^/products/(.*)$ /items/$1 permanent;
}

location ~* \.(jpg|jpeg|png|gif)$ {
    expires 30d;
    add_header Cache-Control "public";
}

⚖️ 3. Nginx 与 Apache 的不同点

详细对比:

特性 Nginx Apache
架构模型 事件驱动、异步非阻塞 多进程/多线程、同步阻塞
并发处理 单进程可处理数万并发 受限于进程/线程数量
内存使用 较低且稳定 随并发数线性增长
静态内容 性能极高 性能一般
动态内容 需转发给后端处理器 内置模块支持(如 mod_php)
配置方式 集中式配置,不支持 .htaccess 支持分布式 .htaccess
热部署 支持 有限支持
学习曲线 较陡峭 相对平缓

选择建议:

  • 选择 Nginx:高并发、静态内容多、内存受限

  • 选择 Apache:需要 .htaccess、共享主机环境、传统应用


🔁 4. Nginx 如何处理 HTTP 请求?

详细架构解析:

4.1 事件驱动模型

c

bash 复制代码
// 伪代码表示事件循环
while (true) {
    events = epoll_wait(epoll_fd, events_list, MAX_EVENTS, -1);
    for (i = 0; i < events; i++) {
        if (events_list[i].events & EPOLLIN) {
            // 处理读事件
            handle_read_event(events_list[i].data.fd);
        }
        if (events_list[i].events & EPOLLOUT) {
            // 处理写事件
            handle_write_event(events_list[i].data.fd);
        }
    }
}

4.2 请求处理流程

  1. 接收连接:Worker 进程接受新连接

  2. 解析请求:解析 HTTP 头部,确定虚拟主机

  3. 匹配 Location:根据 URI 匹配 location 块

  4. 处理请求:执行相应的处理逻辑(静态文件、代理等)

  5. 生成响应:构建 HTTP 响应

  6. 发送响应:异步发送响应数据

4.3 多进程架构

bash 复制代码
Master Process (PID: 1001)
├── Worker Process (PID: 1002) → 处理连接 A、C、E...
├── Worker Process (PID: 1003) → 处理连接 B、D、F...
└── Cache Manager/Loader (PID: 1004)

🚫 5. 如何使用未定义的服务器名称阻止请求?

详细配置说明:

bash 复制代码
# 方法1:使用空服务器名
server {
    listen 80;
    server_name "";
    return 444;  # Nginx 自定义状态码,关闭连接
}

# 方法2:默认服务器捕获所有未匹配请求
server {
    listen 80 default_server;
    server_name _;
    deny all;
    return 444;
}

# 方法3:针对特定非法域名
server {
    listen 80;
    server_name malicious.com *.hacker.org;
    access_log off;
    error_log off;
    return 444;
}

应用场景:

  • 防止域名恶意指向

  • 阻止扫描器探测

  • 减少无效请求的资源消耗


🛡️ 6. 反向代理服务器的优点

详细优势分析:

6.1 安全性增强

bash 复制代码
# 隐藏后端服务器信息
proxy_pass http://backend;
proxy_hide_header X-Powered-By;
proxy_hide_header Server;

# 添加安全头
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;

6.2 负载均衡

bash 复制代码
upstream app_servers {
    zone backend 64k;
    least_conn;
    
    server 10.1.1.1:8080 max_fails=3 fail_timeout=30s;
    server 10.1.1.2:8080 max_fails=3 fail_timeout=30s;
    server 10.1.1.3:8080 max_fails=3 fail_timeout=30s backup;
}

6.3 内容缓存

bash 复制代码
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=my_cache:10m;

location / {
    proxy_cache my_cache;
    proxy_cache_valid 200 302 10m;
    proxy_cache_valid 404 1m;
    proxy_pass http://backend;
}

6.4 SSL 终端

bash 复制代码
server {
    listen 443 ssl;
    ssl_certificate /path/to/cert.pem;
    ssl_certificate_key /path/to/key.pem;
    
    location / {
        proxy_pass http://backend;  # 后端使用 HTTP
    }
}

🚀 7. Nginx 的最佳用途

详细应用场景:

7.1 静态内容服务

bash 复制代码
server {
    location ~* \.(css|js|png|jpg|jpeg|gif|ico|svg)$ {
        expires 1y;
        add_header Cache-Control "public, immutable";
        access_log off;
    }
    
    location /static/ {
        alias /var/www/static/;
        autoindex off;
    }
}

7.2 动态内容代理

bash 复制代码
# Spring Boot 应用 (内嵌 Tomcat/Jetty)
location /spring-boot/ {
    # 代理到 Spring Boot 应用
    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;
    proxy_set_header X-Forwarded-Host $host;
    proxy_set_header X-Forwarded-Port $server_port;
    
    # 超时设置
    proxy_connect_timeout 30s;
    proxy_send_timeout 30s;
    proxy_read_timeout 30s;
    
    # 缓冲设置
    proxy_buffering on;
    proxy_buffer_size 4k;
    proxy_buffers 8 4k;
    
    # 启用 WebSocket 支持
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
}

# Spring Boot Actuator 端点
location /spring-boot/actuator/ {
    proxy_pass http://127.0.0.1:8080/actuator/;
    proxy_set_header Host $host;
    
    # 安全限制
    allow 192.168.1.0/24;
    allow 10.0.0.0/8;
    deny all;
    
    access_log off;
}

7.3 负载均衡器

bash 复制代码
upstream microservices {
    zone upstreams 64k;
    
    server api1.example.com:8080 weight=2;
    server api2.example.com:8081;
    server api3.example.com:8082 backup;
    
    # 健康检查
    health_check interval=5s fails=3 passes=2;
}

👨‍💼 8. Master 和 Worker 进程

详细进程架构:

8.1 Master 进程职责

bash 复制代码
# 查看进程树
$ pstree -p | grep nginx
nginx(1001)─┬─nginx(1002)
            ├─nginx(1003)
            ├─nginx(1004)
            └─nginx(1005)

Master 进程功能:

  • 读取和验证配置文件

  • 绑定监听端口

  • 管理 Worker 进程(启动、停止、重启)

  • 平滑升级二进制文件

  • 重新打开日志文件

8.2 Worker 进程职责

bash 复制代码
# 配置 Worker 进程
worker_processes auto;  # CPU 核心数
worker_cpu_affinity auto;
worker_rlimit_nofile 100000;  # 文件描述符限制

events {
    worker_connections 10240;  # 每个 Worker 最大连接数
    use epoll;  # 事件模型
    multi_accept on;
}

Worker 进程特性:

  • 独立的进程,互不影响

  • 处理实际的网络连接

  • 使用异步非阻塞 I/O

  • 可配置的 CPU 亲和性


🔧 9. 如何在非 80 端口启动 Nginx?

详细配置方法:

9.1 修改默认配置文件

bash 复制代码
# /etc/nginx/sites-available/default
server {
    listen 8080;  # 改为 8080 端口
    listen [::]:8080;
    
    server_name example.com;
    root /var/www/html;
    
    index index.html index.htm;
}

9.2 多端口监听

bash 复制代码
server {
    listen 80;
    listen 443 ssl;
    listen 8080;
    listen 8443 ssl;
    
    server_name example.com;
    # ... 其他配置
}

9.3 SELinux 环境下的注意事项

bash 复制代码
# 检查当前端口上下文
semanage port -l | grep http

# 添加新端口
semanage port -a -t http_port_t -p tcp 8080

# 重启 Nginx
systemctl restart nginx

9.4 防火墙配置

bash 复制代码
# 开放端口
ufw allow 8080/tcp
firewall-cmd --permanent --add-port=8080/tcp
firewall-cmd --reload

❗ 10. 替换错误为 502/503

详细错误处理配置:

10.1 基本错误页面配置

bash 复制代码
http {
    # 定义错误页面
    error_page 500 502 503 504 /50x.html;
    error_page 404 /404.html;
    
    location = /50x.html {
        root /usr/share/nginx/html;
        internal;
    }
    
    location = /404.html {
        root /usr/share/nginx/html;
        internal;
    }
}

10.2 动态错误处理

bash 复制代码
location /api/ {
    proxy_pass http://backend;
    proxy_intercept_errors on;
    
    # 将 502 错误转换为 503
    error_page 502 =503 /maintenance.html;
    
    # 自定义错误处理
    error_page 404 = @fallback;
    error_page 500 502 503 504 = @down;
}

location @fallback {
    try_files $uri $uri/ @proxy;
}

location @down {
    add_header Retry-After 3600;
    return 503 "Service temporarily unavailable";
}

10.3 FastCGI 错误拦截

bash 复制代码
location ~ \.php$ {
    fastcgi_pass unix:/var/run/php/php-fpm.sock;
    fastcgi_intercept_errors on;
    
    # 拦截 FastCGI 错误
    error_page 500 502 503 504 /error.php;
    
    include fastcgi_params;
}

🔗 11. 保留 URL 中的双斜线

详细配置说明:

11.1 merge_slashes 指令

bash 复制代码
server {
    # 关闭斜线合并
    merge_slashes off;
    
    location /api/ {
        # 某些路径允许双斜线
        merge_slashes off;
        proxy_pass http://backend;
    }
    
    location /static/ {
        # 静态资源通常不需要双斜线
        merge_slashes on;
        try_files $uri $uri/ =404;
    }
}

11.2 应用场景

  • API 路径/api/v1//users 可能需要保留双斜线

  • 文件路径//share//file.txt 特殊文件系统

  • URL 重写:保留原始 URL 结构

11.3 正则表达式处理

bash 复制代码
location ~* "^//+(.*)$" {
    # 处理多个斜线开头的请求
    rewrite "^//+(.*)$" /$1 break;
    proxy_pass http://backend;
}

🔁 12. ngx_http_upstream_module 的作用

详细模块功能:

12.1 上游服务器定义

bash 复制代码
upstream backend {
    # 基础配置
    server 10.0.1.1:8080;
    server 10.0.1.2:8080;
    
    # 负载均衡方法
    least_conn;  # 最少连接
    
    # 健康检查
    health_check interval=5s fails=3 passes=2;
}

12.2 服务器参数详解

bash 复制代码
upstream app_servers {
    # 服务器状态
    server 10.0.1.1:8080 weight=5;    # 主服务器,权重高
    server 10.0.1.2:8080 weight=3;    # 次要服务器
    server 10.0.1.3:8080 down;        # 停机维护
    server 10.0.1.4:8080 backup;      # 备份服务器
    
    # 故障转移设置
    server 10.0.1.5:8080 max_fails=3 fail_timeout=30s;
    
    # 解析器用于动态 DNS
    resolver 8.8.8.8 valid=30s;
}

12.3 代理配置

bash 复制代码
location / {
    proxy_pass http://backend;
    
    # 超时设置
    proxy_connect_timeout 5s;
    proxy_send_timeout 10s;
    proxy_read_timeout 30s;
    
    # 缓冲设置
    proxy_buffering on;
    proxy_buffer_size 4k;
    proxy_buffers 8 4k;
    
    # 重试机制
    proxy_next_upstream error timeout invalid_header;
    proxy_next_upstream_tries 3;
    proxy_next_upstream_timeout 30s;
}

💥 13. 什么是 C10K 问题?

详细技术解析:

13.1 问题定义

C10K(Concurrent 10,000 Connections)指的是服务器同时处理一万个并发连接的技术挑战。

13.2 传统服务器的限制

c

bash 复制代码
// 传统阻塞 I/O 模型
while (1) {
    client_fd = accept(server_fd);  // 阻塞
    read(client_fd, buffer);        // 阻塞
    process_request(buffer);
    write(client_fd, response);     // 阻塞
    close(client_fd);
}

13.3 Nginx 的解决方案

c

bash 复制代码
// 事件驱动模型
while (1) {
    n = epoll_wait(epoll_fd, events, MAX_EVENTS, -1);
    for (i = 0; i < n; i++) {
        if (events[i].data.fd == server_fd) {
            // 接受新连接
            client_fd = accept(server_fd);
            set_nonblocking(client_fd);
            add_to_epoll(client_fd);
        } else {
            // 处理现有连接
            handle_client(events[i].data.fd);
        }
    }
}

13.4 现代解决方案

  • I/O 多路复用:epoll(Linux)、kqueue(BSD)

  • 异步 I/O:io_uring(Linux)

  • 用户态网络栈 :DPDK、FD.io


📊 14. stub_status 和 sub_filter 指令

详细功能说明:

14.1 stub_status 指令

bash 复制代码
# 启用状态页面
server {
    listen 80;
    server_name status.example.com;
    
    location /nginx_status {
        stub_status on;
        access_log off;
        allow 192.168.1.0/24;
        deny all;
    }
}

状态信息解读:

bash 复制代码
Active connections: 291
server accepts handled requests
 16630948 16630948 31070465
Reading: 6 Writing: 179 Waiting: 106
  • Active connections:当前活跃连接数

  • accepts:接受的客户端连接总数

  • handled:处理的连接数

  • requests:客户端请求总数

  • Reading:正在读取请求头的连接数

  • Writing:正在写入响应的连接数

  • Waiting:空闲客户端连接数

14.2 sub_filter 指令

bash 复制代码
location / {
    proxy_pass http://backend;
    
    # 内容替换
    sub_filter 'http://old-domain.com' 'https://new-domain.com';
    sub_filter 'Old Text' 'New Text';
    sub_filter_once off;  # 替换所有出现
    sub_filter_types text/html text/css;  # 指定 MIME 类型
    
    # 响应头修改
    sub_filter_last_modified on;
}

应用场景:

  • 域名迁移

  • 内容更新

  • A/B 测试

  • 错误修复


🗜️ 15. 是否支持将请求压缩到上游?

详细压缩配置:

15.1 响应解压缩(gunzip)

bash 复制代码
# 启用解压缩模块
http {
    gunzip on;
    gunzip_buffers 16 8k;
    
    location / {
        proxy_pass http://backend;
        
        # 如果后端返回压缩内容,但客户端不支持
        gunzip on;
    }
}

15.2 请求压缩

bash 复制代码
# 向上游发送压缩请求
location /api/ {
    proxy_pass http://backend;
    
    # 启用请求体压缩
    proxy_set_header Accept-Encoding "gzip";
    
    # 压缩请求体(需要相应模块)
    client_body_in_file_only clean;
    client_body_buffer_size 128K;
}

15.3 响应压缩(gzip)

bash 复制代码
http {
    gzip on;
    gzip_vary on;
    gzip_min_length 1024;
    gzip_comp_level 6;
    gzip_types
        text/plain
        text/css
        text/xml
        text/javascript
        application/javascript
        application/xml+rss
        application/json;
    
    # 预压缩文件支持
    gzip_static on;
}

⏰ 16. 如何在 Nginx 中获得当前的时间?

详细时间变量:

16.1 内置时间变量

bash 复制代码
server {
    location /time {
        # 返回当前时间
        add_header Content-Type "text/plain";
        return 200 "GMT: $date_gmt\nLocal: $date_local\n";
    }
    
    location /api/ {
        proxy_pass http://backend;
        
        # 传递时间戳给后端
        proxy_set_header X-Request-Time $msec;
        proxy_set_header X-Request-Date $date_gmt;
    }
}

16.2 可用时间变量

  • $date_gmt:GMT 格式的当前时间

  • $date_local:本地时区格式的当前时间

  • $time_iso8601:ISO 8601 格式时间

  • $time_local:本地时间的通用日志格式

  • $msec:带毫秒的 Unix 时间戳

16.3 SSI 模块时间显示

bash 复制代码
location /ssi-page {
    ssi on;
    
    # 在 HTML 中嵌入时间
    # <!--# echo var="date_gmt" -->
    # <!--# config timefmt="%Y-%m-%d %H:%M:%S" -->
}

⚙️ 17. Nginx -s 参数的作用

详细信号管理:

17.1 常用信号命令

bash 复制代码
# 重新加载配置(平滑重启)
nginx -s reload

# 立即停止
nginx -s stop

# 优雅停止(处理完当前请求)
nginx -s quit

# 重新打开日志文件(用于日志轮转)
nginx -s reopen

17.2 信号对应关系

bash 复制代码
# 直接向进程发送信号
kill -HUP $(cat /var/run/nginx.pid)    # 等同于 reload
kill -QUIT $(cat /var/run/nginx.pid)   # 等同于 quit
kill -TERM $(cat /var/run/nginx.pid)   # 等同于 stop
kill -USR1 $(cat /var/run/nginx.pid)   # 等同于 reopen

17.3 信号处理流程

bash 复制代码
用户命令: nginx -s reload
    ↓
发送 HUP 信号给 Master 进程
    ↓
Master 检查新配置语法
    ↓
启动新的 Worker 进程
    ↓
优雅关闭旧的 Worker 进程
    ↓
完成平滑重启

🧩 18. 如何在 Nginx 中添加模块?

详细模块管理:

18.1 编译时添加模块

bash 复制代码
# 查看当前已编译模块
nginx -V

# 下载 Nginx 源码
wget http://nginx.org/download/nginx-1.24.0.tar.gz
tar -zxvf nginx-1.24.0.tar.gz
cd nginx-1.24.0

# 配置编译参数(包含现有模块和新模块)
./configure \
    --prefix=/etc/nginx \
    --sbin-path=/usr/sbin/nginx \
    --modules-path=/usr/lib/nginx/modules \
    --with-http_ssl_module \
    --with-http_v2_module \
    --with-http_stub_status_module \
    --add-module=/path/to/custom-module \
    --add-dynamic-module=/path/to/dynamic-module

# 编译和安装
make
make install

18.2 动态模块加载

bash 复制代码
# 在 nginx.conf 中加载动态模块
load_module modules/ngx_http_geoip_module.so;
load_module modules/ngx_stream_geoip_module.so;

http {
    # 使用动态模块
    geoip_country /usr/share/GeoIP/GeoIP.dat;
}

18.3 常用第三方模块

  • OpenResty:LuaJIT 支持

  • Headers More:增强的头部控制

  • Cache Purge:缓存清理

  • Fancy Index:美观的目录列表

18.4 模块开发基础

c

bash 复制代码
// 简单的 Hello World 模块
#include <ngx_config.h>
#include <ngx_core.h>
#include <ngx_http.h>

static ngx_int_t ngx_http_hello_handler(ngx_http_request_t *r) {
    ngx_str_t response = ngx_string("Hello, Nginx Module!");
    
    r->headers_out.status = NGX_HTTP_OK;
    r->headers_out.content_length_n = response.len;
    
    ngx_http_send_header(r);
    return ngx_http_output_filter(r, &response);
}
相关推荐
nandezizai_ddc2 小时前
Debian 初始设置
运维·debian
远程软件小帮手2 小时前
好用的远程软件!ToDesk、向日葵、UU远程横测
运维·服务器·游戏·电脑
std78792 小时前
核电站里,机器人当起“侦察兵”
运维·安全·机器人
HIT_Weston2 小时前
30、【Ubuntu】【远程开发】内网穿透:反向隧道建立(二)
linux·运维·ubuntu
Percep_gan2 小时前
在Linux中安装字体
linux·运维·服务器
q***49453 小时前
如何安装配置Goland并使用固定公网地址SSH远程连接本地服务器
运维·服务器·ssh
Stella25213 小时前
【Jenkins/Termius/集群概念】
运维·servlet·jenkins
清清&3 小时前
【Linux】冯诺依曼体系结构和操作系统的理解
linux·运维·服务器
Crazy________3 小时前
37负载均衡介绍和nginx模块编译安装
运维·nginx·负载均衡