面试题手册

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

服务端阅读 05月30日 20:38

Vercel、Netlify 和 AWS Amplify 该怎么选?

Vercel、Netlify 和 AWS Amplify 都能部署前端应用,但解决的问题不完全一样。Vercel 更适合 Next.js 和重视预览体验的团队;Netlify 更适合静态站点、多框架项目和表单类需求;AWS Amplify 更适合已经在 AWS 生态里、需要认证、存储、数据库一起管理的全栈项目。追问Vercel 一定比 Netlify 快吗?不一定。Next.js 项目在 Vercel 上通常更省心;普通静态站点放 Netlify 也可以很快。性能更多来自框架、缓存、图片处理和访问分布。为什么说 Vercel 有平台锁定风险?如果大量使用 Edge Middleware、ISR、图片优化和项目配置,迁移时要逐项找替代。锁定不是不能用,而是要知道哪些是平台能力。AWS Amplify 为什么成本难预测?它背后可能同时使用构建、存储、数据库、认证、流量、日志等多个 AWS 服务,流量变化后账单更难估算。小团队怎么选?Next.js 先选 Vercel;官网、博客、文档选 Netlify;除非团队熟悉 AWS 或后端明确要用 AWS,否则不建议一开始上 Amplify。迁移平台注意什么?先列出环境变量、函数、边缘逻辑、图片优化、表单、认证和 DNS 依赖,灰度验证后再切全量流量。
服务端阅读 05月30日 20:38

Vercel 多环境部署怎么配置才不容易出错?

Vercel 做多环境部署,核心不是多建几个分支,而是把 Production、Preview、Development 的触发方式、环境变量和数据资源隔离清楚。main 对应生产,Pull Request 和功能分支对应 Preview,本地通过 vercel dev 对应 Development。这样团队能在合并前拿到真实预览地址,又不会让测试请求误连生产数据库。追问为什么不能只用一个 .env 文件?一个文件短期省事,长期容易把测试密钥、生产数据库和本地回调混在一起。支付、登录、推送这类功能尤其危险。NODE_ENV 和 VERCEL_ENV 有什么区别?NODE_ENV 更偏构建模式,Preview 也常是 production。VERCEL_ENV 才表示 production、preview 或 development,更适合环境路由。Preview 环境需要独立数据库吗?只看静态页面可以不要;涉及登录、写入、回调或迁移时建议隔离。最低成本是测试库加命名空间,更稳是每个 PR 临时 schema。多环境最常见的坑是什么?变量改完不重新部署、Preview 误用生产 API、回调地址只配生产域名。排查时先看 Deployment Environment。写段代码const apiBase = { production: process.env.API_URL, preview: process.env.PREVIEW_API_URL, development: 'http://localhost:3001' }[process.env.VERCEL_ENV || 'development'];
服务端阅读 05月30日 20:38

MCP 错误处理和重试机制应该怎么实现?

MCP 的错误处理和重试机制,关键不是“失败就再试一次”,而是先判断失败能不能重试。参数校验失败、权限不足、工具不存在这类错误重试没有意义;网络抖动、上游 5xx、限流、临时超时才适合重试。把错误分类、超时、退避、熔断和降级放在一起设计,MCP Server 才不会在上游变慢时把自己也拖垮。追问哪些 MCP 错误不应该重试?400 参数错误、401/403 权限错误、工具名不存在、schema 不匹配都不该重试。应该快速返回,并提示调用方修正输入或重新授权。限流错误应该怎么处理?如果上游返回 Retry-After,优先按它等待;没有这个头时再用指数退避。还要给每个用户或会话设置并发上限。熔断和重试是什么关系?重试解决偶发失败,熔断处理持续失败。上游连续超时或 5xx 达到阈值后,应短时间直接失败或走降级。错误日志怎么写才方便排查?每次工具调用都生成 requestId,并在 MCP 响应、应用日志、上游请求日志里贯穿它。敏感参数要脱敏。降级策略有哪些边界?降级只适合可接受旧数据或部分结果的场景。涉及写入、支付、权限变更或不可逆操作时不要自动降级。写段代码async function retry(fn, max = 3) { for (let i = 0; i < max; i++) { try { return await fn(); } catch (e) { if (!e.retryable || i === max - 1) throw e; await new Promise(r => setTimeout(r, Math.min(1000 * 2 ** i, 8000))); } }}
服务端阅读 05月30日 20:38

MCP 数据持久化和缓存策略该怎么设计?

MCP 的持久化和缓存不能只理解成“把数据存起来”。先区分哪些数据必须长期保留,哪些只是为了减少重复计算:工具定义、资源索引、用户会话、授权状态通常需要持久化;工具调用结果、资源快照、schema 解析结果更适合缓存。分清这条线,才不会把缓存当数据库,也不会把数据库拖成临时变量仓库。追问MCP 哪些数据一定要持久化?工具清单、资源元数据、授权状态和会话恢复信息最好持久化,因为它们影响协议行为和用户体验。单次工具调用中间结果不一定落库,除非要审计或断点续跑。Redis 缓存和数据库版本怎么配合?关键记录带 version 或 updatedAt,缓存 key 或 value 里也保存这个版本。读取时发现版本不一致就丢弃缓存,这比单纯依赖 TTL 更可靠。持久化会带来哪些安全边界?不要把 access token、用户输入的敏感资源和工具返回原文无脑落库。确实要保存时,应加密、设置保留周期,并在日志里只记录 request id。缓存最常见的坑是什么?权限变化后缓存没失效,可能导致用户还能看到旧资源;失败结果缓存太久,也会让故障恢复后仍然返回错误。单机和多实例有什么取舍?单机可以用 SQLite 加内存缓存;多实例必须把会话和缓存外置到 Redis 或数据库,否则请求打到不同实例时会状态丢失。写段代码async function getToolSchema(name: string) { const key = `mcp:schema:${name}`; const cached = await redis.get(key); if (cached) return JSON.parse(cached); const schema = await store.loadToolSchema(name); await redis.set(key, JSON.stringify(schema), { EX: 300 }); return schema;}
前端阅读 05月30日 20:38

Appium 的核心特性是什么?为什么适合跨平台移动自动化?

Appium 是基于 W3C WebDriver 协议的移动端自动化框架,核心价值是用同一套测试思路覆盖 Android、iOS、移动 Web 和混合应用。它不是自己去“点屏幕”,而是由客户端把命令发给 Appium Server,再交给 UiAutomator2、XCUITest 等平台驱动执行。适合黑盒回归、跨平台主流程验证和 CI 冒烟测试,但不适合替代单元测试或追求极限执行速度的白盒 UI 测试。追问Appium 和 Espresso、XCUITest 怎么取舍?只测 Android 且能接触源码时,Espresso 通常更快更稳;只测 iOS 时,XCUITest 的系统集成更直接。Appium 的优势是跨平台和黑盒测试。Appium 为什么不需要重新编译 App?它通过系统自动化框架驱动已安装应用,不要求在业务代码里埋测试 SDK。边界是安全控件、系统弹窗或 WebView 调试开关可能仍要测试包配合。元素定位最容易踩什么坑?最常见的是依赖 XPath 全路径,页面层级变化就全挂。更稳的是让客户端补 accessibility id 或 resource-id。混合应用测试要注意什么?进入 WebView 前要确认调试已开启,并等待 context 出现后再切换。切回原生时也要显式切到 NATIVE_APP。CI 里跑 Appium 有哪些边界?CI 适合跑登录、下单、关键链路等少量稳定用例。设备占用、模拟器启动和网络抖动都会放大失败率。写段命令npm i -g appiumappium driver install uiautomator2appium driver install xcuitestappium --base-path /wd/hub
前端阅读 05月30日 20:13

Appium 测试运行慢时如何定位和优化?

Appium 测试慢,通常是定位、等待、会话创建、设备资源和网络链路叠在一起变慢。优化前先量化:哪一步耗时最长,是启动应用、找元素、切 WebView、执行手势,还是每条命令都慢。没有数据就调参数,很容易把稳定性也一起调没。追问元素定位为什么会拖慢 Appium?每次定位都要跨进程和设备通信,复杂 XPath 还会遍历 UI 树。优先用 id、accessibility id,其次平台特定选择器。隐式等待和显式等待怎么取舍?隐式等待影响几乎每次查找,定位失败尤其拖时间;显式等待只等关键条件,更容易控制成本。少用固定 sleep。会话复用一定更快吗?会话复用能省安装、启动和授权时间,但会带来脏数据、登录态残留和用例污染。冒烟可用 noReset,首次启动类用例要干净环境。并行为什么有时更慢?瓶颈可能在 Appium Server、设备 CPU、USB、模拟器资源和后端环境。Android 并行要给每台设备独立 udid 和 systemPort。性能监控看什么?先看 Appium 命令耗时,再看应用 CPU、内存、网络和日志。所有命令都慢查网络和设备负载,只有定位慢就查选择器。写段配置const capabilities = { automationName: 'UiAutomator2', noReset: true, disableWindowAnimation: true, newCommandTimeout: 60};
前端阅读 05月30日 20:13

Appium 元素找不到或启动失败时如何排查?

Appium 排查不要一上来就改脚本,先把链路拆开:Server 是否可连、设备是否在线、应用是否成功安装和启动、元素是否真的在当前上下文里。很多“找不到元素”不是定位写错,而是页面没加载、弹窗挡住、WebView 没切上下文,或测试连到另一台设备。追问Appium Server 连不上先看什么?先确认端口和服务状态,检查 Appium 版本、4723 是否监听、URL 是否还在用旧的 /wd/hub,以及防火墙或代理。设备连接失败怎么区分?先脱离 Appium,用 adb devices 或 Xcode 设备列表验证设备是否在线。多设备时必须显式写 udid。元素找不到为什么不能只换 XPath?XPath 复杂且慢,层级变化就失效。先用 Appium Inspector 确认元素是否存在,再优先用 id、accessibility id 或平台选择器。应用安装或启动失败卡在哪里?安装失败查路径、包损坏、设备空间和签名冲突;启动失败看 appPackage、appActivity、权限弹窗和 logcat 崩溃日志。点击滑动失败怎么判断?先看元素是否可见、可点击、是否被浮层遮挡,再考虑坐标点击。滑动建议用屏幕比例而非固定像素。写段命令lsof -i :4723appium --log-level debug -p 4723adb devices
前端阅读 05月30日 20:13

Appium 如何测试混合应用并稳定切换 WebView?

Appium 测混合应用,关键是先分清当前操作发生在原生视图还是 WebView。原生导航栏、权限弹窗、底部 Tab 通常留在 NATIVE_APP;H5 页面里的按钮、输入框、DOM 文案要切到 WEBVIEW 后再用 CSS、XPath 或 WebDriver 定位。难点不在 API,而在 WebView 什么时候出现、Chromedriver 是否匹配、页面是否加载完成。追问什么时候需要切换到 WebView?只有目标元素属于 H5 DOM 时才切换。原生控件不要硬切 WebView 找,系统弹窗、原生返回按钮、底部导航栏通常仍在 NATIVE_APP。WebView 上下文找不到怎么排查?先确认 Android 应用开启 WebView 调试,再检查页面是否加载完成。iOS 还要确认 Web Inspector、证书和真机调试权限。Chromedriver 版本不匹配会怎样?可能能看到上下文,但切换后查 DOM 或执行 JS 报 session 错误。要配置 chromedriverExecutableDir 或自动下载策略。定位元素优先用什么?WebView 内优先稳定 CSS 或 data-testid,原生侧优先 accessibility id 或 resource-id。不要依赖易变层级 XPath。切换后为什么还要等待?上下文切换只说明进入执行环境,不代表页面元素可交互。要显式等待目标元素可见或可点击。写段代码const contexts = await driver.getContexts();const webview = contexts.find(c => c.includes('WEBVIEW'));if (webview) await driver.context(webview);
前端阅读 05月30日 20:13

Appium 如何进行数据驱动测试才稳定?

Appium 做数据驱动测试,核心是把测试步骤和测试数据拆开:脚本负责打开页面、输入、点击、断言,账号、密码、预期文案、设备差异、边界值放到 JSON、CSV、Excel、数据库或接口里。这样新增场景时通常只改数据,不改自动化逻辑,回归覆盖会稳定很多。追问数据源选 JSON、CSV 还是 Excel?JSON 适合层级结构,CSV 适合简单二维数据,Excel 对测试同学友好但 CI 里容易遇到空值类型、日期格式问题。最容易踩什么坑?测试数据之间互相污染,比如同一手机号被多条用例注册。另一个坑是只换输入不换断言,跑很多数据却没有真正覆盖业务规则。一条数据失败后要不要继续?回归场景建议继续跑,并记录 caseId、设备、输入数据、截图和关键日志。冒烟测试可以关键链路失败就中止。动态生成数据好不好?手机号、订单号适合动态生成;空密码、特殊字符等边界值最好显式写在文件里。动态数据还要有清理逻辑。和 Page Object 怎么配合?Page Object 管页面操作,数据驱动管输入和预期。用例层读取数据后调用页面方法,断言也要带 caseId。写段代码for (const tc of require('./login-cases.json').testCases) { it(`${tc.id} ${tc.description}`, async () => { await loginPage.login(tc.username, tc.password); expect(await loginPage.resultText()).toBe(tc.expected); });}
服务端阅读 05月30日 20:13

Zookeeper 架构中 Leader、Follower 和 Observer 有什么区别?

Zookeeper 是主从协同架构,但角色边界很清楚:Leader 负责写请求排序、事务提案和提交协调;Follower 负责本地读、转发写请求、参与选举和投票;Observer 只同步数据和服务读请求,不参与选举,也不计入写入多数派。设计重点不是所有节点都可写,而是用少量投票节点保证一致性,再用 Observer 扩展读能力。追问写请求怎么流转?客户端连到 Follower 时,写请求会被转发给 Leader,由 Leader 生成事务提案并广播。超过半数 Follower ACK 后才提交。Observer 为什么能提升读性能?Observer 不参加投票,增加它不会提高多数派门槛,也不会拖慢 Leader 等待 ACK 的路径。它适合承接跨机房或大规模客户端读流量。为什么常用奇数个投票节点?3 个节点能容忍 1 个故障,5 个能容忍 2 个。4 个投票节点也只能容忍 1 个故障,却多了同步和运维成本。配置容易踩什么坑?每台机器的 myid 必须和 server.X 对应。Observer 需要在节点配置里声明 peerType=observer,并在集群配置中标成 observer。跨机房部署合适吗?投票节点不建议跨高延迟机房,网络抖动会放大成选举和会话超时。远端读流量可考虑 Observer。
服务端阅读 05月30日 20:13

Zookeeper Leader 选举机制是怎样工作的?

Zookeeper 的 Leader 选举不是谁先启动谁当 Leader,而是看哪个节点最适合承接已提交历史。Fast Leader Election 会在 LOOKING 状态下交换投票,每张票通常包含 epoch、zxid 和 sid:先比较选举轮次,再看 zxid 谁更新,zxid 相同才比较 sid。某个候选者拿到超过半数投票后成为 Leader。追问Leader 选举什么时候触发?集群首次启动、Leader 宕机、网络分区导致多数 Follower 失联时,节点都会进入 LOOKING。短暂 GC、磁盘卡顿也可能让 Follower 误判超时。zxid 和 sid 谁更重要?zxid 更重要,因为它代表节点看到的事务进度。只有 zxid 一样时才比较 sid,sid 大只是为了打破平票。为什么必须超过半数才能当选?多数派机制保证任意两个成功多数集合一定有交集,新 Leader 能接触到上一任已提交事务信息。选举期间客户端会怎样?写请求通常会失败、阻塞或连接断开,需要客户端重试。业务侧要设置合理 sessionTimeout 和重试退避。排查选举问题看什么?先确认 myid 和 zoo.cfg 的 server.X 是否对应,再检查 2888/3888 端口。日志里的 LEADING、FOLLOWING、Cannot open channel 很关键。
服务端阅读 05月30日 20:13

Zookeeper 如何通过 ZAB 协议保证数据一致性?

Zookeeper 的一致性主要靠 ZAB 协议保证。所有写请求最终交给 Leader 排序,Leader 分配全局递增的 zxid,再把提案广播给 Follower;超过半数节点 ACK 后,事务才提交。代价是写入要等多数派,延迟不会像单机缓存那样低;好处是 Leader 宕机后,新 Leader 能根据 zxid 找到较完整的提交历史,避免已提交数据丢失或未提交数据乱入。追问ZAB 和普通主从复制最大区别是什么?普通主从复制常见问题是主节点确认太早,故障时从节点未必拥有同一批数据。ZAB 要求事务拿到多数派 ACK 再提交。zxid 为什么能决定数据新旧?zxid 是事务全局序号,高位通常关联 Leader epoch,低位表示任期内事务递增。选主和同步时比较 zxid 判断谁更新。读请求为什么不一定强一致?Follower 和 Observer 异步接收提交消息,可能比 Leader 慢。必须读最新时可以先执行 sync(),但有协调成本。Leader 崩溃时怎么避免事务丢失?新 Leader 会和其他节点对齐事务日志:落后的补发 DIFF,差太多的发 SNAP,未提交尾巴会 TRUNC 回滚。怎么判断一致性问题来自哪里?先确认节点角色和存活,再看日志里的 zxid、leader election、syncLimit 超时。很多读旧值只是连到了落后 Follower。
服务端阅读 05月30日 20:13

Zookeeper 性能怎么优化?哪些参数最容易踩坑?

Zookeeper 性能优化先分清读多、写多还是连接多。读多可以加 Observer 或让客户端分散到 Follower;写多瓶颈通常在 Leader、事务日志 fsync 和过半确认;连接多、Watcher 多、znode 大,会把内存和网络打满。有效优化不是把参数调大,而是减少无意义写入、控制节点大小、把事务日志放到稳定低延迟磁盘。追问加节点一定能提升性能吗?不一定。Follower 或 Observer 能分担读请求,但写请求仍要 Leader 发起并等待过半确认,投票节点越多,写入链路可能越长。dataDir 和 dataLogDir 为什么分开?事务日志每次写入都很敏感,最好放低延迟 SSD 或独立盘;快照体积大但频率低,可以放普通数据盘。Watcher 多会带来什么问题?Watcher 会占服务端内存,事件触发时还会产生通知风暴。客户端重连后无脑重复注册,会导致 watch_count 持续上涨。单个 znode 为什么不建议放大数据?Zookeeper 是协调元数据系统,不是文件存储。大节点会放大网络传输、序列化、快照和事务日志成本。性能压测看哪些边界?至少分读密集、写密集、混合读写、重连风暴和 Watcher 触发场景。每次只改一个参数,记录 P95/P99、磁盘 await、GC pause。写段配置tickTime=2000initLimit=10syncLimit=5maxClientCnxns=100dataLogDir=/data/zookeeper/txnlogautopurge.purgeInterval=1
服务端阅读 05月30日 20:13

Zookeeper、Etcd 和 Consul 有什么区别?该怎么选?

Zookeeper、Etcd 和 Consul 都能做分布式协调,但出发点不一样。Zookeeper 更像协调原语库,擅长临时节点、顺序节点、Watcher、分布式锁和老牌 Java/大数据生态;Etcd 是强一致 KV,Raft、revision、租约和 Watch 更贴近 Kubernetes 控制面;Consul 把服务发现、健康检查、多数据中心和 KV 打包在一起,适合微服务治理。追问Consul 是 AP 还是 CP?不能简单说 Consul 全部是 AP。服务发现依赖 Gossip,读到的信息可能短暂滞后;Server 集群和 KV 一致读依赖 Raft,更接近 CP。Zookeeper 和 Etcd 的 Watch 有什么差别?Zookeeper 的 Watch 是一次性通知,触发后需要重新注册。Etcd Watch 基于 revision,可以从指定版本继续消费事件,但要处理 compaction 后版本过旧的问题。为什么 Kubernetes 选 Etcd?Etcd 的 Raft KV、revision、租约和 gRPC API 更符合 Kubernetes 的对象存储与控制循环模型。Zookeeper 数据模型更偏传统中间件生态。老系统要不要迁到 Etcd?如果只是为了技术更新,通常不值得。临时节点、顺序节点、ACL、Watcher 语义都要重做,只有控制面重构时才值得评估。三者性能怎么比较才靠谱?按读写比例、值大小、Watcher 数量、磁盘 fsync 和网络延迟压测。不要只看单机 benchmark。
服务端阅读 05月30日 20:13

Zookeeper 连接超时、脑裂和数据不一致怎么排查?

Zookeeper 出问题时不要先调参数,先判断是客户端、网络、磁盘还是集群选举问题。连接超时通常看 sessionTimeout、端口连通性和服务端负载;脑裂要看是否真的出现多个可写 Leader,多数情况下是网络分区或监控误判;数据不一致多半是读到了落后的 Follower,需要用 sync() 或改读 Leader。追问连接超时一定是服务端问题吗?不一定。先用 nc 验证 2181 端口,再看客户端 DNS、负载均衡、防火墙和连接池是否耗尽。服务端 latency_max 很高时,还要查磁盘 I/O、GC 暂停和 outstanding 请求堆积。Zookeeper 会不会真的脑裂?Zookeeper 依赖过半机制,正常配置下不会允许两个 Leader 同时提交事务。危险点通常是偶数节点、跨机房高延迟部署、错误 myid/server 配置或监控误判。数据不一致时 sync() 为什么有用?Follower 读可能落后于 Leader,sync(path) 会让当前连接先同步到较新的事务点。代价是多一次网络往返,强一致读路径不要滥用。Watcher 泄漏怎么判断?看 echo wchs | nc zk1 2181 和客户端注册逻辑。很多泄漏来自异常重试时重复注册,修复时要让 Watcher 与业务对象生命周期绑定。故障恢复最怕什么?最怕只恢复快照不恢复事务日志,或不同节点混用不同版本数据目录。恢复前先停集群、备份现状,再按 zxid 最新且完整的快照和日志恢复。写段命令echo ruok | nc zk1 2181echo stat | nc zk1 2181echo mntr | nc zk1 2181 | egrep 'latency|connections|outstanding|synced'
服务端阅读 05月30日 19:58

Zookeeper 运维监控要看哪些指标和告警?

Zookeeper 运维的重点不是“进程活着就行”,而是确认多数派健康、写入延迟可控、客户端连接没有失控。日常先看四类指标:集群角色和节点存活、请求延迟、连接与 Watcher 数量、磁盘和 JVM 状态。stat 能看 leader/follower,mntr 适合接 Prometheus exporter,cons 能排查连接来源,wchs 可以判断 Watcher 是否异常膨胀。追问线上最应该优先盯哪个指标?优先看 zk_avg_latency、zk_max_latency 和 zk_outstanding_requests。节点存活重要,但很多事故在节点没挂前,延迟和排队已经先报警了。Watcher 数量突然升高说明什么?通常说明客户端重复注册、服务实例目录过大,或某个配置监听没有去重。短期定位来源连接,长期要改客户端代码。Zookeeper 磁盘满了会怎样?常见表现是写入失败、延迟飙升、Leader 不稳定,严重时节点无法启动。要开启 autopurge,并监控 dataDir 和 dataLogDir。滚动重启为什么不能一口气重启多台?Zookeeper 需要多数派可用,5 节点同时停 3 台就失去法定人数。稳妥做法是一台一台重启并确认状态。写段命令echo stat | nc zk1 2181echo mntr | nc zk1 2181 | egrep 'latency|outstanding|watch_count'echo cons | nc zk1 2181 | wc -l
服务端阅读 05月30日 19:58

Zookeeper 架构和数据模型该怎么设计才稳?

Zookeeper 要稳,先别把它当数据库用,而要当成“小而关键的协调层”。生产集群通常选 3 或 5 个投票节点:3 节点能容忍 1 台故障,5 节点能容忍 2 台故障;节点数不是越多越好,写入要多数派确认,7 台以上会增加选举和同步成本。部署时尽量跨机架或可用区,但不要把网络延迟拉得太大。追问为什么生产集群常用 3 或 5 个节点?Zookeeper 依赖多数派,4 个节点仍然只能容忍 1 台故障,因为多数派需要 3 票。偶数节点增加机器和同步成本,却不提升容错收益。dataDir 和 dataLogDir 为什么建议分开?事务日志是写请求关键路径,磁盘抖动会直接放大写延迟。快照文件更偏后台持久化,和日志分盘更稳。Zookeeper 适合存业务大数据吗?不适合,它适合配置、状态、锁节点、服务实例这类小数据。大对象会增加网络复制、快照体积和恢复时间。Watcher 最容易踩什么坑?原生 Watcher 触发一次就失效,收到事件后要重新注册。回调里不要做重活,应投递异步任务。分布式锁一定要自己实现吗?不建议,Curator 的 InterProcessMutex 已处理大量边界。业务侧更应该关注超时时间、finally 释放锁和锁粒度。写段配置tickTime=2000initLimit=10syncLimit=5dataDir=/data/zookeeper/datadataLogDir=/data/zookeeper/logsautopurge.purgeInterval=1
前端阅读 05月30日 19:58

Chrome 的 V8 引擎如何执行 JavaScript?

V8 执行 JavaScript 不是直接把源码一路翻成机器码。大致流程是:源码先被解析成 AST,再由 Ignition 生成并执行字节码;运行中如果某段代码频繁执行,V8 会收集类型反馈,把它交给 TurboFan 优化成机器码。优化依赖“假设”,比如对象形状稳定、函数参数类型稳定;一旦假设被打破,就会发生去优化。追问隐藏类和内联缓存是什么?V8 会给结构相似的对象建立隐藏类,用来快速定位属性。内联缓存会记录某个属性访问曾经遇到的对象形状。为什么不建议频繁 delete 属性?delete 可能改变对象形状,让原本稳定的隐藏类失效。热点路径里更常见做法是置为 null 或创建新对象。V8 的垃圾回收怎么影响页面?大量临时对象会增加 minor GC 频率,长期被闭包、全局数组、事件监听器引用的对象会进入老生代,严重时页面会间歇卡顿。代码怎么写更友好?让对象结构稳定、避免热路径混用类型、减少循环里的临时对象。先用 Performance 和 Memory 确认瓶颈,再优化热点。写段代码function makeUser(id, name) { return { id, name, active: true }; }const u = makeUser(1, 'A');u.active = false;
前端阅读 05月30日 19:58

Chrome 缓存机制有哪些?强缓存和协商缓存怎么选?

Chrome 缓存是一组从近到远的命中链路。页面请求资源时,可能先被 Service Worker 接管,再命中内存缓存或磁盘缓存;HTTP 层又分强缓存和协商缓存。强缓存看 Cache-Control: max-age,没过期就不问服务器;协商缓存会带 If-None-Match 或 If-Modified-Since 去问服务器,没变就返回 304。追问强缓存和协商缓存怎么取舍?带内容 hash 的 JS、CSS、图片适合强缓存很久;HTML 入口更适合短缓存或协商缓存,避免用户一直拿旧入口。ETag 和 Last-Modified 有什么区别?Last-Modified 依赖修改时间,精度受构建流程影响;ETag 通常基于内容或版本生成,更精确但有计算成本。memory cache 和 disk cache 有什么区别?memory cache 快,通常跟当前页面生命周期相关;disk cache 更持久。开发者主要通过 HTTP 头影响策略。Service Worker 缓存会不会覆盖 HTTP 缓存?会,它能拦截 fetch 并决定读 Cache Storage 还是走网络。缓存策略写错会导致用户长期拿旧数据。写段配置Cache-Control: public, max-age=31536000, immutableETag: "app-v42"
前端阅读 05月30日 19:58

Chrome 事件循环中宏任务和微任务到底怎么执行?

Chrome 的事件循环可以先记一句话:同步代码先进调用栈,栈清空后清空微任务,然后浏览器选择是否渲染,再执行下一个宏任务。宏任务包括 script、setTimeout、用户事件等;微任务包括 Promise.then、queueMicrotask、MutationObserver。微任务优先级高,但太多会让渲染一直没机会发生。追问setTimeout(fn, 0) 为什么不是立刻执行?它只是把回调放进宏任务队列,必须等当前同步代码和本轮微任务执行完。后台标签页和嵌套定时器还可能被节流。Promise.then 和 requestAnimationFrame 谁先执行?Promise.then 属于微任务,会在当前宏任务结束后尽快清空;rAF 通常在下一次渲染前执行。实际项目常见坑是什么?接口返回后连续触发大量 Promise 回调,在里面同步计算列表、改 DOM、再追加微任务,页面就会点击无响应。怎么拆重任务?把非关键计算切片,用 setTimeout、MessageChannel 或 requestIdleCallback 给浏览器处理输入和渲染的机会。写段代码console.log('A');setTimeout(() => console.log('B'), 0);Promise.resolve().then(() => console.log('C'));console.log('D'); // A D C B