如何处理将视频和图像上传到存储服务器?

问题描述 投票:1回答:1

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

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

我在所有服务器上都使用复制的Galera数据库来运行,这既出于安全性考虑,也易于从每个服务器访问用户帐户。换句话说,每个服务器始终具有数据库的本地副本。所有用户都是虚拟用户only

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

解决方案1

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

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

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

一个缺点是FTP很烦人,防火墙很烦人。我也更喜欢FTP而不是SSH(SFTP),而不是TLS之上的FTP(FTPS)。但是,只有ProFTPD具有用于SSH的模块,但是与PureFTPd相比,使用它确实很痛苦(很多问题,包括无法使用的配置选项和文件权限错误),但是PureFTPd仅支持TLS。

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

解决方案2

使用NFS或CIFS在Web服务器上本地安装存储服务器(Samba非常擅长自动恢复,以防万一机器掉下来)。

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

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

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

这是一所相当古老的学校,但它可以工作。

解决方案3

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

此设置的可能优点是,用户直接上传到已分配给他们的存储服务器,而不是通过我们的主Web服务器(防止它成为可能的瓶颈)。

解决方案4

在存储服务器上使用GlusterFS,并构建可以轻松扩展的集群。我已经测试了GlusterFS,它可以很好地达到此目的。

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

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

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

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

任何想法,建议和意见,将不胜感激。

你怎么做?

php go data-storage zfs
1个回答
0
投票

Web应用程序应与基础存储无关,以防我们在谈论文件存储;关注点分离。

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

ZFS不具备共享存储的功能,因此基本上可以选择以下选项:

  1. 哪个基础文件系统?
  2. 我是否想通过(S)FTP(S)提供其他访问模式?
  3. 如何使我的文件系统可在多个服务器上使用?是GlusterFS,CIFS还是NFS?

所以,让我们逐步讲解。

文件系统

我知道ZFS令人着迷,但问题在于:例如,xfs的最大文件系统大小为8 exb减去一个字节。专门的术语是“负载”。为您提供联系:国会图书馆拥有大约20TB的数字媒体-可以容纳大约40万次。即使是出色的ext4也可以容纳5万个LoC。而且,如果您拥有那么多数据,则FS是您最小的担心。建立下两个发电厂,以使您的设备正常运行。

Gist想得很好,但是请使用您认为合适的任何东西。我个人使用xfs(在LVM上)几乎完成所有操作。

其他访问方法

当然,为什么不呢?除了安全噩梦(特权升级,还有其他人吗?)。 ProFTPd内置在咖啡机和厨房水槽中,是我可以用于任何用途的last FTP服务器。它具有庞大的代码库,非常适合accidentally introducing vulnerabilities

基本上,可以归结为项目中存在的技能。你们可以适当加固系统和FTP服务器,然后monitor进行安全保护吗?除非您的答案是自信的“是的,当然,他们有丰富的经验!”您应该使出现的攻击面最小化。

Gist除非您真的知道自己在做什么,否则不要这样做。而且,如果您不得不问,您可能不必问。没有意图冒犯,只是陈述事实。

共享文件系统

就我个人而言,我对GlusterFS的体验还不够完美。当涉及网络延迟和填充时,复制具有相当大的要求。简而言之:如果我们要谈论多个可用区,例如EMEA,APAC和NCSA,那几乎是不可能的。您会被困在georeplication上,这对于您描述的用例而言并不理想。

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

Gist在全球范围内共享的文件系统,复制延迟中等,访问时间很难做到[[very,并且可能变得昂贵。[[very

哈哈,聪明人,你有什么建议?规模。慢慢来首先,您应该能够与基于文件的简单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的功能。由于原因:

MongoDB带有一个称为副本集的概念,可通过服务器之间的透明自动故障转移来确保可用性

    [它带有一个相当简单的自动数据分区机制,称为分片群集
  1. 它带有无限数量的称为mongos查询路由器的访问网关,用于访问分片数据。
  2. 对于客户端,除了连接URL,所有这些都是透明的。因此,它的存储后端是由单个服务器还是由具有600个节点的全局复制分片集群组成,几乎没有什么区别(除了read preferencewrite concern之外)。
  3. 如果操作正确,则不会出现单点故障,您可以跨可用性区域进行复制,同时使“热”数据保持在各个用户附近。
  • 我创建了一个repository on GitHub,其中包含接口建议的示例,并实现了基于文件系统的存储库以及MongoDB存储库。您可能想看看它。目前缺少缓存。如果您希望看到它已实施,请在此处打开一个问题。
  • © www.soinside.com 2019 - 2024. All rights reserved.