运维常见面试题_04_Nginx与DNS服务
Q86. 什么是惊群问题Nginx 是如何解决的1. 是什么惊群thundering herd指多个进程/线程同时阻塞在同一个事件上如对同一监听 socket 执行 accept当事件到达时内核把所有等待者全部唤醒但最终只有一个能成功处理其余被唤醒后发现无事可做又重新睡眠造成大量无谓的上下文切换和 CPU 消耗。2. 为什么用它Nginx 是典型的master 多 worker模型多个 worker 进程默认都监听同一个端口。若无保护机制一个连接到达会唤醒所有 worker大部分白忙一场。解决惊群能显著降低高并发下的 CPU 开销。3. 怎么用它Nginx 的解决手段按演进顺序accept_mutex 互斥锁早期方案多个 worker 共享一把 accept 锁只有抢到锁的 worker 才能 accept 新连接其余 worker 在锁上等待避免同时被唤醒。旧版本默认accept_mutex on;。listen 的 reuseportLinux 3.9Nginx 1.9.1 支持为每个 worker 建立独立的监听 socket由内核按 4 元组 hash 把新连接直接分发到某个 worker 的独立队列无需抢锁从源头消除惊群吞吐更高server { listen 8080 reuseport; # 每个 worker 独立队列内核负载均衡 }EPOLLEXCLUSIVE内核 4.5epoll 事件只唤醒一个等待者。从 Nginx 1.11.3 起若内核支持 EPOLLEXCLUSIVE 或使用了 reuseportaccept_mutex默认关闭避免额外锁开销。另外 worker 进程通过events块的非阻塞事件驱动epoll模型并发处理海量连接master 进程只负责信号与 worker 管理不参与 accept。4. 使用场景面试考察对 Nginx 多进程模型的深层理解。答题关键先说清多个等待者被同时唤醒、只有一者能干活的惊群现象再按 accept_mutex → reuseport → EPOLLEXCLUSIVE 的演进讲 Nginx 的三种解法并点出 reuseport 在高并发下的取舍连接分布不均时可能倾斜。Q87. 如何配置 Nginx 记录 upstream 服务器的真实响应时间1. 是什么Nginx 内置了多个 upstream 相关变量可在日志中记录后端到底处理了多久。核心变量有$upstream_response_time后端返回响应所花时间秒精确到毫秒、$upstream_connect_time与后端建立连接耗时1.9.1、$upstream_addr实际处理请求的后端地址、$upstream_status后端返回的状态码。2. 为什么用它$request_time是 Nginx 收到请求到返回响应的完整耗时含与客户端传输、等待后端的全部时间无法区分瓶颈在前端、网络还是后端。记录 upstream 时间才能量化后端慢还是网络慢/前端慢。3. 怎么用它在http块定义自定义日志格式并在 access_log 中启用http { log_format upstream $remote_addr [$time_local] $request status$status request_time$request_time upstream_connect$upstream_connect_time upstream_resp$upstream_response_time upstream_addr$upstream_addr upstream_status$upstream_status; server { access_log /var/log/nginx/access.log upstream; } }解读要点$request_time与$upstream_response_time相差大 → 慢在网络/客户端用户带宽小、上传慢、长连接等待两者几乎相等且都大 → 后端应用本身慢去优化 SQL/接口/缓存$upstream_connect_time大 → 后端建连慢查后端半连接队列溢出、负载过高一个请求内部多次访问 upstream如内部重定向时upstream 相关变量可能是逗号分隔的多个值如0.010, 0.024按顺序对应每次后端调用$upstream_response_time在未访问后端如命中 Nginx 缓存时为-。4. 使用场景线上慢请求排查——用日志里$request_time与$upstream_response_time的差值定位是后端慢还是网络/客户端慢配合$upstream_addr还能看出负载是否倾斜到某台后端。面试要点分清request_time与upstream_response_time的语义差异这是核心考察点。Q88. 如何配置 Nginx 将 HTTP 请求重定向到 HTTPS1. 是什么让所有通过http://80 端口访问的请求自动跳转到https://443 端口通常用 HTTP 301/302 重定向实现。2. 为什么用它HTTPS 已加密流量强制跳转可避免明文访问对正式站点用 301 永久跳转还能保证 SEO 权重集中到 https 地址。3. 怎么用它推荐用return指令比 rewrite 高效不经过正则匹配server { listen 80; server_name example.com www.example.com; return 301 https://$host$request_uri; # 保留原路径与查询参数 } server { listen 443 ssl; server_name example.com www.example.com; ssl_certificate /etc/nginx/ssl/example.com.pem; ssl_certificate_key /etc/nginx/ssl/example.com.key; # 其余业务配置... }备选 rewrite 写法server { listen 80; server_name example.com; rewrite ^(.*)$ https://$host$1 permanent; }要点$host保留用户访问的域名$request_uri保留原路径和?查询串避免跳转后丢失参数301 permanent永久适合正式站点利于 SEO、浏览器缓存跳转临时活动页可用302只监听 80 且只做跳转的 server 块里不要再写业务 location避免重复处理可配合add_header Strict-Transport-Security max-age31536000 always;HSTS强制浏览器后续直接用 https 访问。4. 使用场景上线 HTTPS 时的统一跳转、迁移 https 后清理 http 入口、合规要求禁止明文传输。面试要点首选return 301 https://$host$request_uri;并解释$host/$request_uri的作用和 301/302 的区别。Q89. Nginx 返回 502 Bad Gateway 错误可能的原因有哪些如何排查1. 是什么502 Bad Gateway 表示 Nginx 作为网关/反向代理向上游upstream 后端发出请求后没有收到后端的有效响应或后端不可达。2. 为什么用它502 是反代架构下最高频的故障多数情况问题不在 Nginx 本身而在后端。掌握原因分类与排查顺序能快速定位是后端挂了还是配置/网络/超时问题。3. 怎么用它先看 error.log再逐项排查tail-f/var/log/nginx/error.log# 第一步看具体错误决定排查方向按 error.log 报错分类定位connect() failed (111: Connection refused)→后端没启动或端口不对systemctl status svc、curl http://127.0.0.1:端口直连验证检查proxy_pass的地址与端口是否写错connect() failed (110: Connection timed out)→后端网络不通检查防火墙/安全组、路由SELinux 拦截可用getenforce/setenforce 0临时验证upstream timed out→后端处理太慢后端负载高、慢 SQL、线程池打满调大proxy_connect_timeout/proxy_read_timeout/proxy_send_timeoutno live upstreams while connecting to upstream→后端全部不可用健康检查全挂、后端全部宕机或 weight/backup 配置有问题FastCGI 场景php-fpm 等502php-fpm未启动、fastcgi_pass的 socket 路径不对或权限不足unix:/run/php-fpm/www.sock属主不匹配后端连接数打满tomcat 线程池、MySQL 连接池耗尽看后端自身日志与ss -ant连接数。4. 使用场景反代后端故障、发布后服务未拉起、后端接口偶发超时的线上排查。面试要点先背结论502 是 Nginx 没拿到后端的有效响应先看 error.log再按直连后端 → 网络/防火墙 → 超时参数 → 后端资源的顺序展开能说出111 Connection refused、110 Timeout、no live upstreams三种典型报错对应的原因。Q90. Nginx 的 access_log 和 error_log 主要关注哪些信息1. 是什么access_log按请求记录每一次访问流量/访问行为error_log记录运行过程中的错误与异常排障入口。两者的文件、格式、关注点完全不同。2. 为什么用它access_log 用于流量统计、慢请求分析、安全审计error_log 是 Nginx 问题排查的第一现场。会读这两个日志是 Nginx 运维基本功。3. 怎么用它access_log 关注的信息核心变量log_format main $remote_addr - $remote_user [$time_local] $request $status $body_bytes_sent $http_referer $http_user_agent $request_time $upstream_addr $upstream_response_time $http_x_forwarded_for; access_log /var/log/nginx/access.log main;来源信息$remote_addr客户端 IP、$http_x_forwarded_for真实客户端 IP需上游代理透传、$http_user_agent、$http_referer请求信息$request方法 URI、$request_time总耗时、$request_length响应信息$status状态码、$body_bytes_sent响应体大小后端信息$upstream_addr、$upstream_response_time、$upstream_status分析用途PV/UV、TOP IP/TOP URL、状态码分布、慢请求按$request_time排序、带宽与流量估算。注意默认格式只含时间、IP、请求、状态、大小不含耗时与 upstream 信息。error_log 关注的信息error_log /var/log/nginx/error.log warn; # 级别debug info notice warn error crit alert emerg日志级别生产通常error或warn调试用debug会记录海量信息常见错误connect() failed后端连不上、upstream timed out上游超时、no live upstreams后端全挂、worker_connections are not enough连接数不够调大worker_connections、too many open files句柄耗尽查 ulimit、open() ... failed (13: Permission denied)权限问题、recv() failed客户端提前断开每条记录含时间、级别、worker 连接号*123可与 access_log 关联、具体错误、相关文件/行号。4. 使用场景用户报网站慢/打不开先看 error.log 有没有报错再做 access_log 的慢请求与状态码分析安全事件用 access_log 排查恶意 IP/异常路径。面试要点一句话区分——access_log 面向请求流量分析error_log 面向错误故障定位排障顺序永远是先 error_log。Q91. 如何用 OpenResty 实现更复杂的业务逻辑1. 是什么OpenResty 是带 LuaJIT 的 Nginx把 Nginx 从纯转发层升级成能跑业务逻辑的应用平台。它通过ngx_lua模块在请求处理的各个阶段rewrite/access/content/log注入 Lua 脚本直接读取/修改请求、访问 Redis/MySQL、并发请求后端并把结果拼装返回。2. 为什么用它传统架构中鉴权、限流、聚合等逻辑都要跑到后端应用做每次都要经历一次网络往返。OpenResty 把这些逻辑下沉到 Nginx 层就地执行LuaJIT 编译执行极快大幅降低延迟和下游压力且支持热更新reload 即生效。3. 怎么用它# 共享内存字典跨 worker 共享用于计数/缓存 lua_shared_dict mycache 10m; server { location /api/order { access_by_lua_block { -- 1) 鉴权校验 Token local token ngx.var.http_authorization if not token or token ~ secret then ngx.exit(ngx.HTTP_FORBIDDEN) end -- 2) 限流基于共享字典做简单计数生产用 lua-resty-limit-traffic local d ngx.shared.mycache local n d:incr(ngx.var.remote_addr, 1, 1) if n 100 then ngx.exit(ngx.HTTP_TOO_MANY_REQUESTS) end } content_by_lua_block { -- 3) 聚合并发请求两个后端再拼装返回 local res1 ngx.location.capture(/upstream/inventory) local res2 ngx.location.capture(/upstream/user) ngx.say(ngx.encode_json({ inventory cjson.decode(res1.body), user cjson.decode(res2.body) })) } } }常用能力阶段钩子rewrite_by_lua_block改写请求、access_by_lua_block鉴权限流、content_by_lua_block生成响应、log_by_lua_block异步日志上报核心 APIngx.var.*读写 Nginx 变量、ngx.req读/改请求、ngx.say/ngx.print输出、ngx.redirect跳转、ngx.location.capture子请求访问内部 location、ngx.timer.at定时任务、ngx.shared.DICTworker 间共享存储生态库lua-resty-redis/lua-resty-mysql直连缓存/数据库、lua-resty-limit-traffic限流、lua-resty-jwtJWT、resty.http对外发起 HTTP典型业务动态黑白名单、基于 Redis 的灰度/AB 分流、URL 级限流与熔断、请求聚合网关、边缘鉴权。注意点禁止在 Lua 里做阻塞调用如同步socket:connect会卡住整个 worker阻塞操作用 cosocket 异步模型业务逻辑保持精简复杂计算仍建议回落到后端应用排查 Lua 问题用error_log调debug级别 ngx.log输出。4. 使用场景网关型业务鉴权/限流/灰度在边缘统一做、API 聚合、缓存穿透防护、业务规则频繁变更又不愿重启后端的场景。面试要点讲清OpenResty Nginx LuaJIT把逻辑放到各阶段钩子里就地执行举一个可落地的例子如限流或鉴权并强调不能阻塞 worker这个关键约束。Q92. 如何配置 Nginx 的缓存来加速后端动态应用1. 是什么Nginx 的proxy_cache反向代理缓存可以把后端返回的响应缓存到本地磁盘下次相同请求直接由 Nginx 返回不再打到后端从而显著降低后端压力与响应延迟。2. 为什么用它动态应用如 Java/PHP/Node 后端处理请求开销大而很多动态接口实际上内容变化不频繁。用 Nginx 做一层缓存把重复请求拦在 Nginx 层后端只处理真实变化的数据和缓存未命中的请求。3. 怎么用它# http 块定义缓存区路径、目录分层、共享内存、磁盘上限、清理策略 proxy_cache_path /var/cache/nginx levels1:2 keys_zonemycache:10m max_size1g inactive60m use_temp_pathoff; server { location / { proxy_pass http://backend; # 开启缓存 proxy_cache mycache; proxy_cache_key $scheme$request_method$host$request_uri; # 缓存 key proxy_cache_valid 200 302 10m; # 200/302 缓存 10 分钟 proxy_cache_valid 404 1m; # 404 只缓存 1 分钟 proxy_cache_min_uses 1; # 至少被访问 1 次才缓存 # 精细控制用户态/带会话 Cookie 的请求绕过缓存避免串数据 proxy_cache_bypass $cookie_session; proxy_no_cache $cookie_session; add_header X-Cache-Status $upstream_cache_status; # 观察命中情况 } }参数与调优要点proxy_cache_pathlevels1:2生成两级子目录避免单目录文件过多keys_zone是共享内存存 key 与缓存元数据10m约可存几万 keymax_size为磁盘上限超限按 LRU 淘汰inactive指定时间内没被访问则清理proxy_cache_key默认$scheme$proxy_host$request_uri业务一般要加上$host、方法按需加版本号参数避免命中旧缓存缓存命中判断$upstream_cache_status取值HIT命中/MISS未命中/EXPIRED过期已回源/BYPASS被绕过动态应用缓存策略只缓存 GET/HEAD带登录 Cookie 或用户态的请求用proxy_cache_bypass/proxy_no_cache绕过敏感接口不缓存清除缓存rm -rf /var/cache/nginx/*或按 key 删除线上常配合加版本号参数实现即时失效后端主动配合让后端返回Cache-Control/Expires头Nginx 按业务语义缓存比统一写死时长更灵活。4. 使用场景热点接口缓存加速、静态化页面缓存、突发流量如秒杀时保护后端。面试要点能默写核心指令proxy_cache_path、proxy_cache、proxy_cache_key、proxy_cache_valid说清$upstream_cache_status的 HIT/MISS 判断方法并强调用户态/带 Cookie 请求要绕过缓存避免串数据。Q93. 描述 DNS 递归查询和迭代查询的过程。1. 是什么DNS 查询分两种交互方式递归查询recursive指 DNS 服务器替客户端查到底并返回最终答案迭代查询iterative指 DNS 服务器只返回下一站该问谁的指引由查询方自己去逐级追问。2. 为什么用它理解两类查询才能看懂 digtrace的输出、理解根服务器/顶级域/权威服务器的分工也才能解释为什么改完 DNS 记录要等生效。3. 怎么用它以解析www.example.com为例递归查询客户端 → 本地 DNS客户端把查询交给本地 DNS如运营商114.114.114.114要求你替我把最终结果查出来本地 DNS 必须返回最终的 A 记录或 NXDOMAIN 等失败结果不能只给个半成品优点客户端实现简单缺点查询压力集中在 DNS 服务器所以服务器会做缓存。迭代查询本地 DNS → 各级服务器本地DNS --(迭代)-- 根服务器(.) → 返回 .com 顶级域服务器地址 本地DNS --(迭代)-- .com 顶级域服务器 → 返回 example.com 权威服务器地址 本地DNS --(迭代)-- example.com 权威服务器 → 返回 www.example.com 的 A 记录根服务器全球 13 组根服务器只回答.com/.cn该问谁顶级域服务器.com、.cn只回答example.com 该问谁权威服务器NS 记录指向的服务器才给出最终的记录每一级都支持缓存命中即无需继续往下问。4. 使用场景dig trace www.example.com可直观看到根 → 顶级域 → 权威的迭代过程排查域名解析慢时用dig 8.8.8.8与dig 本地对比判断慢在本地 DNS 还是权威侧。面试要点一句话区分——递归是帮你查到底迭代是指路让你自己去查典型拓扑是客户端→本地 DNS 递归本地 DNS→根→TLD→权威 迭代。Q94. A记录, CNAME, MX记录, TXT记录, SRV记录 分别是什么1. 是什么DNS 不只是域名→IP它还支持多种记录类型每种记录承载一类映射信息。2. 为什么用它配置域名解析、企业邮箱、微信/企业认证、服务发现都依赖不同记录类型。会区分它们才能正确建解析也能看懂dig返回的各类记录。3. 怎么用它记录类型含义格式示例典型用途A 记录域名 → IPv4 地址example.com A 1.2.3.4最基本的网站解析IPv4IPv6 用AAAACNAME 记录别名 → 指向另一个域名www.example.com CNAME example.comCDN/别名接入注意同一主机名不能同时有 A 和 CNAMEMX 记录邮件交换记录指定收件服务器及优先级example.com MX 10 mail.example.com邮件路由数字越小优先级越高多个 MX 用于冗余/负载TXT 记录任意文本信息example.com TXT vspf1 include:... -allSPF/DKIM/DMARC 邮件安全验证、域名所有权验证SRV 记录服务定位指明特定服务与协议的主机 端口_sip._tcp.example.com SRV 10 60 5060 sip.example.com服务发现SIP、LDAP、XMPP 等格式为_service._proto.name 优先级、权重、端口、目标主机补充优先级/权重MX 用数字小优先SRV 先按优先级priority 小者优先同优先级内按权重weight 越大分配越多负载均衡常见混淆CNAME 的别名链最终仍解析到 A 记录TXT 记录与邮件头无直接关系只是认证/验证用的文本主机记录表示根域名本身 A与 MX可共存但www CNAME与www A不可共存。4. 使用场景新域名上线A/CNAME、配置企业邮箱MX TXT/SPF、服务内网发现SRV、域名归属验证TXT。面试要点每个记录说一个词定义 一个示例——A 指 IP、CNAME 指别名、MX 管邮件、TXT 放文本认证、SRV 定位服务端口并点出 CNAME 与 A 不能共存、MX 数字小优先这两个易错点。Q95. 如何用 dig 和 nslookup 命令查询各种记录并分析输出1. 是什么digLinux/BIND 自带的 DNS 查询工具和nslookupWindows/Linux 均内置都能发 DNS 查询dig功能更强、输出更详细适合分析nslookup简单易用适合快速查询。2. 为什么用它查解析结果、验证修改是否生效、分析解析慢/失败都是高频运维操作熟练使用这两个命令尤其是 dig 的trace是 DNS 排错的基础。3. 怎么用它dig 常用用法digexample.com# 默认查询 A 记录digexample.com A / MX / TXT / CNAME / SRV / NS# 查指定类型dig8.8.8.8 example.com# 指定 DNS 服务器digshort example.com# 只输出答案简洁digtrace example.com# 从根服务器开始迭代追踪全链路dig-x1.2.3.4# 反向解析 PTRdigexample.com noall answer# 只显示答案区dig 输出分析关键区块;; QUESTION SECTION: # 查询的问题域名 类型 ;example.com. IN A ;; ANSWER SECTION: # 答案记录值 TTL缓存秒数 类型 example.com. 300 IN A 1.2.3.4 ;; AUTHORITY SECTION: # 权威服务器NS 记录找谁确认 ;; ADDITIONAL SECTION: # 附加信息如 NS 对应的 A 记录 ;; Query time: 12 msec # 本次查询耗时 ;; status: NOERROR # NOERROR 正常 / NXDOMAIN 域名不存在 / SERVFAIL 服务器故障 / REFUSED 拒绝nslookup 常用用法nslookupexample.com# 默认查 Anslookup-typemx example.com# 查 MXnslookup-typens example.com# 查 NS权威服务器nslookup-typetxt example.com# 查 TXTnslookup-typesrv _sip._tcp.example.com# 查 SRVnslookup-typeptr4.3.2.1# 反查 PTRnslookupexample.com8.8.8.8# 指定 DNS 服务器# 交互模式输入 nslookup 后 set typemx 切换类型再输入域名查询分析思路对比dig 8.8.8.8与dig 本地DNS的结果是否一致 → 判断是本地缓存/污染问题还是上游问题status: NXDOMAIN→ 域名确实不存在SERVFAIL→ 权威服务器有问题NOERROR但无答案 → 该类型记录未配置看 TTL 判断缓存多久生效——修改 DNS 记录后旧记录在 TTL 内可能仍被缓存Query time大 → 排查权威服务器慢或本地 DNS 到上游的网络质量Windows 下nslookup够用深入分析trace、多服务器对比建议用dig。4. 使用场景上线前验证解析、域名到期/迁移后检查、排查域名解析慢/解析失败、配置邮件后验证 MX/TXT 是否生效。面试要点会查指定类型记录、会指定服务器、能看懂trace的链路和NOERROR/NXDOMAIN/SERVFAIL三者的含义。