Kubernetes环境下Windshaft-CartoDB从Millstone缓存获取SVG时出现ENOENT错误
看起来你遇到的是Windshaft-CartoDB在K8s多副本场景下,重启后首次请求触发的Millstone缓存文件重命名失败问题,这个情况我之前帮人排查过类似的,大概率和缓存目录的隔离性或者并发竞争有关,给你几个具体的排查和解决方向:
1. 检查Pod的临时目录隔离性
K8s里每个Pod都有独立的/tmp目录,不过如果你为了让多副本共享缓存,挂载了同一个PVC(持久化存储卷)到/tmp/millstone/cache,就会出现多个Pod同时读写缓存文件的竞争问题——比如Pod A正在下载文件到xxx.download,还没完成重命名,Pod B就去操作同一个文件,或者Pod A的重命名操作被Pod B的文件操作干扰,直接导致重命名失败抛出ENOENT。
如果是这种情况,你可以这么处理:
- 取消缓存目录的共享挂载,让每个Pod使用自己的本地临时目录,虽然会失去跨Pod的缓存共享,但能彻底避免竞争问题;
- 要是必须共享缓存,给每个Pod的缓存目录加独立的前缀,比如基于Pod的名称或ID,修改Millstone的缓存路径配置,让不同Pod的缓存文件互不干扰。
2. 确保缓存目录在Pod启动时已初始化
有时候Pod重启后,/tmp/millstone/cache目录可能没有被自动创建,Millstone在下载文件时尝试创建临时文件但找不到目录,也会触发类似的错误。你可以在Pod的启动命令里加一步初始化操作:
mkdir -p /tmp/millstone/cache && chmod 777 /tmp/millstone/cache
把这个命令加到Windshaft容器的启动脚本最前面,确保目录存在且有足够的读写权限。
3. 调整Millstone的缓存并发控制
Millstone本身的缓存机制在高并发场景下可能存在竞态条件,尤其是在Pod刚启动、大量请求涌入的时候,多个请求同时尝试下载同一个SVG文件,导致重命名操作冲突。你可以试试:
- 调整Windshaft的请求限流配置,在Pod启动初期限制并发请求数,避免同时触发大量缓存下载操作;
- 查看Millstone的版本,是否有已知的缓存竞态bug,如果是旧版本,升级到最新的稳定版,可能已经修复了这类文件操作的并发问题。
4. 临时规避:预热缓存
如果重启后首次请求必现这个错误,你可以在Pod启动完成后,自动发起一个预热请求,触发缓存文件的创建,这样后续的用户请求就不会踩坑了。比如在启动脚本最后加一个curl请求,调用Windshaft的某个接口生成需要的SVG缓存。
补充一句,你提到错误正好出现4次,对应你的4个Pod,这也印证了每个Pod在首次处理请求时都遇到了这个问题,进一步说明是每个Pod自身的缓存初始化或者并发处理的问题。
内容来源于stack exchange

