本地能跑,上线就崩:文件预览服务的五个隐蔽坑与排障实录
本期敖行客研发实战日记邀请传奇后端人物——GGB,分享文件预览服务上线踩过的一堆阴间大坑完整复盘生产环境 5 个藏到离谱的疑难 bug 排坑全过程。解决本地跑丝滑、一部署上线直接原地翻车的诡异问题深挖病根同时附上落地解法。帮各位后端同行躲开中间件、容器部署里防不胜防的隐形坑以后再遇上玄学报错也能从容上手排查告别排查 bug 熬秃脑袋的日子GGB 江湖人称“后端补刀位”。常年与服务端、容器和各种诡异 bug 为伍信奉“日志不会骗人骗人的是写日志的人”。最大的爱好是把别人眼里的“玄学问题”一层层扒到根因再用最少的改动把它摁死。找不到他的时候他大概率正盯着一段堆栈发呆.......文件预览服务基于开源的 kkFileView就是把 Office、PDF、图片、代码等各种格式在浏览器里直接预览。听起来是“拿来即用”真正接入生产后才发现坑一个接一个而且大多在网上搜不到现成答案。下面按踩坑顺序复盘。一、最隐蔽的坑多副本部署下“第一次打开必 404第二次就好了”现象很妖同一个文件、同一个地址第一次预览报 404过几分钟再点就正常。后台日志却明明白白写着“转换成功”而且只花了几百毫秒。排查了一圈编码、缓存、前端时序最后靠时间戳锁定真相——404 返回的时间正好是转换完成时间往后推 120 秒等待超时。也就是说文件确实转出来了但请求它的那个进程一直没找到。真相服务是 K8s 多副本部署转换后的 PDF 只落在“产生它的那个 Pod”的本地磁盘上。负载均衡把预览请求发给 Pod A 完成转换下一个取文件的请求却被转发到 Pod BPod B 本地根本没有这个文件于是 404。为什么第二次就好了 纯属运气负载均衡又把我扔回A了经验凡是“先转换、再按 URL 取产物”的服务多副本部署必须用共享存储NFS/NAS挂载产物目录否则本地磁盘 内存状态天然不一致本地单实例永远复现不出来最容易被忽略。二、本地能跑、上线就崩环境差异集中爆发#1. office.home 配置LibreOffice 的安装路径本地是 Windows 的 C:/Program Files/LibreOffice服务器容器里是 /usr/lib/libreoffice。代码里如果写死了路径上线直接找不到。办法用环境变量占位符 ${KK_OFFICE_HOME:默认值} 兼容两端有环境变量用环境变量没有用默认值一份配置两边通用。#2. 编译打包的 JDK 版本项目要求 Java 21但 maven-compiler-plugin 的 release21 参数在旧版 Maven 上会触发“不支持发行版本 21”的假报错错误信息还被 fork 模式藏起来。去掉 release、改用 source/target 后顺利打包。一句话报错信息看不全时先想办法把它逼出来别盲改。三、带批注的 Word 一转就崩带批注comments的 docx 转 PDF 时容器里的 LibreOffice 直接 abort 崩溃Signal 6堆栈指向构建批注 UI 部件时找不到资源。本地完整版 LibreOffice 没问题容器里的精简版缺了 UI 资源文件。一度以为关掉“导出批注”就行结果没用——只要文档带批注LibreOffice打开时就要构建那个UI部件跟导不导出无关。最终结论是治本要在容器里补装完整的 LibreOffice 中文字体。经验第三方组件的崩溃先分清是“调用方用法”问题还是“组件自身安装不完整”问题方向错了白费力气。四、Excel 预览中文全乱码变天书xlsx 转成 HTML 后中文全变成“项目列表”这种乱码。典型的 UTF-8 被当成别的编码处理。根因藏得很深代码用了一个“自动嗅探编码”的工具去读 LibreOffice 转出的 HTML这个工具自作聪明结果把本来是 UTF-8 的文件误判成了 Latin1用错编码读进内存就把中文读坏了再写回文件乱码就永久固化了——文件头声明的还是 utf-8所以浏览器也救不回来。改法不再瞎猜直接读取文件头里自己声明的字符集LibreOffice 明确写了 charsetutf-8按它正确读取。经验编码问题要分清是“读的时候坏的”还是“显示的时候坏的”两者修法完全不同靠看一眼乱码字节就能判断。五、自己挖的坑拦截器误伤静态资源为了解决转换时序问题我加了个拦截器请求图片/PDF 时如果文件还没转好就等待。但它把 xlsx 预览页的 CSS 图标、PPT 懒加载图片这些资源本来就是先请求不存在就404前端会自动重试的设计。拦截器把它们也拦下来死等 120 秒把样式搞坏了。修正拦截器只在“文件确实正在转换中”时才等待其他情况一律放行、自己绝不返回 404交给后续处理器决定。经验给系统加“等待/重试”这类兜底逻辑时一定要想清楚边界否则兜底反而成了新的故障源。六、小结环境差异是生产事故的最大来源本地能跑不代表线上能跑编码、路径、组件完整性、部署副本数每一项都可能翻车。排查靠证据不靠猜时间戳、堆栈、乱码字节这些都是能直接指向根因的硬线索。改动要最小、要治本能一行配置解决的不动代码能定位根因的不打补丁。至此文件预览服务的几个核心问题已逐一解决预览体验从“时好时坏”变成稳定可用。复杂系统没有银弹能做的就是把每个坑都扒到底、记下来下次少踩一个。