“Faraday::ConnectionFailed: Broken pipe” 在上传 Tempfile 到 S3 预签名 URL 时发生。

huangapple go评论65阅读模式
英文:

"Faraday::ConnectionFailed: Broken pipe" when uploading Tempfile to S3 Presigned URL

问题

Sure, here is the translated portion of your text:

在我的Ruby on Rails应用程序中,我需要使用Faraday Ruby gem将大约30MB或更大的MP4视频资源上传到Amazon S3的预签名URL。这个操作经常失败,出现Faraday::ConnectionFailed: Broken pipe错误。我想了解为什么会发生这种情况以及如何解决,因为我需要使这个操作更加可靠。

视频资源被存储为Tempfile,然后通过PUT请求流式传输到S3预签名URL。

这种失败并不是百分之百发生。这个操作经常在没有失败的情况下成功,而且在失败后的重试后也经常成功。如果必须说,大约50%的时间会发生失败。

Ruby版本2.3.1

Rails版本5.0.0

Faraday版本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'
...

如果您需要进一步的帮助,请随时提出。

英文:

In my Ruby on Rails application, I need to upload large (~30MB or greater) MP4 video assets to an Amazon S3 Presigned URL using the Faraday Ruby gem. This operation frequently fails with a Faraday::ConnectionFailed: Broken pipe error. I want to understand why exactly this happens and how to address it, as I need to make this operation much more reliable.

The video asset is stored as a Tempfile and streamed out to a PUT request to the S3 presigned URL.

This failure does not occur 100% of the time. This operation often succeeds without this failure, and also will succeed often after a failure-induced retry. If I had to say, failures happen 50% of the time.

Ruby 2.3.1

Rails 5.0.0

Faraday 0.17.3 (adapter = net/http. I have tried changing adapter to httpclient but results in a similar error HTTPClient::KeepAliveDisconnected: Broken pipe. I prefer to stick with net/http.)

Relevant Code

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)

From online research, I see that a timeout may be at play so I tried passing the following block to the conn.put request. It didn't seem to help.
{ |req| req.options.timeout = 180 }

Full Stack Trace

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'

答案1

得分: 0

网络中断似乎是引起错误的原因。Broken pipe 是一个特定的错误,当客户端尝试从服务器关闭的套接字中读取数据时发生。

有一些方法可以尝试修复此问题:

1. 增加超时值。

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

2. 实施重试机制。

您可以使用 Faraday Retry 插件 来自动重试失败的请求,但需要确保与 Faraday 版本 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('/')
英文:

It seems your error is caused by network interruption. Broken pipe is a specific error that occurs when the client tries to read data from a socket that has been closed by the server.

There are a few things you can try to fix this issue:

1. Increase the timeout value.

The timeout value is the amount of time that the client will wait for a response from the server before giving up.

2. Implement a retry mechanism.

You can use Faraday Retry plugin to automatically retry failed requests, but you need to ensure compatibility with Faraday version 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('/')

huangapple
  • 本文由 发表于 2023年5月22日 13:57:04
  • 转载请务必保留本文链接:https://go.coder-hub.com/76303362.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定