中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

如何在Docker里跑Java

發布時間:2021-12-13 17:42:51 來源:億速云 閱讀:186 作者:iii 欄目:云計算

本篇內容介紹了“如何在Docker里跑Java”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!

背景:眾所周知,當我們執行沒有任何調優參數(如“java-jar mypplication-fat.jar”)的 Java 應用程序時,JVM 會自動調整幾個參數,以便在執行環境中具有最佳性能。

但是許多開發者發現,如果讓 JVM ergonomics (即JVM人體工程學,用于自動選擇和行為調整)對垃圾收集器、堆大小和運行編譯器使用默認設置值,運行在 Linux 容器(docker,rkt,runC,lxcfs 等)中的 Java 進程會與我們的預期表現嚴重不符。

懶人超精簡閱讀版:

a.JVM 做不了內存限制,一旦超出資源限制,容器就會出錯

b.即使你多給些內存資源,也沒什么卵用,只會錯上加錯

c.解決方案:用 Dockfile 中的環境變量來定義 JVM 的額外參數

d.更進一步:使用由 Fabric8 社區提供的基礎 Docker 鏡像來定義 Java 應用程序,將始終根據容器調整堆大小

詳細全文:

我們往往把容器當虛擬機,讓它定義一些虛擬 CPU 和虛擬內存。其實容器更像是一種隔離機制:它可以讓一個進程中的資源(CPU,內存,文件系統,網絡等)與另一個進程中的資源完全隔離。Linux 內核中的 cgroups 功能用于實現這種隔離。

然而,一些從執行環境收集信息的應用程序已經在 cgroups 存在之前就被執行了。“top”,“free”,“ps”,甚至 JVM 等工具都沒有針對在容器內執行高度受限的 Linux 進程進行優化。

1.存在的問題

為了演示,我用“docker-machine create -d virtualbox –virtualbox-memory ‘1024’ docker1024”在1GB RAM 的虛擬機中創建了 docker daemon。接下來,在一個虛擬內存為100MB 的容器里面跑三個不同的Linux distribution,執行 “free -h”命令,結果是:它們都顯示了995MB 的總內存。

如何在Docker里跑Java

即使在 Kubernetes / OpenShift 集群中,結果也類似。

我在一個15GB 內存的集群中跑一個 Kubernetes Pod ,并將 Pod 的內存限制為512M (通過“kubectl run mycentos –image=centos -it –limits=’memory=512Mi'”命令實現),最后顯示的總內存卻是14GB

如何在Docker里跑Java

如果想知道為什么會發生這種情況,建議您閱讀博客“Memoryinside Linux containers – Or why don’t free and top work in a Linux container?”(https://fabiokung.com/2014/03/13/memory-inside-linux-containers/)

docker switches(-m,-memory和-memory-swap)和kubernetes switch(–limits)在進程超過限制的情況下,會指示 Linux 內核殺死該進程;但 JVM 是完全不知道限制,所以在進程超過限制的時候,糟糕的事情就發生了!

為了模擬在超過指定的內存限制后被殺死的進程,我們可以通過“docker run -it –name mywildfly -m=50m jboss/wildfly” 命令在50MB 內存限制的容器中跑WildFly應用 server,用 “dockerstats” 命令來檢查容器限制。

如何在Docker里跑Java

但是在幾秒鐘之后,Wildfly 的容器執行將被中斷并顯示:*** JBossAS process (55) received KILL signal ***

“docker inspect mywildfly -f ‘{{json.State}}'” 命令顯示由于 OOM(內存不足),該容器已被殺死。注意容器 “state” 中的OOMKilled = true。

如何在Docker里跑Java

2.JAVA的應用程序是如何被影響的?

在docker daemon里用 Dockerfile 中定義的參數-XX:+ PrintFlagsFinal和-XX:+ PrintGCDetails起一個 java 應用。

其中 machine:1GB RAM 容器內存:限制為150M (對于這個Spring Boot應用,似乎夠用)

這些參數允許我們讀取初始JVM人機工程學參數,并了解有關垃圾收集(GC)執行的詳細信息。

動手試一下:

如何在Docker里跑Java

我已經在“/ api / memory /”上準備了一個端點,它使用 String 對象加載 JVM 內存來模擬消耗大量內存的操作。我們來調用一次:

如何在Docker里跑Java

此端點將回復“分配超過80%(219.8 MiB)的最大允許 JVM 內存大小(241.7 MiB)”

在這里我們可以提至少兩個問題:

  • 為什么JVM最大允許內存241.7 MiB?

  • 如果這個容器將內存限制為150MB,那為什么它允許Java分配近220MB?

首先,我們需要回顧一下 JVM 人機工程學頁面上關于“最大堆大小”的內容:是物理內存的1/4。由于 JVM 不知道它在一個容器內執行,所以允許最大堆大小將接近260MB。鑒于我們在容器初始化期間添加了-XX:+ PrintFlagsFinal標志,我們可以檢查這個值:

如何在Docker里跑Java

其次,我們需要了解,當我們在 docker 命令行中使用參數“-m 150M”時,docker daemon將在RAM中限制150M ,在 Swap 中限制為150M。因此,該過程可以分配300M。這就解釋了為什么我們的進程沒有被殺死。

docker 命令行中的內存限制(-memory)和swap(-memory-swap)之間的更多組合可以在這里(https://docs.docker.com/engine/reference/run/#example-run-htop-inside-a-container)找到。

3.提供更多內存是否靠譜?

不了解問題的開發者往往認為環境不能為執行 JVM 提供足夠的內存。所以通常的解決辦法是提供更多內存,這實際上會使事情變得更糟。

我們假設將 daemon 從1GB 更改為8GB (使用“docker-machinecreate -d virtualbox –virtualbox-memory ‘8192’ docker8192”創建),并將容器內存從150M 更改為800M :

如何在Docker里跑Java

請注意這次, “curl http://`docker-machine ipdocker8192`:8080/api/memory” 命令甚至沒有執行完,因為在8GB 環境中計算的 JVM 的MaxHeapSize 為2092957696字節(?2GB)。檢查 “docker logs mycontainer|grep -i MaxHeapSize”

如何在Docker里跑Java

該應用將嘗試分配超過1.6GB 的內存,這超出了此容器的限制(RAM 中的800MB + Swap中的800MB),并且該進程將被殺掉。

很顯然,用增加內存且讓 JVM 自定義參數的方式在容器里跑Java,不是什么好主意 在容器內部運行 Java 應用程序時,我們應該根據應用程序需求和容器限制設置最大堆大小(-Xmx參數)。

4.解決方案

Dockerfile 的一個細微變化允許用戶指定一個環境變量來定義 JVM 的額外參數。 檢查以下行:

如何在Docker里跑Java

現在我們可以使用 JAVA_OPTIONS 環境變量來通知 JVM 堆的大小。對于這個應用程序,300M 就夠了。稍后可以檢查日志并獲取314572800字節(300MBi)的值

對于docker,您可以使用“-e”switch指定環境變量。

如何在Docker里跑Java

在Kubernetes中,您可以使用switch “-env = [key = value]”設置環境變量:

如何在Docker里跑Java

再進一步

如果可以根據容器限制自動計算堆的值,該怎么做?

使用由Fabric8社區提供的基礎Docker鏡像,就可以搞定。這個鏡像 fabric8 / java-jboss-openjdk8-jdk 使用一個腳本來計算容器限制,并使用50%的可用內存作為上限。 請注意,這個50%的內存比可以被復寫。 您還可以使用此鏡像來啟用/禁用調試,診斷等。

如何在Docker里跑Java

下面一起看看 Dockerfile 是如何作用于這個 Spring Boot 應用程序:

搞定!現在,無論容器內存限制是多少,我們的 Java 應用程序將始終根據容器調整堆大小,而不是根據 daemon 調整堆大小。

如何在Docker里跑Java

“如何在Docker里跑Java”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

合川市| 长治市| 杭锦后旗| 蒲城县| 阳信县| 苍山县| 丹巴县| 德庆县| 南昌市| 大庆市| 天等县| 大同市| 乐业县| 乃东县| 永康市| 文登市| 旬阳县| 德兴市| 遂川县| 万山特区| 伽师县| 阿巴嘎旗| 锡林郭勒盟| 阳城县| 外汇| 巴中市| 百色市| 金阳县| 嘉鱼县| 宁阳县| 长岛县| 友谊县| 唐海县| 广汉市| 上高县| 石河子市| 武胜县| 宁海县| 淳化县| 太湖县| 资中县|