jQuery Dropzone プラグインと paperclip gem を使用してビデオをアップロードできる Rails 4 アプリケーションがあります。アップロードされた各動画は複数の形式にエンコードされ、delayed_paperclip、av-transcoder、sidekiq gem を使用してバックグラウンドで Amazon S3 にアップロードされます。
すべてがほとんどのビデオで正常に動作しますが、アップロードがドロップゾーン プラグインのプログレス バーの終わりのように見える値に達した後、1.1GB のようなより大きなサイズでは、Nginx 504 ゲートウェイ タイムアウトが返されます。
サーバーに関する限り、Rails アプリは、ロード バランサーの背後にある 2 台のサーバー上の Nginx + Passenger で実行されます (ここでも Nginx が使用されます)。ロード バランサーのアップストリーム セクションにタイムアウトを設定していません。client_max_body_size
(ロード バランサーとサーバーの両方で) 2000M に設定されていますpassenger_pool_idle_time
。大きな値 (600) に設定しようとしましたが、役に立ちませんでした。設定(600秒)も試しましたがsend_timeout
、何も違いはありませんでした。
注: これらの変更を行うときは、両方のサーバーとロード バランサーのホスト ファイルで変更を行い、その後常に nginx を再起動しました。
this oneとthis oneのような同様の問題に関するいくつかの回答も読みましたが、まだこれを理解できません。Googleもそれほど役に立ちませんでした。
paperclip/delayed_paperclip プロセス全体に不慣れな人向けの追加の注意事項。ファイルがサーバーにアップロードされ、ユーザーに関する限り、操作はバックグラウンドでビデオの後処理 (エンコード/S3 へのアップロード) で行われます。 ) はジョブとして Redis にプッシュされ、Sidekiq は時間/リソースがあるときはいつでもそれを処理します。
この問題の原因は何ですか? これをデバッグして解決するにはどうすればよいですか?
アップデート
Sergey's answer のおかげで、問題を解決できました。私は Paperclip の特定のバージョンに制限されていたため、修正された最新バージョンに更新できませんでした。
アップロードを処理するために使用するエンジンでは、engine_name.rb
ファイルに次のコードを追加して、修正が必要な Paperclip のメソッドをオーバーライドしました。
Paperclip::AbstractAdapter.class_eval do
def copy_to_tempfile(src)
link_or_copy_file(src.path, destination.path)
destination
end
def link_or_copy_file(src, dest)
Paperclip.log("Trying to link #{src} to #{dest}")
FileUtils.ln(src, dest, force: true) # overwrite existing
@destination.close
@destination.open.binmode
rescue Errno::EXDEV, Errno::EPERM, Errno::ENOENT => e
Paperclip.log("Link failed with #{e.message}; copying link #{src} to #{dest}")
FileUtils.cp(src, dest)
end
end
Paperclip::AttachmentAdapter.class_eval do
def copy_to_tempfile(source)
if source.staged?
link_or_copy_file(source.staged_path(@style), destination.path)
else
source.copy_to_local_file(@style, destination.path)
end
destination
end
end
Paperclip::Storage::Filesystem.class_eval do
def flush_writes #:nodoc:
@queued_for_write.each do |style_name, file|
FileUtils.mkdir_p(File.dirname(path(style_name)))
begin
move_file(file.path, path(style_name))
rescue SystemCallError
File.open(path(style_name), "wb") do |new_file|
while chunk = file.read(16 * 1024)
new_file.write(chunk)
end
end
end
unless @options[:override_file_permissions] == false
resolved_chmod = (@options[:override_file_permissions] &~ 0111) || (0666 &~ File.umask)
FileUtils.chmod( resolved_chmod, path(style_name) )
end
file.rewind
end
after_flush_writes # allows attachment to clean up temp files
@queued_for_write = {}
end
private
def move_file(src, dest)
# Support hardlinked files
if File.identical?(src, dest)
File.unlink(src)
else
FileUtils.mv(src, dest)
end
end
end