Как обработать загрузку видео и изображений на серверы хранения? - PullRequest
1 голос
/ 19 октября 2019

Я нахожусь в процессе разработки приложения (на Go или, возможно, на PHP), где пользователям необходимо загружать фотографии и изображения.

Я настроил несколько зеркальных серверов хранения ZFS в разных местах, но я сомневаюсь в том, как позволить пользователям лучше загружать файлы. ZFS обрабатывает квоты и резервирование.

Я работаю с реплицированной базой данных Galera на всех серверах, как для безопасности, так и для легкого доступа к учетным записям пользователей с каждого сервера. Другими словами, каждый сервер постоянно имеет локальную копию базы данных. Все пользователи являются виртуальными пользователями только .

Пока у меня есть следующие параметры настройки:

Решение 1

ВыполняетсяSFTP (ProFTPD с модулем) или FTPS (Pure-FTP с TLS) на серверах хранения с виртуальными пользователями.

Это дает людям прямой доступ к серверам хранения с помощью клиента, такого как Filezilla. В то же время пользователи могут также загружать файлы с помощью нашего веб-интерфейса с нашего основного веб-сервера.

Одним из преимуществ этой настройки является то, что FTP-сервер может обрабатывать виртуальных пользователей. Наше веб-приложение также будет отправлять файлы через SFTP или FTPS.

Одним из недостатков является то, что FTP раздражает брандмауэр. Также я предпочитаю FTP через SSH (SFTP), а не FTP через TLS (FTPS). Тем не менее, только ProFTPD имеет модуль для SSH, но было очень трудно (много проблем с нерабочими параметрами конфигурации и ошибками разрешения доступа к файлам) работать по сравнению с PureFTPd, но PureFTPd поддерживает только TLS.

Запуск с реальными учетными записями SSH / SCP и использование PAM не вариант.

Решение 2

Монтирование серверов хранения локально на веб-сервереиспользуя NFS или CIFS (Samba отлично подходит для автоматического возобновления работы в случае отказа коробки).

В этой настройке пользователи могут только загружать через наш основной веб-сервер. Приложение веб-сервера и приложение, работающее на серверах хранения, должны поддерживать возобновляемую загрузку. Я изучал использование протокола tus.

Недостатком обеих вышеуказанных настроек является то, что необходимо как-то управлять емкостью хранилища. Когда сервер хранения 1 достигает максимального числа пользователей, приложение должно знать это, а затем создавать виртуальных пользователей только для сервера хранения 2, 3 и т. Д.

Я рассчитал, сколько пользователей может хранить каждый сервер хранения, изатем попросите веб-приложение проверить базу данных у виртуальных пользователей, чтобы узнать, когда нужно переместить вновь созданных пользователей на следующий сервер хранения.

Это довольно старая школа, но она работает.

Решение 3

То же, что и решение 2 (без FTP), но клонируйте наше веб-приложение, загрузите файлы на каждый сервер хранения и затем перенаправьте пользователей (или предоставьте им физическую ссылку на сервер хранения,s1.example.com, s2.example.com и т. д.)

Возможное преимущество этой настройки заключается в том, что пользователи загружают данные непосредственно на сервер хранения, которому они назначены, а не проходят через наш основной веб-сервер (предотвращение его превращения в возможное узкое место).

Решение 4

Используйте GlusterFS на хранилищеСерверы и создать кластер, который можно легко расширить. Я протестировал GlusterFS, и он очень хорошо работает для этой цели.

Преимущество этой настройки заключается в том, что мне не нужно заботиться о том, куда физически отправляются файлы, на каких серверах хранения, и я могу легко расширитьхранилища путем добавления большего количества серверов в кластер.

Однако недостатком здесь снова является то, что наш основной веб-сервер может стать узким местом.

Я также рассмотрел добавление балансировщика нагрузки и затем использование несколькихвеб-сервер, если наш основной веб-сервер становится узким местом для загрузки файлов.

В любом случае, я предпочитаю, чтобы все было просто! Я не люблю добавлять вещи. Я хочу, чтобы его было легко поддерживать в долгосрочной перспективе.

Любые идеи, предложения и советы будут с благодарностью.

Как вы это делаете?

1 Ответ

0 голосов
/ 20 октября 2019

Веб-приложение должно быть независимым от основного хранилища, если мы говорим о хранилище файлов;Разделение проблем.

(S) FTP (S), с другой стороны, не является методом хранения. Это протокол связи. Это не мешает вам иметь общее хранилище. См. Выше.

ZFS не включает в себя возможность общего хранилища, поэтому вы в основном выбираете следующие варианты:

  1. Какая базовая файловая система?
  2. Хочу ли я предложить дополнительный режим доступа через (S) FTP (S)?
  3. Как сделать мою файловую систему доступной на нескольких серверах? GlusterFS, CIFS или NFS?

Итак, давайте разберемся с этим.

Файловая система

Я знаю, что ZFS интригует, но вот что: xfs дляпример уже имеет максимальный размер файловой системы 8 exbibytes минус один байт. Специалист термин для этого "s ... нагрузка". Чтобы дать вам связь: в Библиотеке конгресса хранится около 20 ТБ цифровых носителей - и она поместится примерно в 400 000 раз. Даже хороший старый ext4 может содержать 50 тыс. Локов. И если вы храните столько данных, ваша FS - ваша самая маленькая проблема. Построить следующую пару электростанций, чтобы ваши вещи продолжали работать, по-видимому.

Суть Приятно думать, но используйте все, что вам удобно. Лично я использую xfs (в LVM) практически для всего.

Дополнительные методы доступа

Конечно, почему бы и нет? Помимо кошмара безопасности (повышение привилегий, кто-нибудь?). А ProFTPd с встроенной кофемашиной и кухонной раковиной - это последний FTP-сервер, который я бы использовал для чего угодно. У него огромная кодовая база, которая позволяет случайно вводить уязвимости .

В основном все сводится к навыкам, присутствующим в проекте. Можете ли вы, ребята, правильно укрепить систему и FTP-сервер и контролировать это для инцидентов безопасности? Если ваш ответ не является уверенным "Да, конечно, много с опытом!"Вы должны минимизировать поверхность атаки, которую вы представляете.

Суть Не делайте этого, если вы действительно не знаете, что делаете. И если вам нужно спросить, вы, вероятно, нет. Без обид, просто констатация фактов.

Общая файловая система

Лично я сделал ... менее совершенный опыт работы с GlusterFS. Репликация имеет довольно много требований, когда речь идет о задержке в сети и прочем. В двух словах: если мы говорим о нескольких зонах доступности, скажем, EMEA, APAC и NCSA, это почти невозможно. Вы застряли бы в георепликации , что не идеально для описанного вами варианта использования.

С другой стороны, у NFS и CIFS есть проблема, что вообще нет репликации,и всем клиентам необходим доступ к одному и тому же экземпляру сервера, чтобы получить доступ к данным - вряд ли это хорошая идея, если вы считаете, что вам нужен базовый ZFS, чтобы ладить.

Gist Общие файловые системы наГлобальный масштаб с половинными приличными задержками репликации и временем доступа составляет очень трудно сделать и может стоить очень дорого.

Ха-ха, 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. Для клиента, кроме URL-адреса соединения, все это прозрачно. Таким образом, не имеет значения (почти, кроме предпочтений чтения и записи ), является ли его серверная часть хранилища отдельным сервером или глобально реплицированным сегментированным кластером с 600 узлами.
  5. Если все сделано правильно, нет ни одной точки отказа, вы можете реплицировать по зонам доступности, сохраняя «горячие» данные рядом с соответствующими пользователями.

Я создал репозиторий на GitHub , который содержит пример предложения интерфейса и реализует репозиторий на основе файловой системы, а также репозиторий MongoDB. Возможно, вы захотите взглянуть на это. На данный момент не хватает кеширования. Если вы хотите, чтобы это было реализовано, откройте вопрос там.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...