nginx相关面试题30道
一、基础概念与核心特性
1. 什么是 Nginx?它的主要用途有哪些?
答案:
Nginx 是一款高性能的开源 Web 服务器、反向代理服务器及负载均衡器,基于事件驱动的异步非阻塞架构,擅长处理高并发场景。
主要用途:
- 静态资源服务(HTML/CSS/JS/ 图片等)
- 反向代理与负载均衡(分发请求到后端服务器集群)
- API 网关(处理动态请求转发)
- 缓存服务(通过
proxy_cache
或fastcgi_cache
加速动态内容) - 实时消息代理(支持 WebSocket 长连接)
2. Nginx 相比 Apache 的核心优势是什么?
答案:
对比维度 | Nginx | Apache |
---|---|---|
架构 | 单主进程 + 多 worker 进程(异步非阻塞) | 多进程 / 线程(同步阻塞,如 prefork/worker) |
高并发性能 | 支持数万并发连接,内存占用低 | 并发能力较低,内存占用高 |
静态资源处理 | 原生高效,无需插件 | 需要mod_static 等插件 |
动态请求处理 | 需配合 FastCGI/Proxy 转发给后端 | 可通过模块(如mod_php )直接处理 |
配置灵活性 | 基于模块化设计,配置简洁 | 模块化丰富但配置较复杂 |
解析:Nginx 的异步非阻塞模型(基于 epoll/kqueue)避免了多线程 / 进程的上下文切换开销,适合高并发、低延迟场景;Apache 则在需要复杂模块(如 PHP 解析)时更便捷。
3. 解释 Nginx 的 Master-Worker 进程模型及其作用
答案:
- Master 进程:
- 读取并验证配置文件(
nginx.conf
) - 管理 Worker 进程(启动 / 停止 / 重启 / 平滑升级)
- 监听端口,将请求分发到 Worker 进程
- 读取并验证配置文件(
- Worker 进程:
- 实际处理客户端请求,单进程支持数千并发连接
- 通过
worker_connections
控制单个进程最大连接数 - 多 Worker 进程间通过负载均衡(如轮询)处理请求
优势:Master 负责管理,Worker 专注处理请求,实现资源隔离与高效并发。
4. 什么是反向代理?反向代理与正向代理的区别?
答案:
- 反向代理:位于服务器端,代理后端集群接收客户端请求,隐藏真实服务器地址。例如 Nginx 接收请求后转发到 Tomcat/Node.js 服务器。
- 正向代理:位于客户端侧,代理客户端向目标服务器发送请求(如浏览器通过代理访问外网)。
核心区别: - 反向代理代理的是服务器,客户端不知道真实后端;正向代理代理的是客户端,服务器不知道真实客户端 IP。
5. 简述 Nginx 处理 HTTP 请求的流程
答案:
- 客户端发送请求到 Nginx 监听端口(如 80/443)。
- Master 进程接收请求,分配给某个 Worker 进程。
- Worker 进程根据
server
块和location
匹配规则处理请求:- 若为静态资源,直接读取文件返回(如
root
/alias
指定路径)。 - 若为动态请求,通过
proxy_pass
/fastcgi_pass
转发到后端服务器。
- 若为静态资源,直接读取文件返回(如
- 后端服务器处理请求并返回结果,Nginx 将响应返回给客户端(可能经过缓存、压缩等处理)。
二、配置与优化
6. 如何配置 Nginx 监听多个端口?如何指定域名绑定?
答案:
server {listen 80; # 监听80端口listen 443 ssl; # 监听443端口并启用HTTPSserver_name example.com www.example.com; # 绑定域名# 配置HTTPS证书ssl_certificate /path/to/cert.pem;ssl_certificate_key /path/to/key.pem;
}
7. 如何实现 URL 重写(Rewrite)?举例说明场景
答案:
使用rewrite
指令结合正则表达式实现重写,场景如:
- 强制 HTTPS:
server {listen 80;server_name example.com;rewrite ^(.*)$ https://$server_name$1 permanent; # 301重定向 }
- 路径跳转:
location /old-path/ {rewrite ^/old-path/(.*)$ /new-path/$1 break; # 内部重写,不返回客户端 }
指令说明:permanent
(301)、redirect
(302)、break
(内部跳转)。
8. 如何配置 Nginx 禁止特定 IP 访问?
答案:
使用ngx_http_access_module
模块:
location / {deny 192.168.1.100; # 禁止单个IPdeny 192.168.1.0/24; # 禁止IP段allow all; # 允许其他IP
}
9. 如何优化 Nginx 的静态资源访问性能?
答案:
- 开启
sendfile
高效传输:http {sendfile on; # 直接通过内核传输文件,减少用户态/内核态拷贝tcp_nopush on; # 合并TCP包,减少网络IO }
- 配置缓存头(
Cache-Control
/Expires
):location ~* \.(js|css|png|jpg)$ {expires 7d; # 浏览器缓存7天add_header Cache-Control "public"; }
- 启用 Gzip 压缩:
gzip on; gzip_types text/css application/javascript;
10. 如何限制客户端请求频率(限流)?
答案:
使用ngx_http_limit_req_module
模块(漏桶算法):
http {limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s; # 按IP限流,每秒1请求server {location / {limit_req zone=one burst=5 nodelay; # 突发请求允许5个排队}}
}
Nginx 的惊群问题(Thundering Herd Problem)及解决方案
什么是惊群问题?
当多个进程(如 Nginx 的 Worker 进程)同时监听同一个端口时,若有新的连接请求到达,所有等待该端口的进程会被同时唤醒,但最终只有一个进程能成功处理连接,其他进程会重新进入休眠状态。这种现象称为 惊群效应(Thundering Herd Problem)。
影响:频繁的进程上下文切换会消耗 CPU 资源,降低服务器性能,尤其在高并发场景下更为明显。Nginx 惊群问题的触发场景
Nginx 使用 Master-Worker 多进程模型:
- Master 进程:负责管理 Worker 进程,监听端口并分配连接。
- Worker 进程:多个 Worker 进程共同监听 Master 进程打开的端口,等待处理客户端请求。
在旧版本的 Nginx(或未优化配置时),当新连接到达时,所有 Worker 进程会被唤醒并竞争处理连接,导致惊群效应。解决方案:利用
SO_REUSEPORT
套接字选项现代操作系统(如 Linux 3.9+、FreeBSD 10+)支持
SO_REUSEPORT
选项,允许 多个套接字绑定到同一 IP 地址和端口,内核会自动将连接请求分发到不同的 Worker 进程,避免惊群问题。配置步骤
在 Nginx 配置中启用
use_reuseport
:worker_processes 4; # 设置合理的 Worker 进程数(建议等于 CPU 核心数) worker_rlimit_nofile 65535; # 调整文件描述符限制events {worker_connections 1024; # 每个 Worker 进程的最大连接数use epoll; # 使用高效的事件驱动模型(Linux 推荐 epoll)multi_accept on; # 一次尽可能多地接受新连接(可选优化) }http {# 在 http 块或 server 块中添加:server {listen 80 reuseport; # 关键配置:启用 SO_REUSEPORTserver_name example.com;# ... 其他配置} }
listen 80 reuseport
:告诉内核使用SO_REUSEPORT
选项绑定端口,每个 Worker 进程独立监听自己的套接字。worker_processes
需大于 1,否则无需处理惊群问题。验证配置生效:
重启 Nginx 后,通过ss -ltnp | grep nginx
查看端口监听情况,应看到每个 Worker 进程独立监听端口:tcp LISTEN 0 128 :::80 :::* users:(("nginx",pid=1234,fd=6),("nginx",pid=1235,fd=6),("nginx",pid=1236,fd=6),("nginx",pid=1237,fd=6))
每个 Worker 进程对应一个独立的监听套接字(
fd=6
是示例文件描述符)。其他优化:
accept_mutex
锁(旧方案)在不支持
SO_REUSEPORT
的系统中,Nginx 默认通过accept_mutex
互斥锁 缓解惊群问题:
- 多个 Worker 进程竞争一把锁,只有获得锁的进程才能处理新连接,减少同时唤醒的进程数。
- 配置示例(默认开启,无需手动设置):
缺点:锁竞争仍会带来一定性能损耗,不如events {accept_mutex on; # 启用互斥锁(默认 on)accept_mutex_delay 50ms; # 锁竞争失败后的等待时间(默认 50ms) }
SO_REUSEPORT
高效。
三、负载均衡与代理
11. Nginx 支持哪些负载均衡算法?如何配置?
答案:
- 轮询(默认):依次分配请求到后端服务器。
upstream backend {server 192.168.1.1;server 192.168.1.2; }
- 权重轮询(
weight
):按权重分配,适用于性能不均的服务器。server 192.168.1.1 weight=3; # 权重3(默认1)
- IP 哈希(
ip_hash
):相同 IP 固定访问同一服务器(解决 Session 问题)。upstream backend {ip_hash;server 192.168.1.1; }
- 最少连接(
least_conn
):分配给当前连接最少的服务器。upstream backend {least_conn;server 192.168.1.1; }
- URL 哈希(需自定义模块,如
ngx_http_upstream_hash_module
):按 URL 哈希值分配。
12. 如何实现后端服务器的健康检查?
答案:
使用ngx_http_proxy_module
的proxy_next_upstream
指令,配置失败重试:
upstream backend {server 192.168.1.1 max_fails=3 fail_timeout=30s; # 3次失败则标记为不可用,30s后重试server 192.168.1.2;
}
location / {proxy_pass http://backend;proxy_next_upstream error timeout http_502 http_504; # 失败时转发到下一台服务器
}
13. 反向代理时如何传递客户端真实 IP?
答案:
默认 Nginx 传递的X-Forwarded-For
可能被多级代理修改,需配置:
location / {proxy_pass http://backend;proxy_set_header X-Real-IP $remote_addr; # 传递真实客户端IPproxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # 保留代理链IP
}
14. 如何配置 Nginx 作为 WebSocket 代理?
答案:
需在proxy_pass
中设置 WebSocket 协议头:
location /ws/ {proxy_pass http://websocket-server;proxy_http_version 1.1;proxy_set_header Upgrade $http_upgrade;proxy_set_header Connection "upgrade";
}
15. 什么是动静分离?如何实现?
答案:
动静分离:将静态资源(如图片、JS)与动态请求(如 API)分离处理,静态资源由 Nginx 直接响应,动态请求转发给后端服务器。
实现方式:
server {location /static/ {root /var/www/app; # 直接返回静态文件autoindex on; # 开启目录浏览(可选)}location /api/ {proxy_pass http://backend-api; # 转发动态请求}
}
四、高级特性与故障处理
16. 如何配置 Nginx 的 HTTP 缓存(Proxy Cache)?
答案:
使用ngx_http_proxy_cache_module
模块:
http {proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=my_cache:10m max_size=10g inactive=60m;proxy_cache_key $scheme$host$request_uri; # 缓存键规则server {location / {proxy_pass http://backend;proxy_cache my_cache; # 启用缓存proxy_cache_valid 200 302 1h; # 200/302响应缓存1小时proxy_cache_valid 404 1m; # 404响应缓存1分钟}}
}
17. 常见的 502 Bad Gateway 错误原因及解决方法?
答案:
原因:
- 后端服务器宕机或未启动
- 后端服务请求超时(Nginx 等待后端响应超时)
- 负载均衡配置错误(如
upstream
服务器地址错误) - 后端服务连接数耗尽
解决方法:
- 检查后端服务状态(
systemctl status tomcat
等)。 - 调整 Nginx 超时参数:
proxy_connect_timeout 10s; # 连接后端超时 proxy_read_timeout 30s; # 读取后端响应超时
- 增加后端服务器节点或优化服务性能。
18. 如何查看 Nginx 的实时并发连接数?
答案:
- 使用
nginx -s status
(需配置stub_status
模块):
访问location /status {stub_status on;access_log off; }
http://your-nginx/status
查看:Active connections: 123 server accepts handled requests 10000 10000 20000 Reading: 2 Writing: 50 Waiting: 71 # Waiting为空闲keep-alive连接
- 命令行工具:
netstat -ant | grep :80 | wc -l
(统计 80 端口连接数)。
19. 如何实现 Nginx 配置的平滑重启?
答案:
- 验证配置正确性:
nginx -t
- 平滑重启(不中断现有连接):
nginx -s reload # 重新加载配置 nginx -s reopen # 重新打开日志文件
- 原理:Master 进程生成新 Worker 进程,旧 Worker 处理完剩余请求后退出。
20. 如何禁止 Nginx 记录特定 URL 的访问日志?
答案:
在location
中关闭日志记录:
location /static/ {root /var/www/static;access_log off; # 关闭该路径的访问日志
}
五、扩展与实战
21. 如何为 Nginx 添加自定义模块?
答案:
- 下载 Nginx 源码并解压:
wget http://nginx.org/download/nginx-1.24.0.tar.gz tar -zxvf nginx-1.24.0.tar.gz
- 编译时添加模块(以
ngx_http_sub_module
为例):cd nginx-1.24.0 ./configure --add-module=/path/to/module make && make install
- 重启 Nginx 使模块生效。
22. 如何配置 Nginx 支持 HTTP/2?
答案:
- 确保编译时启用
ngx_http_v2_module
(默认开启)。 - 配置 HTTPS 并启用 HTTP/2:
server {listen 443 ssl http2; # 声明HTTP/2server_name example.com;ssl_certificate /path/to/cert.pem;ssl_certificate_key /path/to/key.pem;# 其他HTTPS优化配置(如TLS版本、加密算法) }
23. 如何实现 Nginx 的请求体大小限制?
答案:
通过client_max_body_size
指令限制(默认 1MB):
http {client_max_body_size 10m; # 允许最大请求体10MBserver {location /upload/ {client_max_body_size 50m; # 针对特定路径单独配置}}
}
24. 解释 Nginx 中root
与alias
的区别
答案:
- root:将请求路径拼接到配置路径后查找文件。
例:root /var/www; location /static/
→ 访问/static/test.js
对应文件/var/www/static/test.js
。 - alias:直接替换请求路径为配置路径。
例:alias /var/www/static/; location /static/
→ 访问/static/test.js
对应文件/var/www/static/test.js
。
关键区别:alias
会覆盖location
路径,root
则拼接路径;alias
后需加/
,root
无需。
25. 如何配置 Nginx 的跨域资源共享(CORS)?
答案:
使用add_header
添加 CORS 响应头:
location /api/ {proxy_pass http://backend;add_header Access-Control-Allow-Origin *; # 允许所有来源add_header Access-Control-Allow-Methods "GET, POST, OPTIONS";add_header Access-Control-Allow-Headers "DNT,User-Agent,Content-Type";if ($request_method = 'OPTIONS') {return 204; # 处理预检请求}
}
六、性能与安全
26. 如何优化 Nginx 的 SSL/TLS 性能?
答案:
- 启用 TLS 1.3(比 1.2 更快):
ssl_protocols TLSv1.3 TLSv1.2;
- 选择高效加密算法:
ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384; ssl_prefer_server_ciphers on;
- 开启会话缓存(减少握手次数):
ssl_session_cache shared:SSL:10m; ssl_session_timeout 10m;
27. 如何防范 Nginx 的 CC 攻击(分布式请求伪造)?
答案:
- 限制同一 IP 的并发连接数(
ngx_http_limit_conn_module
):limit_conn_zone $binary_remote_addr zone=conn_limit:10m; server {location / {limit_conn conn_limit 10; # 单个IP最多10个连接limit_conn_status 429; # 超出限制返回429} }
- 结合 WAF(如 ModSecurity)或云防护服务。
28. 解释 Nginx 中worker_rlimit_nofile
的作用
答案:
该指令用于设置 Worker 进程的最大打开文件数,解决 “Too many open files” 错误。
worker_rlimit_nofile 65535; # 单个Worker进程最多打开65535个文件描述符
场景:高并发场景下,需确保该值大于worker_connections
(默认 1024)。
29. 如何实现 Nginx 的请求日志切割?
答案:
- 手动切割:
mv /var/log/nginx/access.log /var/log/nginx/access.log.`date +%Y%m%d` kill -USR1 `cat /var/run/nginx.pid` # 通知Nginx重新生成日志文件
- 自动切割(通过 cron 任务):
0 0 * * * mv /var/log/nginx/access.log /var/log/nginx/access.log.$(date +\%Y\%m\%d) && /usr/sbin/nginx -s reopen
30. 简述 Nginx 在微服务架构中的应用场景
答案:
- API 网关:统一入口,处理请求路由、限流、认证。
- 静态资源服务器:独立部署,减轻后端压力。
- 服务网格边缘代理:配合 Istio/Linkerd 处理南北向流量。
- 灰度发布:通过权重轮询或流量镜像实现分批次发布。
0voice · GitHub