Laravel生产环境无法删除/覆盖文件,疑与Octane缓存相关?
问题描述
本地环境中,文件的存储与删除操作均正常。
if ($subchan->styles_path != null) { Storage::disk('public')->delete($filePath.'/'.$filename); } Storage::disk('public')->put($filePath.'/'.$filename, $text);
其中put和delete功能都正常,甚至无需执行delete,因为put会直接覆盖旧文件。
但在生产环境中,仅能完成文件上传操作,无法删除文件,也无法通过上传新文件覆盖旧文件,始终停留在首次上传的文件。错误日志中无任何报错信息。
编辑补充:这可能是我遇到过的最诡异的生产环境Bug,似乎文件被缓存了:文件实际已被替换,但变更需数小时后才会显示。我使用了Laravel Octane,这会是问题的诱因吗?
问题分析与解决方案
结合你提到的Laravel Octane和文件延迟更新的现象,这大概率是Octane的进程缓存或者文件系统/CDN缓存导致的,具体原因和解决办法如下:
1. Laravel Octane常驻进程的缓存问题
Octane依赖Swoole、RoadRunner这类常驻进程提升性能,进程启动后加载的配置、文件状态等会被缓存,不会随请求实时刷新。如果你的文件操作依赖的动态配置(比如$subchan->styles_path)被缓存到进程全局变量,或者Octane缓存了文件系统的状态,就会出现实际文件已更新,但应用读取旧内容的情况。
解决办法:
- 动态配置(如渠道的存储路径)不要缓存到进程全局变量,每次请求时实时从数据库或配置文件中获取
- 若有文件内容缓存,更新文件后主动调用
Cache::forget()清除对应缓存键 - 定期重启Octane进程,比如部署更新时强制重启,或通过定时任务每日重启一次,避免进程长时间运行导致缓存堆积
2. 存储磁盘/CDN的缓存策略
如果public磁盘使用云存储(如AWS S3、阿里云OSS)或开启了CDN加速,这些服务默认会缓存文件内容,即使服务器端文件已更新,CDN节点的缓存未过期时,用户看到的还是旧文件。
解决办法:
- 检查云存储/CDN的缓存规则,缩短文件缓存过期时间,或在文件更新后调用对应API清除该文件的CDN缓存
- 本地文件系统的话,检查是否开启了OS层面的文件缓存,或OPcache等PHP缓存,确保文件变更能被实时感知
3. Laravel Storage门面的实例缓存
在常驻进程环境下,Storage门面可能会缓存磁盘实例或文件状态,导致后续操作读取旧状态。
解决办法:
- 避免复用Storage磁盘实例,每次文件操作都通过
Storage::disk('public')重新获取实例,不要把实例缓存到全局变量中 - 部分存储驱动支持清除内部缓存,可在文件更新后尝试调用
Storage::disk('public')->forget($filePath.'/'.$filename)
内容的提问来源于stack exchange,提问作者Felix
相关产品推荐
相关产品推荐

