Q&A Verstaan ​​Java geheue gedrag in Docker
Ons huidige Kubernetes-kluster wat in Google Container Engine (GKE) loop, bestaan ​​uit n1-standard-1masjientipes (1 virtuele SVE en 3,75 GB geheue) wat Debian GNU/Linux 7.9 (wheezy) gebruik wat deur Google onderhou word. Weens verhoogde vrag en geheuegebruik van ons dienste moet ons ons nodusse na 'n groter masjientipe opgradeer. Terwyl ons dit in ons toetsgroep probeer het, het ons iets ervaar wat (vir ons) nogal vreemd lyk.
Die geheue wat deur die JVM-toepassing verbruik word wanneer dit na 'n Google-nodus ontplooi word, blyk eweredig te wees aan die aantal kerne wat op die nodus beskikbaar is. Selfs as ons die JVM max geheue (Xmx) op 128Mb stel, verbruik dit ongeveer 250Mb op 'n 1-kern masjien (dit is verstaanbaar aangesien die JVM meer geheue verbruik as die maksimum limiet as gevolg van GC, die JVM self ens), maar dit verbruik ongeveer 700Mb op 'n 2-kern masjien ( n1-standard-2) en ongeveer 1,4 Gb op 'n 4-kern masjien ( n1-standard-4). Die enigste ding wat verskil is die masjientipe, dieselfde Docker-beeld en konfigurasies word gebruik.
As ek byvoorbeeld SSH in 'n masjien gebruik met 'n n1-standard-4masjientipe en hardloop sudo docker stats <container_name>, kry ek dit:
As ek dieselfde Docker-beeld met presies dieselfde (toepassing) konfigurasie plaaslik (mac osx en docker-masjien) gebruik, sien ek:
Wat baie meer in pas is met wat ek sou verwag as gevolg van die Xmxinstelling (vir die rekord het ek 8 kerns en 16 Gb geheue). Dieselfde ding word bevestig wanneer ek top -p <pid>op die GKE-instansie hardloop wat my 'n RES/RSS-geheuetoewysing van 1.1 tot 1.4 Gb gee.
Die Docker-beeld word soos volg gedefinieer:
Ek het ook probeer byvoeg:
wat ek in verskeie drade soos hierdie aanbeveel het gesien, maar dit lyk nie of dit enige verskil maak nie. Ek het ook probeer om na 'n ander Java-basisbeeld te verander sowel as om alpine linux te gebruik, maar dit lyk ook nie of dit dinge verander nie.
My plaaslike Docker-weergawe is 1.11.1 en die Docker-weergawe in Kubernetes/GKE is 1.9.1. Die Kubernetes-weergawe (as dit saak maak) is v1.2.4.
Wat ook interessant is, is dat as ons veelvuldige gevalle van die peul/houer na dieselfde masjien/nodus ontplooi, sommige gevalle baie minder geheue sal toeken. Die eerste drie kan byvoorbeeld 1.1-1.4Gb geheue toewys, maar dan ken die 10 opeenvolgende houers slegs ongeveer 250 Mb elk toe, wat ongeveer is wat ek elke keer sou verwaginstansie toe te ken. Die probleem is dat as ons die geheue beperking van die masjien bereik, die eerste drie gevalle (diegene wat 1.1Gb geheue toeken) blykbaar nooit hul toegewese geheue vrystel nie. As hulle geheue sou vrystel wanneer die masjien onder verhoogde druk is, sou ek nie hieroor bekommerd wees nie, maar aangesien hulle die geheuetoewysing behou, selfs wanneer die masjien gelaai is, word dit 'n probleem (aangesien dit verbied dat ander houers op hierdie masjien geskeduleer word en dus word hulpbronne vermors).
Wat kan hierdie gedrag veroorsaak? Is dit 'n JVM-kwessie? Docker-kwessie? VM probleem? Linux kwessie? Konfigurasieprobleem? Of dalk 'n kombinasie?
Wat kan ek probeer doen om die geheuetoewysing van die JVM in hierdie geval te beperk?
Wanneer jy spesifiseer
dan word die waardes wat jy van plan is om JVM-argumente ( -Xmx128m -server) te wees as opdragreëlargumente na die Hoofklas in die .jar-lêer deurgegee. Hulle is beskikbaar as die args in jou public static void main(String... args)metode.
Let daarop dat dit ook waar is as jy 'n hoofklas op naam bestuur, eerder as om 'n uitvoerbare jarlêer te spesifiseer .
Om dit as JVM-argumente, eerder as argumente aan jou program deur te gee, moet jy hulle voor die -jararg.
Die probleem was met die JVM-instellings wat in die Dockerfile. Ons het ons JVM so begin:
maar toe ons oorgeskakel het na:
die instellings is in ag geneem. Ek verstaan ​​egter steeds nie hoekom ek dit nie plaaslik gesien het nie, maar ek is net bly dat ons dit reggekry het.
Redelike geheuelimietalarm vir 2GB-masjien wat RHEL5-bedryfstelsel gebruik
wanneer word die jvm-hoop deur die bedryfstelsel toegewys
Monitor Java-toepassingsgeheue binne Cloud Foundry
docker-masjien geheue toewysing
Waarom gebruik dieselfde Java-diens tot 4x die RAM wanneer 1 kern vs 2 cores gebruik word
Java-toepassing word in kubernetes doodgemaak terwyl die hulpbronlimiete en hoopgrootte gespesifiseer word