The Skinny on Fat, Thin, Hollow, and Uber - DZone Java

Iată cam tot ce ați putea dori să știți despre tehnicile dvs. preferate de ambalare pentru Java - JAR-uri subțiri, JAR-uri grase/uber, JAR-uri subțiri și JAR-uri goale.

Alăturați-vă comunității DZone și obțineți experiența completă a membrilor.

Recent mă jucam cu diverse tehnici de ambalare a microserviciilor Java și rulam pe OpenShift folosind diferite runtime și cadre pentru a ilustra diferențele lor (WildFly Swarm vs. WildFly, Spring Boot vs. lumea etc.). Cam în același timp în care făceam acest lucru, un fir intern de listă de e-mail s-a aprins discutând unele dintre diferențe și folosind termeni precum Uber JARs, Thin WARs, Skinny WARs și câțiva alții. Unii oameni au evidențiat avantajele și dezavantajele fiecăruia, în special beneficiile abordării WAR subțiri atunci când sunt combinate cu straturi de imagine docker.

Și m-am gândit în sinea mea: nu asta face deja toată lumea? Chiar trebuie să se gândească dezvoltatorii la aceste lucruri? Dar, înainte de a intra în asta, vreau să definesc diferiții termeni pe care i-am auzit și măcar să-i înțeleg direct în propriul meu cap.

Calificativele (în ordine crescătoare a dimensiunii logice):

  • Slab - Conține NUMAI biții pe care îi introduceți literalmente în editorul de cod și NIMIC altceva.
  • Subţire - Conține toate cele de mai sus PLUS dependențele directe ale aplicației de aplicația dvs. (drivere db, biblioteci de utilități etc.).
  • Gol - Inversul Thin - Conține doar biții necesari pentru a rula aplicația, dar NU conține aplicația în sine. Practic, un „server de aplicații” preambalat pe care vă puteți implementa ulterior aplicația, în același stil ca serverele tradiționale de aplicații Java EE, dar cu diferențe importante, vom ajunge mai târziu.
  • Grăsime/Uber - Conține bitul pe care îl scrii literalmente PLUS dependențele directe ale aplicației tale PLUS biții necesari pentru a rula aplicația „pe cont propriu”.

thin

Acum să definim modul în care calificativele se mapează în lumea aplicațiilor Java și a tipurilor de pachete (JAR, WAR etc.).

GRAS/Uber JAR

Maven și în special Spring Boot au popularizat această abordare binecunoscută a ambalajului, care include tot ce este necesar pentru a rula întreaga aplicație într-un mediu standard Java Runtime (adică pentru a putea rula aplicația cu java -jar myapp.jar). Cantitatea de elemente suplimentare de runtime incluse în Uberjar (și dimensiunea fișierului său) depinde de caracteristicile cadrului și de runtime pe care le folosește aplicația dvs.

Război subțire

Dacă sunteți dezvoltator Java EE, este posibil să faceți deja acest lucru. Este ceea ce faceți de mai bine de un deceniu, așa că felicitări sunteți încă cool! Un WAR subțire este o aplicație web Java EE care conține doar conținutul web și logica de afaceri pe care ați scris-o, împreună cu dependențe terțe. Nu conține nimic furnizat de runtime-ul Java EE, prin urmare este „subțire”, dar nu poate rula „singur” - trebuie să fie implementat pe un server de aplicații Java EE sau un container Servlet care conține „ultima milă” de biți necesari pentru a rula aplicația pe JVM.

JAR subțire

La fel ca un WAR WAR, cu excepția utilizării formatului de ambalare JAR. De obicei, aceasta este utilizată de aplicații specializate/arhitecturi de pluginuri care utilizează formatul de ambalare JAR pentru plugin-ul construit special sau pentru artefacte de execuție. De exemplu, formatul .kjar din Drools.

Skinny WAR

Deși mai puțin cunoscut decât frații săi, un Război slab este mai subțire decât un Război subțire, deoarece nu include niciuna dintre bibliotecile terțe de care depinde aplicația. Acesta conține NUMAI codul (octet) pe care, în calitate de dezvoltator, îl introduceți literalmente în editorul dvs. Acest lucru are mult sens în lumea docker a imaginilor de containere stratificate, unde dimensiunea stratului este importantă pentru sănătatea DevOps, iar Adam Bien a făcut o treabă minunată demonstrând și explicând acest lucru. Mai multe despre asta mai târziu.

Skinny JAR

La fel ca un Skinny WAR, cu excepția utilizării ambalajelor JAR și a cadrelor construite în jurul său, cum ar fi WildFly Swarm și Spring Boot. Acest lucru are, de asemenea, un ton de sens pentru sănătatea CI/CD (și factura dvs. AWS) - întrebați doar Hubspot. Aici luați un Război subțire și eliminați toate dependențele terță parte. Ați rămas cu cea mai mică unitate atomică de aplicație (încercarea de a reda sunete mai mici ca o idee teribilă, dar cu Java 9/JPMS este posibilă) și trebuie să fie implementată într-un timp de execuție care o așteaptă ȘI are toate alți biți necesari pentru a rula aplicația (cum ar fi un HAR JAR)

Hollow JAR

Acesta este un runtime al aplicației Java care conține un server de aplicații „suficient” pentru a rula aplicații, dar nu conține nicio aplicație în sine. Poate rula singur, dar nu este atât de util atunci când rulează singur, deoarece nu conține aplicații și nu va face altceva decât să se inițializeze singur. Unele proiecte precum WildFly Swarm vă permit să personalizați cât este „suficient”, în timp ce altele (cum ar fi Paraya Micro sau TomEE) oferă distribuții pre-construite ale combinațiilor populare de componente runtime, cum ar fi cele definite de Eclipse MicroProfile.

Celelalte combinații

  • Hollow WAR - În teorie, ați putea împacheta un fel de aplicație pentru a rula într-un alt server de aplicații și apoi a implementa aplicații în acel strat interior. Mult noroc cu asta!
  • Fat/Uber WAR - Nu are sens cu ideea generală că Fat/Ubers poate fi rulat cu java-jar.
  • Fișiere EAR - prin definiție, un fișier EAR nu poate fi gol, gras sau slab, deci tot ce puteți crea este un EAR subțire (care este ceea ce este deja, prin definiție). Deplasați-vă, nimic de văzut aici, cu excepția faptului că fișierele EAR ar putea fi vehiculul care transportă dependențe pentru WAR-uri slabe din EAR.

De ce sa te deranjezi?

Creșterea computerului închiriat și popularitatea proceselor DevOps, a containerelor Linux și a arhitecților de microservicii au făcut din nou importanța aplicației (numărul de octeți care alcătuiesc aplicația dvs.). Atunci când implementați în medii de dezvoltare, testare și producție de mai multe ori pe zi (uneori sute pe oră sau chiar de 2 miliarde de ori pe săptămână), minimizarea dimensiunii aplicației dvs. poate avea un impact uriaș asupra eficienței generale a DevOps și asupra funcționalității dvs. sănătate psihică. Nu trebuie să minimizați liniile de cod din aplicația dvs., dar ar trebui să reduceți de câte ori aplicația dvs. și dependențele acesteia trebuie să treacă printr-o rețea, să se deplaseze pe sau pe un disc sau să fie procesate de un program . Asta înseamnă să împărțiți aplicația în diferite părți ambalate, astfel încât să poată fi separate în mod corespunzător și tratate ca atare (și chiar versionate, dacă doriți).