S3 Upload/Download 超时问题
S3 Upload/Download Timeout Issues
我正在尝试通过 Heroku 上的 ruby-on-rails 应用使用 S3 文件存储和 sdk 访问来创建地理标记图像的 kmz 格式文件。
当 "project" 视图加载时,我正在 运行 处理文件,但是我编写的用于访问 S3 和处理文件的实例方法需要大约 40 秒才能完成,导致504 超时错误。
我已经研究过在没有本地下载的情况下对 S3 本身进行压缩,但这似乎不可行。有没有更好的方法来处理这个 download/upload 进程以加快它的速度,或者有更好的地方 运行 它以避免超时?
项目控制器中的方法:
# GET /projects/1
# GET /projects/1.json
def show
@pictures = @project.pictures.all
@project.generate_kml
@project.download_project
@project.generate_kmz
end
详细信息:
def generate_kml
content = []
content.push('<?xml version="1.0" encoding="UTF-8"?>')
content.push('<kml xmlns="http://www.opengis.net/kml/2.2" xmlns:gx="http://www.google.com/kml/ext/2.2" xmlns:kml="http://www.opengis.net/kml/2.2" xmlns:atom="http://www.w3.org/2005/Atom">')
content.push('<Document>')
content.push("<name>#{self.id}.kmz</name>")
#cycles through each picture in db for the current project
self.pictures.each do |pic|
pic_title = pic.image.to_s.split('/').last
content.push('<Placemark>')
content.push("<name>#{pic_title}</name>")
content.push('<description>')
content.push('<![CDATA[')
line = '<img style="max-width:1000px;" src="' + '' + pic_title + '">'
content.push(line)
content.push(']]>')
content.push('</description>')
content.push('<Point>')
content.push("<coordinates>-#{pic.long},#{pic.lat}</coordinates>")
content.push('</Point>')
content.push('</Placemark>')
end
content.push('</Document>')
content.push('</kml>')
#pushes upload to S3 folder
s3 = Aws::S3::Resource.new
obj = s3.bucket(ENV['S3_BUCKET']).object("uploads/" + "#{self.id}" + "/doc.kml")
File.open("kml_temp", "w+") { |f|
f.puts(content)
obj.put(body: f)
}
end
def generate_kmz
#create
directory_to_zip = "/tmp/#{self.id}"
output_file = "/tmp/kmz_directory/#{self.id}.kmz"
zf = ZipFileGenerator.new(directory_to_zip, output_file)
zf.write()
#send to S3
s3 = Aws::S3::Resource.new
obj = s3.bucket(ENV['S3_BUCKET']).object("uploads/kmz_directory/" + "#{self.id}.kmz")
obj.upload_file("/tmp/kmz_directory/#{self.id}.kmz")
end
def download_project
#tmp cleanup
#FileUtils.rm_r '/tmp'
#delete target directory if exists
if Dir.exist?("/tmp/#{self.id}")
FileUtils.remove_dir("/tmp/#{self.id}")
end
#create kmz_dir if needed
if Dir.exist?("/tmp/kmz_directory")
else
FileUtils.mkdir "/tmp/kmz_directory"
end
#create target dir
FileUtils.mkdir "/tmp/#{self.id}"
#download pics
s3 = Aws::S3::Resource.new
s3.bucket(ENV['S3_BUCKET']).object_versions({ prefix:"uploads/#{self.id}" }).each do |object|
#get file name
full_key = object.key
file_name = full_key.to_s.split('/').last
#save to /tmp
object.get(response_target: "/tmp/#{self.id}/#{file_name}")
end
end
Heroku 将 Web 请求限制为 30 秒。通常长 运行 进程是在 worker dynos 上使用诸如 sidekiq 或延迟作业之类的东西完成的。您的 Web 客户端可以每隔几秒轮询一次 ProjectsController#show
操作,当文件准备就绪时,该操作可以将带有 link 的页面呈现到 s3 存储桶中的 kml 文件。
我正在尝试通过 Heroku 上的 ruby-on-rails 应用使用 S3 文件存储和 sdk 访问来创建地理标记图像的 kmz 格式文件。
当 "project" 视图加载时,我正在 运行 处理文件,但是我编写的用于访问 S3 和处理文件的实例方法需要大约 40 秒才能完成,导致504 超时错误。
我已经研究过在没有本地下载的情况下对 S3 本身进行压缩,但这似乎不可行。有没有更好的方法来处理这个 download/upload 进程以加快它的速度,或者有更好的地方 运行 它以避免超时?
项目控制器中的方法:
# GET /projects/1
# GET /projects/1.json
def show
@pictures = @project.pictures.all
@project.generate_kml
@project.download_project
@project.generate_kmz
end
详细信息:
def generate_kml
content = []
content.push('<?xml version="1.0" encoding="UTF-8"?>')
content.push('<kml xmlns="http://www.opengis.net/kml/2.2" xmlns:gx="http://www.google.com/kml/ext/2.2" xmlns:kml="http://www.opengis.net/kml/2.2" xmlns:atom="http://www.w3.org/2005/Atom">')
content.push('<Document>')
content.push("<name>#{self.id}.kmz</name>")
#cycles through each picture in db for the current project
self.pictures.each do |pic|
pic_title = pic.image.to_s.split('/').last
content.push('<Placemark>')
content.push("<name>#{pic_title}</name>")
content.push('<description>')
content.push('<![CDATA[')
line = '<img style="max-width:1000px;" src="' + '' + pic_title + '">'
content.push(line)
content.push(']]>')
content.push('</description>')
content.push('<Point>')
content.push("<coordinates>-#{pic.long},#{pic.lat}</coordinates>")
content.push('</Point>')
content.push('</Placemark>')
end
content.push('</Document>')
content.push('</kml>')
#pushes upload to S3 folder
s3 = Aws::S3::Resource.new
obj = s3.bucket(ENV['S3_BUCKET']).object("uploads/" + "#{self.id}" + "/doc.kml")
File.open("kml_temp", "w+") { |f|
f.puts(content)
obj.put(body: f)
}
end
def generate_kmz
#create
directory_to_zip = "/tmp/#{self.id}"
output_file = "/tmp/kmz_directory/#{self.id}.kmz"
zf = ZipFileGenerator.new(directory_to_zip, output_file)
zf.write()
#send to S3
s3 = Aws::S3::Resource.new
obj = s3.bucket(ENV['S3_BUCKET']).object("uploads/kmz_directory/" + "#{self.id}.kmz")
obj.upload_file("/tmp/kmz_directory/#{self.id}.kmz")
end
def download_project
#tmp cleanup
#FileUtils.rm_r '/tmp'
#delete target directory if exists
if Dir.exist?("/tmp/#{self.id}")
FileUtils.remove_dir("/tmp/#{self.id}")
end
#create kmz_dir if needed
if Dir.exist?("/tmp/kmz_directory")
else
FileUtils.mkdir "/tmp/kmz_directory"
end
#create target dir
FileUtils.mkdir "/tmp/#{self.id}"
#download pics
s3 = Aws::S3::Resource.new
s3.bucket(ENV['S3_BUCKET']).object_versions({ prefix:"uploads/#{self.id}" }).each do |object|
#get file name
full_key = object.key
file_name = full_key.to_s.split('/').last
#save to /tmp
object.get(response_target: "/tmp/#{self.id}/#{file_name}")
end
end
Heroku 将 Web 请求限制为 30 秒。通常长 运行 进程是在 worker dynos 上使用诸如 sidekiq 或延迟作业之类的东西完成的。您的 Web 客户端可以每隔几秒轮询一次 ProjectsController#show
操作,当文件准备就绪时,该操作可以将带有 link 的页面呈现到 s3 存储桶中的 kml 文件。