CarrierWave上传大文件至Google Cloud Bucket超时失败排查
问题根因
你配置的超时参数完全没有生效:
config.fog_attributes哈希里的参数会作为对象元数据传给Google Cloud Storage,不会被底层HTTP客户端(HTTPClient、Google::Apis客户端)读取,你设置的open_timeout_sec/send_timeout_sec/read_timeout_sec放在这里属于无效配置,客户端一直使用默认的超时阈值,大文件上传传输时间超过默认值就会抛出HTTPClient::SendTimeoutError和Google::Apis::TransmissionError。- 配置存在遗漏:缺少大文件分片上传配置、远程文件下载超时配置、客户端重试策略配置,单纯拉长超时时间无法解决大文件上传过程中的网络波动问题。
修复方案
1. 调整超时参数位置
将HTTP客户端相关的超时参数移到config.fog_credentials层级,这是fog-google读取客户端配置的正确位置。
2. 开启大文件分片(可恢复)上传
配置分片上传阈值,超过指定大小的文件自动走resumable分片上传,单块分片传输失败只需要重传对应分片,不需要重传整个文件,大幅降低超时概率。
3. 补充远程文件下载超时配置
如果使用remote_url拉取远程文件再上传,需要单独配置CarrierWave下载器的超时时间,这个配置默认不继承fog的超时参数。
4. 配置合理重试策略
给Google API客户端开启自动重试,遇到网络超时、5xx错误时自动重试,避免偶发网络问题直接导致上传失败。
修正后的完整配置代码如下:
begin CarrierWave.configure do |config| config.fog_provider = 'fog/google' config.fog_credentials = { provider: 'Google', google_project: '{project name}', google_json_key_location: '{My json key-file location}', # 客户端超时参数统一放在credentials层级,单位为秒 open_timeout_sec: 300, send_timeout_sec: 300, read_timeout_sec: 300, # 开启分片上传,超过100MiB的文件自动走可恢复分片上传 google_storage_resumable: true, resumable_threshold: 100 * 1024 * 1024 } config.fog_directory = 'test-bucket' # 签名URL过期时间,单位秒,不需要放在fog_attributes里 config.fog_authenticated_url_expiration = 600 # 配置remote_url下载远程文件的超时时间,单位秒 config.downloader_timeout = 600 # 配置Google API客户端重试策略 Google::Apis::RequestOptions.default.retries = 3 Google::Apis::RequestOptions.default.max_elapsed_time = 900 Google::Apis::RequestOptions.default.retry_interval = 2 end rescue => error puts error.message end
注意事项
- 不需要把超时时间设置到600000秒(约166小时),常规网络环境下单块分片传输300秒超时完全足够,超时时间设置过长会导致网络异常时进程长时间挂死无响应。
- 如果服务器本身到GCS的网络带宽较低,可以适当调小分片大小(比如设为20MiB),降低单块传输的耗时。
- 不要把业务相关配置(比如签名URL过期时间)和HTTP客户端配置混放在
fog_attributes里,fog_attributes仅用于设置GCS对象的自定义元数据、存储类型、缓存规则这类和存储对象本身相关的属性。
内容的提问来源于stack exchange,提问作者sagar verma
相关产品推荐
相关产品推荐

