ruby “法拉第::连接失败:将Tempfile上传到S3预签名URL时“管道破裂

nfzehxib  于 2023-05-28  发布在  Ruby
关注(0)|答案(1)|浏览(139)

在我的Ruby on Rails应用程序中,我需要使用Faraday Ruby gem将大型(~ 30 MB或更大)MP4视频资产上传到Amazon S3预签名URL。此操作经常失败,并出现Faraday::ConnectionFailed: Broken pipe错误。我想知道为什么会发生这种情况,以及如何解决它,因为我需要使这个操作更加可靠。
视频资产存储为Tempfile,并通过PUT请求流传输到S3预签名的URL。
这种故障不会100%发生。此操作通常在没有此失败的情况下成功,并且通常在失败引起的重试之后也将成功。如果我不得不说,失败发生在50%的时间里。
Ruby2.3.1
导轨5.0.0
法拉第0.17.3(适配器= net/http。我尝试将适配器更改为httpclient,但结果出现类似的错误HTTPClient::KeepAliveDisconnected: Broken pipe。我更喜欢使用net/http

相关编码

headers = { content_type: 'video/mp4', content_length: tempfile.size.to_s }
conn = Faraday.new(url: presigned_url)
resp = conn.put(presigned_url_path, tempfile, headers)

从在线研究中,我发现可能是超时,所以我尝试将以下块传递给conn.put请求。好像没什么用。{ |req| req.options.timeout = 180 }

全栈跟踪

WARN: Faraday::ConnectionFailed: Broken pipe
WARN: /usr/local/lib/ruby/2.3.0/openssl/buffering.rb:322:in `syswrite'
/usr/local/lib/ruby/2.3.0/openssl/buffering.rb:322:in `do_write'
/usr/local/lib/ruby/2.3.0/openssl/buffering.rb:340:in `write'
/usr/local/lib/ruby/2.3.0/net/http/generic_request.rb:206:in `copy_stream'
/usr/local/lib/ruby/2.3.0/net/http/generic_request.rb:206:in `send_request_with_body_stream'
/usr/local/lib/ruby/2.3.0/net/http/generic_request.rb:123:in `exec'
/usr/local/bundle/gems/aws-sdk-core-3.15.0/lib/seahorse/client/net_http/patches.rb:28:in `block in new_transport_request'
/usr/local/bundle/gems/aws-sdk-core-3.15.0/lib/seahorse/client/net_http/patches.rb:27:in `catch'
/usr/local/bundle/gems/aws-sdk-core-3.15.0/lib/seahorse/client/net_http/patches.rb:27:in `new_transport_request'
/usr/local/lib/ruby/2.3.0/net/http.rb:1407:in `request'
/usr/local/lib/ruby/2.3.0/net/http.rb:1400:in `block in request'
/usr/local/lib/ruby/2.3.0/net/http.rb:853:in `start'
/usr/local/lib/ruby/2.3.0/net/http.rb:1398:in `request'
/usr/local/bundle/gems/faraday-0.17.3/lib/faraday/adapter/net_http.rb:87:in `perform_request'
/usr/local/bundle/gems/faraday-0.17.3/lib/faraday/adapter/net_http.rb:43:in `block in call'
/usr/local/bundle/gems/faraday-0.17.3/lib/faraday/adapter/net_http.rb:92:in `with_net_http_connection'
/usr/local/bundle/gems/faraday-0.17.3/lib/faraday/adapter/net_http.rb:38:in `call'
/usr/local/bundle/gems/faraday-0.17.3/lib/faraday/request/url_encoded.rb:15:in `call'
/usr/local/bundle/gems/faraday-0.17.3/lib/faraday/rack_builder.rb:143:in `build_response'
/usr/local/bundle/gems/faraday-0.17.3/lib/faraday/connection.rb:387:in `run_request'
/usr/local/bundle/gems/faraday-0.17.3/lib/faraday/connection.rb:175:in `put'
vngu2lb8

vngu2lb81#

您的错误似乎是由网络中断引起的。Broken pipe是一个特定的错误,当客户端试图从服务器关闭的套接字读取数据时发生。
您可以尝试以下几种方法来解决此问题:

1.增加超时值。

超时值是客户端在放弃之前等待服务器响应的时间量。

2.实现重试机制。

您可以使用Faraday Retry plugin自动重试失败的请求,但需要确保与法拉第0.17.3版本的兼容性。

require 'faraday'
require 'faraday/retry'

retry_options = {
  max: 2,
  interval: 0.05,
  interval_randomness: 0.5,
  backoff_factor: 2
}

conn = Faraday.new(...) do |f|
  f.request :retry, retry_options
  #...
end

conn.get('/')

相关问题