【问题标题】:How to handle video and image upload to storage servers?如何处理视频和图像上传到存储服务器?
【发布时间】:2023-04-06 22:47:01
【问题描述】:

我正在开发用户需要上传照片和图像的应用程序(使用 Go 或可能使用 PHP)。

我已经在不同的位置设置了几个 ZFS(镜像)存储服务器,但我对如何让用户最好地上传文件感到怀疑。 ZFS 处理配额和预留。

我在所有服务器上运行一个复制的 Galera 数据库,这既是为了安全,也是为了方便地从每台服务器访问用户帐户。换句话说,每台服务器始终拥有数据库的本地副本。所有用户都是仅限的虚拟用户。

到目前为止,我已经测试了以下设置选项:

解决方案 1

在具有虚拟用户的存储服务器上运行 SFTP(带模块的 ProFTPD)或 FTPS(带 TLS 的纯 FTP)。

这使人们可以使用 Filezilla 等客户端直接访问存储服务器。同时,用户还可以使用我们的 Web GUI 从我们的主网络服务器上传。

此设置的一个优点是 FTP 服务器可以处理虚拟用户。我们的 Web 应用程序还将通过 SFTP 或 FTPS 发送文件。

一个缺点是 FTP 很简单,对防火墙很烦。我也更喜欢 FTP over SSH (SFTP),而不是 FTP over TLS (FTPS)。但是,只有 ProFTPD 有 SSH 模块,但与 PureFTPd 相比,使用起来确实很痛苦(许多问题与非工作配置选项和文件权限错误),但 PureFTPd 仅支持 TLS。

使用真实的 SSH/SCP 帐户运行并使用 PAM 不是一种选择。

解决方案 2

使用 NFS 或 CIFS 在 Web 服务器上本地安装存储服务器(Samba 非常适合自动恢复,以防机器出现故障)。

在此设置中,用户可以通过我们的主网络服务器上传。 Web 服务器应用程序以及在存储服务器上运行的应用程序需要支持可恢复上传。我一直在研究使用 tus 协议。

上述两种设置的一个缺点是需要以某种方式管理存储容量。当存储服务器 1 达到其最大用户数时,应用程序需要知道这一点,然后才为存储服务器 2、3 等创建虚拟用户。

我已经计算出每个存储服务器可以容纳多少用户,然后让 Web 应用程序使用虚拟用户检查数据库,以查看何时需要将新创建的用户移动到下一个存储服务器。

这是相当古老的学校,但它确实有效。

解决方案 3

与解决方案 2 相同(无 FTP),但克隆我们的 Web 应用程序将内容上传到每个存储服务器,然后重定向用户(或为他们提供存储服务器的物理链接,s1.example.com,s2.example。 com等)

这种设置的可能优势是用户可以直接上传到他们分配到的存储服务器,而不是通过我们的主网络服务器(防止它成为可能的瓶颈)。

解决方案 4

在存储服务器上使用 GlusterFS,构建易于扩展的集群。我已经对 GlusterFS 进行了测试,它非常适合此目的。

这种设置的优点是我不需要关心文件在哪些存储服务器上的物理位置,而且我可以通过向集群添加更多服务器来轻松扩展存储。

但是,这里的缺点是我们的主 Web 服务器可能会成为瓶颈。

我也考虑过添加一个负载均衡器,然后使用多个 Web 服务器,以防我们的主 Web 服务器成为上传文件的瓶颈。

无论如何,我更喜欢保持简单!我不喜欢添加东西。从长远来看,我希望它易于维护。

我们将不胜感激任何想法、建议和意见。

你是怎么做到的?

【问题讨论】:

  • 我能做些什么来改善我的答案吗?

标签: php go data-storage zfs


【解决方案1】:

如果我们谈论文件存储,Web 应用程序应该与底层存储无关;关注点分离。

另一方面,(S)FTP(S) 不是一种存储方法。它是一种通信协议。它并不排除您拥有共享存储空间。见上文。

ZFS 不具备包含共享存储的能力,因此您基本上可以选择以下几种方式:

  1. 哪个底层文件系统?
  2. 我想通过 (S)FTP(S) 提供额外的访问模式吗?
  3. 如何使我的文件系统在多个服务器上可用? GlusterFS、CIFS 还是 NFS?

那么,让我们来看看吧。

文件系统

我知道 ZFS 很有趣,但事情是这样的:例如,xfs 的最大文件系统大小已经是 8 exbibytes 减去 1 个字节。对此的专业术语是“a s...load”。给你一个关系:国会图书馆拥有大约 20TB 的数字媒体 - 并且可以容纳大约 400k 次。即使是好的 ol' ext4 也可以容纳 50k LoC。如果您拥有这么多数据,那么您的 FS 就是您最不关心的问题。建造接下来的几个发电厂以保持您的东西运转大概是。

要点 很好想,但使用任何你觉得舒服的东西。我个人几乎所有事情都使用 xfs(在 LVM 上)。

其他访问方法

当然,为什么不呢?除了安全噩梦(特权升级,有人吗?)。而 ProFTPd,内置咖啡机和厨房水槽是我将用于任何事情的最后 FTP 服务器。它有一个庞大的代码库,适合accidentally introducing vulnerabilities

基本上归结为项目中存在的技能。你们能正确强化系统和 FTP 服务器并监控安全事件吗?除非你的回答是自信的“是的,ofc,有很多经验!”你应该尽量减少你呈现的攻击面。

要点不要,除非你真的知道自己在做什么。如果你不得不问,你可能不会。无意冒犯,只是陈述事实。

共享文件系统

就个人而言,我对 GlusterFS 的体验并不完美。当涉及到网络延迟和其他东西时,复制有相当多的要求。简而言之:如果我们谈论多个可用区,比如 EMEA、APAC 和 NCSA,那几乎是不可能的。你会被困在georeplication,这对于你描述的用例来说不太理想。

另一方面,NFS 和 CIFS 的问题是根本没有复制,所有客户端都需要访问同一个服务器实例才能访问数据 - 如果您认为需要底层 ZFS,这不是一个好主意相处。

要点在全球范围内共享文件系统具有一半的复制延迟和访问时间非常很难做到并且可以得到 非常很贵。

哈哈,Smartypants,你有什么建议?

规模。慢慢地。一开始,您应该能够为您的文件使用一个简单的基于 FS 的存储库。然后检查各种其他方式的大规模共享存储并迁移到它。

转向实现,我什至会更进一步,你应该让你的存储成为一个接口:

// Storer takes the source and stores its contents under path for further reading via
// Retriever.
type Storer interface {
    StreamTo(path string, source io.Reader) (err error)
}

// Retriever takes a path and streams the file it has stored under path to w.
type Retriever interface {
    StreamFrom(path string, w io.Writer) (err error)
}

// Repository is a composite interface. It requires a
// repository to accept andf provide streams of files
type Repository interface {
    Storer
    Retriever
    Close() error
}

现在,您可以很容易地实现各种存储方法:

// FileStore represents a filesystem based file Repository.
type FileStore struct {
    basepath string
}

// StreamFrom statisfies the Retriever interface.
func (s *FileStore) StreamFrom(path string, w io.Writer) (err error) {

    f, err := os.OpenFile(filepath.Join(s.basepath, path), os.O_RDONLY|os.O_EXCL, 0640)
    if err != nil {
        return handleErr(path, err)
    }
    defer f.Close()
    _, err = io.Copy(w, f)
    return err
}

就个人而言,我认为这将是GridFS 的一个很好的用例,尽管它的名称不是文件系统,而是 MongoDB 的一个特性。至于原因:

  1. MongoDB 带有一个称为副本集的概念,以通过服务器之间透明的自动故障转移来确保可用性
  2. 它带有一种相当简单的自动数据分区机制,称为分片集群
  3. 它带有无限数量的访问网关,称为mongos 查询路由器,用于访问您的分片数据。
  4. 对于客户端,除了连接 U​​RL,这一切都是透明的。因此,无论它的存储后端是由单个服务器还是由具有 600 个节点的全局复制分片集群组成,它都没有区别(几乎除了 read preferencewrite concern)。
  5. 如果操作正确,不会出现单点故障,您可以跨可用区进行复制,同时将“热”数据保持在各个用户附近。

我创建了一个repository on GitHub,其中包含接口建议的示例,并实现了基于文件系统的存储库以及 MongoDB 存储库。你可能想看看它。它目前缺乏缓存。如果您希望看到实现,请在此处打开一个问题。

【讨论】:

  • 总体同意(除了 boo 非 ZFS ;)——这不仅对存储容量有好处)。如果您想在本地存储数据,GridFS 似乎是一个合理的选择。但是,如果您已经在云环境中构建,那么您应该只使用您的云提供商提供的任何 blob 存储(Google Cloud Storage、Amazon S3 等),因为这样您就不必关心底层存储实现并且可以更多地关注产品中面向用户的部分。
  • 同意。并且取决于您想要做什么,特别是如果您想为轻松迁移做好准备,即使是 Minio 也是一个不错的选择。不知道确切的要求很难说。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-03-02
  • 2017-02-01
  • 1970-01-01
  • 2010-09-08
  • 2011-06-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多