Ponieważ pamiętam jak serwery aplikacji, kontenery się tworzyły to znam odpowiedź:
"są po nic - bezużyteczne".
Z perspektywy roku 2019 (i 2015 też).
Te twory miały sens w roku 2000. Zostały stworzone, aby rozwiązać ówczesne problemy:
- brak ram,
- zarządzanie konfiguracją (security, sięć itp).
Odnośnie RAM
Każdy wystartowany JVM pożera trochę ramu, do tego inicjuje różnego rodzaju pule, które są niezbędne, żeby aplikacja szybko działała (baza, http, pule wątków itd).
Pod koniec lat 90tych spece it stwierdzili, że można będzie dużo RAM na serwerach oszczędzić jak te wszystkie elementy wyciągniemy jako wspólny middleware i będziemy więcej aplikacji odpalać w ramach jednego kontenera. Żeby lepiej przybliżyć, o jakich rozmiarach RAM mówimy - mój pierwszy serwer java startowałem na maszynie z 4MB RAM (megabajtach, nie gigabajtach!) i musiałem zwiększyć RAM do 8GB, bo inaczej nie działał. Wypasione serwery miały wtedy 128MB RAM :-)
W praktyce okazało się, że RAM stał się tani i 99% aplikacji jest odpalanych samodzielnie - jeden tomcat jedna aplikacja.
Odnośnie konfiguracji - zwykle nie chcemy w aplikacji zaszywać na sztywno takich rzeczy jak porty http, adresy bazy danych itp. To wszystko dzięki tomcatowi (czy innemu serwerowi) można mieć w jednym konfigu (jako XML).
I fajnie, tylko że od kilku lat spopularyzowały się kontenery typu Docker
, które zapewniają to samo, a co więcej dla dowolnej technologii, a nie tylko javy. Zamiast mieć 6 rodzajów specjalistów od konfiguracji, można mieć teraz jeden typ na prawie wszystko
.
Jak widać te dwie przyczyny są lekko już nieaktualne, ale to nie koniec.
Gorzej, żeby te nieaktualne problemy rozwiązać trzeba ponieść duży koszt, związany ze sposobem działania kontenerów:
W przypadku użycia kontenera Startujemy jakaś aplikację kontener ( np. tomcat), a ona dopiero czyta naszą paczkę, konfigi i startuje aplikację.
I mamy często problemy typu:
-
konflikty klas, jeśli serwer wewnętrznie korzysta z jakiś bibliotek i my chcemy z podobnych to biada jak np. je dołączymy, albo jeszcze dołączymy w innej wersji, dzieją się cuda (typowo przy klasach związanych z logowaniem (`org.apache.log4j.Logger cannot be cast to org.apache.log4j.Logger), api servletów, commonsach, parsowaniu XML itp.
-
długi czas startu - serwer startuje, a potem skanuje nasze paczki - i czyta np. 500 klas, chociaż powinien się zainteresować tylko jedną z nich..., bo tam mamy servlet,
-
deployment, zabawy z wrzucaniem paczek na serwer to ciekawa historia, pakowanie do wara, które jest sztuką, czasem serwer nie załapie zmian, czasem (praktycznie zawsze) są wycieki pamięci przy restarccie aplikacji (war) itp.
-
testowalność aplikacji opartych o kontenery jest kijowa - taki prosty test typu :
- załóż testową baze danych
- wrzuć dane
- wystartuj serwer z tą testową bazą
- odpal REST i sprawdź czy serwis zwraca zakładany rezultat
Przy korzystaniu z servletów (i czegokolwiek co jest nakładką na nie: JSP, spring-mvc*
) jest dość trudny do wykonania, do tego długo trwa.
Problemów są mniejsze jeśli korzystamy z embedded serwera - wtedy konflikty klas są łatwiejsze do ogarnięcia, deployment odpada, a i również jakoś da się testować (choć nadal powoli).
Jakkolwiek, uważam że embedded serwery (tomcat itp) to kupa przykryta dywanem
. Niby nie widać, ale jednak śmierdzi. Pod spodem nadal działa sobie stara technologia zaprojektowana pod zupełnie inny sposób używania.
W 2019 jeśli robimy klasyczny REST serwis mamy dużo technologii/ bibliotek, które nie są oparte o servlety
(pierwotne źródło zła).
Panowie z technology radar, którzy są względnie konserwatywni, uznali serwery aplikacji za zbędne w 2015 :
https://www.thoughtworks.com/radar/platforms/application-servers
Wszystko to wyżej aplikuje się (nawet bardziej ) do tzw. pełnych serwerów aplikacji - Java EE.
Wersja TL;DR
Olać kontenery, korzystać z bibliotek (w ostateczności z frameworków).
Edit:
Używasz tego co ci potrzeba! Jak sie okaże że potrzebujesz wszystkiego czego dostarcza taki tomcat czy jetty to użyjesz tego tomcata, zamiast składać te wszystkie funkcjonalności z kawałków.
To podejście ma wadę. Czasem chcemy dołożyć jakąś bibliotekę, która częšciowo pokrywa się z tym co zapewnia tomcat i nagle się okazuje, że tracimy tydzień na walkę z konfliktami klas//bz.apache.org/bugzilla/show_bug.cgi?id=62353