Skip to content

2026-05-11 学习日志

知识点

  • [K8s/GPU] qGPU 资源泄漏排查:nvidia-smi 空闲但调度器报 0/2 nodes available,根因是 qGPU-device-plugin 元数据残留,重启 qgpu-manager/kubelet 或清理 device-plugin checkpoint 可解 → 详见 /topics/k8s/gpu/
  • [DRMS] pdfmake 卡顿的真凶不是 pdfmake 渲染慢,而是 0.3.xpdfDoc.getBlob() 从 callback 改成 Promise,老代码 callback 被静默忽略 → worker 里 postMessage 永远不触发 → 表现为"一直在生成中" → 详见 /topics/projects/drms/
  • [前端/性能] "卡住" ≠ "慢":Promise 没 resolve 和 CPU 烧 10s 看上去一样,但修复方向完全不同;换方案前一定先把根因刨到底 → 详见 /topics/frontend/performance/
  • [代码评审] AI CR(TAPD 上的自动评审)这次直接指出「pdfDoc.getBlob().then(...) 的 Promise 链未添加 catch 处理」,顺着这条才发现原代码.then 都没有——AI CR 在发现 Promise 类问题上确实更敏锐

问题与解决

  • 问题 1: qGPU Pod 调度失败,nvidia-smi 显示 GPU 空闲但 K8s 报资源不足
  • 真因 1: qGPU-device-plugin 元数据泄漏,整卡 Pod 删除后资源未释放
  • 修复 1: kubectl rollout restart daemonset -n qgpu / 重启 kubelet / 手动清理 /var/lib/kubelet/device-plugins/kubelet_internal_checkpoint
  • 问题 2: 之前一直把"PDF 导出卡 10s+"归因为 pdfmake 性能差,为此花了 2 天做 puppeteer 方案替换
  • 真因 2: pdfmake@0.3.6getBlob 签名从 (callback) => void 变成 () => Promise<Blob>,老代码里写的 callback 既不会被调用也不会报错,返回的 Promise 没人 .then(),worker 里紧跟的 postMessage 永远不触发
  • 修复 2: 改成 .getBlob().then(...).catch(...) 的 Promise 链

问题与解决

  • 问题: 之前一直把"PDF 导出卡 10s+"归因为 pdfmake 性能差,为此花了 2 天做 puppeteer 方案替换
  • 真因: pdfmake@0.3.6getBlob 签名从 (callback: (b: Blob) => void) => void 变成 () => Promise<Blob>,老代码里写的 pdfDoc.getBlob((blob) => {...}) 中那个 callback 既不会被调用也不会报错(pdfmake 接到多余参数就丢),返回的 Promise 没人 .then(),所以 worker 里紧跟的 postMessage({ type: 'data' }) / postMessage({ type: 'end' }) 永远不触发
  • 修复:
    ts
    pdfDoc
      .getBlob()
      .then((blob) => {
        postMessage({ type: 'data', data: { blob, filename } });
        postMessage({ type: 'end' });
      })
      .catch((error) => {
        console.error('[worker] Error generating PDF blob:', error);
        postMessage({ type: 'error', message: error?.message });
        postMessage({ type: 'end' });
      });
  • 反思: 之前沉淀过的知识点里没能帮我排出这个根因——下次升级第三方库时应该有显式清单:「是否动过这个库的版本?」「新版 API 签名变了吗?」「所有调用点都切了吗?」

今日总结

今天最大的教训是:在换技术方案之前,先确认当前方案的根因问题到底是什么。花了 2 天搭 puppeteer + 浏览器单例 + 并发队列,结果原方案只是 getBlob API 升级后没切调用风格,加个 .then 就好。

puppeteer 方案本身的价值仍在(真 PDF、视觉一致、文本可检索),但它从"刚性替代"降级为"可选增强",作为新旧共存的第二入口留给视觉一致性要求高的场景用。线上的 pdfmake 入口补上 .then + .catch 就能解决 95% 用户的卡顿投诉。

pdfmake 这类有 callback → Promise 演进史的老库,升级时最坑的不是报错,而是 callback 被静默丢掉,类型检查如果没跟上就一路溜到生产。以后类似场景(pdfmake / jspdf / html2canvas / docx)的升级要强制走一遍"所有调用点签名对齐"的检查。

持续学习,每天进步 🚀