Skip to content

本轮 服务器运维面试题库(带答案)

【面试题】1. 请解释 Nginx 的 location 匹配优先级规则,并举例说明精确匹配和正则匹配的区别。 ​

【标准答案】 Nginx 的 location 匹配有四种类型,优先级从高到低:

  1. 精确匹配 = — 最高优先级,完全匹配时立即停止搜索
  2. 前缀匹配 ^~ — 匹配后停止正则搜索
  3. 正则匹配 ~ 或 ~* — 区分大小写和不区分大小写的正则
  4. 普通前缀匹配 — 无修饰符,优先级最低

举例说明:

nginx
location = /api/user {
    # 精确匹配,只匹配 /api/user
    proxy_pass http://backend;
}

location ~ ^/static/.*\.(jpg|png)$ {
    # 正则匹配,匹配 /static/ 下的 jpg/png 文件
    expires 30d;
}

location /api/ {
    # 普通前缀匹配,匹配所有 /api/ 开头的请求
    proxy_pass http://backend;
}

关键点:精确匹配用 = 适合单一固定路径;正则匹配用 ~ 适合模式匹配场景。面试时强调实际配置经验,比如用 = 匹配健康检查接口 /health,用 ~ 匹配静态资源缓存规则。


【面试题】2. Tomcat 出现 OOM(内存溢出)时,你如何排查和解决?请详细说明排查步骤。 ​

【标准答案】 OOM 排查分三步走:

第一步:定位问题类型

  • java.lang.OutOfMemoryError: Java heap space → 堆内存不足
  • java.lang.OutOfMemoryError: PermGen space / Metaspace → 类加载过多(JDK8+ 是 Metaspace)
  • java.lang.OutOfMemoryError: GC overhead limit exceeded → GC 效率过低

第二步:获取现场证据

bash
# 查看 Tomcat 进程 PID
ps -ef | grep tomcat

# 生成 heap dump(OOM 时自动生成,需配置)
jmap -dump:format=b,file=heap.hprof <pid>

# 查看堆内存使用情况
jmap -heap <pid>

# 查看 GC 情况
jstat -gcutil <pid> 1000 10

第三步:分析与解决

  1. 用 MAT(Memory Analyzer Tool)或 JProfiler 分析 hprof 文件
  2. 找出占用内存最大的对象,定位内存泄漏点
  3. 检查代码中是否有未关闭的连接、集合无限增长、大对象未释放等

优化方案:

  • 调整 JVM 参数:-Xms2g -Xmx4g -XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=512m
  • 添加 OOM 自动导出:-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp/heap.hprof
  • 优化代码,修复内存泄漏

面试时强调:生产环境必须配置 HeapDumpOnOutOfMemoryError,出问题才有证据可查。


【面试题】3. Nginx 配置了负载均衡后,后端服务器健康检查如何实现?请对比主动检查和被动检查的优劣。 ​

【标准答案】 Nginx 健康检查有两种方式:

被动检查(原生支持)

nginx
upstream backend {
    server 192.168.1.10:8080 max_fails=3 fail_timeout=30s;
    server 192.168.1.11:8080 max_fails=3 fail_timeout=30s;
}
  • max_fails:失败次数阈值
  • fail_timeout:标记为不可用的时间窗口

原理:Nginx 在代理请求时,如果后端返回错误或超时,记录失败次数;达到阈值后,暂时剔除该服务器。

主动检查(需 nginx_plus 或第三方模块)

nginx
# 商业版 Nginx Plus
upstream backend {
    zone backend 64k;
    server 192.168.1.10:8080;
    server 192.168.1.11:8080;
    
    health_check interval=5s uri=/health;
}

对比:

维度被动检查主动检查
实现复杂度低(原生)高(需商业版或模块)
发现故障速度慢(需真实流量触发)快(主动探测)
资源消耗无额外消耗有定时探测开销
适用场景请求量稳定的服务对可用性要求极高的服务

我的实践经验:中小规模项目用被动检查即可,配合 proxy_connect_timeout 和 proxy_read_timeout 控制超时;大规模高可用场景推荐 Nginx Plus 或用 HAProxy 替代,它的主动健康检查更强大。


【面试题】4. Linux 服务器负载突然飙高(load average > CPU 核心数),你如何快速定位瓶颈? ​

【标准答案】 高负载排查四步法:

第一步:确认负载类型

bash
# 查看 load average 和 CPU 核心
top  # 按 1 展开各核心
uptime  # 快速看 load average

# 判断:load average > CPU 核心数 = 系统过载

第二步:定位资源瓶颈

bash
# CPU 密集型:us% + sy% 很高
top -c  # 查看具体进程命令

# I/O 密集型:wa%(iowait)很高
iostat -x 1 10  # 查看磁盘 IO

# 内存不足:频繁 swap
free -h
vmstat 1 10  # 看 si/so(swap in/out)

第三步:找出罪魁祸首

bash
# CPU 占用最高的进程
top -c
ps aux --sort=-%cpu | head -20

# I/O 占用最高的进程
iotop -oP  # 需安装 iotop

# 网络连接异常
netstat -antp | grep ESTABLISHED | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -rn
ss -s  # 快速统计连接状态

第四步:紧急处理

bash
# CPU 飙高:如果是异常进程,直接杀掉
kill -9 <pid>

# I/O 飙高:检查磁盘空间、慢查询日志
df -h
# MySQL 慢查询日志,Nginx access log 异常增长等

# 内存不足:重启占用过高的服务,或临时扩容 swap
dd if=/dev/zero of=/swapfile bs=1G count=4
chmod 600 /swapfile
mkswap /swapfile
swapon /swapfile

面试加分点:我会用 atop 或 sar 持续监控,提前发现趋势;dmesg | tail 检查是否有 OOM killer 或硬件错误。高负载往往是多个因素叠加,需要系统化排查。


【面试题】5. 如何配置 Nginx 实现 HTTPS 双向认证?什么场景需要双向认证? ​

【标准答案】 HTTPS 双向认证:不仅客户端验证服务器证书,服务器也验证客户端证书。

适用场景:

  • 企业内部 API 对接,只允许授权客户端访问
  • 金融/支付系统,要求客户端身份强认证
  • 物联网设备与服务器通信

配置步骤:

nginx
server {
    listen 443 ssl;
    server_name api.example.com;
    
    # 服务器证书(客户端验证服务器)
    ssl_certificate /etc/nginx/ssl/server.crt;
    ssl_certificate_key /etc/nginx/ssl/server.key;
    
    # 客户端证书验证(服务器验证客户端)
    ssl_client_certificate /etc/nginx/ssl/ca.crt;  # CA 证书
    ssl_verify_client on;  # 强制客户端认证
    ssl_verify_depth 2;
    
    # SSL 优化配置
    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;
    
    location / {
        proxy_pass http://backend;
    }
}

客户端证书生成流程:

bash
# 1. 生成客户端私钥和 CSR
openssl genrsa -out client.key 2048
openssl req -new -key client.key -out client.csr

# 2. 用 CA 签发客户端证书
openssl x509 -req -in client.csr -CA ca.crt -CAkey ca.key \
  -CAcreateserial -out client.crt -days 365

# 3. 打包为 PKCS#12 格式(供浏览器导入)
openssl pkcs12 -export -clcerts -in client.crt -inkey client.key \
  -out client.p12

测试:

bash
curl --cert client.crt --key client.key https://api.example.com

面试时强调:双向认证成本高,需要为每个客户端签发和管理证书,通常配合证书撤销列表(CRL)或 OCSP 使用,适合安全要求极高的场景。


【面试题】6. 请解释 Keepalived + Nginx 高可用方案的原理,并说明如何避免脑裂问题。 ​

【标准答案】 Keepalived 原理:

  • 基于 VRRP(虚拟路由冗余协议)实现 IP 漂移
  • 两台 Nginx 服务器配置主备角色,共享虚拟 IP(VIP)
  • 主节点故障时,VIP 自动漂移到备节点,实现秒级切换

架构示意:

                  VIP: 192.168.1.100
                         |
        +----------------+----------------+
        |                                 |
   Master (Keepalived)              Backup (Keepalived)
   192.168.1.10 (Nginx)            192.168.1.11 (Nginx)

Keepalived 配置示例(主节点):

vrrp_instance VI_1 {
    state MASTER
    interface eth0
    virtual_router_id 51
    priority 100
    advert_int 1
    
    authentication {
        auth_type PASS
        auth_pass 1234
    }
    
    virtual_ipaddress {
        192.168.1.100
    }
    
    # 监控 Nginx 进程
    track_script {
        check_nginx
    }
}

Nginx 健康检查脚本:

bash
#!/bin/bash
# /etc/keepalived/check_nginx.sh
if [ $(ps -C nginx --no-header | wc -l) -eq 0 ]; then
    systemctl start nginx
    sleep 2
    if [ $(ps -C nginx --no-header | wc -l) -eq 0 ]; then
        systemctl stop keepalived
    fi
fi

脑裂问题及解决方案:

脑裂现象:主备都认为自己是主,同时持有 VIP,导致流量混乱或数据不一致。

原因:

  1. 网络分区(防火墙阻断 VRRP 组播)
  2. Keepalived 进程异常但未退出
  3. 服务器负载过高导致心跳超时

解决方案:

  1. 多播地址配置正确:确保 VRRP 组播包能互通
  2. 降低优先级逻辑:Nginx 异常时自动降低优先级,而不是直接停止 Keepalived
  3. 增加仲裁机制:引入第三方节点或服务做仲裁
  4. 监控告警:监控 VIP 冲突、Keepalived 状态异常
  5. 日志审计:定期检查 /var/log/messages 中的 VRRP 状态切换记录
bash
# 检测脑裂脚本(在备节点运行)
#!/bin/bash
VIP=192.168.1.100
MASTER_IP=192.168.1.10

# 如果能 ping 通主节点,但本机也有 VIP,说明脑裂
if ping -c 1 $MASTER_IP &> /dev/null; then
    if ip addr show | grep -q $VIP; then
        echo "脑裂告警!主备同时持有 VIP"
        # 发送告警,可选择关闭本机 VIP
    fi
fi

面试加分点:生产环境建议 Keepalived + Nginx + 监控 三位一体,配合脚本实现 Nginx 故障自动重启、Keepalived 状态监控、VIP 冲突检测。


【面试题】7. Tomcat Connector 有哪几种线程模型?NIO 和 APR 有什么区别?生产环境如何选择? ​

【标准答案】 Tomcat Connector 有三种线程模型:

1. BIO(Blocking I/O,阻塞式)

  • Tomcat 8.5 之前的默认模型
  • 每个请求占用一个线程,线程阻塞等待请求
  • 缺点:并发能力差,线程资源消耗大
  • 适用:低并发场景,已逐渐淘汰

2. NIO(Non-blocking I/O,非阻塞式)

  • Tomcat 8.5+ 的默认模型
  • 基于 Java NIO API,使用少量线程处理大量连接
  • 优点:高并发、资源利用率高
  • 适用:高并发、连接数多但请求处理时间长的场景

3. APR(Apache Portable Runtime)

  • 使用本地库(C 语言实现),性能最优
  • 需要 Tomcat Native 库支持
  • 优点:性能接近 Nginx,SSL 性能优秀
  • 适用:对性能要求极高、大规模生产环境

配置方式(server.xml):

xml
<!-- NIO(默认) -->
<Connector port="8080" protocol="org.apache.coyote.http11.Http11NioProtocol"
           maxThreads="200" minSpareThreads="25" acceptCount="100" />

<!-- APR(需安装 Tomcat Native) -->
<Connector port="8080" protocol="org.apache.coyote.http11.Http11AprProtocol"
           maxThreads="200" />

NIO vs APR 对比:

维度NIOAPR
实现方式Java APIC 本地库
性能优秀最优(提升 10-20%)
SSL 性能一般优秀(OpenSSL 加速)
部署复杂度低(开箱即用)高(需编译安装 Native)
稳定性高(纯 Java)依赖系统库,需版本匹配
跨平台完全跨平台依赖系统,需单独编译

生产环境选择建议:

  • 常规项目:NIO 足够,默认配置即可,无需额外折腾
  • 高并发/SSL 密集:APR,但需要运维团队有能力编译和维护 Tomcat Native
  • Spring Boot 内嵌 Tomcat:默认 NIO,可通过配置切换 APR(需添加依赖)

我的实践经验:90% 的项目用 NIO 即可;APR 的性能提升有限,但部署和维护成本高,只有在性能成为明确瓶颈时才考虑。SSL 性能优化更推荐用 Nginx 做卸载,而非在 Tomcat 层折腾 APR。


【面试题】8. 如何用 ELK Stack(Elasticsearch + Logstash + Kibana)搭建服务器日志监控系统?请简述架构和数据流。 ​

【标准答案】 ELK Stack 架构:

应用服务器 → Filebeat → Logstash → Elasticsearch → Kibana
                 ↓
           Kafka(可选,缓冲层)

组件职责:

  • Filebeat:轻量级日志采集器,部署在应用服务器,实时收集日志
  • Logstash:数据处理管道,解析、过滤、转换日志格式
  • Elasticsearch:分布式搜索引擎,存储和索引日志
  • Kibana:可视化平台,日志查询、仪表盘、告警

部署步骤:

1. 安装 Elasticsearch(数据存储)

yaml
# docker-compose.yml
services:
  elasticsearch:
    image: elasticsearch:8.12.0
    environment:
      - discovery.type=single-node
      - xpack.security.enabled=false
    ports:
      - "9200:9200"
    volumes:
      - es_data:/usr/share/elasticsearch/data

2. 安装 Logstash(数据处理)

ruby
# /etc/logstash/conf.d/nginx.conf
input {
  beats {
    port => 5044
  }
}

filter {
  grok {
    match => { "message" => "%{COMBINEDAPACHELOG}" }
  }
  date {
    match => [ "timestamp", "dd/MMM/yyyy:HH:mm:ss Z" ]
  }
}

output {
  elasticsearch {
    hosts => ["http://elasticsearch:9200"]
    index => "nginx-%{+YYYY.MM.dd}"
  }
}

3. 安装 Kibana(可视化)

yaml
kibana:
  image: kibana:8.12.0
  environment:
    - ELASTICSEARCH_HOSTS=http://elasticsearch:9200
  ports:
    - "5601:5601"

4. 安装 Filebeat(日志采集)

yaml
filebeat.inputs:
- type: log
  enabled: true
  paths:
    - /var/log/nginx/access.log
  fields:
    app: nginx
  fields_under_root: true

output.logstash:
  hosts: ["logstash:5044"]

高可用架构:

  • Elasticsearch 集群(至少 3 节点)
  • Kafka 作为缓冲层,防止日志高峰时 Logstash 崩溃
  • Logstash 多实例负载均衡

典型查询场景:

  1. 统计 5xx 错误趋势:Kibana 可视化面板
  2. 慢请求分析:响应时间 > 1s 的请求
  3. 异常 IP 追踪:某个 IP 的访问频率、请求路径
  4. 业务指标监控:API 调用成功率、响应时间分布

面试加分点:

  • 提到 Elasticsearch 生命周期管理(ILM),自动删除或归档旧日志
  • 提到 Filebeat vs Fluentd 的选择:Filebeat 更轻量,Fluentd 功能更丰富
  • 提到 Kibana 告警:可配置 Watcher 或集成 Prometheus Alertmanager

【面试题】9. Linux 服务器的 iptables 和 firewalld 有什么区别?生产环境应该用哪个?请举例配置 Web 服务器防火墙规则。 ​

【标准答案】 iptables vs firewalld 对比:

维度iptablesfirewalld
架构规则链,需手动管理顺序区域(Zone)概念,策略化管理
配置方式命令行规则,重启失效XML 配置文件,支持运行时/永久分离
动态更新需重启服务或重载规则支持运行时修改,无中断
学习曲线复杂,需理解链和表相对简单,区域概念直观
适用系统CentOS 6 及以下CentOS 7+、RHEL 7+、Fedora
底层netfilter底层仍是 iptables(nftables)

生产环境选择:

  • CentOS 7+ 默认 firewalld,建议使用 firewalld
  • 老系统或习惯 iptables,可继续使用
  • 大规模自动化部署,firewalld 更易管理

firewalld 配置 Web 服务器示例:

bash
# 查看默认区域
firewall-cmd --get-default-zone
# public

# 开放 HTTP/HTTPS
firewall-cmd --permanent --add-service=http
firewall-cmd --permanent --add-service=https

# 开放自定义端口(如 8080)
firewall-cmd --permanent --add-port=8080/tcp

# 允许特定 IP 访问 SSH
firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.1.0/24" service name="ssh" accept'

# 拒绝特定 IP
firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="10.0.0.100" reject'

# 开启端口转发(将 8080 转发到 80)
firewall-cmd --permanent --add-forward-port=port=8080:proto=tcp:toport=80

# 重载配置
firewall-cmd --reload

# 查看当前规则
firewall-cmd --list-all

iptables 配置示例(等价规则):

bash
# 清空规则
iptables -F

# 允许本地回环
iptables -A INPUT -i lo -j ACCEPT

# 允许已建立的连接
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

# 开放 HTTP/HTTPS
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
iptables -A INPUT -p tcp --dport 443 -j ACCEPT

# 允许特定网段 SSH
iptables -A INPUT -p tcp --dport 22 -s 192.168.1.0/24 -j ACCEPT

# 拒绝其他入站
iptables -A INPUT -j DROP

# 保存规则
service iptables save  # CentOS 6
iptables-save > /etc/sysconfig/iptables

面试加分点:

  • 提到 ufw(Ubuntu):ufw allow 80/tcp,更简单
  • 提到 安全加固:默认拒绝所有入站,只开放必要端口,SSH 改用非标准端口
  • 提到 Fail2ban:自动封禁暴力破解 IP,与 iptables/firewalld 联动

我的经验:现代 Linux 发行版建议用 firewalld 或 nftables(iptables 的继任者),配置更清晰,动态管理更方便。关键是默认拒绝策略 + 最小权限原则。


【面试题】10. 请设计一个 LVS + Keepalived + Nginx 的高可用负载均衡架构,并说明各组件的作用和故障切换流程。 ​

【标准答案】 架构设计:

                        用户请求
                           |
                    VIP: 192.168.1.100
                           |
            +--------------+--------------+
            |                             |
    LVS Master (Keepalived)      LVS Backup (Keepalived)
    192.168.1.10                 192.168.1.11
            |                             |
            +--------+---------+----------+
                     |
        +------------+------------+------------+
        |            |            |            |
    Nginx 1      Nginx 2      Nginx 3      Nginx N
    RS1          RS2          RS3          RS N

组件职责:

  1. LVS(Linux Virtual Server)

    • 四层负载均衡(基于 IP + 端口)
    • DR 模式:请求经过 LVS,响应直接返回客户端(性能最优)
    • NAT 模式:请求和响应都经过 LVS(简单但性能受限)
    • 作用:高性能流量分发,支持十万级并发
  2. Keepalived

    • 实现 LVS 主备高可用
    • VRRP 协议保证 VIP 漂移
    • 健康检查:监控后端 Nginx 服务器状态
    • 作用:故障自动切换,秒级恢复
  3. Nginx

    • 七层负载均衡(基于 HTTP 头、URL)
    • 反向代理、SSL 卸载、缓存
    • 作用:业务层流量调度、SSL 处理、静态资源服务

为什么需要 LVS + Nginx 两层?

  • LVS:四层,性能极高,但功能单一
  • Nginx:七层,功能丰富,但性能低于 LVS
  • 组合使用:LVS 承接海量连接 → Nginx 做智能分发和业务处理

配置示例:

Keepalived + LVS(主节点):

bash
# /etc/keepalived/keepalived.conf
global_defs {
    router_id LVS_MASTER
}

vrrp_instance VI_1 {
    state MASTER
    interface eth0
    virtual_router_id 51
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1234
    }
    virtual_ipaddress {
        192.168.1.100
    }
}

# LVS 配置
virtual_server 192.168.1.100 80 {
    delay_loop 6
    lb_algo rr        # 轮询
    lb_kind DR        # DR 模式
    persistence_timeout 0
    protocol TCP
    
    # 后端 Nginx 服务器
    real_server 192.168.1.20 80 {
        weight 1
        TCP_CHECK {
            connect_timeout 3
            connect_port 80
        }
    }
    
    real_server 192.168.1.21 80 {
        weight 1
        TCP_CHECK {
            connect_timeout 3
            connect_port 80
        }
    }
}

后端 Nginx 配置(Real Server):

bash
# DR 模式需要在后端服务器配置 VIP(不响应 ARP)
echo "1" > /proc/sys/net/ipv4/conf/lo/arp_ignore
echo "2" > /proc/sys/net/ipv4/conf/lo/arp_announce
echo "1" > /proc/sys/net/ipv4/conf/all/arp_ignore
echo "2" > /proc/sys/net/ipv4/conf/all/arp_announce

# 在 lo 接口绑定 VIP
ip addr add 192.168.1.100/32 dev lo

故障切换流程:

  1. LVS Master 故障

    • Keepalived 检测到 Master 失效
    • Backup 接管 VIP,成为新 Master
    • 切换时间:1-3 秒(advert_int 决定)
  2. 后端 Nginx 故障

    • Keepalived 的 TCP_CHECK 检测到 Nginx 端口不可达
    • 自动从 LVS 调度列表中移除该节点
    • 恢复后自动加回
  3. Nginx 进程崩溃

    • Nginx 内置 master-worker 机制自动重启 worker
    • 如果 master 崩溃,用 systemd 或 supervisor 自动拉起

面试加分点:

  • 提到 健康检查策略:TCP_CHECK(端口检查)、HTTP_GET(HTTP 健康检查)、SSL_GET(HTTPS)
  • 提到 会话保持:persistence_timeout 参数,或用 IP Hash
  • 提到 监控告警:Prometheus 监控 LVS 连接数、Keepalived 状态、Nginx 请求数
  • 提到 容量规划:LVS 可支持百万级并发,Nginx 单机 5-10 万 QPS

我的实践经验:

  • 小规模场景:单 Nginx + Keepalived 足够
  • 中大规模:LVS + Keepalived + 多 Nginx
  • 超大规模:引入 DNS 轮询、CDN、多机房部署
  • 关键是监控和告警,出问题第一时间知道,而不是等用户反馈