Azure Blob Storage - synchronizacja stanu na blobie z metadanymi w bazie

0

Używam azure blob storage jako miejsce przechowywania plików.

Użytkownik podczas tworzenia nowej "sprawy" może wgrywać załączniki (albo dodawać załączniki do istniejącej sprawy, analogiczna sytuacja) - strzela więc do api i dostaje token do kontenera i bezpośrednio do niego wrzuca pliki, nie chcę przepuszczać tego ruchu przez serwer aplikacyjny. W momencie tworzenia sprawy razem z danymi o sprawie przesyła jeszcze dane plików - np. jakieś komentarze, kategorie, itd. oraz adresy plików, które wrzucił na bloba.

Chciałbym zapewnić, że na blobie nie przechowuję niepotrzebnie plików, do których nie mam referencji w bazie.
Może to powstać np. w sytuacji gdy ktoś zacznie uploadować pliki, ale nie zapisze sprawy i wyłączy przeglądarkę, albo przy tworzeniu sprawy wrzuci plik do kontenera, po chwili jednak się rozmyślił i chce go usunąć, ale blob storage na chwilę przestał odpowiadać. Podobnie w sytuacji wgrywania dodatkowych plików do istniającej sprawy, udało się wrzucić na bloba, ale już nie udało się zapisać informacji o tym w bazie przy kolejnym strzale, użytkownik zobaczył błąd i odświeżył stronę.

Na szybko wpadłem na pomysł, żeby każdy taki upload najpierw trafiał na blobie do jakiegoś kontenera "staging", który byłby automatycznie czyszczony co jakiś czas (można to nawet z automatu skonfigurować na azure blob storage, albo słuchać na eventy z event grida i sobie kolejkować, albo nawet ręcznie co X czasu skanować bloba i usuwać pliki starsze niż X czasu). W momencie strzału do api z listą plików byłyby one kopiowane z kontenera stagingowego do kontenera docelowego dla danej sprawy - pewnie warto to przepuścić przez jakąś kolejkę.
Dodatkową zaletą takiego rozwiązania jest to, że zanim skopiuję pliki do kontenera docelowego i będą widoczne dla innych użytkowników, mogę je jeszcze przeskanować pod kątem jakiegoś malware'u.

Co o tym myślicie?
A może jest jakiś prostszy sposób? ;)

1

Generalnie upload prosto z frontu to strzal w stope.
Możesz w pierwszym kroku wrzucac do storage bloba z jakims prefixem. I ustawic regule na azurze ze wszystkie pliki z danym prefixem beda kasowane po X dni. A na backendzie juz jak potwierdzasz ten plik wpisem na bazie, zrobic rename który usunie ten prefix. Ale nie jest z tym tak rózowo, azure na chwile obecną nie oferuje rename, trzeba kopiowac i usuwać.

Najlepiej jednak robic upload przez backend. Wtedy masz kontrole co trafia do storage i pewnosc ze nie bedziesz mial tam zadnych zombie plików.

0
kzkzg napisał(a):

Najlepiej jednak robic upload przez backend. Wtedy masz kontrole co trafia do storage i pewnosc ze nie bedziesz mial tam zadnych zombie plików.

Akurat tutaj wydaje mi się, że pewność będzie taka sama. Bo dla pewności i tak będę potrzebował albo reguły na blobie, albo jakiegoś procesu, który wyczyści niepotrzebne pliki. Przy uploadzie przez backend zawsze może mi apka zdechnać po tym jak wrzuciłem na bloba, a nie zapisałem tego w bazie (albo przy odwrotnej kolejności, będę miał wpis w bazie bez fizycznego pliku, jeszcze gorsze).

1

A co zrobisz jak ci ktoś podejrzy ten token i spoza przeglądarki zuploaduje jakoś niepożądany plik?

0

Hmm, no jak podejrzy token do bloba to tak samo mógłby podejrzeć ciasteczko/token do api :P

Ale zakładając, że podejrzał tylko token do bloba to właśnie wrzuci plik do jakiegoś stagingowego kontenera i nic się nie stanie. Użytkownik aplikacji nigdy nie poinformuje api, że wrzucił taki plik i reguły na blobie/proces w tle ten plik po jakimś czasie usunie.

0

@some_ONE:

Hmm, no jak podejrzy token do bloba to tak samo mógłby podejrzeć ciasteczko/token do api :P

ale koniec końców i tak serwer waliduje wszystko zanim wyśle do storage

Ale zakładając, że podejrzał tylko token do bloba to właśnie wrzuci plik do jakiegoś stagingowego kontenera i nic się nie stanie. Użytkownik aplikacji nigdy nie poinformuje api, że wrzucił taki plik i reguły na blobie/proces w tle ten plik po jakimś czasie usunie.

Muszę przyznać że jest to dość ciekawe podejście, ale wydaje mi się że nie poszedłbym w tym kierunku - no bo co się stanie gdy ktoś wrzuci np. 100 plików 1GB? albo 10TB? 100TB? albo milion plików 1KB? czy jest ograniczenie?


Widzę takie scenariusze:

1 Upload do AZ [success]
2 Appka umiera
3 Request do Appki (zapis dokumentu) [fail]

Mamy plik w AZ, nie mamy informacji w bazie, user dostaje komunikat błędu, a plik zostanie usunięty po czasie.

1 Upload do Appki (pod spodem Upload do AZ) [success]
2 Appka umiera
3 Request do Appki (zapis dokumentu) [fail]

Mamy plik, mamy go w bazce, user dostaje komunikat błędu, a plik zostanie usunięty po czasie.

0

Azure blob niestety nie pozwala na ograniczenie wagi pliku przy uploadzie. Nie mniej, można to ograniczać pośrednio przez czas ważności tokena. Jeżeli token skończy się w trakcie uploadu to zostanie on przerwany.

0

@Inclouds:

Jeżeli token skończy się w trakcie uploadu to zostanie on przerwany.

przecież to z kilometra brzmi jak: niereliable, problematyczne dla userów - no bo co gdy ma słaby upload, oraz dla ciebie, bo trzeba wymyślić jakieś $sane_values

Azure blob niestety nie pozwala na ograniczenie wagi pliku przy uploadzie.

z czego to wynika?

0
WeiXiao napisał(a):

@Inclouds:

Jeżeli token skończy się w trakcie uploadu to zostanie on przerwany.

przecież to z kilometra brzmi jak: niereliable, problematyczne dla userów - no bo co gdy ma słaby upload, oraz dla ciebie, bo trzeba wymyślić jakieś >>$sane_values

No trzeba, nie ma rozwiązań idealnych, dlatetego jest ich tyle, bo każde ma swoje wady i zalety. W tym przypadku musisz sobie odpowiedzieć na pytanie czy akceptujesz gorszą kontrolę nad uploadem w zamian za lepsza skalowalność i odciążenie serwera.

Azure blob niestety nie pozwala na ograniczenie wagi pliku przy uploadzie.

z czego to wynika?

Nie wiem, też mnie to ciekawi 🙂

1

Wrzucasz formularz do bazy, dostajesz identyfikator pliku pod jakim masz wrzucić plik i wysyłasz tak dane do blob storage. pod BS masz podpięte [przechwytywanie eventów](https://docs.microsoft.com/en-us/azure/storage/blobs/storage-blob-event-overview , która wrzuci dane o pliku do kolejki, w tle stawiasz asynchroniczny serwis, który nasłuchuje na tej kolejce, jak dostanie event to sprawdza co tam chcesz, przenosi go do "czystego" kontenera i wiążesz z danymi w bazie.

1
WeiXiao napisał(a):

ale koniec końców i tak serwer waliduje wszystko zanim wyśle do storage

No tak, większa kontrola nad uploadem tak jak wspomniał @Inclouds to niewątpliwie zaleta uploadu przez backend. Wadą natomiast jest dodatkowe obciążenie serwera (zarówno CPU/RAM, jak i obciążenie sieci) przepychaniem streama od klienta na bloba. Chociaż tutaj warto byłoby zweryfikować tak na prawdę jak zasobożerne to jest.

A z tym walidowaniem wszystkiego co masz na myśli?
Chodzi o np. rozmiar wrzucanego pliku? Ok, ale żeby z góry taki request odrzucić to musiałbym go wczytywać do pamięci i jak zobaczę że przekracza limit (np. 1 GB) to odrzucać, ale ten 1GB pamięci na serwerze by zjadło.
Mógłbym też zacząć od razu go przepychać na bloba i podczas czytania śledzić ile przerzuciłem i przerywać operację jak rozmiar zostanie przekroczony bez commitowania tego na blobie (gdybym to robił w ten sposób i uploadował nie na bloba, tylko na jakiś dysk to pewnie znowu mógłbym zostać z zombie plikami tym razem na dysku :P ).

Ale zakładając, że podejrzał tylko token do bloba to właśnie wrzuci plik do jakiegoś stagingowego kontenera i nic się nie stanie. Użytkownik aplikacji nigdy nie poinformuje api, że wrzucił taki plik i reguły na blobie/proces w tle ten plik po jakimś czasie usunie.

Muszę przyznać że jest to dość ciekawe podejście, ale wydaje mi się że nie poszedłbym w tym kierunku - no bo co się stanie gdy ktoś wrzuci np. 100 plików 1GB? albo 10TB? 100TB? albo milion plików 1KB? czy jest ograniczenie?

Nie ma.
Co do miliona plików to mógłbym wygenerować token do pojedynczego bloba, ale jak miałbym funkcjonalność wrzucania kilku plików to ktoś mógłby wygenerować ich kilka (chociaż tutaj już można jakiś rate-limiting po stronie api wprowadzić).
Na rozmiar niestety limitu w ten sposób nie założę, poza tym co pisał @Inclouds, czyli jakiś rozsądny czas życia tokenu.

1 użytkowników online, w tym zalogowanych: 0, gości: 1