【问题标题】:Moving files directly from S3 to FTP将文件直接从 S3 移动到 FTP
【发布时间】:2019-07-06 22:42:30
【问题描述】:

我正在 AWS(EC2 窗口)上运行基于媒体的 Web 应用程序。我正在尝试通过在 Auto Scaling 组上添加应用程序和 Web 服务器来实现可扩展性。

我的问题是我需要将媒体存储分离到 S3,以便我可以与不同的应用服务器集群共享它。但我必须将这些媒体文件从 S3 移动到不同的 FTP 服务器。为此,我必须将文件从 S3 下载到应用服务器,然后进行 FTP 上传,这需要花费太多时间。请注意,我使用 ColdFusion 作为应用服务器。

现在我有 2 个选项来解决这个问题

  1. 将 S3 实例挂载到 EC2 实例(我知道不建议这样做,也不确定这是否有助于提高 FTP 上传速度)。
  2. 使用Lamda service 将文件直接从 S3 上传到 FTP 服务器

我不能对每个 EC2 实例使用单独的 EBS 卷,因为

  1. 存储量大,成本高
  2. 我需要在附加到 EC2 实例的不同 EBS 卷上同步媒体存储

EFS 不是一个选项,因为我使用的是 Windows 存储。

谁能提出更好的解决方案?

【问题讨论】:

  • FWIW,据我所知,这一切都与 ColdFusion 无关。您可能会就服务器故障询问您的存储问题。
  • AWS 几个月前宣布了一项允许您使用 S3 代替 FTP 服务器的内容。你调查过吗? aws.amazon.com/blogs/aws/…

标签: amazon-web-services amazon-s3 amazon-ec2 coldfusion scalability


【解决方案1】:

用 python 很简单

from ftplib import FTP
from socket import _GLOBAL_DEFAULT_TIMEOUT
import urllib.request

class FtpCopier(FTP):

    source_address = None
    timeout = _GLOBAL_DEFAULT_TIMEOUT

    # host → ftp host name / ip
    # user → ftp login user
    # password → ftp password
    # port → ftp port
    # encoding → ftp servver encoding
    def __init__(self, host, user, password, port = 21, encoding = 'utf-8'):

        self.host = host
        self.user = user
        self.password = password
        self.port = port
        self.connect(self.host, self.port)
        self.login(self.user, self.password, '')
        self.encoding = encoding

    # url → any web URL (for example S3)
    # to_path → ftp server full path (check if ftp destination folders exists)
    # chunk_size_mb → data read chunck size
    def transfer(self, url, to_path, chunk_size_mb = 10):

        chunk_size_mb = chunk_size_mb * 1048576 # 1024*1024
        file_handle = urllib.request.urlopen(url)
        self.storbinary("STOR %s" % to_path, file_handle, chunk_size_mb)

使用示例:

ftp = FtpCopier("some_host.com", "user", "p@ssw0rd")
ftp.transfer("https://bucket.s3.ap-northeast-2.amazonaws.com/path/file.jpg", "/path/new_file.jpg")

但请记住,lambda 处理时间限制为15 minutes。因此在文件传输完成之前可能会出现超时。我建议使用 ECS Fargate 代替 lambda。这允许你想多长时间就保持正在运行的进程。

如果 S3 文件不公开,请使用 presigned URLs 通过 urllib 访问它。

aws s3 presign s3://bucket/path/file.jpg --expires-in 604800

【讨论】:

  • 您好,感谢您的回答。你能详细说明你在用timeout = _GLOBAL_DEFAULT_TIMEOUT做什么吗?
  • 正如您在父类 FTP 中看到的 github.com/python/cpython/blob/main/Lib/ftplib.py ,调用构造函数时设置了超时。我的__init__ 方法没有超时参数,所以我需要在子FtpCopier 类中手动设置它。其实我不记得为什么我重写了构造函数。看起来像标准的做同样的事情。
  • 有道理!谢谢你的回答。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-07-27
  • 1970-01-01
  • 2021-12-19
  • 2015-04-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多