一、Nginx 基础:源码编译 + 服务管理
1. 源码编译
核心步骤
bash
# 1. 装依赖(少一个编译会跪)
dnf install gcc openssl-devel pcre2-devel zlib-devel -y
# 2. 编译配置(记核心参数,其余按需加)
./configure \
--prefix=/usr/local/nginx \ # 安装根路径(固定好记)
--user=nginx --group=nginx \ # 普通用户运行,规避权限风险
--with-http_ssl_module \ # 必开:支持HTTPS
--with-stream \ # 必开:支持四层负载(TCP/UDP)
--with-http_stub_status_module # 可选:监控Nginx状态
# 3. 编译+安装(make别加-j,容易崩掉)
make && make install
配套操作
- 创建专用用户:
useradd -s /sbin/nologin -M nginx; - 环境变量:
vim ~/.bash_profile加PATH=/usr/local/nginx/sbin:$PATH,source生效; - 系统服务:写
nginx.service文件,实现systemctl管理(开机自启 / 重启)。
2. 平滑升级 / 回滚
- 升级逻辑:编译新版本→替换二进制文件→发信号
kill -USR2 主进程ID,不中断服务; - 回滚逻辑:备份新文件→替换回旧二进制→
kill -HUP 主进程ID→kill -WINCH 新进程ID回收; - 核心考点:别用
kill -9!面试问 "Nginx 升级不中断服务的原理",就说 "信号控制进程替换"。
二、Nginx 核心配置:从基础到实用
1. 虚拟主机 & 路径匹配
location 匹配优先级(记死):=(精确)> ^~(前缀)> ~/~*(正则)> 无符号(模糊)
root vs alias(易混点):
- root:路径拼接(
root /a+ 访问/b→/a/b) - alias:路径替换(
alias /a+ 访问/b→/a)
2. 实用小功能
| 功能 | 核心配置 / 操作 |
|---|---|
| 访问认证 | htpasswd -cmb .htpasswd 用户名 密码 + auth_basic + auth_basic_user_file |
| 自定义错误页 | error_page 404/502 /error.html,搭配 alias 指向自定义页面 |
| 下载服务器 | autoindex on(列表)+ limit_rate 1024k(控速)+ autoindex_localtime on(时间优化) |
| 防盗链 | valid_referers + if ($invalid_referer),非法来源返回 404 / 跳转防盗链图片 |
| 长连接优化 | 配置keepalive_timeout(时长)+ keepalive_requests(次数),减少握手开销 |
3. 反向代理 & 负载均衡
七层代理(HTTP/HTTPS)
- 基础配置:定义
upstream集群,proxy_pass转发,weight调权重,backup设备用节点; - 进阶优化:
- 动静分离:
.php/.jsp转发给后端(Tomcat/PHP-FPM),静态文件 Nginx 直接处理; - 缓存加速:
proxy_cache缓存动态页面,压测 QPS 直接翻倍; - 透传信息:
proxy_set_header X-Forwarded-For $remote_addr,让后端拿到真实客户端 IP。
四层代理(TCP/UDP)
核心:开启stream模块,可代理 MySQL(3306/TCP)、DNS(53/UDP);
配置示例:
stream {
upstream mysql_server {
server 172.25.254.10:3306 max_fails=3 fail_timeout=30s;
server 172.25.254.20:3306 max_fails=3 fail_timeout=30s;
}
server {
listen 172.25.254.100:3306;
proxy_pass mysql_server;
}
}
三、进阶拓展:Nginx + 生态整合
实验 1:Nginx 防 DDOS 攻击(安全防护必做)
实验目标
限制单个 IP 的并发连接数和请求频率,抵御简单的 CC/DDOS 攻击,保护后端服务。
核心原理
利用limit_conn_zone(限制并发连接)+limit_req_zone(限制请求频率),结合共享内存记录 IP 状态。
完整代码 & 步骤
bash
# /usr/local/nginx/conf/conf.d/anti_ddos.conf
http {
# 1. 定义连接数限制:共享内存conn_limit,key为IP,大小10M
limit_conn_zone $remote_addr zone=conn_limit:10m;
# 2. 定义请求频率限制:10r/s(每秒10次),桶容量20
limit_req_zone $remote_addr zone=req_limit:10m rate=10r/s;
server {
listen 80;
server_name anti-ddos.timinglee.org;
location / {
root /usr/local/nginx/html;
# 限制单个IP最大并发连接数10
limit_conn conn_limit 10;
# 限制请求频率:burst=20(突发请求缓冲),nodelay(不延迟处理)
limit_req zone=req_limit burst=20 nodelay;
# 超过限制返回503
limit_req_status 503;
limit_conn_status 503;
}
}
}
bash
# 验证效果(用ab压测)
ab -n 1000 -c 50 http://anti-ddos.timinglee.org/
# 效果:超过10并发/10r/s的请求返回503,后端服务不会被打垮!
实验 2:Nginx 日志切割 + ELK 分析
实验目标
解决 Nginx 日志越积越大的问题,自动切割日志,并对接 ELK(Elasticsearch+Logstash+Kibana)分析日志。
步骤 1:日志自动切割(用 shell 脚本 + 定时任务)
bash
# /root/nginx_log_cut.sh
#!/bin/bash
# 日志目录
LOG_DIR="/usr/local/nginx/logs"
# 昨天的日期
YESTERDAY=$(date -d "yesterday" +%Y%m%d)
# 切割access.log
mv $LOG_DIR/access.log $LOG_DIR/access_$YESTERDAY.log
# 向Nginx主进程发信号,重新生成日志文件
kill -USR1 $(cat $LOG_DIR/nginx.pid)
# 删除7天前的旧日志
find $LOG_DIR -name "access_*.log" -mtime +7 -delete
bash
# 加执行权限+定时任务(每天0点执行)
chmod +x /root/nginx_log_cut.sh
echo "0 0 * * * /root/nginx_log_cut.sh" >> /var/spool/cron/root
crontab -l # 验证定时任务
步骤 2:ELK 对接日志
bash
# Logstash配置文件 /etc/logstash/conf.d/nginx_log.conf
input {
file {
path => "/usr/local/nginx/logs/access_*.log"
start_position => "beginning"
sincedb_path => "/dev/null"
}
}
filter {
grok {
match => { "message" => "%{HTTPD_COMBINEDLOG}" }
}
date {
match => [ "timestamp", "dd/MMM/yyyy:HH:mm:ss Z" ]
}
}
output {
elasticsearch {
hosts => ["172.25.254.40:9200"] # ES地址
index => "nginx-access-%{+YYYY.MM.dd}"
}
stdout { codec => rubydebug }
}
验证效果
启动 Logstash 后,Kibana 可可视化查看:访问 IP 分布、请求状态码、热门接口、响应时间等,快速定位异常请求。
实验 3:Nginx 解决跨域问题
实验目标
前端访问不同域名的后端接口时,解决浏览器 "跨域限制" 问题。
核心原理
通过添加Access-Control-Allow-*响应头,允许指定域名跨域访问。
完整代码 & 步骤
bash
# /usr/local/nginx/conf/conf.d/cors.conf
server {
listen 80;
server_name api.timinglee.org;
location /api {
proxy_pass http://172.25.254.10:8080; # 后端接口地址
# 核心:跨域配置
add_header Access-Control-Allow-Origin *; # 允许所有域名(生产可指定具体域名)
add_header Access-Control-Allow-Methods "GET,POST,PUT,DELETE,OPTIONS"; # 允许的请求方法
add_header Access-Control-Allow-Headers "Content-Type,Authorization"; # 允许的请求头
# 处理OPTIONS预检请求
if ($request_method = OPTIONS) {
return 204; # 预检请求直接返回204,不转发到后端
}
}
}
验证效果
前端页面访问http://api.timinglee.org/api时,浏览器控制台不会再报 "CORS policy" 错误,正常请求数据。
实验 4:Nginx + Keepalived 实现高可用
实验目标
搭建双 Nginx 节点的高可用集群,主节点宕机后备节点自动接管 VIP,避免 Nginx 单点故障。
实验环境
| 节点 | IP 地址 | 角色 |
|---|---|---|
| Nginx 主节点 | 172.25.254.100 | MASTER |
| Nginx 备节点 | 172.25.254.101 | BACKUP |
| VIP | 172.25.254.200 | 对外访问 IP |
步骤 1:安装 Keepalived(两台节点都执行)
bash
dnf install keepalived -y
步骤 2:主节点 Keepalived 配置
bash
# /etc/keepalived/keepalived.conf
global_defs {
router_id NGINX_MASTER
}
# 监控Nginx状态:Nginx挂了就降低优先级
vrrp_script check_nginx {
script "/usr/bin/systemctl is-active nginx"
interval 2
weight -20
}
vrrp_instance VI_1 {
state MASTER
interface eth0 # 绑定VIP的网卡
virtual_router_id 51
priority 100 # 主节点优先级更高
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
172.25.254.200/24 # VIP地址
}
track_script {
check_nginx
}
}
步骤 3:备节点 Keepalived 配置
bash
global_defs {
router_id NGINX_BACKUP
}
vrrp_script check_nginx {
script "/usr/bin/systemctl is-active nginx"
interval 2
weight -20
}
vrrp_instance VI_1 {
state BACKUP
interface eth0
virtual_router_id 51
priority 90 # 优先级低于主节点
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
172.25.254.200/24
}
track_script {
check_nginx
}
}
步骤 4:启动 & 验证
bash
# 两台节点启动Keepalived
systemctl enable --now keepalived
# 验证1:主节点有VIP,备节点无
ip a show eth0 # 主节点能看到172.25.254.200
# 验证2:停掉主节点Nginx,VIP自动切到备节点
systemctl stop nginx # 主节点执行
ip a show eth0 # 备节点能看到VIP
实验 5:Docker+Nginx 容器化部署
实验目标
用 Docker 部署 Nginx,挂载配置 / 日志 / 静态文件目录,实现 "配置持久化、日志可查"。
步骤 1:准备目录结构
bash
mkdir -p /docker/nginx/{conf,conf.d,html,logs}
步骤 2:编写 Nginx 配置文件
bash
# /docker/nginx/conf/nginx.conf
worker_processes auto;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /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 /var/log/nginx/access.log main;
sendfile on;
keepalive_timeout 65;
include /etc/nginx/conf.d/*.conf;
}
bash
# /docker/nginx/conf.d/default.conf
server {
listen 80;
server_name localhost;
root /usr/share/nginx/html;
index index.html;
location / {
try_files $uri $uri/ =404;
}
}
步骤 3:启动 Docker 容器
bash
# 拉取Nginx镜像
docker pull nginx:1.28.1
# 启动容器(挂载目录+端口映射)
docker run -d \
--name nginx-docker \
-p 8080:80 \
-v /docker/nginx/conf/nginx.conf:/etc/nginx/nginx.conf \
-v /docker/nginx/conf.d:/etc/nginx/conf.d \
-v /docker/nginx/html:/usr/share/nginx/html \
-v /docker/nginx/logs:/var/log/nginx \
nginx:1.28.1
验证效果
bash
# 访问测试
curl http://172.25.254.100:8080
# 修改静态文件(容器内无需重启Nginx)
echo "Docker Nginx Test" > /docker/nginx/html/index.html
curl http://172.25.254.100:8080 # 立即生效
# 查看日志
cat /docker/nginx/logs/access.log