本轮 服务器运维面试题库(带答案)
生成时间:2026-05-21 21:59
【面试题】1. Nginx的location匹配规则优先级是怎样的?请详细说明四种匹配模式的区别。
【标准答案】Nginx的location匹配有四种模式,优先级从高到低是:精确匹配 > 正则匹配 > 前缀匹配(含^~)> 普通前缀匹配。
具体来说:
- 精确匹配
=:完全匹配指定URI,优先级最高,一旦匹配立即停止搜索。比如location = /exact只匹配/exact这个路径,多一个字符都不行。 - 正则匹配
~和~*:~区分大小写,~*不区分大小写。正则匹配按配置文件中的顺序匹配,匹配第一个就停止。所以正则location的顺序很重要,要把更具体的规则放前面。 - 前缀匹配带
^~:匹配到后停止搜索正则,优先级高于普通前缀匹配。适合静态资源路径,比如location ^~ /static/,匹配到后直接返回静态文件,不再尝试正则匹配。 - 普通前缀匹配:没有任何修饰符的location,会进行最长前缀匹配,但还会继续检查正则规则。如果正则能匹配上,就用正则;否则用最长前缀匹配的结果。
面试时可以这样举例:配置了 location /api/ 和 location ~ ^/api/users$,请求 /api/users 会走正则规则,因为正则优先级更高。但如果配置 location ^~ /api/,同样请求会走前缀匹配,因为 ^~ 阻止了正则匹配。
【面试题】2. Keepalived如何实现Nginx高可用?请描述双机热备方案的架构和切换机制。
【标准答案】Keepalived通过VRRP协议实现Nginx高可用,核心思路是VIP漂移。双机热备方案通常是一主一备,两台Nginx服务器上部署Keepalived,共享一个虚拟IP(VIP),对外提供服务。
架构要点:
- Master节点:优先级配置较高(比如priority 100),持有VIP,对外提供服务。Nginx正常,Keepalived发送VRRP广播。
- Backup节点:优先级较低(比如priority 90),监听VRRP广播,不持有VIP。一旦收不到Master的广播(Master宕机或网络故障),Backup接管VIP,开始对外服务。
- 切换机制:通过
vrrp_script配置健康检查脚本,周期性检测Nginx进程状态。如果检测失败,降低自身优先级,触发VIP切换。 - 故障恢复:Master恢复后,优先级高的节点重新抢占VIP(可以配置
nopreempt关闭抢占,让Backup继续服务直到故障)。
配置示例关键点:
vrrp_script检测Nginx:killall -0 nginxtrack_script引用健康检查脚本virtual_ipaddress配置VIP(如192.168.1.100)state MASTER/BACKUP定义角色interface指定网卡
切换时间通常在秒级(默认 advert_int 1秒,抢占延迟可调)。生产环境建议配置邮件告警和日志记录,确保切换事件可追溯。
【面试题】3. Linux系统load average的含义是什么?数值多高算异常?如何排查?
【标准答案】Load average是系统负载平均值,表示在一段时间内等待运行的进程队列长度,包括正在运行的进程和等待CPU的进程。通过uptime或top命令可以看到三个数值:1分钟、5分钟、15分钟的平均负载。
数值多少算异常? 判断标准是与CPU核心数对比:
- 单核系统:load average > 1 表示负载高
- 4核系统:load average > 4 表示负载高
- 16核系统:load average > 16 表示负载高
- 一般经验值:load average超过核心数的70%就需要关注,超过核心数需要排查
排查思路:
- 先看是CPU密集还是IO密集:
top查看CPU的us(用户态)和sy(系统态)占比高,说明CPU密集;wa(IO等待)高,说明磁盘或网络IO压力大。 - CPU密集:用
top或htop找高CPU进程,ps -eo pid,ppid,cmd,%cpu,%mem --sort=-%cpu | head,分析进程代码或优化算法。 - IO密集:用
iostat -x 1看磁盘IO,iotop找高IO进程。如果是磁盘满,df -h检查空间,du -sh *找大文件;如果是网络IO,netstat或ss看连接状态,tcpdump抓包分析。 - 进程状态:
top中关注D状态进程(不可中断睡眠,通常是IO等待),大量D状态进程会导致load飙升但CPU使用率不高。
举例:load average显示10,CPU核心8,top发现wa占60%,iostat显示磁盘util 100%,最后定位到某个MySQL实例在做全表扫描——这就是典型的IO密集型负载高。
【面试题】4. Tomcat的Connector三种线程模型(BIO/NIO/APR)有什么区别?生产环境如何选择?
【标准答案】Tomcat Connector支持三种线程模型,性能差异明显:
BIO(阻塞IO,默认到Tomcat 8.0):
- 每个请求一个线程,线程阻塞等待请求完成
- 线程数 = 并发连接数,高并发下线程资源消耗大
- 适合低并发场景,配置简单,性能最差
- 配置:
<Connector protocol="HTTP/1.1" />(Tomcat 8.0前默认)
NIO(非阻塞IO,Tomcat 8.5+默认):
- 使用Java NIO API,少量线程处理大量连接
- 通过Selector多路复用,一个线程管理多个连接
- 线程数远小于并发连接数,资源利用率高
- 适合高并发、长连接场景
- 配置:
<Connector protocol="org.apache.coyote.http11.Http11NioProtocol" />
APR(Apache Portable Runtime):
- 使用本地库(C语言实现),性能最高
- 需要安装APR库和Tomcat Native库
- 在高并发、大流量场景下性能优于NIO约10-20%
- 配置:
<Connector protocol="org.apache.coyote.http11.Http11AprProtocol" />
生产环境选择建议:
- Tomcat 8.5+ 默认NIO,多数场景够用,无需改动
- 如果是超高并发(万级QPS以上)或对性能敏感,安装APR库使用APR模式
- 判断是否需要APR:先用NIO压测,如果CPU成瓶颈且连接数高,考虑APR
- 安装APR:
yum install apr apr-util,编译tomcat-native,配置LD_LIBRARY_PATH
实际面试中可以说:我们线上环境用NIO,配合线程池调优(maxThreads=500,acceptCount=100),单实例支撑5000 QPS没问题。如果需要更高性能,会切换APR并增加Tomcat实例做负载均衡。
【面试题】5. 如何排查Nginx返回502 Bad Gateway错误?请给出完整排查流程。
【标准答案】502 Bad Gateway表示Nginx作为代理无法从上游服务器获取有效响应。排查流程:
第一步:查看Nginx错误日志
tail -f /var/log/nginx/error.log- 典型错误信息:
connect() failed (111: Connection refused):上游服务未启动或端口不对connect() failed (113: No route to host):防火墙阻断或网络不通upstream timed out (110: Connection timed out):上游服务响应慢recv() failed (104: Connection reset by peer):上游服务主动断开
第二步:检查上游服务状态
- 确认后端服务是否启动:
systemctl status tomcat/php-fpm - 检查端口监听:
netstat -tlnp | grep <端口>或ss -tlnp | grep <端口> - 本地测试上游服务:
curl http://127.0.0.1:<后端端口>
第三步:检查Nginx配置
- upstream地址是否正确:
upstream backend { server 127.0.0.1:8080; } - proxy_pass是否指向正确的upstream
- 检查超时配置:
proxy_connect_timeout、proxy_read_timeout是否过短
第四步:网络连通性
- 防火墙规则:
iptables -L -n或firewall-cmd --list-all - SELinux策略:
getenforce,临时关闭测试setenforce 0 - telnet测试:
telnet <上游IP> <上游端口>
第五步:资源瓶颈
- 后端服务进程数是否达到上限:
ps -ef | grep php-fpm | wc -l - 后端服务连接数是否耗尽:
netstat -an | grep ESTABLISHED | wc -l - 内存是否不足:
free -m,触发OOM会用dmesg | grep -i kill
常见原因总结:
- 后端服务挂了或未启动(最常见)
- 端口配置错误
- 防火墙/SELinux阻断
- 后端服务处理慢,超时断开
- 后端服务进程数或连接数达到上限
面试时可以举例:某次502是因为PHP-FPM进程数达到上限,pm.max_children配置太小,调大后解决。另一次是防火墙新规则阻断了内网端口,添加例外规则后恢复。
【面试题】6. Linux系统如何限制进程的资源使用?ulimit和cgroup有什么区别?
【标准答案】Linux限制进程资源有两种主要方式:ulimit和cgroup,适用场景不同。
ulimit方式:
- 限制单个用户或session的资源,包括文件描述符数、进程数、内存等
- 配置文件:
/etc/security/limits.conf,格式:<domain> <type> <item> <value> - 常见配置:
* soft nofile 65535:所有用户软限制文件描述符数* hard nofile 65535:硬限制* soft nproc 65535:进程数限制
- 生效方式:重新登录或用
ulimit -n 65535临时设置 - 局限:只能限制单个用户,不能精确控制某个进程组;重启失效
cgroup方式:
- Linux内核级资源隔离,精确控制进程组的CPU、内存、磁盘IO、网络带宽
- 通过文件系统接口配置:
/sys/fs/cgroup/(cgroup v2)或/sys/fs/cgroup/<controller>/(cgroup v1) - 常用controller:
cpu:CPU时间片和权重cpuset:绑定CPU核心memory:内存使用上限blkio:块设备IO限制
- 使用场景:Docker容器、Kubernetes Pod资源限制、多租户环境
配置示例(cgroup v2):
# 创建控制组
mkdir /sys/fs/cgroup/myapp
# 限制内存为1GB
echo 1G > /sys/fs/cgroup/myapp/memory.max
# 限制CPU使用率为50%
echo 50000 > /sys/fs/cgroup/myapp/cpu.max # 格式: quota period
# 将进程加入控制组
echo <PID> > /sys/fs/cgroup/myapp/cgroup.procs区别总结:
| 维度 | ulimit | cgroup |
|---|---|---|
| 控制粒度 | 用户级别 | 进程组级别 |
| 资源类型 | 文件描述符、进程数、内存等 | CPU、内存、磁盘IO、网络带宽 |
| 动态调整 | 需重新登录或手动设置 | 运行时动态调整 |
| 容器化 | 不适用 | Docker/K8s底层机制 |
| 复杂度 | 简单,一行配置 | 复杂,需要理解cgroup hierarchy |
面试时强调:生产环境推荐用cgroup,因为更精确、更灵活,Docker和K8s都基于cgroup实现资源限制。ulimit适合简单场景,比如防止某个用户打开过多文件导致系统资源耗尽。
【面试题】7. Prometheus+Grafana监控体系的架构是怎样的?如何设计告警规则?
【标准答案】Prometheus+Grafana是目前最流行的开源监控方案,架构清晰,扩展性强。
架构组成:
- Prometheus Server:核心组件,负责数据采集(Pull模式)和存储(时序数据库TSDB)
- 配置
prometheus.yml定义抓取目标(targets)和频率(scrape_interval) - 支持服务发现(Consul、K8s、文件发现等)
- 配置
- Exporters:数据暴露器,将系统/应用指标转换为Prometheus格式
node_exporter:主机监控(CPU、内存、磁盘、网络)mysqld_exporter:MySQL监控nginx-vts-exporter:Nginx监控- 应用自定义metrics暴露接口(如Spring Boot Actuator)
- Pushgateway:临时任务推送数据的网关(Prometheus是Pull模式,短任务无法被抓取时使用)
- Alertmanager:告警管理,处理Prometheus发送的告警,去重、分组、路由、通知
- Grafana:可视化面板,查询Prometheus数据,展示图表和仪表盘
数据模型:
- 格式:
metric_name{label1="value1", label2="value2"} value timestamp - 示例:
http_requests_total{method="GET", status="200"} 1234 - PromQL查询语言:
rate(http_requests_total[5m])计算5分钟请求速率
告警规则设计: 配置在prometheus.yml的rule_files中,示例:
groups:
- name: node_alerts
rules:
# CPU使用率超过80%持续5分钟告警
- alert: HighCPUUsage
expr: 100 - (avg by(instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) > 80
for: 5m
labels:
severity: warning
annotations:
summary: "High CPU usage on {{ $labels.instance }}"
description: "CPU usage is {{ $value }}%"
# 内存使用率超过90%告警
- alert: HighMemoryUsage
expr: (1 - (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes)) * 100 > 90
for: 5m
labels:
severity: critical
# 磁盘使用率超过85%告警
- alert: DiskSpaceLow
expr: (1 - (node_filesystem_avail_bytes{fstype!~"tmpfs|overlay"} / node_filesystem_size_bytes)) * 100 > 85
for: 10m
labels:
severity: warning告警设计原则:
- 避免噪音:设置合理的
for持续时间,瞬时抖动不告警 - 分级告警:warning、critical、emergency,不同级别不同通知渠道
- 告警聚合:Alertmanager配置
group_by和group_wait,同类告警合并通知 - 业务指标:除了系统指标,监控业务指标(如API错误率、订单量异常)
- 告警抑制:节点故障时,抑制该节点上所有服务的告警,避免告警风暴
通知渠道配置: Alertmanager支持邮件、Slack、钉钉、企业微信、Webhook等。生产环境推荐多渠道:critical级别电话+短信,warning级别IM通知。
面试时可以补充:我们线上有自建Grafana仪表盘,展示API响应时间P99、错误率、QPS等业务指标,配合告警规则,能做到5分钟内发现问题并通知值班人员。
【面试题】8. Nginx如何配置HTTPS?证书更新流程是怎样的?
【标准答案】Nginx配置HTTPS分为三步:获取证书、配置Nginx、证书更新。
第一步:获取SSL证书
- 申请渠道:Let's Encrypt(免费)、阿里云/腾讯云(付费证书)、商业CA
- Let's Encrypt自动申请:
certbot --nginx -d example.com -d www.example.com - 手动申请:生成CSR(
openssl req -new -newkey rsa:2048 -nodes -keyout domain.key -out domain.csr),提交CA,获取证书文件
第二步:Nginx配置HTTPS
server {
listen 443 ssl http2;
server_name example.com;
# 证书文件
ssl_certificate /etc/nginx/ssl/example.com.crt;
ssl_certificate_key /etc/nginx/ssl/example.com.key;
# SSL协议和加密套件
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256';
ssl_prefer_server_ciphers on;
# SSL会话缓存
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
# HSTS(可选,强制HTTPS)
add_header Strict-Transport-Security "max-age=31536000" always;
location / {
proxy_pass http://backend;
}
}
# HTTP跳转HTTPS
server {
listen 80;
server_name example.com;
return 301 https://$server_name$request_uri;
}第三步:证书更新流程 Let's Encrypt证书有效期90天,需要定期更新:
- 自动更新:配置cron定时任务,
certbot renew --quiet每天执行,到期前30天自动续期 - 手动更新:
certbot renew,然后nginx -s reload重新加载配置 - 脚本示例:
# /etc/cron.daily/certbot-renew
#!/bin/bash
certbot renew --quiet --post-hook "nginx -s reload"商业证书更新流程:
- CA发送邮件提醒证书即将过期(通常提前30天)
- 登录CA管理后台,重新申请证书(可以用原有CSR,也可以重新生成)
- 下载新证书文件,替换服务器上的证书文件
nginx -s reload重新加载配置(不中断服务)- 验证证书:
openssl s_client -connect example.com:443 | openssl x509 -noout -dates
证书链配置: 有些CA签发的证书需要配置证书链(中间证书),否则浏览器报错:
- 证书文件内容顺序:服务器证书 → 中间证书 → 根证书
- 或者用
ssl_trusted_certificate单独指定CA证书链
SSL配置最佳实践:
- 禁用不安全协议:只保留TLSv1.2和TLSv1.3
- 加密套件优先使用ECDHE(前向保密)
- 启用OCSP Stapling加速证书验证:
ssl_stapling on; ssl_stapling_verify on; - 定期测试SSL配置:
nmap --script ssl-enum-ciphers -p 443 example.com或在线工具SSL Labs
面试时可以说:我们用Let's Encrypt自动续期,配置了cron每天检查,证书到期前自动更新并reload Nginx,无需人工干预。同时用监控检测证书过期时间,剩余不足14天时发送告警。
【面试题】9. Docker容器的网络模式有哪些?各有什么使用场景?
【标准答案】Docker容器有5种网络模式,不同模式适用于不同场景。
1. bridge模式(默认)
- 每个容器有独立的network namespace,分配虚拟网卡和IP
- 容器通过虚拟网桥(docker0)连接宿主机
- 容器间可以通过IP互相访问
- 对外访问通过NAT(宿主机iptables规则)
- 使用场景:普通应用容器,需要网络隔离
- 配置:
docker run --network bridge <image>(默认无需指定)
2. host模式
- 容器与宿主机共享network namespace,无网络隔离
- 容器直接使用宿主机的IP和端口
- 性能最好,无NAT开销
- 使用场景:高性能网络应用、需要监听大量端口的服务
- 配置:
docker run --network host <image> - 注意:端口冲突问题,容器内监听的端口会占用宿主机端口
3. none模式
- 容器有独立的network namespace,但没有网络设备(只有loopback)
- 完全禁用网络
- 使用场景:安全要求高的应用、离线计算任务、需要自定义网络配置
- 配置:
docker run --network none <image>
4. container模式
- 与指定容器共享network namespace
- 共享IP、端口、路由表、iptables规则
- 使用场景:容器间需要共享网络栈、监控容器、sidecar模式
- 配置:
docker run --network container:<容器名或ID> <image>
5. 自定义网络(user-defined bridge)
- 创建自定义bridge网络,容器可以互相通过容器名访问(DNS解析)
- 更灵活的网络隔离和配置
- 使用场景:微服务架构,容器间需要通过服务名访问
- 配置:
docker network create mynet
docker run --network mynet --name app1 <image>
docker run --network mynet --name app2 <image>
# app2可以通过http://app1访问app1生产环境推荐:
- 微服务架构:使用自定义bridge网络或overlay网络(跨主机)
- 高性能网络:使用host模式(如Nginx、Redis)
- 安全隔离:使用none模式+自定义网络配置
- K8s环境:使用CNI插件(Flannel、Calico等),不直接用Docker网络
跨主机通信方案:
- overlay网络:Docker Swarm原生支持,跨主机容器互通
- macvlan:容器拥有独立MAC地址,直接接入物理网络
- CNI插件:Kubernetes使用,支持多种网络方案(Flannel、Calico、Weave)
面试时可以举例:我们线上用自定义bridge网络部署微服务,每个服务一个网络,服务间通过容器名访问。性能敏感的Nginx和Redis用host模式,直接使用宿主机网络,性能提升约10%。
【面试题】10. 如何设计一个支持百万级并发的高性能服务器架构?
【标准答案】百万级并发架构设计是系统工程,需要从接入层、应用层、数据层、存储层四层优化,加上缓存、消息队列、监控告警支撑。
一、接入层设计
- DNS负载均衡:域名解析到多个VIP,实现地域级流量分发
- CDN加速:静态资源、图片、视频通过CDN分发,减少源站压力
- 四层负载均衡:LVS+Keepalived,单机支撑百万并发连接(内核态转发,无用户态开销)
- 七层负载均衡:Nginx集群,配置多个upstream,支持健康检查和动态扩容
- HTTPS卸载:Nginx处理SSL,减轻应用层压力
二、应用层设计
- 微服务拆分:按业务域拆分服务,独立部署和扩容
- 无状态设计:应用服务无状态,Session存储到Redis,支持水平扩展
- 连接池:数据库连接池、HTTP连接池、Redis连接池,复用连接减少开销
- 异步处理:耗时操作异步化(消息队列),提升响应速度
- 服务治理:服务注册发现(Nacos/Consul)、熔断降级(Sentinel/Hystrix)、限流(令牌桶/漏桶)
三、数据层设计
- 读写分离:主库写入,从库读取,减轻主库压力
- 分库分表:水平拆分(按用户ID哈希),单表控制在千万级
- 数据库连接池:Druid/HikariCP,控制最大连接数
- SQL优化:索引优化、慢查询监控、避免全表扫描
四、缓存层设计
- 多级缓存:本地缓存(Guava/Caffeine)+ 分布式缓存(Redis)
- 缓存穿透/击穿/雪崩防护:布隆过滤器、互斥锁、过期时间随机化
- Redis集群:哨兵模式或Cluster模式,支持故障转移和水平扩展
- 缓存预热:启动时加载热点数据到缓存
五、消息队列设计
- 削峰填谷:流量高峰时消息堆积到队列,消费端按能力处理
- 异步解耦:核心流程同步,非核心流程异步(如发送通知、日志记录)
- 消息可靠性:确认机制、持久化、重试策略
- 技术选型:Kafka(高吞吐)、RocketMQ(事务消息)、RabbitMQ(灵活路由)
六、存储层设计
- 对象存储:OSS/COS存储文件、图片、视频,CDN加速
- 日志存储:ELK收集日志,冷热数据分离
- 时序数据库:InfluxDB/TDengine存储监控数据
七、基础设施
- 容器化部署:Docker+Kubernetes,Pod水平自动伸缩(HPA)
- 服务网格:Istio/Envoy,流量管理、可观测性
- 监控告警:Prometheus+Grafana,监控CPU、内存、QPS、延迟、错误率
- 链路追踪:Jaeger/Zipkin,定位分布式系统瓶颈
架构示意:
用户 → DNS → CDN → LVS(四层) → Nginx(七层) → 网关(限流鉴权)
→ 微服务集群 ← Redis集群
→ 消息队列 ← 异步消费者
→ MySQL主从集群
→ OSS对象存储性能调优要点:
- Linux内核参数:文件描述符、TCP连接参数、内存管理
- Nginx调优:worker进程数、连接数、epoll、缓冲区
- JVM调优:堆大小、GC策略、线程池
- 数据库调优:索引、查询优化、连接数
面试时可以举例:我们某个电商活动,QPS从日常5000飙升到50万,通过LVS+Nginx接入、微服务自动扩容到100个实例、Redis集群缓存热点商品、Kafka削峰,最终平稳支撑了活动流量。关键点是提前压测和自动化扩容。
总结:以上10道题覆盖了Nginx配置、高可用、Linux运维、Tomcat调优、故障排查、监控告警、容器化、架构设计等核心知识点。面试时要结合实际项目经验,用具体数字和案例佐证,体现实战能力。