当前位置: 首页 > 知识库问答 >
问题:

503使用Carrierwave上传到S3时减速

敖涵容
2023-03-14

我在后台工作中使用Rails和Carrierwave将许多小文件上传到S3,并且达到了S3的速率限制。我现在的想法是在每次上传之前都放一个睡眠0.1,但这似乎不是一个很好的解决方案

关于如何通过S3API和某种类型的回退来处理这个问题,有什么建议吗?

正在进行上载的Ruby代码,此方法在循环中被调用数千次:

    def attach_audio(object:, audio_field:, attachment:)
      return true if Rails.env.test?

      language_code, voice_id = language_and_voice(object)

      resp = polly.synthesize_speech(
        output_format: 'mp3',
        voice_id: voice_id,
        text: audio_field.to_s,
        language_code: language_code
      )

      audio_filename = "#{object.class.to_s.downcase}_#{attachment}_#{object.id}_#{voice_id}.mp3"
      audio_path = "#{Rails.root}/db/audio/#{audio_filename}"
      IO.copy_stream(resp.audio_stream, audio_path)

      object.send(attachment + '=', Pathname.new(audio_path).open)
      object.save!
    end

上载程序类

class AudioUploader < BaseUploader

  def store_dir
    "uploads/audio/#{model.target_language}/#{self.class.to_s.underscore}/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
  end

  def extension_whitelist
    %w[mp3]
  end
end
class BaseUploader < CarrierWave::Uploader::Base
  if Rails.env.test?
    storage :file
  else
    storage :fog
  end

  def store_dir
    "uploads/#{self.class.to_s.underscore}/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
  end
end

AWS的回应

Message

Excon::Error::ServiceUnavailable: Expected(200) <=> Actual(503 Service Unavailable) excon.error.response :body => "<Error><Code>SlowDown</Code><Message>Please reduce your request rate.</Message><RequestId>176C22715A856A29</RequestId><HostId>L/+

Traceback

Excon::Error::ServiceUnavailable: Expected(200) <=> Actual(503 Service Unavailable)
excon.error.response
  :body          => "<Error><Code>SlowDown</Code><Message>Please reduce your request rate.</Message><RequestId>176C22715A856A29</RequestId><HostId>xxxxxxxxxxxxxxxxxxxxxxxxx</HostId></Error>"
  :cookies       => [
  ]
  :headers       => {
    "Connection"       => "close"
    "Content-Type"     => "application/xml"
    "Date"             => "Wed, 18 Nov 2020 07:31:29 GMT"
    "Server"           => "AmazonS3"
    "x-amz-id-2"       => "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
    "x-amz-request-id" => "176C22715A856A29"
  }
  :host          => "example-production.s3-eu-west-1.amazonaws.com"
  :local_address => "xxx.xx.xxx.xxx"
  :local_port    => 50276
  :path          => "/uploads/audio/fr/audio_uploader/word/audio_file/8015423/word_audio_file_8015423_Mathieu.mp3"
  :port          => 443
  :reason_phrase => "Slow Down"
  :remote_ip     => "xx.xxx.xx.x"
  :status        => 503
  :status_line   => "HTTP/1.1 503 Slow Down\r\n"

  File "/app/vendor/bundle/ruby/2.6.0/gems/excon-0.71.1/lib/excon/middlewares/expects.rb", line 13, in response_call
  File "/app/vendor/bundle/ruby/2.6.0/gems/excon-0.71.1/lib/excon/middlewares/response_parser.rb", line 12, in response_call
  File "/app/vendor/bundle/ruby/2.6.0/gems/excon-0.71.1/lib/excon/connection.rb", line 448, in response
  File "/app/vendor/bundle/ruby/2.6.0/gems/excon-0.71.1/lib/excon/connection.rb", line 279, in request
  File "/app/vendor/bundle/ruby/2.6.0/gems/fog-xml-0.1.3/lib/fog/xml/sax_parser_connection.rb", line 35, in request

etc

编辑

链接的AWS文档引用了前缀,这似乎可以解决问题

Amazon S3会自动扩展到高请求率。例如,您的应用程序可以在存储桶中的每个前缀每秒至少实现3,500个PUT/COPY/POST/DELETE或5,500个GET/HEAD请求。存储桶中的前缀数量没有限制。您可以通过并行化读取来提高读取或写入性能。例如,如果您在Amazon S3存储桶中创建10个前缀来并行化读取,您可以将读取性能扩展到每秒55,000个读取请求。

但是我不明白如何在Carrierwave的背景下实现它。

共有3个答案

林博厚
2023-03-14

根据AWS文档,前缀aka key prefix类似于一个目录名,它允许您在bucket中的同一目录下存储类似的数据。您需要找到如何对上载进行分组的方法。在您的情况下,它可能是从对象创建附加目录。id值作为名称。

边银龙
2023-03-14

如果您在没有ActiveJob的情况下使用Sidekiq,则可以使用Sidekiq限制的gem和threshold选项来减缓后台作业中的上载速度。

示例:

class UploadWorker
  include Sidekiq::Worker
  include Sidekiq::Throttled::Worker

  sidekiq_options :queue => :uploads
  sidekiq_throttle({
    # Allow maximum 1K jobs being processed within one second window.
    :threshold => { :limit => 1_000, :period => 1.second }
  })

  def perform
    # do your thing
  end
end
湛文乐
2023-03-14

从这里开始

例如,应用程序在一个bucket中的每个前缀每秒至少可以实现3500个PUT/COPY/POST/DELETE或5500个GET/HEAD请求。

你知道你的极限是什么。现在你需要理解什么是前缀,这很容易。考虑一下:

/uploads/audio/fr/audio_uploader/word/audio_file/8015423/word_audio_file_8015423_Mathieu.mp3

这里的前缀是什么?答复:

/uploads/audio/fr/audio_uploader/word/audio_file/8015423

前缀是除对象名称之外的所有内容。因此,问题的答案在于你是否有能力设计一个方案,这样你就永远不会超过亚马逊为每个前缀定义的限制。

例如,您可以使用一个旋转计数器,例如从0到99,并将要保存的对象与存储该对象的旋转计数器点之间的关系存储在某个位置[以便您以后可以读取它]。如果你要实现这一点,你的问题将减少到现在的百分之一;实际上,你可能不需要一直到100,如果你需要的话,你可以在将来增加它。现在,这个:

/uploads/audio/fr/audio_uploader/word/audio_file/8015423/word_audio_file_8015423_Mathieu.mp3

将存储在:

/上载/audio/fr/audio\u uploader/word/audio\u file/00/8015423/word\u audio\u file\u 8015423\u Mathieu。mp3

下一个在.../01/...以此类推,第100个对象存储在.../99/...然后第101个对象存储回.../00/...[你显然不必使用这两个字符]。

这个过程为您的逻辑带来的额外步骤是,出于检索目的,您需要知道word_audio_file_8015423_Mathieu.mp3在.../00/...并且,例如,word_audio_file_8015424_Mark.mp3在.../01/...等等。这意味着您必须存储对象与其保存位置之间的关系。另一方面,如果可以接受搜索所有位置以查找您想要的对象,您甚至可能不需要这样做。

我强烈认为这会解决你的问题。

 类似资料:
  • 在Michael Hartl的The Rails教程第11章的结尾,我通过创建存储桶、使用IAM设置用户并授予用户Amazon S3FullAccess策略,成功地启用了用户上传到Amazon S3服务。允许我网站上的未知用户完全访问存储桶以在我的网站上上传图像,这感觉很脏而且非常不安全,我不确定我是否应该有这种感觉。我在 http://awspolicygen.s3.amazonaws.com/

  • 问题内容: 我添加了将Base64图像与Carrierwave结合使用的解决方案,以尝试从Java类上传图像。现在这是我的FileUploader类的样子- 我认为问题出在哪里: 图片型号: 现在,当进行Post调用时,保存在数据库中的文件路径为nil,但其他所有内容均已保存。这是java / android类: 有人有什么想法吗?我整天都被困住了。我想是因为我对Ruby不太了解,所以我要么(1)

  • 问题内容: 我正在尝试使用将图片上传到亚马逊s3 ,但出现此错误: TypeError:预期opts.s3为对象node_modules / multer-s3 / index.js:69:20 这是我的服务器代码: 为什么我收到此错误? 问题答案: 完成 并正常工作的Node Cheat | 使用multer-s3上传到s3 。 码: 对于完整的回购 : 克隆node-cheat express

  • 问题内容: 尝试将文件上传到S3存储桶时遇到问题。一切正常,除了我的文件参数似乎不合适。我正在使用Amazon S3 SDK从Node.js上载到S3。 这些是我的路线设置: 这是items.upload()函数: 将param 设置为类似字符串的效果很好。根据doc,param必须获取 (缓冲区,类型数组,Blob,字符串,ReadableStream)对象数据。 但是,上传文件对象失败,并显示

  • 当用户上传图片时,我正在动态调整图像大小。原始图片存储在Amazon S3上一个名为djangobucket的bucket中。在这个桶中,包含数千个文件夹。 每个文件夹都以用户命名。我不必担心存储桶创建或文件夹创建,因为所有这些都是从客户端处理的。 下图为: 如您所见,Bob有许多图片。一旦用户将图片上传到S3,我就会通过URL通过Django下载它,在这种情况下,它将是:http://s3.am

  • 我正在尝试复制一个邮递员放置请求,其中它正在代码给出的S3位置上传csv文件。 网址就像https://us-east-1-e9qpbo283.s3.amazonaws.com/bulk-bucket/a4894e7b-7e42-4fcc-9f84-e7n00db6d581/input/file 查询参数为