面试题手册

梳理高频技术问题,帮助你按主题复习和查漏补缺。

服务端阅读 05月27日 22:33

GraphQL 与 REST API 的核心区别是什么

核心答案GraphQL 和 REST 的根本区别在于谁决定返回什么数据:REST 由服务端定义固定响应结构,GraphQL 由客户端按需声明字段。这一差异向下传导,影响了端点设计、版本策略、缓存机制等几乎所有技术选型。关键区别数据获取REST 需要多个端点拼装数据,容易过度获取或获取不足。GraphQL 单次请求即可精确拿到所需字段,典型场景:一个页面需要用户信息 + 订单列表,REST 要两次请求,GraphQL 一条 query 搞定。端点与版本REST 每个资源一个 URL,变更时走 v1/v2 版本控制。GraphQL 只有一个端点,通过 Schema 演进和字段废弃来避免破坏性变更,无需版本号。缓存REST 直接利用 HTTP 缓存(ETag、Cache-Control),成熟且零成本。GraphQL 因查询体在 POST 中,无法原生使用 HTTP 缓存,需要 Apollo Client 等方案在应用层实现。错误处理REST 用 HTTP 状态码(404、500)表达语义。GraphQL 无论成功失败都返回 200,错误信息放在响应体的 errors 字段中,客户端必须自行解析。实时数据REST 依赖轮询或 WebSocket 补丁方案。GraphQL 原生支持 Subscription,基于 WebSocket 实现服务端推送。选型建议选 GraphQL:多端异构客户端、复杂嵌套查询、移动端省流量、快速迭代频繁变更字段选 REST:简单 CRUD、公共 API 需要易用性、团队不熟悉 GraphQL、强依赖 HTTP 缓存追问方向GraphQL 的 N+1 查询问题怎么解决?(DataLoader 批量加载)为什么说 GraphQL 不适合做文件上传?(二进制传输需 multipart,query 本身是 JSON,需额外规范)两者能混用吗?(可以,REST 做健康检查/文件上传,GraphQL 做业务查询)
计算机基础阅读 05月27日 22:32

CDN 缓存策略有哪些?命中率怎么优化?

直接回答CDN 缓存策略核心就三件事:控制缓存多久(TTL)、区分缓存谁(Cache Key)、决定何时更新(刷新机制)。优化命中率的关键是:减少回源、合理分 TTL、忽略无关参数、预热热门资源。缓存策略拆解TTL 策略——最基础的缓存控制TTL 决定内容在边缘节点的存活时间:静态资源(图片、字体、CSS/JS 带 hash):设长 TTL,甚至 max-age=31536000, immutable半静态内容(商品页、文章页):分钟级 TTL,配合软刷新动态接口(用户数据、实时行情):不缓存或秒级 TTL,走协商缓存(ETag / Last-Modified)Cache-Control: public, max-age=31536000, immutable // 带 hash 的静态资源Cache-Control: public, max-age=300, s-maxage=60 // CDN 缓 60s,浏览器缓 5minCache-Control: no-cache, ETag: "v2-abc" // 协商缓存Cache Key 策略——决定哪些请求共享缓存默认 Cache Key 是完整 URL。问题在于:?utm_source=weibo 和 ?utm_source=zhihu 本是同一资源,却被分成两条缓存,白白回源。优化方式:忽略无关查询参数:过滤 utm_*、timestamp 等不影响内容的参数自定义 Cache Key:加入 Cookie 中的地区码,忽略 PHPSESSIDVary 头:让 CDN 按 Accept-Encoding 区分 gzip/br 版本分层缓存——边缘 → 区域 → 源站请求查找顺序:边缘节点 → 区域节点 → 源站。边缘未命中会回区域,区域未命中才回源。所以优化重点是让请求尽量在边缘命中。命中率优化实战1. 忽略 URL 参数这是命中率低最常见的原因。一条 ?token=xxx 就能让缓存全部失效。阿里云 CDN 实测:忽略无关参数后命中率可从 40% 提升到 90%+。2. 大文件分片回源(Range 回源)用户看视频只看了前 5 分钟,但 CDN 回源拉了整个文件。开启 Range 回源后只拉需要的片段,减少回源流量,也提升字节命中率。3. 缓存预热新版本发布或大促前,主动把热门资源推到各边缘节点。两种方式:API 预热:调用 CDN 控制台接口主动推送模拟请求:用脚本批量请求触发被动缓存4. 版本化发布代替刷新与其发版后全站刷新缓存,不如在文件名里带 hash:app.3f2a1b.js。内容变了 hash 就变,旧缓存自然过期,无需主动刷新。5. 监控命中率指标请求命中率 = 缓存命中请求数 / 总请求数字节命中率 =(边缘响应流量 - 回源流量)/ 边缘响应流量请求命中率 >90% 为健康,70%-90% 需要优化,<70% 必须排查。追问:内容更新后用户还看到旧版本怎么办?三层解法,按优先级:文件名带 hash,一劳永逸(最推荐)URL 刷新,精确清除单条缓存全站刷新,最后手段,会瞬间压高源站追问:缓存命中率突然下降怎么排查?按这个顺序查:看是否有新参数打入了 Cache Key(查访问日志里的 URL 变体)看源站是否返回了 no-store / private 头看 TTL 是否被覆盖缩短看是否有大流量回源(可能是爬虫或攻击绕过缓存)
前端阅读 05月27日 22:32

Chrome 浏览器如何进行性能优化?

Chrome 性能优化从哪几个维度入手?三大维度:加载性能(资源到浏览器的时间)、渲染性能(浏览器绘制页面的效率)、运行时性能(页面交互的流畅度)。面试中按这个框架回答,比零散列举更有说服力。加载性能怎么优化?核心目标是缩短首屏时间。关键手段:资源压缩:Brotli 替代 Gzip,CSS/JS 做 Tree Shaking 删除死代码,图片用 WebP/AVIF 格式代码分割:路由级懒加载,首屏只加载关键 CSS 和 JS,非关键资源 defer 或 async缓存策略:静态资源配强缓存(Cache-Control: max-age),API 走协商缓存(ETag/Last-Modified)预加载:<link rel="preload"> 加载关键资源,<link rel="prefetch"> 预取下一页资源<link rel="preload" href="/critical.css" as="style"><link rel="preload" href="/hero.webp" as="image">追问:首屏 LCP 6 秒怎么排查?先用 DevTools Performance 面板定位 LCP 元素,再看网络瀑布图找阻塞链,逐项优化。渲染性能怎么优化?关键是减少重排(Layout)和重绘(Paint),因为它们会阻塞主线程。批量 DOM 操作:用 DocumentFragment 或 requestAnimationFrame 合并更新CSS 动画优先:用 transform 和 opacity 做动画,这两个属性只触发合成层,不触发布局和绘制避免强制同步布局:读写样式分开,不要在循环中交替读取 offsetWidth 和修改样式will-change 谨慎使用:提前告知浏览器该元素将变化,但滥用会导致图层爆炸// 差:读写交替,触发强制同步布局elements.forEach(el => { const width = el.offsetWidth; // 读 el.style.width = width * 2 + "px"; // 写});// 好:先读完再写const widths = elements.map(el => el.offsetWidth);elements.forEach((el, i) => { el.style.width = widths[i] * 2 + "px";});追问:如何判断页面是否存在布局抖动?DevTools Performance 面板中紫色 Layout 块频繁出现且与 Recalculate Style 交替就是布局抖动。运行时性能怎么优化?长任务拆分:超过 50ms 的任务会阻塞交互,用 requestIdleCallback 或 scheduler.yield() 拆分事件委托:列表场景在父元素绑定一个监听器,而非每个子元素都绑定防抖节流:scroll/resize/input 事件必须节流,搜索建议用防抖内存泄漏排查:DevTools Memory 面板拍快照对比,关注 Detached DOM 节点和未清理的定时器追问:内存泄漏常见原因有哪些?未清除的 setInterval、闭包持有大对象引用、DOM 移除后事件监听器未移除、全局变量意外挂载。用什么工具度量性能?Lighthouse:一键生成性能评分和优化建议Performance 面板:录制用户操作,分析主线程占用、布局、绘制耗时Core Web Vitals:LCP(加载)、INP(交互)、CLS(稳定),这三个指标直接影响搜索排名性能优化不是罗列清单,而是先度量再优化。找到瓶颈,针对性处理,才是面试官想听到的思路。
前端阅读 05月27日 22:32

Chrome 浏览器的多进程架构是怎样的?

Chrome 多进程架构将浏览器功能拆分到独立进程中运行,核心目标是隔离故障、提升安全和利用多核性能。最新版 Chrome 打开一个页面至少启动 4 个进程:浏览器进程、渲染进程、GPU 进程和网络进程。五种核心进程浏览器进程是整个浏览器的"总管",负责地址栏、书签、前进后退等 UI 交互,同时协调其他子进程的创建与销毁。渲染进程是数量最多的进程,每个标签页(严格说是每个站点)分配一个。它运行 Blink 排版引擎和 V8 引擎,将 HTML/CSS/JS 转化为可交互页面。渲染进程被沙箱隔离,即使被恶意代码攻破也无法直接访问系统资源。GPU 进程专门处理 GPU 任务,最初只为 3D CSS,现在所有页面合成和 UI 绘制都依赖它。网络进程负责所有网络请求,从浏览器进程中独立出来后,网络 I/O 不再阻塞 UI 线程。插件进程运行浏览器扩展,每个插件独立一个进程,崩溃不影响其他页面。架构演进:从多进程到面向服务2016 年起 Chrome 推进 SOA(面向服务架构)重构,将浏览器进程内的模块(存储、网络、UI 等)拆成独立服务,按需运行在独立进程或合并到现有进程中。资源充裕时拆分更细,资源紧张时合并更省内存——这种弹性是传统多进程架构做不到的。Site Isolation 站点隔离2018 年 Spectre 漏洞暴露了同进程内不同 iframe 可互相读取内存的风险。Chrome 随即上线 Site Isolation:不同站点(same-site)的页面强制分到不同渲染进程,即使同一标签页内的跨站 iframe 也不例外。这是对"每个标签页一个进程"策略的重要补丁。进程间通信各进程通过 Mojo(Chrome 现代 IPC 框架)进行异步消息传递,大数据场景使用共享内存。渲染进程通过 RenderProcess 对象与浏览器进程保持连接。追问方向Chrome 多进程的内存代价如何?——每个进程独立一份 V8 堆和 Blink 对象,内存开销显著,Chrome 用进程复用(Process Sharing)缓解。渲染进程为什么必须沙箱化?——渲染进程直接执行第三方代码,沙箱限制其系统调用,即使被攻破也只能在受限环境中操作。如何用 DevTools 观察进程?——打开 chrome://process-internals 或任务管理器(Shift+Esc)查看各进程的内存和 CPU 占用。
服务端阅读 05月27日 22:28

Kafka Consumer Group Rebalance 什么时候触发?四种分配协议有什么区别?

核心答案Consumer Group Rebalance 是 Kafka 在组成员或订阅变化时重新分配 Partition 的过程。面试抓住三点:什么触发、怎么分配、如何减影响。什么情况会触发 Rebalance?三个维度:成员变化:Consumer 加入/退出/宕机/心跳超时(超过 session.timeout.ms)订阅变化:Consumer 订阅的 Topic 发生变动分区变化:Topic 分区数增减追问:Consumer 处理慢会触发吗?会。两次 poll() 间隔超过 max.poll.interval.ms,Coordinator 认为 Consumer 已死,踢出并触发 Rebalance。Rebalance 分几步?JoinGroup:所有 Consumer 向 Group Coordinator 发请求,Coordinator 选出 Leader ConsumerSyncGroup:Leader 制定分区分配方案,发给 Coordinator,再下发给所有 Consumer开始消费:Consumer 按新方案消费只有 Leader Consumer 负责分配,其他 Consumer 被动接收方案。四种分配策略有什么区别?| 策略 | 分配方式 | 优点 | 缺点 ||------|----------|------|------|| Range(默认) | 按 Partition 序号范围连续分配 | 简单 | 不整除时不均匀 || RoundRobin | 轮询分配所有 Partition | 多 Topic 时更均匀 | 订阅不一致时可能不均 || Sticky | 均匀分配 + 尽量保持上次分配 | 减少 Partition 迁移 | — || CooperativeSticky | 增量式,只重分配受影响 Partition | 不停消费,减少 STW | Kafka 2.4+ 支持 |关键区分:Range 和 RoundRobin 属 Eager 协议——Rebalance 时所有 Consumer 先停消费再重新分配。CooperativeSticky 属 Cooperative 协议,只迁移需要变动的 Partition,其余不受影响。怎么减少 Rebalance 的负面影响?1. 调参数避免误判max.poll.interval.ms=600000session.timeout.ms=30000heartbeat.interval.ms=100002. 用 CooperativeSticky 策略避免全量 STW,只重分配受影响分区。3. 手动管理 Offsetenable.auto.commit=falseconsumer.commitSync();自动提交在 Rebalance 期间可能丢数据或重复消费,手动提交更可控。4. 静态成员(Static Membership)设置 group.instance.id,Consumer 重启后 Coordinator 仍认为同一成员,不触发 Rebalance。追问方向Eager 协议下 Rebalance 期间能消费吗?不能。Cooperative 协议下未受影响分区可以怎么监控?关注 RebalanceRatePerSec 和 RebalanceTotal 指标Kafka 4.0 消费者组协议变化?原生支持增量 Rebalance,不再需要 Eager 回退
服务端阅读 05月27日 22:26

GraphQL 性能优化有哪些策略?

核心答案GraphQL 性能优化的关键在于六个方向:解决 N+1 查询、限制查询复杂度、缓存策略、查询持久化、分页优化、监控分析。其中 N+1 问题是面试最高频考点。N+1 查询问题与 DataLoader查询嵌套关系时,每个父对象都触发一次子查询,10 篇文章就产生 10 次 author 查询。DataLoader 通过批量 + 缓存解决:const DataLoader = require('dataloader');const userLoader = new DataLoader(async (ids) => { const users = await User.findAll({ where: { id: ids } }); return ids.map(id => users.find(u => u.id === id));});// Resolver 中Post: { author: (post) => userLoader.load(post.authorId)}DataLoader 在单次 tick 内收集所有 load 调用,合并为一次批量查询,相同 id 自动去重。追问:DataLoader 的缓存策略在什么场景下会失效? 当跨请求复用同一 DataLoader 实例时,缓存会返回脏数据。正确做法是每个请求创建新实例。查询深度与复杂度限制恶意查询可以无限嵌套,必须设防:const depthLimit = require('graphql-depth-limit');const { createComplexityLimitRule } = require('graphql-validation-complexity');const server = new ApolloServer({ typeDefs, resolvers, validationRules: [ depthLimit(7), createComplexityLimitRule(1000) ]});深度限制防嵌套炸弹,复杂度限制防字段爆炸。两者缺一不可。缓存策略三层缓存各有分工:字段级 Redis 缓存:对 Resolver 结果按 fieldName:args 做 TTL 缓存,适合读多写少的数据Apollo Client 缓存:客户端用 InMemoryCache 做 normalized 缓存,按 __typename:id 去重CDN 缓存:配合持久化查询(见下文),GET 请求可直接走 CDN查询持久化客户端将查询文本算 hash,服务端只传 hash 执行:const { createPersistedQueryLink } = require('@apollo/client/link/persisted-queries');const { sha256 } = require('crypto-hash');const link = createPersistedQueryLink({ sha256, useGETForHashedQueries: true });好处:请求体从几 KB 缩到几十字节,可走 GET + CDN 缓存,还降低了查询被篡改的风险。游标分页offset 分页在数据变更时会出现重复或遗漏,游标分页用有序字段(如 id、createdAt)做游标,稳定性不受数据量影响:type Query { posts(after: String, first: Int): PostConnection!}监控与分析上线前接 Apollo Studio 或自建 metrics,记录每个 Resolver 的耗时和错误率。性能问题不是"有没有"的问题,而是"在哪"的问题,没有监控就是盲调。追问:如果 Resolver 耗时突然翻倍,你会从哪些方向排查? 先看数据库慢查询日志,再检查 DataLoader 是否失效(缓存击穿),最后确认是否有新增的深嵌套查询绕过了复杂度限制。
服务端阅读 05月27日 22:23

Kafka 和 RabbitMQ、RocketMQ 怎么选?

核心区别一图看懂| 维度 | Kafka | RabbitMQ | RocketMQ ||------|-------|----------|----------|| 定位 | 分布式流处理平台 | 传统消息代理 | 分布式消息中间件 || 吞吐量 | 百万级 TPS | 万级 TPS | 十万级 TPS || 延迟 | 毫秒级 | 微秒级 | 毫秒级 || 消息留存 | 按时间/容量保留,消费后不删 | 消费确认后删除 | 可配置保留策略 || 消费模型 | Pull 拉取 | Push 推送为主 | Push + Pull 均支持 || 路由能力 | 基于 Topic 和分区 | Exchange 多种路由模式 | Topic + Tag 两级过滤 || 顺序保证 | 分区内有序 | 队列内有序 | 全局顺序消息 || 事务消息 | 支持(0.11+) | 不支持 | 原生支持,最完善 || 适用场景 | 日志流、事件流、大数据管道 | 任务队列、微服务通信、复杂路由 | 电商订单、金融交易、事务消息 |为什么 Kafka 吞吐量远超另外两个?Kafka 的核心设计围绕"顺序写磁盘 + 零拷贝 + 分区并行"三个点。磁盘顺序写速度可达 600MB/s,远超随机写的 100KB/s。零拷贝(sendfile 系统调用)让数据直接从页缓存到网卡,跳过用户态拷贝。分区机制则将负载分散到多个 Broker 并行处理。RabbitMQ 的优势不在于吞吐,而在于路由灵活性——四种 Exchange 类型(direct、topic、fanout、headers)能实现复杂的消息分发逻辑,延迟也在微秒级别,适合对实时性要求高但吞吐不大的场景。RocketMQ 在事务消息上做得最完善:半消息 + 本地事务 + 回查机制,保证分布式事务的最终一致性,这是 Kafka 和 RabbitMQ都不具备的。选型怎么决策?三个问题就能定:消息量大吗? 日均亿级以上选 Kafka,百万级以下 RabbitMQ 够用需要消息回溯吗? Kafka 天然支持,RabbitMQ 消费完就删涉及钱吗? 金融、订单场景选 RocketMQ,事务消息是刚需很多团队的做法是 Kafka 做事件流 + RabbitMQ 做任务队列,各取所长。面试追问方向Kafka 为什么用 Pull 不用 Push? Push 模式下消费者处理能力不一,慢消费者会拖垮 Broker;Pull 让消费者按自己节奏消费,还方便回溯和批量拉取RocketMQ 的 NameServer 和 Kafka 的 ZooKeeper 有什么区别? NameServer 无状态、无主从,部署简单但功能弱于 ZK;Kafka 新版 KRaft 模式已去 ZK 依赖消息积压怎么处理? Kafka 扩分区 + 增 Consumer;RabbitMQ 临时加消费者队列;RocketMQ 调大消费线程池
计算机基础阅读 05月27日 22:21

CDN 如何配置 HTTPS?三种回源模式有什么区别?

直接回答CDN 配置 HTTPS 主要有三种方式:自定义证书上传、CDN 免费证书、SNI 多域名证书。HTTPS 回源模式分三档:Flexible(仅客户端加密)、Full(全链路加密但不验证源站证书)、Full Strict(全链路加密且严格验证源站证书),生产环境应选 Full Strict。HTTPS 配置方式自定义证书上传:购买或申请 SSL 证书后,在 CDN 控制台上传 .crt 证书和 .key 私钥。优点是完全可控,支持通配符和 EV 证书;缺点是需手动续期。CDN 免费证书:主流 CDN 支持 Let's Encrypt 等免费证书,自动签发和续期,适合中小站点。Cloudflare 的 Universal SSL 就属此类。SNI 方式:CDN 在同一 IP 上通过 SNI 区分不同域名的证书,客户端握手时携带域名,服务端返回对应证书。现代浏览器均支持。# Cloudflare 启用 Universal SSL 示例curl -X PATCH "https://api.cloudflare.com/client/v4/zones/{zone_id}/settings/ssl" \ -H "Authorization: Bearer {api_token}" \ -H "Content-Type: application/json" \ -d '{"value":"strict"}'三种 HTTPS 回源模式这是面试核心,务必理解三者区别:Flexible:用户→CDN 走 HTTPS,CDN→源站走 HTTP。源站无需证书,但回源链路明文传输,存在中间人风险。仅适合测试环境或纯静态内容。Full:全链路 HTTPS,但 CDN 不验证源站证书是否合法(自签名证书也接受)。比 Flexible 安全,但无法防御源站侧的证书伪造攻击。Full Strict:全链路 HTTPS + 严格证书验证,要求源站证书由受信 CA 签发且域名匹配。安全性最高,证书异常会直接拒绝连接。金融、政务等场景必选。关键配置实践强制 HTTPS 跳转和 HSTS 是标配:# Nginx 强制跳转server { listen 80; return 301 https://$host$request_uri;}# HSTS 响应头add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;SSL 协议只保留 TLS 1.2 和 1.3,禁用弱加密套件。启用 OCSP Stapling 减少握手延迟,配置会话缓存复用 SSL 连接:ssl_protocols TLSv1.2 TLSv1.3;ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;ssl_session_cache shared:SSL:10m;ssl_stapling on;ssl_stapling_verify on;常见坑无限重定向循环:CDN 开启强制 HTTPS,源站又把 HTTPS 重定向回 HTTP,形成死循环。解决办法是源站只监听 80 端口或正确识别 CDN 传递的 X-Forwarded-Proto 头。混合内容警告:HTTPS 页面加载了 HTTP 资源,浏览器会拦截。用 CSP 头自动升级:Content-Security-Policy: upgrade-insecure-requests。证书链不完整:只上传了域名证书缺少中间证书,导致客户端无法验证。解决:按域名证书→中间证书的顺序拼接后上传。追问方向SNI 在什么场景下会失效?老旧客户端(IE6/Windows XP)不支持 SNI,CDN 如何兼容?如果源站证书过期,Full Strict 模式下会发生什么?如何做到零停机续期?CDN 开启 HSTS 后源站切换回 HTTP 会有什么后果?
计算机基础阅读 05月27日 22:21

CDN 如何实现视频加速?有哪些关键技术?

CDN 如何实现视频加速?有哪些关键技术?CDN 视频加速的核心思路:把视频切片、多码率编码、缓存在离用户最近的边缘节点,播放时根据网络状况动态选择码率和分片,从而降低首屏时间、减少卡顿。一、自适应码率(ABR)播放器实时检测带宽和缓冲区水位,动态切换码率档位。主流 ABR 算法分三类:基于缓冲区:缓冲区低选低码率,充足选高码率,实现简单但反应慢基于吞吐量:用近期下载速率预估带宽,选不超过带宽的最高码率,反应快但波动大混合算法:同时参考缓冲区和吞吐量,BOLA 和 MPC 是工业界常用方案追问:ABR 切换时为什么会出现画面模糊再清晰?因为切换发生在分片边界,中间需要等当前分片播完才能请求新码率分片,这段时间画面保持旧码率。二、视频编码优化| 编码格式 | 相比 H.264 体积 | 编码速度 | 兼容性 | 典型场景 ||---------|----------------|---------|--------|---------|| H.264 | 基准 | 快 | 最好 | 通用点播 || H.265 | 小 50% | 慢 3-5x | 较差 | 高清/带宽受限 || AV1 | 小 60% | 极慢 | 有限 | 未来/超高清 |生产中通常生成多码率多分辨率版本(码率阶梯),编码参数重点控制:GOP 大小(关键帧间隔)、maxrate/bufsize(码率上限)、帧率(动态场景 60fps,静态 24fps)。三、流媒体协议:HLS vs DASHHLS(Apple 主导):m3u8 播放列表 + .ts 分片,生态成熟,iOS 原生支持。DASH(MPEG 标准):mpd(XML)+ .m4s 分片,跨平台,灵活度更高。两者都能跑在纯 HTTP 上,天然适配 CDN 缓存。CMAF 格式让 HLS 和 DASH 共用同一套 fMP4 分片,只需维护两份 manifest,存储成本减半。追问:直播场景下 HLS 延迟为什么高?如何优化?HLS 延迟 = 分片时长 x 3(编码缓冲 + 播放列表刷新 + 缓冲区预载)。优化方向:缩短分片到 2-4 秒、用 LL-HLS 的部分分片预加载、或改用 WebRTC/FLV 方案。四、CDN 缓存策略分片缓存:每个 .ts/.m4s 独立缓存,命中率高,TTL 可设较长(1-24h)播放列表缓存:.m3u8/.mpd 动态更新,TTL 短(直播 5s,点播 5min)缓存锁:proxy_cache_lock 防止同一分片并发回源击穿缓存智能预加载:播放器预取后续 2-3 个分片和下一码率档位五、传输层优化HTTP/2 多路复用减少连接数、头部压缩降低开销;HTTP/3(QUIC)基于 UDP 减少握手延迟、改善弱网拥塞控制。点播用 HTTP 足够,直播低延迟场景倾向 UDP(WebRTC)。六、播放体验优化首屏慢的典型链路:DNS 解析 → TCP 连接 → TLS 握手 → 请求 m3u8 → 请求分片 → 解码首帧。优化手段:预连接、初始选低码率快速起播、增加关键帧频率(GOP 缩小到 1-2 秒)、预加载首屏分片。拖动进度条时,需要定位到目标时间对应的关键帧所在的分片。关键帧间隔越短,seek 响应越快,但编码效率略降。七、质量监控关键指标:首屏时间、卡顿率、码率切换频率、平均播放码率。播放端通过 waiting/playing 事件采集缓冲数据,定时上报,服务端做聚合告警。追问:卡顿率高但码率切换少,可能是什么原因?ABR 没有及时降码率,可能是吞吐量估算偏高、缓冲区水位阈值设置过高,或者分片缓存未命中导致回源延迟。
计算机基础阅读 05月27日 22:21

CDN 如何防御 DDoS 攻击?有哪些安全防护机制?

CDN 能防住 DDoS 吗?核心机制是什么CDN 确实能防御 DDoS,但靠的不是单点硬扛,而是分布式架构把攻击流量"化整为零"。核心思路:隐藏源站 IP + 全球节点分散流量 + 智能清洗恶意请求。DDoS 防护:流量清洗是关键CDN 防御 DDoS 的核心是流量清洗——在边缘节点识别并过滤恶意流量,只把正常请求回源。清洗分三层:L3/L4 网络层:过滤 SYN Flood、UDP Flood、ICMP Flood 等协议级攻击。边缘节点直接丢弃不符合 TCP/IP 规范的畸形包,对特定攻击源 IP 在骨干网层面封禁L7 应用层:分析 User-Agent、Cookie、TLS 指纹等,用 JS Challenge 或滑块验证判断请求是否来自真人。AI 行为分析会给每个请求打信誉分,低分直接拦截Anycast 架构:攻击流量根据地理位置被吸引到最近的边缘节点,把大规模分布式攻击拆成多个小流量就地处理,不集中到单点限流是清洗的辅助手段:# 单 IP 限流limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;location /api/ { limit_req zone=api burst=20 nodelay;}WAF:应用层攻击的防火墙WAF(Web Application Firewall)防护 SQL 注入、XSS、CSRF、文件包含等 Web 攻击:输入验证:过滤用户输入中的恶意载荷输出编码:对响应内容编码,防止 XSS 执行规则匹配:基于正则或签名库拦截已知攻击模式# 防注入和 XSSif ($args ~* "union.*select.*from") { return 403; }if ($args ~* "<script|javascript:") { return 403; }WAF 部署模式:反向代理(CDN 作为代理入口)、透明代理(旁路拦截)、DNS 模式(通过 DNS 重定向引流)。访问控制:限源、限地、防盗链IP 黑白名单——直接放行或封禁特定 IP 段:allow 192.168.1.0/24;deny all;地理位置限制——仅允许特定国家/地区访问,或屏蔽高风险地区:geo $allowed_country { default no; CN yes;}if ($allowed_country = no) { return 403; }Referer 检查——防盗链,阻止第三方直接引用你的资源:valid_referers none blocked example.com *.example.com;if ($invalid_referer) { return 403; }加密传输与 Token 鉴权HTTPS + HSTS 保证传输层安全。Token 认证防止资源被非法访问——服务端用密钥、路径、时间戳生成签名,CDN 边缘校验签名合法性:import hashlib, timedef generate_token(secret, path, ts): return hashlib.sha256(f"{secret}{path}{ts}".encode()).hexdigest()爬虫防护识别合法爬虫(如 Googlebot)放行,恶意爬虫限流或封禁。方法:User-Agent 分析、行为模式识别、访问频率监控。分层防御才是正确姿势单一机制防不住复杂攻击,生产环境必须分层:用户 → CDN 边缘节点(流量清洗) → WAF(应用层防护) → 源站(深度防御)边缘节点:基础过滤、限流、清洗WAF:应用层攻击拦截源站:最小权限、定期审计、应急响应面试回答时记住:CDN 防御 DDoS 靠分布式 + 智能清洗,不是硬扛;应用安全靠 WAF + 访问控制组合拳;生产环境必须分层,没有银弹。追问:CDN 能防住多大规模的 DDoS? 看厂商能力。主流高防 CDN 的 Anycast 网络总带宽可达 10Tbps+,远超单机高防的 1Tbps 上限。关键在于 Anycast 架构能把流量分散到全球节点,不是靠一台机器硬抗。
计算机基础阅读 05月27日 22:19

CDN 性能监控有哪些核心指标?怎么搭建监控体系?

CDN 性能监控的五个核心指标缓存命中率——CDN 监控的第一指标。命中率 = 缓存命中请求数 / 总请求数 × 100%,静态资源目标 95% 以上,整体 90% 以上。命中率骤降往往意味着缓存键配置错误或 TTL 过短,这是面试最爱追问的点。TTFB(首字节时间)——从请求发出到收到第一个字节的耗时,包含 DNS 解析、TCP 连接、TLS 握手和服务器处理。静态内容 P95 应低于 100ms,动态内容低于 500ms。注意:要分开统计命中和未命中的 TTFB,否则平均值会掩盖问题。回源率——回源请求数占总请求的比例,目标低于 10%。回源率高直接导致源站压力大、用户延迟高。面试常见追问:缓存命中率突然从 95% 掉到 60%,你怎么排查?思路:检查是否有大范围缓存失效(批量 purge)、缓存键是否冲突、TTL 是否被改短。错误率——4xx 和 5xx 占总请求比例,4xx 目标低于 0.1%,5xx 低于 0.01%。5xx 飙升通常意味着源站过载或 CDN 节点异常,4xx 激增则可能是配置错误(如回源 URL 改了但 CDN 规则没更新)。带宽与 QPS——带宽监控分边缘带宽和回源带宽,QPS 关注峰值和均值。流量突增需要区分是正常业务高峰还是攻击,结合错误率和延迟一起判断。监控体系怎么搭三层架构:数据采集 → 存储/计算 → 可视化/告警。采集层用 CDN 厂商的日志流(Cloudflare Logs、AWS CloudFront 实时日志)或自建 Nginx 日志,关键字段包括 request_time、upstream_cache_status、upstream_response_time。存储计算层用 Prometheus 做指标聚合,ELK 做日志检索。可视化用 Grafana 搭看板,按地域、ISP、内容类型分维度展示。告警规则要设置三个:TTFB P95 超阈值持续 5 分钟、缓存命中率低于 80% 持续 10 分钟、5xx 错误率超 1% 持续 3 分钟。告警通道走企业 IM + 值班电话,5xx 告警级别必须高于延迟告警。面试追问方向缓存命中率低怎么优化? 检查缓存键是否包含不必要的动态参数、TTL 是否合理、是否需要分层缓存(parent cache + edge cache)。如何区分 CDN 问题还是源站问题? 对比命中请求和未命中请求的 TTFB,如果命中请求也慢,问题在 CDN 层;如果只有未命中慢,问题在源站或回源链路。多 CDN 怎么监控? 统一指标口径,用同一套 Grafana 看板对比各厂商的命中率、延迟和错误率,按地域做流量调度。掌握五个核心指标(命中率、TTFB、回源率、错误率、带宽/QPS)加一套采集-存储-告警的完整方案,面试基本够用。
计算机基础阅读 05月27日 22:18

CDN 故障排查的流程是什么?有哪些常用工具?

直接回答CDN 故障排查的核心流程:确认范围 → 检查DNS → 检查网络连通性 → 检查缓存状态 → 检查源站 → 定位修复。第一步,确认故障范围。 问三个问题:是全量用户还是部分地域?是持续报错还是间歇性?是从什么时候开始的?范围判断决定后续排查方向——全局故障看CDN节点和DNS,局部故障看网络链路和缓存。第二步,检查DNS解析。 CDN 依赖 DNS 将用户调度到最近的边缘节点,DNS 出问题一切白搭。用 dig 或 nslookup 确认域名是否正确解析到 CDN CNAME,检查不同地域 DNS 服务器的解析结果是否一致。常见坑:DNS 缓存未更新导致调度到已下线节点。第三步,检查网络连通性。 ping 看延迟,traceroute 或 mtr 看链路丢包,curl -v 看 HTTP 握手各阶段耗时。重点关注 SSL 握手时间——如果证书链不完整或配置错误,握手会失败或变慢。第四步,检查缓存状态。 看响应头里的 X-Cache 字段,HIT 还是 MISS。缓存命中率骤降是最常见的性能劣化原因。排查缓存键配置是否合理、TTL 是否过长导致内容不更新、是否有绕过缓存的请求头。第五步,检查源站。 绕过 CDN 直接访问源站,如果源站也慢,问题在源站不在CDN。看源站负载、响应时间、错误日志。核心工具速查| 场景 | 工具 | 用法 ||------|------|------|| DNS排查 | dig/nslookup | dig @8.8.8.8 example.com || 网络延迟 | ping/mtr | mtr -r -c 10 cdn.example.com || HTTP调试 | curl | curl -w "@format.txt" -o /dev/null -s URL || SSL检查 | openssl | openssl s_client -connect host:443 || 缓存分析 | 日志+响应头 | grep "X-Cache" access.log \| sort \| uniq -c || 日志分析 | ELK Stack | Kibana 看错误率趋势和地域分布 |# curl 计时模板 curl-format.txttime_namelookup: %{time_namelookup}time_connect: %{time_connect}time_starttransfer: %{time_starttransfer}time_total: %{time_total}追问:缓存刷新后用户仍看到旧内容怎么办?先确认刷新是否生效——用 curl -I 检查响应头的 X-Cache 和 Last-Modified。如果刷新成功但用户仍看到旧内容,三个可能:本地浏览器缓存、中间运营商缓存、多CDN节点同步延迟。对应措施:版本化URL(app.js?v=2)、缩短TTL、检查CDN供应商的刷新接口是否覆盖全部节点。追问:如何预防CDN故障?三件事:监控告警(节点可用性、缓存命中率、错误率)、健康检查(定时探测各节点)、容灾预案(多CDN切换、源站冗余、DNS快速切流量)。面试中能讲出"监控+容灾"两条线,基本过关。
服务端阅读 05月27日 22:18

GraphQL 生态中有哪些必须掌握的工具?

核心工具分类GraphQL 生态工具按职责分四层:服务端框架、客户端库、开发辅助、治理安全。面试中常考的是每层选型依据和它们之间的配合方式。服务端框架Apollo Server 是目前使用最广的 GraphQL 服务端,开箱支持 Federation、订阅和插件体系。GraphQL Yoga 更轻量,适配边缘运行时(Bun、Deno),适合对包体积敏感的场景。// Apollo Server 最小启动const { ApolloServer } = require("@apollo/server");const server = new ApolloServer({ typeDefs: `type Query { hello: String! }`, resolvers: { Query: { hello: () => "world" } }});选型关键:需要多团队联邦架构选 Apollo Server;追求轻量和多运行时部署选 Yoga。客户端库三足鼎立:Apollo Client(生态最全,缓存最强)、Relay(Meta 出品,编译时优化,适合超大规模应用)、urql(7KB,交换器架构,适合中小项目)。// urql 最小配置import { createClient, cacheExchange, fetchExchange } from "urql";const client = createClient({ url: "/graphql", exchanges: [cacheExchange, fetchExchange]});面试追问方向:Apollo Client 的 normalized cache 如何工作?Relay 的 fragment 机制为什么能减少过度请求?开发辅助GraphQL Code Generator 从 Schema 自动生成 TypeScript 类型和 React Hooks,是类型安全的核心工具。Apollo Sandbox / GraphiQL 提供交互式查询调试。DataLoader 批量合并请求,解决经典的 N+1 查询问题。// DataLoader 解决 N+1const DataLoader = require("dataloader");const userLoader = new DataLoader(async ids => { const users = await User.findByIds(ids); return ids.map(id => users.find(u => u.id === id));});治理与安全GraphQL Shield 用声明式规则做字段级权限控制,Envelop 提供可插拔插件做限流和查询深度限制。Apollo Studio 负责全链路监控、Schema 变更追踪和性能分析。// GraphQL Shield 权限规则const { shield, rule } = require("graphql-shield");const isAdmin = rule()((_, __, ctx) => ctx.user?.role === "ADMIN");const permissions = shield({ Query: { users: isAdmin }, Mutation: { deleteUser: isAdmin }});选型速查| 场景 | 推荐工具 ||------|----------|| 服务端搭建 | Apollo Server / Yoga || 客户端状态管理 | Apollo Client || 超大规模前端 | Relay || 类型生成 | Code Generator || N+1 优化 | DataLoader || 权限控制 | GraphQL Shield || 全链路监控 | Apollo Studio |实际项目中,服务端 Apollo Server + Code Generator + DataLoader、客户端 Apollo Client 或 urql 是最常见的组合。工具选型没有绝对标准,关键是理解每个工具解决什么问题,再按团队规模和技术栈做取舍。
服务端阅读 05月27日 22:18

GraphQL 客户端开发需要掌握哪些核心知识?

GraphQL 客户端开发需要掌握哪些核心知识?GraphQL 客户端的核心职责是把查询、缓存、状态管理三件事做好。Apollo Client 是目前最主流的选择,面试中围绕它的问题也最多。Apollo Client 的缓存机制是怎样的?Apollo Client 使用规范化缓存(Normalized Cache),把每个对象按 __typename:id 拆开存储,而不是按查询维度缓存整棵树。这意味着同一用户在不同查询中返回时,缓存只存一份,修改一处全局生效。InMemoryCache 的 typePolicies 可以自定义合并策略。分页场景下用 merge 函数拼接新旧数据,用 keyArgs 声明哪些参数影响缓存键。追问:cache-and-network 和 network-only 有什么区别?cache-and-network 先返回缓存数据再发请求更新,适合需要即时反馈的列表页;network-only 跳过缓存直接请求,适合对数据新鲜度要求高的场景。useQuery 的 fetchPolicy 怎么选?常用策略按优先级排列:cache-first(默认):有缓存就用,没有才请求。适合读多写少的详情页cache-and-network:缓存和请求并行,先展示旧数据再更新。适合列表页network-only:每次都请求,适合订单状态等实时数据cache-only:只用缓存,离线场景或纯本地数据时使用选错策略是缓存不更新的头号原因。比如详情页用了 cache-first,编辑后返回列表,数据没变——因为缓存没失效。如何处理 Mutation 后的缓存更新?三种方式,按推荐程度排序:cache.modify + writeFragment:手动更新缓存中受影响的字段,精确且高效refetchQueries:Mutation 成功后重新查询指定 Query,简单但多一次网络请求乐观更新(Optimistic Response):先假设成功更新 UI,服务端返回后再修正,体验最好但实现复杂实际项目中推荐方式 1 为主,关键操作加乐观更新。避免滥用 refetchQueries,它会让请求量翻倍。分页加载怎么实现?偏移分页用 fetchMore 传入新的 offset,在 updateQuery 中拼接结果。游标分页用 after 游标,配合 pageInfo.hasNextPage 判断是否还有数据。游标分页更适合实时性强的场景(聊天记录、动态流),因为偏移分页在数据插入后会导致重复或遗漏。但游标分页不支持跳页,只能顺序加载。全局错误处理怎么配置?用 onError Link 统一拦截。graphQLErrors 是业务逻辑错误(校验失败、权限不足),networkError 是网络层错误(断网、超时)。认证过期是常见场景:在 onError 中检测 401 错误码,静默刷新 Token 后用 forward(operation) 重发请求,用户无感知。Subscription 在生产环境要注意什么?WebSocket 连接不稳定是最大问题。必须实现自动重连:Apollo Client 的 split Link 按 Operation 类型分流,Query/Mutation 走 HTTP,Subscription 走 WebSocket。WebSocket 断开后用指数退避重连,避免服务器压力过大。还要注意连接鉴权——WebSocket 建连时通过 connectionParams 传递 Token,服务端在 onConnect 中验证。Apollo Link 链式调用原理是什么?Apollo Link 采用中间件模式,每个 Link 处理请求后传给下一个。常用链路:authLink → errorLink → httpLink。setContext 注入请求头,onError 捕获错误,HttpLink 发出请求。顺序很重要——errorLink 放在 httpLink 前面才能拦截到网络错误。掌握缓存策略选择、Mutation 缓存更新、分页实现、错误处理这四块,基本覆盖了 GraphQL 客户端面试的核心考察点。理解规范缓存的存储模型是串联所有知识点的基础。
服务端阅读 05月27日 22:13

Nginx 如何进行安全配置?有哪些安全最佳实践?

Nginx 如何进行安全配置?有哪些安全最佳实践?核心思路是:隐藏信息、限制访问、加密传输、防御攻击,四层递进。一、隐藏服务器指纹攻击者第一步是信息收集,版本号是最直接的突破口。server_tokens off;关掉之后,响应头和错误页不再暴露 Nginx 版本。面试追问:还能怎么隐藏? 可以用 more_set_headers 模块改掉 Server 字段本身,或者在前端反代层抹掉这个头。二、访问控制与限流IP 限制和速率限制是防暴力攻击的第一道门。# IP 白名单location /admin { allow 192.168.1.0/24; deny all;}# 限流limit_req_zone $binary_remote_addr zone=req:10m rate=10r/s;limit_req zone=req burst=20 nodelay;limit_conn_zone $binary_remote_addr zone=conn:10m;limit_conn conn 10;面试追问:burst 和 nodelay 区别是什么? burst 允许突发排队,nodelay 让排队的请求立即处理而不延时等待,否则超出的请求会被延迟处理。三、SSL/TLS 与安全头HTTPS 是底线配置,安全头加固浏览器端防护。ssl_protocols TLSv1.2 TLSv1.3;ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384;ssl_prefer_server_ciphers on;ssl_session_cache shared:SSL:50m;ssl_session_tickets off;add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;add_header X-Frame-Options "SAMEORIGIN" always;add_header X-Content-Type-Options "nosniff" always;add_header Content-Security-Policy "default-src 'self'" always;面试追问:为什么关 sslsessiontickets? 默认的 session ticket key 是明文保存在 worker 共享内存中的,多台 Nginx 之间无法复用,且存在前向安全性问题。集群部署时应手动轮换 key 或直接关闭。四、文件与目录防护禁止访问隐藏文件和敏感后缀,堵住信息泄露的口子。location ~ /\. { deny all; }location ~* \.(htaccess|ini|log|sql|bak|swp)$ { deny all; }autoindex off;五、超时与缓冲区防止慢速攻击和缓冲区溢出。client_body_timeout 10;client_header_timeout 10;keepalive_timeout 5;send_timeout 10;client_max_body_size 10m;client_header_buffer_size 1k;面试追问:如果只改一个配置,改哪个? 先关 server_tokens,零成本高风险。然后上 HTTPS,这是生产环境硬性要求。限流和访问控制按业务场景逐步加。常见误区用 if 正则匹配 SQL 注入或 XSS 关键词来拦截攻击,这是错误的。Nginx 的 if 在 location 中行为不稳定,且正则容易被编码绕过。防注入应交给 WAF(如 ModSecurity)或应用层参数校验,Nginx 只做流量层防护。
服务端阅读 05月27日 22:13

Nginx 性能调优需要关注哪些关键参数?

Nginx 性能调优需要关注哪些关键参数?Nginx 调优的核心思路是:减少不必要的系统调用、充分利用内核零拷贝能力、压缩传输体积、避免连接浪费。下面按影响程度从大到小逐项说明。Worker 进程与连接worker_processes 设为 auto,让 Nginx 自动匹配 CPU 核心数。worker_rlimit_nofile 调到 100000,避免文件描述符耗尽。每个 worker 的 worker_connections 可设 65535,理论最大并发 = worker 数 × 65535。multi_accept on 让 worker 一次性接收所有就绪连接,accept_mutex off 在高并发下减少锁争用。worker_processes auto;worker_rlimit_nofile 100000;events { worker_connections 65535; use epoll; multi_accept on; accept_mutex off;}零拷贝与传输优化sendfile on 跳过用户态拷贝,数据从内核直接到 socket。tcp_nopush on 让数据攒满一个包再发,配合 sendfile 减少系统调用次数。tcp_nodelay on 禁用 Nagle 算法,避免小包延迟。三者同时开启并不矛盾:tcpnopush 在 sendfile 阶段生效,最后一个包由 tcpnodelay 立即发出。sendfile on;tcp_nopush on;tcp_nodelay on;Gzip 压缩压缩能将文本响应体积缩减 60%-80%,直接降低带宽和传输耗时。gzip_comp_level 建议设 4-6,再高收益递减但 CPU 开销上升。gzip_min_length 设 1024,避免压缩小响应反而变大。别忘了通过 gzip_types 覆盖 JSON、SVG 等常见 MIME 类型。gzip on;gzip_vary on;gzip_min_length 1024;gzip_comp_level 5;gzip_types text/plain text/css application/json application/javascript application/xml image/svg+xml;连接复用与超时keepalive_timeout 控制客户端长连接保持时间,默认 75s,可视业务缩短到 30-60s。keepalive_requests 限制单连接最大请求数,防止连接泄漏。对上游服务器也要开长连接:upstream 块中 keepalive 32 保持 32 条空闲连接,减少反复握手开销。keepalive_timeout 60s;keepalive_requests 1000;upstream backend { server 10.0.0.1:8080; keepalive 32;}缓冲区与文件缓存client_body_buffer_size 和 client_header_buffer_size 按业务调整,过小会触发临时文件写入拖慢请求。open_file_cache 缓存频繁访问的文件描述符,减少磁盘 stat 调用,对静态资源场景效果显著。client_header_buffer_size 2k;client_body_buffer_size 128k;open_file_cache max=10000 inactive=20s;open_file_cache_valid 30s;open_file_cache_min_uses 2;日志降耗写日志是高并发下的隐性瓶颈。静态资源 access_log off 直接关掉;动态请求的日志加 buffer=32k flush=5s,写操作先进内存再批量落盘。追问:调了参数怎么验证效果?用 wrk 或 ab 做基准测试,对比调优前后的 QPS、P99 延迟和错误率。生产环境通过 stub_status 模块持续监控活跃连接数和请求处理量。记住一个原则:每次只改一个参数,观察效果后再改下一个,否则无法定位哪个改动真正有效。
服务端阅读 05月27日 22:13

Nginx 日志怎么配置?有哪些格式和优化方法?

Nginx 如何配置日志?有哪些日志格式和优化方法?Nginx 提供了访问日志(accesslog)和错误日志(errorlog)两种日志类型。面试中常考的是日志格式自定义、条件记录和性能优化三条主线。访问日志与自定义格式访问日志通过 log_format 定义格式,再用 access_log 引用。常用三种格式:main 格式:记录 IP、请求行、状态码、Referer、UA、耗时等基础信息detailed 格式:在 main 基础上增加 upstream 地址、状态、X-Forwarded-For、request_idJSON 格式:用 escape=json 转义,方便 ELK/Grafana Loki 等工具直接解析log_format main "$remote_addr - $remote_user [$time_local] " ""$request" $status $body_bytes_sent " ""$http_referer" "$http_user_agent" " "$request_time $upstream_response_time";log_format json_combined escape=json "{" ""time_local":"$time_local", ""remote_addr":"$remote_addr", ""request":"$request", ""status":"$status", ""request_time":"$request_time"" "}";access_log /var/log/nginx/access.log main;追问:accesslog 和 errorlog 有什么区别? accesslog 记录每次请求的详细信息,可自定义格式;errorlog 记录服务器错误,不支持自定义格式,只能设级别(debug/info/notice/warn/error/crit/alert/emerg)。日志性能优化高并发场景下日志写入会成为瓶颈,核心优化手段:关闭不必要的日志:静态资源、健康检查路径用 access_log off缓冲写入:access_log ... buffer=32k flush=5s,减少磁盘 I/O 次数gzip 压缩:access_log ... gzip=9,节省磁盘空间条件记录:用 map + if= 只记录特定状态码或慢请求map $status $loggable { ~^[23] 0; default 1;}access_log /var/log/nginx/access.log main if=$loggable;location ~* \.(css|js|jpg|png|gif|ico)$ { access_log off;}access_log /var/log/nginx/access.log main buffer=32k flush=5s;追问:buffer 和 flush 参数分别控制什么? buffer 控制缓冲区大小,写满才刷盘;flush 控制最大等待时间,超时强制刷盘。两者配合保证日志既不丢又不多写。日志轮转与分离单文件日志会无限增长,必须配合 logrotate 轮转:# /etc/logrotate.d/nginx/var/log/nginx/*.log { daily rotate 14 compress delaycompress missingok sharedscripts postrotate [ -f /var/run/nginx.pid ] && kill -USR1 $(cat /var/run/nginx.pid) endscript}kill -USR1 让 Nginx 重新打开日志文件,不会中断服务。按业务分离日志同样重要:API 请求写独立文件,不同 server 块各写各的,便于精准排查问题。常用变量速查| 变量 | 说明 ||------|------|| $remoteaddr | 客户端 IP || $status | 响应状态码 || $requesttime | 请求总耗时 || $upstreamresponsetime | 上游响应时间 || $httpxforwarded_for | 真实客户端 IP |生产环境建议用 JSON 格式 + 缓冲写入 + logrotate 轮转 + 条件过滤,四板斧组合基本够用。
服务端阅读 05月27日 22:12

Nginx 监控运维怎么做?stub_status、Prometheus、ELK 怎么选?

答案前置:Nginx 监控运维的核心思路Nginx 监控围绕三条线展开:指标采集(stub_status / 日志)→ 存储与展示(Prometheus+Grafana / ELK / Zabbix)→ 告警与响应(阈值告警 + 自动化脚本)。面试中常考的不是你背了多少工具名,而是能不能说清楚每一步为什么这么做、不同规模场景怎么选型。内置指标:stub_status 能拿到什么?stub_status 是 Nginx 自带的状态模块,开启后在指定路径暴露一组关键指标:location /nginx_status { stub_status on; access_log off; allow 127.0.0.1; deny all;}访问后返回:Active connections(当前活跃连接数)、accepts/handled/requests(累计连接与请求数)、Reading/Writing/Waiting(读请求头、写响应、空闲等待的连接数)。追问:Waiting 数量大说明什么? 如果 Active connections ≈ Waiting,说明大量连接是 keep-alive 空闲态,连接复用率高是好事;但如果同时 Writing 偏低而请求排队,就要检查上游响应是否过慢。日志监控:比 stub_status 更细的粒度stubstatus 只有粗粒度指标,真正定位问题靠日志。关键是自定义 logformat 加入上游响应时间:log_format detailed '$remote_addr - [$time_local] "$request" $status ' 'rt=$request_time uct=$upstream_connect_time ' 'uht=$upstream_header_time urt=$upstream_response_time';access_log /var/log/nginx/detailed.log detailed;request_time 是总耗时,upstream_response_time 是上游处理耗时,两者差值就是 Nginx 自身开销。如果差值大,排查 Nginx 层面的缓冲、压缩或 DNS 解析。对于 ELK 场景,直接输出 JSON 格式日志省掉 Logstash 的 grok 解析:log_format json_log escape=json '{"time":"$time_local","ip":"$remote_addr",' '"status":$status,"rt":$request_time,"urt":"$upstream_response_time"}';access_log /var/log/nginx/json.log json_log;Prometheus + Grafana:云原生场景首选nginx-prometheus-exporter 把 stub_status 的指标转为 Prometheus 格式,Grafana 做可视化:# prometheus.ymlscrape_configs: - job_name: 'nginx' static_configs: - targets: ['localhost:9113']选型逻辑: 容器化/K8s 环境下 Prometheus 是事实标准,开箱即用 Service Discovery,Grafana 社区模板丰富。Nginx Plus 用户还可以用官方 nginx-plus-exporter 拿到更细的 upstream 指标。ELK Stack:日志深度分析场景当需求不只是看指标曲线,而是要按 IP、URL、状态码做聚合分析和历史追溯,ELK 更合适。Filebeat 采集 → Logstash 清洗 → Elasticsearch 存储 → Kibana 可视化,链路长但灵活度高。选型对比: Prometheus 适合指标型监控(数字曲线),ELK 适合日志型分析(文本检索+聚合)。小团队二选一推荐 Prometheus,监控告警闭环更短。Zabbix:传统企业环境的选择Zabbix 通过 Agent 调用 stub_status 页面,用正则提取指标配置监控项。适合已有 Zabbix 基建的企业,不推荐新项目为 Nginx 单独搭 Zabbix。告警:监控闭环的关键有监控没告警等于没监控。核心告警规则:5xx 比率超阈值(如 > 1%)触发 criticalActive connections 突增超过 2 倍标准差触发 warningupstreamresponsetime P99 > 2s 触发 warningPrometheus 用 Alertmanager 配路由和静默,ELK 用 Watcher 或 ElastAlert,Zabbix 自带触发器机制。运维常用命令速查nginx -t # 测试配置语法nginx -s reload # 平滑重载,不中断连接nginx -s quit # 优雅停止,处理完当前请求后退出nginx -s reopen # 重新打开日志文件(配合 logrotate)日志轮转用 logrotate,配置 postrotate 里发 USR1 信号让 Nginx 重新打开文件句柄,避免写入已轮转的老文件。面试追问方向stub_status 的 Waiting 和 keep-alive 是什么关系? Waiting 连接就是 keep-alive 空闲连接,keepalive_timeout 控制超时回收。Nginx 502 怎么排查? 先查 upstream 是否存活,再看 Nginx error log 里 connect() failed 的具体原因,最后检查 proxy_read_timeout 配置。如何不重启更新配置? nginx -t && nginx -s reload,reload 会 fork 新 worker 加载新配置,老 worker 处理完手头请求后退出。Prometheus 和 ELK 怎么选? 指标监控选 Prometheus(轻量、告警闭环好),日志分析选 ELK(全文检索、聚合灵活),大团队通常两套都搭。
服务端阅读 05月27日 22:12

Nginx 如何配置 WebSocket 代理?

Nginx 如何配置 WebSocket 代理?WebSocket 建立在 HTTP/1.1 之上,通过 Upgrade 机制将 HTTP 连接升级为全双工长连接。Nginx 默认会清除 Upgrade 头,所以必须手动配置才能正确代理 WebSocket。核心配置(三行必写)location /ws { proxy_pass http://backend; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade";}proxy_http_version 1.1:WebSocket 要求 HTTP/1.1,Nginx 默认用 1.0Upgrade $http_upgrade:转发客户端的协议升级请求Connection "upgrade":告知 Nginx 这不是普通 HTTP,需要保持升级状态推荐用 map 管理 Connection 头多 location 场景下,硬编码 "upgrade" 会导致非 WebSocket 请求也被标记。用 map 按需切换更安全:map $http_upgrade $connection_upgrade { default upgrade; '' close;}server { location /ws { proxy_pass http://backend; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $connection_upgrade; }}没有 Upgrade 头时走 close,普通请求不受影响。超时:为什么连着连着就断了?Nginx 的 proxy_read_timeout 默认 60 秒。WebSocket 是长连接,如果 60 秒内没有数据传输,Nginx 会主动断开。解决办法:proxy_read_timeout 3600s; # 1小时proxy_send_timeout 3600s;proxy_connect_timeout 60s; # 建连超时保持短即可按业务调,不是越大越好。过长超时意味着僵死连接不会被回收。WSS(WebSocket over TLS)在 SSL server 块里照加那三行即可,Nginx 负责 TLS 卸载,后端仍用 ws://:server { listen 443 ssl; ssl_certificate /etc/nginx/ssl/cert.pem; ssl_certificate_key /etc/nginx/ssl/key.pem; location /ws { proxy_pass http://backend; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $connection_upgrade; }}负载均衡要注意会话保持WebSocket 是有状态长连接,轮询策略会导致重连时切到不同后端。必须用 ip_hash:upstream ws_backend { ip_hash; server 10.0.0.1:8080; server 10.0.0.2:8080;}如果后端是无状态的(如用 Redis Pub/Sub 做消息同步),也可以用轮询。追问:连接断开怎么排查?查 Nginx error log,确认是否超时断开检查 Upgrade / Connection 头是否正确转发确认 proxy_buffering off 已设置,避免数据被缓冲检查防火墙或 CDN 是否拦截长连接用 curl -H "Upgrade: websocket" 手动测试握手是否返回 101
服务端阅读 05月27日 22:11

Nginx 反向代理怎么配置?

Nginx 反向代理怎么配置?反向代理是 Nginx 最核心的用途之一:客户端请求先到 Nginx,再由 Nginx 转发给后端服务器,客户端感知不到真实后端的存在。和正向代理(代理客户端出国)相反,反向代理代理的是服务端。最小可用配置server { listen 80; server_name example.com; location / { proxy_pass http://192.168.1.100:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; }}proxy_pass 指定后端地址,三条 proxy_set_header 是标配——不带这些头,后端拿到的全是 Nginx 的 IP,日志和鉴权都会出问题。多后端负载均衡upstream backend { server 192.168.1.100:8080 weight=3; server 192.168.1.101:8080 weight=1; server 192.168.1.102:8080 backup;}server { listen 80; location / { proxy_pass http://backend; }}四种策略选哪个?轮询(默认)无状态通用;ip_hash 保会话粘性但分布不均;least_conn 适合长连接;加权轮询按机器性能分配。生产环境常用加权轮询 + 健康检查。WebSocket 代理location /ws/ { proxy_pass http://backend; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_read_timeout 3600s;}不加 Upgrade 头,WebSocket 握手直接失败;proxy_read_timeout 不加长,空闲连接会被 Nginx 主动断开,这是最常见的踩坑点。面试追问:反向代理和正向代理的区别?反向代理代理服务端,客户端不知道真实后端是谁;正向代理代理客户端,服务端不知道真实客户端是谁。一句话:正向代理帮客户端藏身份,反向代理帮服务端藏身份。生产环境别漏这些超时三件套:proxy_connect_timeout、proxy_send_timeout、proxy_read_timeout,默认 60s,慢接口要调大缓冲默认开着,大文件上传场景注意 proxy_buffer_size 和 proxy_buffers 调大HTTPS 场景在 Nginx 做 SSL 终止,后端走内网 HTTP,证书只管 Nginx 一层proxy_redirect off 防止后端 302 重定向把内网地址暴露给客户端