Gure inguruan enpresa asko daude Java erabili izan dutenak beraien aplikazioak garatzeko. Horretarako Spring, Tomcat, Weblogic eta JPA bezelako tresnak erabili ohi dira. Azpiegitura hau nahiko egonkorra izan da beti eta aldaketa gutxi jasan ditu.

Azkenaldian, Kubernetes-en oinarrituta dauden “cloud” infraestuktura berriak plazaratu dira (Azure, Openshift, Amazon EKS, etab.). Enpresa asko Kubernetes ebaluatzen hasten direnean zalantza ugari izaten dituzte, adibidez, orain arte erabilitako teknologiak “cloud”-era joateko egokiak al dira?

Beti gertatzen den bezala, zalantzak argitzeko egiten dugun lehenengo gauza Google-i galdetzea da eta emaitzak aztertuz gero, bildurra ematen duten artikuluak aurkitu ditzakegu. Adibidez, Nobody puts Java in a container edo Nobody puts Java in the container.

Nobody puts java in containers

Hau ikusita, hurrengo galdera egiten diogu gure buruari: Java docker edukiontzitan exekutatzea bideragarria da?

Java Ergonomics

Java plataforma, 1995 urtean sortu zen eta hortik gutxira, web zerbitzariak eta aplikazioen zerbitzariak zabaldu ziren web aplikazioak Java lengoaian garatu ahal izateko. Garai horretan, oraindik ez zen edukiontzien kontzeptua existitzen ezta “Cloud Native” mugimendua ere. Normalean Java web aplikazioak (war-ak edo ear-ak), zerbitzari batean exekutatzen ziren beste hainbat aplikazioekin batera.

Java mota horretako azpiegituratan exekutatzeko diseinatua izan zen, hau da, JVM bakarra duen zerbitzari bat. Hori kontutan hartuta, JVM-ak Java Ergonomics prozesua exekutatzen du. Java Ergonomics-aren lana, JVM-aren konfigurazio parametroak kalkulatzea da eta horretarako erabilgarri dauden hardwarearen errekurtsoak aintzat hartzen ditu. Adibidez, Java Ergonomics-ak, JVMaren heap-aren tamaina maximoa ezartzeko zerbitzariak guztira duen RAMaren laurden bat erabiltzen du. Hau da, zerbitzari batek 64GB RAM baditu, lehenetsitako heap-aren tamaina maximoaren balioa 16GBtakoa izango da.

JVM bakoitzeko zerbitzari bat erabiltzen badugu, aurreko planteamenduarekin ez dago inongo arazorik, baino, zer gertatzen da Java Ergonomics Docker edukiontzi batean exekutatzen denean?

Lehenengo esperientziak Java eta Docker-ekin

Java aplikazio bat edukiontzi batean exekutatzen dugunean, Java Ergonomics prozesuak JVMaren parametroak edukiontziaren baliabideen arabera kalkulatzea interesatzen zaigu. Adibidez, edukiontzi bat 4GBekin exekutatzen badugu, Java Ergonomics-ak 1GBeko heap maximoa ezartzea esperoko genuke.

Tamalez, Java aplikazioak edukiontzitan exekutatzen hasi ginenean, gauzak horrela ez zirela ikusi genuen. Java Ergonomics-ak, heap maximoaren kalkulua zerbitzariaren baliabideen arabera egiten zuen, ez edukiontziaren baliabideen arabera. Hortaz, zerbitzariak 64GB RAM bazituen, heap-aren tamaina maximoa 16GBtan ezartzen zen eta ez guk espero genuen 1GBean. Hori dela eta, aplikazio bat eskalatzean (5 edukiontzitara adibidez), zerbitzariaren memoria agortu egiten zen edukiontzi guztien heap-aren baturak zerbitzariaren memoria gainditzen zuelako (16GB * 5 > 64GB).

Hau konpontzeko, Java Ergonomics-en flag batzuk erabili ohi genituen (-Xmx, -Xms, etab.). Hala ere, enpresa askok ez zuten guzti honen berri eta konturatu zirenerako, produkzioan zeuzkaten aplikazioetan memoria arazoak (OOMKilled erroreak) eta erorketak jasaten ari ziren. Arazo hauen eraginez, artikulu asko idatzi ziren Java aplikazioak edukiontzitan exekutatzeko zeuden arriskuak jakinarazteko helburuarekin.

Java Container Aware

Oracle-k arazo hauei erantzuna eman zien eta Java 8u131 eta Java 9 bertsioetan aplikazioak edukiontziekin bateragarriak egin zituzten nahiz eta modu espermientalean eta zenbait gabeziekin izan. Java 8u191 eta Java 10 bertsioetan arazo guzti hauek konpondu egin ziren

Bertsio berri hauetatik aurrera, Java Ergonomics prozesuak JVMaren konfigurazioa kalkulatzeko, edukiontziaren baliabideak automatikoki aintzat hartzen ditu. Java bertsio ezberdinen arteko ezberdintasunak probatu nahi badituzue, Git biltegi honetan dagoen kodearekin frogak egin ditzakezue.

Aldaketa hauekin batera, JVMan edukiontzitara zuzendutako konfigurazio aukera berriak gehitu ziren: InitialRAMPercentage, MaxRAMPercentage y MinRAMPercentage.

Aldaketa guzti hauei esker, Java “Container Aware” dela esaten da Java 8u191 eta Java 10 bertsioetatik aurrera.

Ondorioak

Java 1995. urtean sortu zenean, inorrek ezin zuen aurreikusi Docker eta Kubernetes bezalako teknologiak sortuko zirela. Hori kontutan izanda, Java aplikazioak edukiontzitan exekutatzea bideragarria al da?

Erantzuna baiezkoa da, Java komunitatea teknologia berrietara moldatzen ari da. Lehenengo oztopoa Java Ergonomics-ekin erlazionatuta zegoen eta dagoeneko konponduta dago. Hala eta guztiz ere, badaude beste alor batzuk hobetzeko, adibidez, JVMak duen tamaina. Horren inguruan, gertutik jarraitu beharreko tresna eta framework ugari agertzen hasi dira (Graal Native Image, Micronaut, Quarkus, etab.).