Witam,
Potrzebuję, aby backend aplikacji Rails’owej, poprzez swoje API, był w stanie otrzymywać duże ilości danych z aplikacji mobilnych. Mam też wpływ na aplikację mobilną.
Dane wstępnie miałyby być przesyłane z aplikacji mobilnej do API serwera poprzez HTTP w formie plików, których łączny rozmiar może sięgać od 100Mb - 500Mb.
Jakie rozwiązania polecacie? Może zamiast HTTP lepiej używać websocketów?
Moja wstępna koncepcja jest taka, aby aplikacja mobilna dzieliła dane do mniejszych plików, np. o rozmiarze 1MB, i przesyłała kolejno przez POST HTTP dane na serwer.
Jeśli uważacie, że można by to rozwiązać lepiej, to będę wdzięczny za wszelką pomoc. Pozdrawiam!
Ciekawy problem. Odrzuciłbym z miejsca takie wynalazki jak websockety - służą zupełnie do czegoś innego (2 stronna komunikacja na żywo). Zostałbym po prostu przy http. Trzeba jednak rozwiązać kilka problemów (i nie są to problemy wynikające z http):
Dzielenie dużych plików. Chyba nie trzeba tłumaczyć jak bardzo zdenerwuje użytkownika sytuacja gdy internet mu padnie na chwilę po wrzuceniu 90% z 500MB pliku. Skoro masz wpływ na klienta to taki klient musiałby być na tyle inteligentny, że jest w stanie kontynuować z miejsca gdzie skończył (granulacja w postaci plików rzędu kilku MB powinna być wystarczająca).
Obsługa serwer frontowy (np. nginx) vs backend (rails?). Problem jest taki, że taki “normalny” upload pliku działa tak iż serwer otrzymuje żądania z plikiem, a potem całe to żądanie jest proxowane do backendu. Przez to plik jest kopiowany w pamięci oraz zapisywany na dysku 2x. Nie rozwiązywałem nigdy tego problemu, ale wydaje się, że są na to sposoby: https://coderwall.com/p/swgfvw/nginx-direct-file-upload-without-passing-them-through-backend Działa to tak, że zamiast pliku do backendu wysyłany jest tylko nagłówek ze ścieżką do zapisanego pliku. Taki sposób oznacza jednak, że każdy fizyczny serwer musiałby mieć na przodzie serwer http (nginx), który proxuje żądanie http do procesu aplikacji na tej samej maszynie co nginx. Nie jest to problem, ale trzeba o tym pamiętać.
Łączenie części. Trzeba w odpowiednim momencie połączyć fizycznie pliki. Niby proste, ale sprawa się komplikuje jeśli mamy wiele serwerów. Musielibyśmy albo zapewnić że wszystkie części poszły na ten sam fizycznie serwer (load balancing z jakimś hashowaniem po ip) albo sklejać je w ostatnim asynchronicznie ściągając wszystkie części jeszcze raz z naszych serwerów (raczej bez sensu, ale raczej nie do uniknięcia jeśli mamy nieodpowiedni do tej sytuacji load balancing).
To tak na szybko, zapewne można tu wiele dopisać ciekawych problemów :-).
Nie znam sytuacji jaka panuje w aplikacji, ale ja jestem zwolennikiem odejścia od http jak tylko można. Tzn. http ma konkretne zastosowania i tyle. Może pomyśleć o warstwie transportowej AMQP, kodowaniem plików do base64, granulacja czy coś w ten deseń?
Fajnie byłoby jakbyś podał konkretne ku temu powody. Niezależnie od tego czy się pała miłością do http czy nie prawda jest taka, że internet na tym stoi. Jeśli mam możliwość użyć tak stabilnego narzędzia jak nginx to nie zastanawiam się ani chwili. Każde inne rozwiązanie prawd. będzie musiał rozwiązać część problemów, które w nginxie (czy innym stabilnym serwerze) zostało już dawno rozwiązane.
Dzięki za pomoc!
Właśnie klient jest przygotowany na to, że wysyła mniejsze pliki ok. 100kB, a w razie potrzeby można to dość swobodnie zmienić. Ponieważ na razie korzystam z jednego serwera i obecnie projekt jest na bardzo wczesnym etapie, to korzystam wstępnie z uproszczenia i od razu doklejam przesłane kawałki do pliku wynikowego, ale na pewno te wskazówki o nginx się przydadzą, dzięki! W przyszłości myślę o tym, żeby mieć osobne miejsce do gromadzenia danych. myślę tu mniej więcej o takiej architekturze:
client -> IP load balancing -> web app -> backend API -> storage
To co będzie storage’m to jeszcze nie wiem. Możliwe, że dodatkowy dysk lub może coś pokrewnego Hadoop.
Czy w takim przypadku dałoby się przesyłać pliki poprzez web app od razu do storage, z pominięciem backendu (serwera Rails z API)? Co do gromadzenia danych, to myślę że nie będzie problemu, ponieważ każdy transfer rejestruje w bazie danych, a klient może przesłać w HTTP dowolne parametry jakie byłyby potrzebne.
Napisałem, że nie znam sytuacji jaka Panuje w aplikacji. Zgadzam się z Tobą, że wiele można zrobić po stronie Nginix i jest to jak najbardziej pewne rozwiązanie. Ale protokół http nie został do tego stworzony, jest to rozwiązanie niewydajne w porównaniu do AMQP. Zamiast od razu zastanawiać się nad load balancingiem i rozwiązaniami sprzętowymi lepiej na wstępie zastanowić się co można zrobić po stronie softu.
Protokół http nie został do czego zrobiony? Do uploadu plików? Ja rozumiem, że w przypadku małych requestów http narzut na nagłówki jest spory, ale w przypadku uploadu plików przestaje mieć to znaczenie bo 99% zajmie zawartość pliku (no chyba, że uploadujesz pliki kilku bajtowe…). AMQP jak sama nazwa mówi dotyczy protokołu wiadomości (czyli raczej małych paczek danych). Prosiłbym o jakieś konkretne materiały http vs AMQP w kontekście uploadu plików. W innym przypadku to co napisałeś to jakieś bzdury.