Witam!
Jest to temat skierowany raczej do bardziej zaawansowanych programistów ruby/rails. Ja się niestety do takich nie do końca zaliczam ale, można powiedzieć, stanąłem przed faktem dokonanym. Otóż jakiś czas temu, dla firmy, w której pracuję, musiałem stworzyć prototyp prostego systemu/api do obróbki video. Obsługa go polega na wysłaniu multipartem pliku video pod odpowiedni endpoint w API wraz z dodatkowymi parametrami (z grubsza - preset, którego system ma użyć podczas obróbki video. Presety różnią się sposobem potraktowania pliku. Np. filmy przychodzące z komórek mają mieć zmienione kodeki [ze względu na wymagania azure media services] i mają być obcięte do kwadratu + mają mieć znacznie gorszą jakość).
Narzędzia
W tworzeniu tej aplikacji używamy:
- sidekiq - do obsługi asynchronicznych tasków czyli praktycznie cały proces obróbki video obdywa się za jego pomocą.
- sidekiq-superworker - do obsługi ww. presetów
- FFMPEG - obróbka plików video
- Infrastruktura Windows Azure - jako CDN, dostawca VPSów oraz dostawca narzędzia do obróbki i publikacji video (Windows Media Services). Jesteśmy z azurem politycznie związani i użycie innego narzędzia jak np. Amazon nie wchodzi w grę.
Proces
Proces, przez który przechodzi plik wygląda następująco:
- Plik wysyłany jest do aplikacji wraz z parametrami (presets)
- Aplikacja przetwarza plik (proces przetwarzania odbywa się na serwerze hostującym aplikacje, nie na żadnym amazonie czy innych przeznaczonych do tego serwisach)
- Aplikacja wyciąga klatki kluczowe i zapisuje je na CDNie
- Aplikacja wysyła plik do WIndows Media Services
- Windows Media Services tworzy kilka wersji pliku o różnych jakościach i bitrate i zapisuje je na CDNie
Problem
Ostatnio okazało się, że moja aplikacja będzie użyta w innej produkcyjnej aplikacji. Moja aplikacja jest kompletnie nie skalowalna ani nie gotowa do zastosowania produkcyjnego dlatego musi ulec gruntownemu przerobieniu. Głównym problemem aktualnie jest to, że kroki 2 i 3 są bardzo zasobożerne i jeden serwer może obsłużyć max dwa takie zadania jednocześnie. Prowadzi to do tego, że przykładowo, jeśli 10 osób wrzuciło by 40 minutowe pliki w jakości HD, to ostatnia z tych osób czekała by na jego przetworzenie cały dzień - ale to raczej jasne i byłem tego świadom tworząc prototyp.
Niestety nie jestem w stanie znaleźć żadnych użytecznych materiałów dotyczących infrastruktury używanej przez YouTube dlatego zmuszony jestem odtworzyć coś takiego własnoręcznie. I tutaj właśnie, jako średnio zaawansowany programista ruby/rails, zwracam się z ogromną prośbą do Was. Jeśli macie jakieś pomysły, rady czy jakiekolwiek doświadczenie w podobnej materii, to BŁAGAM o podzielenie się tym ze mną : )
Tak na szybko - mój pomysł polega na tym, aby system ten składał się z jednej aplikacji głównej [master] (która zbierała by requesty o przetworzenie filmu i ogólnie informacje co się aktualnie z którym filmem dzieje) oraz z mini-aplikacji [slave], które zajmowały by się już stricte procesami opisanymi w pkt. 2 i 3. Aby cała ta infrastruktura była elastyczna i odporna na dowolnie duży ruch, proces miał by wyglądać następująco:
- Plik video przychodzi wraz z ustawieniami do aplikacji głównej
- aplikacja główna sprawdza, czy uruchomione są aktualnie jakieś serwery [slave]. Jeśli nie, to:
- Stawia nowy serwer z obrazu dysku przy pomocy Windows Azure API
- Instaluje na nim z gita aplikacje [slave]
- deleguje tej aplikacji “pracę” nad otrzymanym video
- Jeśli istnieje jakiś serwer [slave], który “nie ma nic do roboty”, to deleguje mu obróbkę video
- Aplikacja [slave], która skończy pracę nad video powiadamia [master] o zakończonej pracy i cały proces obróbki kończy się.
Do tego wszystkiego, jeśli [master] uzna, że jakiś [slave] zbyt długo podpiera ścianę, to go uśpi (lub zupełnie skasuje) żeby ograniczyć koszta.
Co myślicie o takim rozwiązaniu? Z góry dzięki za jakąkolwiek pomoc. Jestem jedynym programistą w firmie i potrzebuję z kimś o tym pogadać hehe