服务器运维面试题库
生成时间:2026-05-21 23:35
【面试题】1. Nginx的upstream模块中,ip_hash和least_conn两种负载均衡策略分别适用于什么场景?如果在同一套架构中需要同时使用这两种策略,该怎么配置?
【标准答案】ip_hash基于客户端IP做哈希,保证同一IP始终打到同一后端,适合有状态会话(如未做Session共享的Tomcat集群)。least_conn把请求分给当前活跃连接数最少的服务器,适合请求处理时间差异大的场景(如文件上传、长连接服务)。
两者不能写在同一个upstream块里,但可以在不同upstream块中分别定义,然后用location路由到不同upstream:
upstream session_backend {
ip_hash;
server 10.0.0.1:8080;
server 10.0.0.2:8080;
}
upstream upload_backend {
least_conn;
server 10.0.0.3:8080;
server 10.0.0.4:8080;
}
location /api/ {
proxy_pass http://session_backend;
}
location /upload/ {
proxy_pass http://upload_backend;
}面试关键点:说明策略选型要看业务特征,而不是哪个"更好"。有状态选ip_hash,长耗时选least_conn,无状态短请求用默认轮询就够了。
【面试题】2. 线上服务器出现502 Bad Gateway错误,请描述你的完整排查思路和常见原因。
【标准答案】502说明Nginx作为代理,收到了后端无效响应或根本没收到响应。排查按这个顺序来:
- 先看后端服务是否存活:
systemctl status php-fpm/netstat -tlnp | grep 8080,确认后端进程在不在、端口有没有监听。 - 看Nginx错误日志:
tail -100 /var/log/nginx/error.log,找具体报错——"Connection refused"说明后端没起来或端口不对;"upstream prematurely closed connection"说明后端崩了或超时。 - 检查后端资源:
free -m看内存是否耗尽(OOM Kill了进程)、df -h看磁盘是否满了、ulimit -n看文件描述符是否不够。 - 检查PHP-FPM/应用配置:pm.max_children是否太小导致没有空闲worker;request_terminate_timeout是否把长请求杀了。
- 检查防火墙/SELinux:
iptables -L或getenforce,确认没有拦截后端端口。
最常见三个原因:①后端服务挂了 ②后端资源耗尽(内存/连接数) ③PHP-FPM worker不够。面试时要体现"从外到内、从服务到资源"的排查逻辑。
【面试题】3. 如何用iptables实现只允许特定IP访问服务器的SSH(22端口),其余全部拒绝?请写出完整规则并说明规则顺序的重要性。
【标准答案】规则顺序是关键——iptables从上到下匹配,命中即停。必须先放行再拒绝,顺序反了就把自己锁外面了。
# 先允许本机回环
iptables -A INPUT -i lo -j ACCEPT
# 允许已建立的连接
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
# 允许指定IP访问SSH
iptables -A INPUT -s 192.168.1.100 -p tcp --dport 22 -j ACCEPT
# 允许公司网段访问SSH
iptables -A INPUT -s 10.0.0.0/24 -p tcp --dport 22 -j ACCEPT
# 拒绝其他所有SSH访问
iptables -A INPUT -p tcp --dport 22 -j DROP
# 允许HTTP/HTTPS(业务需要)
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
iptables -A INPUT -p tcp --dport 443 -j ACCEPT
# 最后默认拒绝所有其他入站
iptables -P INPUT DROP面试加分点:①强调用DROP不用REJECT(不暴露服务器存在);②提醒保存规则iptables-save > /etc/sysconfig/iptables;③提到用-I插入到指定位置可以在不删规则的情况下调整顺序;④建议改SSH端口+密钥登录作为纵深防御。
【面试题】4. Tomcat的Connector支持BIO、NIO、APR三种模式,它们有什么区别?生产环境推荐哪个,需要怎么配置?
【标准答案】三种模式的核心区别在IO模型:
- BIO(默认,Tomcat 8.5之前):一个请求一个线程,线程阻塞等待。并发高时线程数暴增,性能最差,已废弃。
- NIO:基于Java NIO,用少量线程处理大量连接,非阻塞IO。Tomcat 8.5+默认就是NIO。性能好,配置简单,不需要额外依赖。
- APR:调用Apache Portable Runtime本地库,用操作系统的epoll/sendfile等原生能力,性能最优,但需要安装apr和tomcat-native库。
生产环境推荐:NIO就够了,绝大多数场景性能够用,零依赖。如果追求极致性能(高并发长连接、大量静态资源),且运维能力足够维护本地库,用APR。
配置方式(server.xml):
<!-- NIO模式 -->
<Connector port="8080" protocol="org.apache.coyote.http11.Http11Nio2Protocol"
maxThreads="200" minSpareThreads="25" acceptCount="100"
connectionTimeout="20000" />
<!-- APR模式,需先安装apr库 -->
<Connector port="8080" protocol="org.apache.coyote.http11.Http11AprProtocol"
maxThreads="200" />面试关键:别只说"APR最好",要说明APR的运维成本和NIO的够用哲学。真正瓶颈往往不在Connector,在业务代码和数据库。
【面试题】5. 请解释Linux的load average三个数字分别代表什么?load average为8,服务器有4核CPU,这正常吗?
【标准答案】uptime或top看到的三个数字分别是过去1分钟、5分钟、15分钟的系统平均负载。负载 = 运行中进程数 + 不可中断等待IO的进程数。
判断是否正常要看CPU核数:负载/CPU核数是关键比。
- 理想状态:负载 ≤ CPU核数(利用率100%以内)
- 4核CPU,负载8,说明平均每个核心排了2个任务,负载率200%,偏高但不一定异常
需要进一步区分:
- 如果是CPU密集型导致:
top看%us高 → 需要优化代码或扩容 - 如果是IO等待导致:
top看%wa高 → 磁盘IO瓶颈,负载高但CPU其实空闲 - 看趋势:1分钟8、5分钟8、15分钟8 → 持续高负载;1分钟8、5分钟3、15分钟1 → 刚刚突增,可能在恢复
# 查看CPU核数
nproc
# 查看详细负载构成
vmstat 1 5 # 看r列(运行队列)和b列(阻塞)
iostat -x 1 # 看磁盘await面试关键:load average高≠CPU忙,可能是IO瓶颈。要先定性再定量。
【面试题】6. Nginx配置proxy_pass时,URI末尾带不带斜杠有什么区别?请举例说明并指出常见踩坑点。
【标准答案】这是Nginx最容易踩的坑之一。核心规则:proxy_pass带了URI(包括只有/),location匹配的部分会被替换;不带URI,原样转发。
# 情况1:proxy_pass带斜杠
location /api/ {
proxy_pass http://backend/;
}
# 请求 /api/user → 转发为 /user(/api/被替换为/)
# 情况2:proxy_pass不带斜杠
location /api/ {
proxy_pass http://backend;
}
# 请求 /api/user → 转发为 /api/user(原样保留)
# 情况3:proxy_pass带路径
location /api/ {
proxy_pass http://backend/v2/;
}
# 请求 /api/user → 转发为 /v2/user(/api/被替换为/v2/)常见踩坑:
- 前端请求
/api/user,后端实际路径是/user,但proxy_pass没加斜杠,导致后端收到/api/user返回404——最常见的错。 - location用
=精确匹配或^~前缀匹配时,行为一样,关键看proxy_pass有没有URI部分。 - 如果后端需要原始路径(比如网关转发),就不加斜杠;如果后端有自己的路径结构,就加斜杠做替换。
面试一句话总结:带斜杠做替换,不带斜杠做拼接,搞不清的时候拿curl测一下就知道了。
【面试题】7. 如何用Prometheus + Grafana监控Nginx?请描述完整的数据采集链路和关键监控指标。
【标准答案】完整链路:Nginx → nginx-prometheus-exporter → Prometheus → Grafana。
部署步骤:
- Nginx开启stub_status模块:
location /stub_status {
stub_status on;
access_log off;
allow 127.0.0.1;
deny all;
}- 部署nginx-prometheus-exporter,采集stub_status数据转为Prometheus格式:
docker run -d --name nginx-exporter \
-e NGINX_STATUS=http://nginx:80/stub_status \
-p 9113:9113 \
nginx/nginx-prometheus-exporter- Prometheus添加抓取配置,Grafana导入Nginx官方Dashboard(11074号模板)。
关键监控指标:
nginx_up:Nginx是否在线(1/0)nginx_connections_active:活跃连接数,反映并发压力nginx_connections_waiting:等待连接数,飙升说明后端响应慢nginx_http_requests_total:总请求数,用rate()算QPSnginx_connections_handled / nginx_connections_accepted:handled < accepted说明有连接被丢弃
告警规则示例:
- 活跃连接数 > 5000 持续5分钟 → P2告警
- QPS突降50% → 可能流量异常或服务故障
- waiting连接数 > 1000 → 后端可能有瓶颈
面试加分:提到除了stub_status,还可以用nginx日志通过mtail/logstash导出自定义指标(如按URL的响应时间P99),实现更细粒度的监控。
【面试题】8. Docker容器的CPU和内存资源限制是怎么设置的?如果容器内进程实际使用超过了限制会发生什么?
【标准答案】资源限制通过docker run参数或docker-compose的deploy配置设置:
# CPU限制:最多用1.5个核
docker run --cpus="1.5" myapp
# 内存限制:最多512MB,swap 256MB
docker run -m 512m --memory-swap 768m myappdocker-compose方式:
deploy:
resources:
limits:
cpus: '1.5'
memory: 512M
reservations:
cpus: '0.5'
memory: 256M超限后的行为:
- 内存超限:触发OOM Killer,容器内最占内存的进程被杀。如果设置了
--oom-kill-disable=true,容器不会被杀但进程会卡死——生产别用这个。整个容器可能因PID 1被杀而退出。 - CPU超限:不会杀进程。CPU限制是通过CFS调度器实现的,超限只是被throttle(限流),进程会变慢但不会崩溃。
运维要点:
- 内存限制建议设为应用实际需求的1.5-2倍,留余量防OOM。
- 用
docker stats实时查看容器资源使用。 - Java应用特别注意:JVM堆内存+元空间+堆外内存总消耗可能远超-Xmx设置,要算整体内存。
- Kubernetes中对应的是resources.limits和resources.requests,机制一样。
面试关键:CPU超限是"慢"不是"死",内存超限是"死"不是"慢"。这个区别很重要。
【面试题】9. 什么是LVS的NAT模式和DR模式?分别适合什么场景?与Nginx负载均衡相比有什么区别?
【标准答案】LVS(Linux Virtual Server)是内核级别的四层负载均衡,两种常用模式:
NAT模式:
- 客户端请求到VIP → Director修改目标IP为RealServer → RealServer响应回Director → Director修改源IP为VIP → 返回客户端
- 请求和响应都过Director,Director容易成瓶颈
- RealServer网关必须指向Director
- 适合规模小、后端跨网段的场景
DR模式(Direct Routing):
- 客户端请求到VIP → Director修改MAC地址直接转发给RealServer → RealServer处理后直接响应客户端(不过Director)
- 只有请求过Director,响应直接回客户端,吞吐量远高于NAT
- 要求Director和RealServer在同一网段、同一物理网络
- 适合大规模高并发场景,生产环境首选
与Nginx对比:
| 维度 | LVS | Nginx |
|---|---|---|
| 工作层 | 四层(L4) | 七层(L7) |
| 性能 | 百万级并发 | 万级并发 |
| 功能 | 纯转发,无应用层逻辑 | 可做URL路由、缓存、限流等 |
| 健康检查 | 需配合keepalived | 自带被动检查 |
| 适用位置 | 最前端四层调度 | 反向代理+七层分发 |
面试关键:不要说"LVS比Nginx好",要说分层使用——最前面放LVS/DPDK做四层分发,后面挂多个Nginx做七层代理,这才是生产架构。
【面试题】10. 简述TLS 1.2握手流程。如果面试官问"为什么TLS 1.3比1.2快",你怎么回答?
【标准答案】TLS 1.2握手流程(RSA密钥交换为例):
- Client Hello:客户端发送支持的TLS版本、密码套件列表、随机数C
- Server Hello:服务端选定的TLS版本、密码套件、随机数S、服务器证书
- 密钥交换:客户端验证证书合法性,生成预主密钥(Pre-Master Secret),用服务器公钥加密发给服务端
- 双方计算主密钥:用C+S+预主密钥计算出Master Secret,再派生出会话密钥
- Finished消息:双方互相发加密的Finished确认握手完成
共2个RTT,第一次应用数据要到第三次往返才能发。
TLS 1.3为什么更快:
- 1-RTT握手:砍掉了Server Key Exchange和Client Key Exchange,Client Hello直接带上密钥共享参数(Key Share),服务端回Server Hello时也带Key Share,一个来回就能算出密钥。
- 0-RTT恢复:之前连过的服务器,用PSK(预共享密钥)在Client Hello中直接带上应用数据,0个额外RTT。但0-RTT有重放攻击风险,只适合幂等请求。
- 砍掉不安全的密码套件:RSA密钥交换、CBC模式、SHA-1全删了,只留AEAD(如AES-GCM)+ ECDHE,更安全也更简单。
面试一句话:1.2是2个RTT,1.3是1个RTT,恢复连接0-RTT。快的本质是把密钥交换提前到第一个包就带上,不用来回确认。