面试题手册

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

服务端阅读 05月29日 22:54

axios 代码怎么做单元测试?Mock 请求的常用方案有哪些?

测试 axios 代码的核心是 隔离网络请求,常用方案有三种:axios-mock-adapter、jest.mock + msw。axios-mock-adapter: 直接拦截 axios 实例的请求,按 URL 和方法注册 mock 响应。适合纯 axios 项目,API 直观。示例:mock.onGet('/api/user').reply(200, { name: 'test' })。可模拟超时、网络错误、指定状态码。缺点是绑定了 axios 实例,切换请求库需重写 mock。jest.mock('axios'): 直接 mock axios 模块,控制 axios.get/post 等方法的返回值。适合快速编写测试,jest.mock('axios') 后用 axios.get.mockResolvedValue() 设定返回。优点是零依赖,缺点是绕过了拦截器逻辑,无法测试中间件行为。MSW(Mock Service Worker): 在 Service Worker 层拦截请求,不依赖任何 HTTP 库。最接近真实网络行为,可共享给集成测试和 E2E。通过 handler 匹配请求并返回 mock 数据。推荐用于新项目。选型建议: 项目只用 axios → axios-mock-adapter;需要快速单元测试 → jest.mock;多请求库或需要更真实模拟 → MSW。 追问: jest.mock 和 jest.spyOn 在 mock axios 时有什么区别? 如何测试请求拦截器中的 Token 注入逻辑? MSW 的 Service Worker 在 Node 环境下如何工作? 如何模拟 axios 的网络超时和 5xx 错误场景? axios-mock-adapter 能否模拟请求进度(onUploadProgress)?
服务端阅读 05月29日 22:54

axios 底层是怎么实现的?核心架构和请求流程是怎样的?

axios 本质是 请求/响应拦截器管道 + 适配器模式,核心流程为:配置合并 → 请求拦截器 → 分发请求 → 响应拦截器 → 返回结果。适配器模式: axios 不直接发请求,而是通过 adapter 抽象层。浏览器环境用 xhr.js(基于 XMLHttpRequest),Node 环境用 http.js(基于 Node 的 http/https 模块)。通过 adapter 配置项可自定义适配器,这是 axios 跨平台的关键。拦截器机制: 维护两个链式数组 request interceptors 和 response interceptors,每个拦截器有 fulfilled 和 rejected 两个回调。请求时将配置、拦截器和 adapter 按 Promise 链顺序串联执行,形成 [req1 → req2 → ... → adapter → ... → res2 → res1] 的管道。配置合并策略: 三层配置合并——默认配置(defaults)→ 实例配置(instance.defaults)→ 请求配置(请求参数),通过 mergeConfig 按策略合并,headers 单独处理。请求流程: axios.request() 是统一入口,其他方法(get/post 等)最终都调用 request。内部创建 Promise 链,将拦截器成对插入链的两端,adapter 在链中间执行实际请求,支持取消(CancelToken)和超时控制。 追问: 拦截器的执行顺序是什么?请求拦截器和响应拦截器分别是正序还是逆序? 如何自定义 adapter 实现 Mock 数据或缓存层? CancelToken 基于什么原理实现的?为什么新增 AbortController 方案? mergeConfig 对不同类型的配置项(如 headers、transformRequest)采用了什么合并策略? axios 的 Promise 链如果中间某个拦截器抛异常,后续拦截器还能执行吗?
服务端阅读 05月29日 22:54

React Native 调试有哪些方法?各调试工具分别适用什么场景?

React Native 调试分 JS 层调试、原生层调试、性能分析 三个层面。JS 层调试: Chrome DevTools 是最基础的方式,通过 Ctrl+M 打开开发者菜单选择 Debug 打开 Chrome 调试。但 Chrome 调试运行在 Chrome V8 而非设备 JSC/Hermes 上,存在兼容差异。推荐使用 Flipper,它内置 React DevTools 和网络检查器,支持断点、Console、组件树检查,是官方推荐的调试平台。原生层调试: Android 用 Android Studio 的 Logcat 过滤 ReactNativeJNI 日志,可对原生模块设断点调试;iOS 用 Xcode 的 LLDB,在 RCTBridge 方法处打断点。性能分析: Perf Monitor(开发者菜单内)查看 FPS 和内存;Systrace 记录帧渲染时间线定位掉帧原因;Hermes 引擎自带 CPU Profiler 生成 Chrome Trace 格式文件。React DevTools Profiler 分析组件渲染耗时和频率。常用工具总结: Flipper(全能调试)、React DevTools(组件树)、Chrome DevTools(JS 断点)、Xcode/Android Studio(原生调试)、Systrace(性能分析)。 追问: Chrome 调试模式和 Hermes 引擎调试有什么区别? Flipper 在新架构下是否还适用?有什么替代方案? 如何对 React Native 的启动耗时进行量化分析? 生产环境如何收集 JS 异常和崩溃日志? Hermes 的 CPU Profiler 生成的 trace 文件如何分析?
服务端阅读 05月29日 22:54

React Native 性能优化怎么做?常见性能瓶颈如何排查和解决?

React Native 性能优化的核心是 减少 JS Bridge 通信、控制重渲染、优化列表滚动 三个方向。减少 Bridge 通信: Bridge 是异步串行的,高频调用会积压队列。将批量操作合并为一次原生调用,使用 Native Modules 批量传递数据而非逐条传递。新架构 Fabric 取代了异步 Bridge,实现同步通信。控制重渲染: 使用 React.memo 包裹子组件避免不必要的 re-render;用 useMemo 缓存计算结果、useCallback 缓存回调函数;列表项拆分为独立组件并 memo 化。避免在 render 中创建内联对象和函数。优化列表: FlatList 替代 ScrollView 渲染长列表,设置 keyExtractor、getItemLayout 提升性能;windowSize 控制渲染窗口大小;removeClippedSubviews 回收不可见视图。VirtualizedList 是 FlatList 的底层,可做更细粒度控制。其他关键点: 图片使用缓存库(如 react-native-fast-image);动画用 useNativeDriver 驱动跑在原生线程;避免在主线程做 JSON 解析等耗时操作;Profiling 工具用 Flipper 或 Systrace 定位瓶颈。 追问: React.memo 的浅比较在什么场景下会失效?如何自定义比较逻辑? FlatList 的 windowSize 参数设为多少合适?过小会有什么副作用? useNativeDriver 为什么不能驱动布局属性(如 height)的动画? 新架构 Fabric 和 TurboModules 相比旧 Bridge 的性能提升体现在哪里? 如何用 Systrace 定位 JS 线程和原生线程的耗时瓶颈?
服务端阅读 05月29日 22:54

Android四大组件分别是什么?各自承担什么职责?

Android四大组件是 Activity、Service、BroadcastReceiver、ContentProvider,它们是构成 Android 应用的基石,各自负责不同的职责边界。Activity 负责用户界面的展示与交互,一个屏幕对应一个 Activity,通过 Intent 实现页面跳转和数据传递,生命周期由系统回调管理(onCreate → onResume → onPause → onDestroy)。Service 在后台执行长时间运行的操作,不提供界面。分为 Started Service(startService 启动,与调用者无关)和 Bound Service(bindService 绑定,允许通信)。注意 Service 仍运行在主线程,耗时操作需开子线程。BroadcastReceiver 监听并响应系统或应用发出的广播消息,如开机启动、网络变化、电量改变。分静态注册(AndroidManifest 声明,应用未启动也可接收)和动态注册(代码注册,跟随组件生命周期)。ContentProvider 管理应用间数据共享,提供标准 CRUD 接口,通过 URI 定位数据。系统联系人、短信等均通过 ContentProvider 暴露。 追问: Activity 的四种启动模式分别适用于什么场景? Service 和 IntentService 的区别是什么?IntentService 为什么已废弃? 静态注册广播在 Android 8.0 后有哪些限制?如何适配? ContentProvider 的 URI 格式是怎样的?如何自定义 Authority? 四大组件中哪些可以在 Manifest 中声明多个实例?
服务端阅读 05月29日 22:48

常见的 DNS 记录类型有哪些?各自什么作用?

7 种必知记录:A——域名→IPv4 地址;AAAA——域名→IPv6 地址;CNAME——域名→另一个域名(别名);MX——邮件服务器地址+优先级;NS——指定域名的权威 DNS 服务器;TXT——任意文本(SPF/DKIM/域名验证);SOA——主权威服务器信息+序列号+TTL。辅助记录:SRV(指定服务端口和主机)、PTR(反向解析 IP→域名)、CAA(指定允许的证书颁发机构)。追问CNAME 和 A 记录能共存吗?不能。同一域名要么 CNAME 要么 A。CNAME 意味着这个域名完全由目标域名定义,再设 A 记录就矛盾了。但子域可以:example.com 用 A,www 用 CNAME 指向 example.com。MX 优先级数字越小越优先吗?是的。优先级 10 的比 20 的先尝试。常用配置:主服务器优先级 10,备用 20。TXT 记录的 SPF 怎么写?v=spf1 include:_spf.google.com ~all——允许 Google 邮件服务器代发,其他标记为软失败。~all=软失败,-all=硬拒绝,+all=全部允许(别用)。SOA 记录的序列号有什么用?从 DNS 服务器用序列号判断 zone 是否更新——序列号变大则拉取新数据。常用格式:YYYYMMDDNN。改了 zone 文件必须递增序列号。SRV 记录什么时候用?指定某服务运行在哪台机器的哪个端口。SIP/LDAP/Kerberos 等协议用 SRV 发现服务器。HTTP 不用 SRV(浏览器不支持)。
服务端阅读 05月29日 22:48

如何监控 DNS 服务的性能和可用性?

三层监控:可用性(能否解析)用 dig/nslookup 定时探测;性能(解析耗时)用 dig +stats 看 Query time,P99 超阈值告警;正确性(解析结果是否正确)对比实际 IP 和预期 IP。工具:Prometheus + Blackbox Exporter 做探测采集,Grafana 展示,Alertmanager 告警。关键指标:解析成功率、平均/P99 延迟、NXDOMAIN 比例(异常高可能是 DNS 劫持)、缓存命中率。追问Blackbox Exporter 怎么配 DNS 探测?prometheus.yml 中配 job:modules: [dnstcp],targets: [8.8.8.8]。用 dnsprobedurationseconds 画延迟图,probe_success 画可用性。如何区分 DNS 服务故障和网络故障?同时监控 ICMP ping 延迟和 DNS 解析延迟。ping 正常但 DNS 超时=DNS 服务问题。ping 也超时=网络问题。多节点探测可定位故障范围。缓存命中率怎么监控?CoreDNS 暴露 corednscachehitstotal 和 corednscachemissestotal,命中率 = hits/(hits+misses)。命中率低说明穿透到上游太多,考虑增大缓存或调 TTL。DNS 监控的告警阈值怎么设?可用性 100ms 告警(正常内网 < 10ms,公网 < 50ms)。NXDOMAIN 比例突增告警。按实际基线调整。如何监控 DNS 劫持?对比多个 DNS 服务器对同一域名的解析结果,不一致则可能被劫持。用 DNSSEC 验证签名。监控 NXDOMAIN 比例突增。
服务端阅读 05月29日 22:48

DNS 在微服务架构中怎么做服务发现?

DNS 服务发现就是用域名代替硬编码 IP:服务 A 调用 service-b.namespace.svc.cluster.local,DNS 返回 service-b 的 IP。Kubernetes 内置 CoreDNS 实现了这套机制——每个 Service 自动注册 DNS 记录。优点:零代码改造、语言无关、兼容现有 HTTP 客户端。缺点:DNS 缓存导致服务上下线有延迟(默认 TTL 30s)、无法做健康检查和负载均衡策略定制。追问DNS 服务发现和 Consul/Nacos 有什么区别?DNS 发现只做域名→IP 映射,无健康检查、无权重路由、无配置中心。Consul/Nacos 是专用服务发现:实时健康检查、权重负载均衡、灰度发布、配置热更新。K8s 中小规模用 DNS 足够,大规模+精细化流量管理用 Istio/Consul。DNS 缓存导致服务下线延迟怎么办?缩短 TTL(K8s CoreDNS 默认 5s)+ 客户端缩短 DNS 缓存时间。根本方案:配合 K8s 就绪探针,Pod 先标记 NotReady 再优雅关闭。Headless Service 和普通 Service 有什么区别?普通 Service 分配 ClusterIP,DNS 返回 VIP。Headless Service 不分配 VIP,DNS 直接返回所有 Pod IP——客户端自己做负载均衡。适合 StatefulSet 场景。跨命名空间的服务发现怎么写?service-b.other-namespace.svc.cluster.local,完整 FQDN 指定命名空间。同命名空间可简写 service-b。DNS 服务发现能做金丝雀发布吗?单独用 DNS 不行——DNS 只能返回一组 IP,无法按比例分配流量。需要 Istio VirtualService 或 Deployment 配合 label selector 切换版本。
服务端阅读 05月29日 22:48

cURL 如何发送和接收 JSON 数据?

发送 JSON:curl -X POST URL -H "Content-Type: application/json" -d '{"key":"value"}'。必须加 Content-Type 头,否则服务器按 form-data 解析。单引号包裹 JSON 防 shell 解析双引号。接收 JSON:curl -s URL | jq . 格式化输出,或 jq .field 提取字段。从文件发送:-d @data.json。追问单引号里怎么写单引号?Shell 中单引号不能嵌套。方案:把 JSON 写进文件用 -d @body.json(最推荐);混引号;或用双引号+转义。jq 常用操作有哪些?格式化:jq .;提取字段:jq .name;数组过滤:jq '.[] | select(.status=="active")';计数:jq length;构造新对象:jq '{name: .user}';jq -e 让 false/null 返回 exit code 1。如何验证 JSON 响应是否符合预期?curl -s URL | jq -e '.status==200 and .data.id != null'——条件为 true 输出 true 且 exit 0,为 false 输出 false 且 exit 1。更复杂的验证用 JSON Schema:ajv validate -s schema.json。PATCH 请求发 JSON 局部更新怎么写?curl -X PATCH URL -H "Content-Type: application/json" -d '{"name":"new name"}'。只传要改的字段。需确认 API 支持PATCH 语义——有些 API 的 PATCH 实际是 PUT 行为。如何发送 JSON 数组?curl -X POST URL -H "Content-Type: application/json" -d '{"items":[{"id":1},{"id":2}]}'。批量操作 API 常用这种格式。
服务端阅读 05月29日 22:48

cURL -X 参数什么作用?PUT/DELETE/PATCH 怎么用?

-X 指定 HTTP 方法,默认 GET。-X POST/PUT/DELETE/PATCH 分别发送对应请求。POST 提交数据用 -d;PUT 全量更新用 -X PUT -d data;DELETE 删资源用 -X DELETE;PATCH 局部更新用 -X PATCH -d partial_data。注意:-d 默认就是 POST,-X POST 可省略。但 PUT/DELETE/PATCH 必须显式指定 -X。追问-X POST 和 -d 有什么区别?-d 发送 POST body 数据,自动设 Content-Type: application/x-www-form-urlencoded。只有 -d 没有 -X 时 cURL 自动用 POST。-X POST 只改方法不改 body,需配合 -d。怎么发 JSON 格式的请求?加 -H "Content-Type: application/json" -d '{"key":"value"}'。不加 Content-Type 服务器可能按 form-data 解析。单引号包裹 JSON 防 shell 解析双引号。PUT 和 PATCH 实际区别?PUT 全量替换——传整个对象,没传的字段被清空。PATCH 局部更新——只传要改的字段。API 设计规范遵循这个语义。DELETE 请求能带 body 吗?技术上可以但 RFC 不推荐。需要带条件的删除用 URL 参数:DELETE /api/users/123?force=true。幂等性是什么?多次调用结果一样。GET/PUT/DELETE 幂等,POST/PATCH 非幂等。PUT 幂等因为每次全量覆盖到同一状态。
服务端阅读 05月29日 22:48

cURL 如何处理 HTTPS 和 SSL/TLS 证书验证?

默认 cURL 验证 SSL 证书(CA 证书+域名匹配+有效期),验证失败报 SSL certificate problem。跳过验证:-k 或 --insecure(仅测试用,生产禁用)。指定 CA 证书:--cacert /path/to/ca.pem。客户端证书(mTLS):--cert client.pem --key client.key。指定 TLS 版本:--tlsv1.2 或 --tlsv1.3。查看证书信息:curl -vI URL 2>&1 | grep SSL。追问为什么 -k 不安全?-k 跳过证书验证 = 不验证服务器身份,中间人可以伪造任何 HTTPS 站点。你在 -k 模式下输入的密码/Token 全部暴露。仅用于测试环境和自签名证书。自签名证书怎么正确处理?把自签名 CA 导入系统信任库,或用 --cacert 指定自签名 CA 文件。这样 cURL 正常验证而不需要 -k。mTLS 是什么场景?双向 TLS:服务器验证客户端证书+客户端验证服务器证书。企业 API 网关、K8s apiserver、零信任网络常用。如何查看证书链和过期时间?curl -vI URL 2>&1 | grep -E "subject:|expire:|issuer:"。或用 openssl s_client。TLS 1.2 和 1.3 有什么区别?1.3 握手从 2-RTT 降到 1-RTT,移除了不安全的密码套件,强制前向保密。cURL 7.54+ 支持 TLS 1.3。
服务端阅读 05月29日 22:48

DNS 解析失败怎么排查和解决?

四步排查:1.确认是否 DNS 问题——ping IP 能通但 ping 域名不行 = DNS 问题;2.定位故障环节——dig +trace 逐级查询看卡在哪一级;3.检查本地——resolv.conf 配置、本地 DNS 缓存、hosts 文件覆盖;4.检查网络——防火墙是否封 UDP 53。常见原因:DNS 服务器宕机、TTL 过期记录被删、CNAME 指向不存在的域名、防火墙拦截。追问dig 和 nslookup 有什么区别?dig 输出详细(TTL、权威服务器、耗时),支持 +trace 逐级追踪。nslookup 交互式,输出简洁但信息少。排查问题优先 dig。NXDOMAIN 和 SERVFAIL 有什么区别?NXDOMAIN = 域名不存在(权威服务器明确说没有),SERVFAIL = 服务器故障(超时/拒绝/DNSSEC 验证失败)。前者是正常响应,后者需要排查。DNSSEC 验证失败怎么办?检查 DS 记录是否正确发布、DNSKEY 是否轮换但 DS 未更新、系统时间是否正确。临时绕过:dig +nodnssec,不推荐生产环境。内网 DNS 解析失败但公网正常?检查内网 DNS 是否配了 forwarders、内网 zone 文件是否正确加载、是否有 Split DNS 配置不一致。常见坑:忘了配反向解析 PTR。移动端 DNS 解析失败怎么排查?切换 WiFi/蜂窝确认是否特定网络问题。运营商 DNS 劫持/过滤很常见,换 8.8.8.8 或 1.1.1.1 排除运营商问题。
服务端阅读 05月29日 22:48

Service Worker 的生命周期有哪些阶段?

四个阶段:注册(register)→ 安装(install)→ 等待(waiting)→ 激活(activate)→ 运行中。register 触发下载 SW 文件,install 事件中预缓存资源,install 成功后进入 waiting 等待旧 SW 退出,activate 时清理旧缓存。跳过等待:skipWaiting() 让新 SW 立即激活,clients.claim() 立即接管页面。默认不跳过——已打开的页面继续用旧 SW 直到关闭。追问为什么要有 waiting 阶段?安全考虑。已打开的页面可能依赖旧 SW 的缓存结构,强制切换可能导致缓存未命中白屏。waiting 确保所有旧页面关闭后才切换。skipWaiting 什么时候该用?紧急修复(如缓存 bug 导致白屏)时用。常规更新不建议——如果新 SW 的缓存 key 和旧的不同,skipWaiting 后页面可能加载失败。SW 什么时候会被销毁?空闲约 30 秒后浏览器自动终止 SW 线程节省内存。下次 fetch/push/sync 事件再唤醒。所以 SW 里不要用全局变量存状态——唤醒后变量重置。持久状态存 IndexedDB。页面关闭后 SW 还活着吗?可能活着(有 push/sync 事件时),也可能被终止。不能假设 SW 常驻。注册失败怎么排查?检查:SW 文件路径是否正确、是否在 HTTPS 下(localhost 例外)、SW 文件是否有语法错误、scope 是否覆盖目标页面。DevTools Application > Service Workers 面板会显示错误。
服务端阅读 05月29日 22:48

cURL 支持哪些协议?FTP/SFTP 怎么用?

cURL 支持 20+ 协议:HTTP/HTTPS/FTP/SFTP/SCP/SMTP/IMAP/LDAP/RTSP 等。FTP 上传:curl -T local.txt ftp://server/remote.txt --user user:pass。SFTP 下载:curl sftp://server/file.txt --user user:pass -o local.txt,用 --key ~/.ssh/id_rsa 指定私钥。SFTP 比 FTP 安全,FTP 明文传输密码不推荐生产使用。追问FTP 和 SFTP 有什么区别?FTP 明文传输(密码和数据都裸奔),端口 21+20。SFTP 基于 SSH 加密,端口 22。FTPS 是 FTP+TLS。新项目一律用 SFTP。如何断点续传?下载续传:curl -C - -O URL(自动检测断点)。上传续传:curl -C - -T file ftp://server/。HTTP 不支持续传上传。如何列 FTP 目录?curl ftp://server/path/ --user user:pass(尾部斜杠表示列目录)。加 -l 只列文件名。cURL 和 scp 命令的区别?scp 语法简单(scp file user@host:path),cURL 支持多协议和断点续传。scp 更直观,cURL 更灵活。如何批量上传文件?用 glob:curl -T "file[01-99].txt" ftp://server/dir/。或 shell 循环。大文件加 --limit-rate 1M 限速。
服务端阅读 05月29日 22:48

cURL 如何处理 HTTP 认证?Basic Auth/Bearer/OAuth 怎么用?

三种认证:Basic Auth——curl -u user:pass URL(密码明文 base64 编码必须配合 HTTPS);Bearer Token——curl -H "Authorization: Bearer TOKEN" URL;OAuth 2.0——先 curl token 端点拿 access_token,再带 token 请求 API。cURL 无内置 OAuth 流程,需手动实现 token 获取和刷新。追问-u 和 -H Authorization 有什么区别?-u user:pass 自动生成 Authorization: Basic 头,更简洁。-H 手动写原始头,适合精确控制。安全做法:用环境变量 -u user:$API_KEY 避免密码出现在 shell history。Bearer Token 过期了怎么刷新?脚本模式:先 curl refreshtoken 端点拿新 accesstoken,替换环境变量,再请求 API。生产建议用 SDK 自动刷新。OAuth 2.0 授权码流程怎么用 cURL 实现?分三步:1.浏览器访问授权 URL 手动授权拿 code;2.curl -X POST token-url 换 token;3.curl -H "Authorization: Bearer TOKEN" 请求资源。第 1 步必须浏览器完成。API Key 和 Bearer Token 有什么区别?API Key 是静态字符串,不过期除非手动轮换。Bearer Token 有过期时间,由 OAuth 签发,可精细控制权限范围(scope)。API Key 适合服务间调用,Bearer Token 适合用户级授权。.netrc 文件有什么用?存储登录凭证:machine api.example.com login user password pass。cURL 加 -n 自动读取,不用 -u 传密码。chmod 600 保护文件权限。
服务端阅读 05月29日 22:48

DNS 服务器有哪些类型?各自什么作用?

四类:递归解析器(Resolver)——用户端入口,代替客户端从根到权威逐级查询,8.8.8.8/1.1.1.1 就是这类;根域名服务器——13 组,返回 TLD 服务器地址;TLD 服务器——管理 .com/.org/.cn 等顶级域,返回权威服务器地址;权威服务器——存储域名最终记录(A/CNAME/MX 等),由域名所有者配置。查询链路:Resolver → 根 → TLD → 权威,每级缓存减少重复查询。追问13 组根服务器够用吗?13 是早期 UDP 包大小限制的结果。实际远不止 13 台——用 Anycast 技术,每组根有数百个实例分布全球。递归解析器会缓存多久?按记录的 TTL 决定。但解析器可以自行调整最低 TTL(如 BIND 默认 5 分钟),防止频繁回源。权威服务器和解析器可以是同一台吗?技术上可以(BIND 同时支持),生产环境不推荐。混合部署互相影响性能和安全。为什么不直接问权威服务器?你需要知道问哪个权威服务器——这就是根和 TLD 的作用:告诉你下一步问谁。DoH 和传统 DNS 有什么区别?传统 DNS 明文传输(UDP 53),可被监听和篡改。DoH 用 HTTPS(443)加密查询,防止中间人。代价是延迟略高。Chrome/Firefox 默认对部分用户开启。
服务端阅读 05月29日 22:48

Service Worker 如何实现离线访问?

SW 拦截 fetch 请求,命中缓存直接返回,未命中则网络请求并缓存响应。三种策略:Cache First(优先缓存,适合静态资源)、Network First(优先网络,适合 API)、Stale-While-Revalidate(返回缓存同时后台更新)。注册 SW 后监听 install 事件预缓存核心文件,fetch 事件中根据策略匹配缓存。追问首次访问能离线吗?不能。SW 注册后首次 install 才缓存资源,首次访问本身还没 SW。解决方案:用 App Shell 模式预缓存核心 HTML/CSS/JS,首次加载完成后后续访问即可离线。哪些资源适合 Cache First?带 hash 的静态资源(/static/app.3a2b.js)、字体、图片——内容不变可以长期缓存。API 响应用 Network First,避免数据过期。离线时表单提交怎么办?存入 IndexedDB 队列,监听 online 事件或用 Background Sync API 在网络恢复后自动重放。Workbox 的 workbox-background-sync 封装了这个逻辑。缓存版本怎么管理?cacheName 带版本号:my-app-v1→v2。activate 事件中遍历 caches.keys(),删除旧版本缓存。PWA 离线和原生 App 离线体验差距大吗?核心差距在后台任务:原生 App 可后台同步/推送,PWA 的 Background Sync 和 Push API 支持度有限(iOS Safari 部分支持)。但基本离线浏览、表单暂存体验已经很接近。
服务端阅读 05月29日 22:48

cURL 如何处理 Cookie 和会话管理?

发送 Cookie:-b "name=value" 发单个,-b cookies.txt 从文件读。保存 Cookie:-c cookies.txt 把响应 Set-Cookie 写入文件。同时发送和保存:-b cookies.txt -c cookies.txt(同一文件读写维持会话)。会话管理就是循环请求时每次 -b -c 同一个 cookie 文件,服务器通过 session_id 识别用户。追问-b 和 -H Cookie 有什么区别?-b "key=val" 自动生成 Cookie 头,更简洁。-H "Cookie: key=val" 手动写原始头,适合精确控制。多个 Cookie:-b "a=1" -b "b=2" 或 -H "Cookie: a=1; b=2"。Cookie 文件格式是什么?Netscape 格式:每行 tab 分隔 7 个字段——domain\tflag\tpath\tsecure\texpiration\tname\tvalue。由 -c 自动生成。如何模拟登录后访问受保护页面?curl -c cookies.txt -X POST login-url -d user=xxx -d pass=xxx,然后 curl -b cookies.txt protected-url。JWT 认证则不同——登录响应里的 token 需手动提取放到 Authorization 头。Cookie 和 Session 有什么区别?Cookie 存客户端,Session 存服务器端。Cookie 里的 session_id 是钥匙,服务器用这把钥匙找 Session 数据。cURL 模拟的是 Cookie 传输层。如何调试 Cookie 问题?加 -v 查看 Cookie 和 Set-Cookie:curl -v -b cookies.txt URL 2>&1 | grep -i cookie。常见问题:Domain/Path 不匹配、Secure 标记在 HTTP 下不发送、SameSite 跨站不携带。
服务端阅读 05月29日 22:48

DNS 为什么用 UDP 又用 TCP?各自什么场景?

标准查询用 UDP 53(快、无连接、适合小报文),区域传送(zone transfer)和超过 512 字节的响应用 TCP 53(可靠、支持大报文)。EDNS0 扩展后 UDP 响应可达 4096 字节,超过仍切 TCP。UDP 无需握手一个包搞定查询延迟最低;TCP 需要三次握手,适合需要可靠传输的场景。追问为什么不全部用 TCP?TCP 三次握手增加延迟——DNS 查询通常一个 UDP 包就够,用 TCP 慢 2-3 倍。DNS 查询量巨大,TCP 的连接开销对 DNS 服务器是灾难。UDP 丢包了怎么办?客户端设超时重试(2-5 秒),换个解析器再查。DNS 设计上幂等——重复查询结果一样,丢包重试即可。什么情况响应会超过 512 字节?大量 CNAME 链、DNSSEC 签名记录(很大)、大量 MX 记录。DNSSEC 几乎总是触发 TCP fallback。区域传送为什么必须 TCP?区域传送同步整个 zone 数据可能几百 KB,必须可靠完整。TCP 的有序可靠传输正好满足。DoH/DoT 对 UDP/TCP 的影响?DoH 和 DoT 都用 TCP/TLS 加密。HTTP/3 用 QUIC(基于 UDP),又回到 UDP 但加了加密和可靠传输。传统 DNS 用 UDP 求快,安全场景用 TCP 加密求稳。
服务端阅读 05月29日 22:48

cURL 如何处理大文件下载和断点续传?

断点续传:curl -C - -O URL(-C - 自动检测已下载部分继续)。原理:cURL 发 Range 头请求剩余部分,服务器返回 206 Partial Content。首次下载中断后重新执行同一命令即可续传。大文件优化:--limit-rate 2M 限速、--max-time 3600 超时保护、-# 显示进度条。前提:服务器必须支持 Range 头。追问怎么判断服务器是否支持断点续传?curl -I URL 看响应头:Accept-Ranges: bytes 表示支持,没有则不支持。下载中断后文件名不对怎么办?-O 用 URL 最后一段作为文件名,重定向后可能不对。用 -o 指定文件名,或 -L 跟随重定向后再用 -O。如何并行下载大文件?cURL 本身不支持分段并行下载。用 aria2c -x 16 -s 16 URL(16 连接并行)。或手动分段 curl -r 并合并。下载到一半磁盘满了怎么办?cURL 不会自动清理部分文件。脚本中 df -h 检查磁盘空间,超过 90% 停止下载并告警。大文件场景用 --max-filesize 限制大小。如何验证下载文件完整性?curl URL -o file && shasum -a 256 -c checksum.txt。或 curl URL | sha256sum 对比预期哈希。