🌍 第18课:Web服务器(nginx)

阶段三:网络配置第6/6课

📚 课程目标

一、Nginx架构

         ┌── Worker Process 1 ──→ 事件循环(epoll)
Master ──┼── Worker Process 2 ──→ 事件循环
Process  ├── Worker Process 3 ──→ 事件循环
         └── Worker Process N ──→ 事件循环

# Master: 读取配置、管理Worker、平滑升级
# Worker: 处理请求、非阻塞IO、事件驱动

1.1 Nginx vs Apache

特性NginxApache
模型事件驱动进程/线程
并发高(C10K+)
静态文件极快
动态处理反向代理到后端内置模块
内存
配置简洁灵活但复杂

二、Nginx安装与基础

$ nginx -v 2>&1
/bin/sh: 1: nginx: not found
nginx not installed
# 安装
sudo apt install nginx     # Debian/Ubuntu
sudo yum install nginx     # RHEL/CentOS

# 服务管理
sudo systemctl enable --now nginx
sudo systemctl reload nginx    # 重载配置(平滑)
sudo systemctl restart nginx   # 重启(中断服务)

# 配置文件结构
/etc/nginx/nginx.conf          # 主配置
/etc/nginx/sites-available/    # 可用站点(Debian)
/etc/nginx/sites-enabled/      # 启用站点
/etc/nginx/conf.d/             # 额外配置(RHEL)
/etc/nginx/mime.types          # MIME类型

三、核心配置

$ cat /etc/nginx/nginx.conf | head -30
user www-data;
worker_processes auto;
pid /run/nginx.pid;
error_log /var/log/nginx/error.log;
include /etc/nginx/modules-enabled/*.conf;

events {
	worker_connections 768;
	# multi_accept on;
}

http {

	##
	# Basic Settings
	##

	sendfile on;
	tcp_nopush on;
	types_hash_max_size 2048;
	# server_tokens off;

	# server_names_hash_bucket_size 64;
	# server_name_in_redirect off;

	include /etc/nginx/mime.types;
	default_type application/octet-stream;

	##
	# SSL Settings

3.1 主配置结构

# /etc/nginx/nginx.conf
user www-data;
worker_processes auto;           # CPU核心数
worker_rlimit_nofile 65535;

events {
    worker_connections 4096;     # 每Worker最大连接数
    use epoll;                   # Linux最佳IO模型
    multi_accept on;
}

http {
    include       mime.types;
    default_type  application/octet-stream;

    sendfile    on;
    tcp_nopush  on;
    tcp_nodelay on;
    keepalive_timeout 65;

    gzip on;
    gzip_types text/plain text/css application/json;

    include /etc/nginx/conf.d/*.conf;
    include /etc/nginx/sites-enabled/*;
}

3.2 虚拟主机(Server Block)

# /etc/nginx/sites-available/example.com
server {
    listen 80;
    server_name example.com www.example.com;
    root /var/www/example.com;
    index index.html index.php;

    access_log /var/log/nginx/example.com.access.log;
    error_log  /var/log/nginx/example.com.error.log;

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

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

# 启用站点
sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx

四、反向代理

# 基本反向代理
server {
    listen 80;
    server_name api.example.com;

    location / {
        proxy_pass http://127.0.0.1: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;
        proxy_set_header X-Forwarded-Proto $scheme;
    }

    # WebSocket代理
    location /ws/ {
        proxy_pass http://127.0.0.1:3001;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
}

五、负载均衡

upstream backend {
    # 轮询(默认)
    server 192.168.1.10:8080;
    server 192.168.1.11:8080;

    # 加权轮询
    # server 192.168.1.10:8080 weight=3;
    # server 192.168.1.11:8080 weight=1;

    # IP哈希(会话保持)
    # ip_hash;

    # 最少连接
    # least_conn;

    # 健康检查
    # server 192.168.1.12:8080 backup;  # 备用服务器
}

server {
    listen 80;
    location / {
        proxy_pass http://backend;
    }
}

六、HTTPS配置

# 使用Let's Encrypt免费证书
sudo apt install certbot python3-certbot-nginx
sudo certbot --nginx -d example.com -d www.example.com

# 自动续期
sudo certbot renew --dry-run   # 测试续期

# 手动HTTPS配置
server {
    listen 443 ssl http2;
    server_name example.com;

    ssl_certificate     /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;
    ssl_prefer_server_ciphers on;
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 10m;
}

# HTTP重定向HTTPS
server {
    listen 80;
    server_name example.com;
    return 301 https://$server_name$request_uri;
}

七、性能优化

# 开启gzip压缩
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_types text/plain text/css application/json application/javascript;

# 静态文件缓存
location ~* \.(jpg|jpeg|png|gif|ico|css|js|woff2)$ {
    expires 30d;
    add_header Cache-Control "public, immutable";
}

# 连接优化
keepalive_timeout 65;
keepalive_requests 1000;

# 缓冲优化
proxy_buffer_size 4k;
proxy_buffers 8 4k;

# 文件句柄缓存
open_file_cache max=1000 inactive=20s;
open_file_cache_valid 30s;

八、故障排查

❌ 502 Bad Gateway

# 后端服务未运行或不可达
# 1. 检查后端
curl http://127.0.0.1:3000/health

# 2. 检查nginx错误日志
sudo tail -20 /var/log/nginx/error.log

# 3. 检查SELinux/AppArmor
sudo setenforce 0  # 临时关闭SELinux测试

❌ 配置语法错误

# 检查配置语法
sudo nginx -t

# 查看加载的配置
sudo nginx -T

九、练习

📝 Nginx配置实战

# 1. 查看当前配置
cat /etc/nginx/nginx.conf | head -30
ls /etc/nginx/sites-enabled/

# 2. 测试配置语法
sudo nginx -t

# 3. 查看日志
sudo tail /var/log/nginx/access.log 2>/dev/null | tail -5
sudo tail /var/log/nginx/error.log 2>/dev/null | tail -5
🏆

成就解锁:Web服务器管理员

✅ 理解Nginx架构

✅ 掌握虚拟主机配置

✅ 学会反向代理与负载均衡

✅ 掌握HTTPS配置

✅ 了解性能优化技巧

🎉 阶段三(网络配置)完成!下一阶段:Shell脚本

十、Nginx日志分析

# 访问日志格式
# log_format main '$remote_addr - $remote_user [$time_local] '
#                  '"$request" $status $body_bytes_sent '
#                  '"$http_referer" "$http_user_agent"';

# 分析TOP 10访问IP
awk '{{print $1}}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -10

# 统计HTTP状态码
awk '{{print $9}}' /var/log/nginx/access.log | sort | uniq -c | sort -rn

# 统计每分钟请求数
awk '{print $4}' /var/log/nginx/access.log | cut -d: -f1,2,3 | sort | uniq -c

# 找出最慢的请求
awk '{{print $NF, $0}}' /var/log/nginx/access.log | sort -rn | head -10

# GoAccess实时分析
sudo apt install goaccess
sudo goaccess /var/log/nginx/access.log -o /var/www/html/report.html --real-time-html

十一、Nginx安全配置

# 安全头
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Content-Security-Policy "default-src 'self'" always;

# 禁止敏感文件访问
location ~ /\. {{
    deny all;
    access_log off;
    log_not_found off;
}}

# 限制请求速率
limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;
location /api/ {{
    limit_req zone=api burst=20 nodelay;
    proxy_pass http://backend;
}}

# IP访问限制
allow 192.168.1.0/24;
allow 10.0.0.0/8;
deny all;

十二、Nginx监控

# 启用stub_status
location /nginx_status {{
    stub_status on;
    access_log off;
    allow 127.0.0.1;
    deny all;
}}

# Prometheus nginx-prometheus-exporter
# 导出更详细的指标供Prometheus采集

十三、Nginx配置模板

# 通用Web服务器模板 /etc/nginx/sites-available/generic
server {{
    listen 80;
    server_name _;
    return 301 https://$host$request_uri;
}}

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

    # SSL
    ssl_certificate     /etc/ssl/certs/example.com.crt;
    ssl_certificate_key /etc/ssl/private/example.com.key;
    ssl_protocols TLSv1.2 TLSv1.3;

    # 安全头
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

    # 日志
    access_log /var/log/nginx/example.com.access.log;
    error_log  /var/log/nginx/example.com.error.log;

    # 静态文件
    root /var/www/example.com/public;
    index index.html;

    # Gzip
    gzip on;
    gzip_types text/plain text/css application/json application/javascript text/xml;

    location / {{
        try_files $uri $uri/ /index.html;
    }}

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

    # 静态资源缓存
    location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff2)$ {{
        expires 30d;
        add_header Cache-Control "public, immutable";
    }}
}}

十四、Nginx速率限制

# 连接数限制
limit_conn_zone $binary_remote_addr zone=connlimit:10m;
limit_conn connlimit 20;  # 每IP最多20个并发连接

# 请求速率限制
limit_req_zone $binary_remote_addr zone=ratelimit:10m rate=10r/s;
location /api/ {{
    limit_req zone=ratelimit burst=20 nodelay;
    # burst: 允许突发20个请求
    # nodelay: 突发请求不延迟处理
}}

# 带宽限制
location /download/ {{
    limit_rate 500k;   # 限速500KB/s
    limit_rate_after 10m;  # 前10MB不限速
}}

# 自定义错误响应
limit_req_status 429;

十五、Nginx与PHP-FPM

# 安装PHP-FPM
sudo apt install php-fpm php-mysql

# Nginx配置PHP
server {{
    listen 80;
    server_name example.com;
    root /var/www/example.com;
    index index.php index.html;

    location ~ \.php$ {{
        fastcgi_pass unix:/run/php/php8.1-fpm.sock;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
    }}
}}

# PHP-FPM优化
# /etc/php/8.1/fpm/pool.d/www.conf
pm = dynamic
pm.max_children = 50
pm.start_servers = 5
pm.min_spare_servers = 3
pm.max_spare_servers = 10
pm.max_requests = 1000