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

溫馨提示×

溫馨提示×

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

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

Docker容器中怎么部署Java微服務

發布時間:2021-07-30 18:11:09 來源:億速云 閱讀:390 作者:Leah 欄目:云計算

Docker容器中怎么部署Java微服務,針對這個問題,這篇文章詳細介紹了相對應的分析和解答,希望可以幫助更多想解決這個問題的小伙伴找到更簡單易行的方法。

基本定位

要確定 docker 容器內存超限問題的直接原因并不難。直接進入docker容器,執行 top 命令,我們發現宿主機是一臺8核16G的機器,而且 docker 并不會屏蔽這些信息,也就是 JVM 會認為自己工作于一臺 16G 內存的機器上。而查看 demo 服務的 Dockerfile,發現運行服務時并沒有對 JVM 的內存進行任何限制,于是 JVM 會根據默認的設置來工作 —— 最大堆內存為物理內存的1/4(這里的描述并不完全準確,因為 JVM 的默認堆內存大小限制比例其實是根據物理內存有所變化的,具體內容請自行搜索資料),而基于模板創建的 ServiceStage 流水線,在部署應用堆棧的時候會把 docker 容器的內存配額默認設置為 512M,于是容器就會在啟動的時候內存超限了。至于以前沒有碰到過這種問題的原因,只是因為以前沒將這么高規格的 ECS 服務器用于流水線部署應用堆棧。

在查詢過相關資料后,我們找到了兩種問題解決方案,一個是直接在 jar 包運行命令里加上 -Xmx 參數來指定最大堆內存,不過這種方式只能將 JVM 堆內存限制為一個固定的值;另一個方法是在執行 jar 包時加上 -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap 參數,讓 JVM 能夠感知到docker容器所設置的 cgroup 限制,相應地調整自身的堆內存大小,不過這個特性是 JDK 8u131 以上的版本才具備的。

最終,我們提醒 ServiceStage 流水線的同學將 CSEJavaSDK demo 的創建模板做了改進,在 Dockerfile 中將打包的基礎鏡像版本由原先的 java:8u111-jre-alpine 升級為了 openjdk:8u181-jdk-alpine,并且在運行服務 jar 包的命令中加上了 -Xmx256m 參數。問題至此已經解決了。

3. 進一步的探究

雖然問題已經解決,但是在好奇心的驅使下,我還是打算自己找個 demo 實際去觸發一下問題,另外看看從網上搜到的解決方法到底好不好用 : )

3.1 準備工作

  1. 創建云上工程

    Docker容器中怎么部署Java微服務

    首先需要在華為云 ServiceStage 創建一個云上工程。

    在 ServiceStage -> 應用開發 -> 微服務開發 -> 工程管理 -> 創建云上工程中,選擇“基于模板創建”,語言選擇 Java, 框架選擇 CSE-Java (SpringMVC),部署系統選擇“云容器引擎CCE”,給你的云上工程取一個名字,比如test-memo-consuming,最后選擇存放代碼的倉庫,就可以完成云上工程的創建了。

    之后云上工程會根據你的選項自動地生成腳手架代碼,上傳到你指定的代碼倉庫中,并且為你創建一條流水線,完成代碼編譯、構建、打包、歸檔鏡像包的操作,并且使用打好的 docker 鏡像包在 CCE 集群中部署一個應用堆棧。

    創建云上工程和流水線不是本文的重點,我就不詳細講操作了 : )。同一個應用堆棧的實例可以部署多個,在這里為了實驗方便就按照默認值1個來部署。

    Docker容器中怎么部署Java微服務

    登錄到 demo 服務所部署的容器,使用curl命令可以調用 demo 服務的 helloworld 接口,可以看到此時服務已經可以正常工作。

  2. 增加實驗代碼

    為了能夠觸發微服務實例消耗更多的內存,我在項目代碼中增加了如下接口,當調用/allocateMemory接口時,微服務實例會不停申請內存,直到 JVM 拋出 OOM 錯誤或者容器內存超限被 kill 掉。

    private HashMap<String, long[]> cacheMap = new HashMap<>();
    
    @GetMapping(value = "/allocateMemory")
    public String allocateMemory() {
    LOGGER.info("allocateMemory() is called");
    try {
      for (long i = 0; true; ++i) {
        cacheMap.put("key">


    此時用來打鏡像包的基礎鏡像是openjdk:8u181-jdk-alpine,jar 包啟動命令中加上了-Xmx256m參數。

    執行流水線,應用堆棧部署成功后,調用/allocateMemory接口觸發微服務實例消耗內存,直到 JVM 拋出 OOM 錯誤,可以在 ServiceStage -> 應用上線 -> 應用管理中選擇相應的應用,點擊進入概覽頁面,查看應用使用內存的情況。

    Docker容器中怎么部署Java微服務 應用使用的內存從 800M+ 陡然下降的時間點就是我重新打包部署的時間,而之后由于調用/allocateMemory接口,內存占用量上升到了接近 400M,并且在這個水平穩定了下來,顯示-Xmx256m參數發揮了預期的作用。

3.2 復現問題

現在將 demo 工程中的 Dockerfile 修改一下,將基礎鏡像改為 java:8u111-jre-alpine,并且刪除啟動命令中的-Xmx256m參數,將其提交為noLimit_oldBase分支,推送到代碼倉庫中。然后編輯流水線,將 source 階段的任務所使用的代碼分支改為noLimit_oldBase分支,保存并重新運行流水線,將新的代碼打包部署到應用堆棧中。

在微服務實例列表中查詢到新的微服務實例的 endpoint IP 后,調用/allocateMemory接口,觀察內存情況,內存從接近 400M 突然掉下去一下,然后又上升到約 450M 的時間點就是修改代碼后的微服務實例部署成功的時間點,之后內存占用量突然下跌就是因為調用/allocateMemory接口導致容器內存超限被 kill 掉了。

如果你事先使用docker logs -f命令查看容器日志的話,那么日志大概是這個樣子的

2018-11-23 15:40:04,920  INFO SCBEngine:152 - receive MicroserviceInstanceRegisterTask event, check instance Id...
2018-11-23 15:40:04,920  INFO SCBEngine:154 - instance registry succeeds for the first time, will send AFTER_REGISTRY event.
2018-11-23 15:40:04,925  WARN VertxTLSBuilder:116 - keyStore [server.p12] file not exist, please check!
2018-11-23 15:40:04,925  WARN VertxTLSBuilder:136 - trustStore [trust.jks] file not exist, please check!
2018-11-23 15:40:04,928  INFO DataFactory:62 - Monitor data sender started. Configured data providers is {com.huawei.paas.cse.tcc.upload.TransactionMonitorDataProvider,com.huawei.paas.monitor.HealthMonitorDataProvider,}
2018-11-23 15:40:04,929  INFO ServiceCenterTask:51 - read MicroserviceInstanceRegisterTask status is FINISHED
2018-11-23 15:40:04,939  INFO TestmemoconsumingApplication:57 - Started TestmemoconsumingApplication in 34.81 seconds (JVM running for 38.752)
2018-11-23 15:40:14,943  INFO AbstractServiceRegistry:258 - find instances[1] from service center success. service=default/CseMonitoring/latest, old revision=null, new revision=28475010.1
2018-11-23 15:40:14,943  INFO AbstractServiceRegistry:266 - service id=8b09a7085f4011e89f130255ac10470c, instance id=8b160d485f4011e89f130255ac10470c, endpoints=[rest://100.125.0.198:30109?sslEnabled=true]
2018-11-23 15:40:34,937  INFO ServiceCenterTaskMonitor:39 - sc task interval changed from -1 to 30
2018-11-23 15:47:03,823  INFO SPIServiceUtils:76 - Found SPI service javax.ws.rs.core.Response$StatusType, count=0.
2018-11-23 15:47:04,657  INFO TestmemoconsumingImpl:39 - allocateMemory() is called
Killed

可以看到allocateMemory方法被調用,然后 JVM 還沒來得及拋出 OOM 錯誤,整個容器就被 kill 掉了。

這里也給大家提了一個醒:不要以為自己的服務容器能啟動起來就萬事大吉了,如果沒有特定的限制,JVM 會在運行時繼續申請堆內存,也有可能造成內存用量超過 docker 容器的配額!

3.3 讓 JVM 感知 cgroup 限制

前文提到還有另外一種方法解決 JVM 內存超限的問題,這種方法可以讓 JVM 自動感知 docker 容器的 cgroup 限制,從而動態的調整堆內存大小,感覺挺不錯的。我們也來試一下這種方法,看看效果如何 ; )

回到demo項目代碼的master分支,將 Dockerfile 中啟動命令參數的-Xmx256m替換為-XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap,提交為useCGroupMemoryLimitForHeap分支,推送到代碼倉庫里。再次運行流水線進行構建部署。

Docker容器中怎么部署Java微服務

等 demo 服務部署成功后,再次調用/allocateMemory接口,容器的內存占用情況如上圖所示(最右邊的那一部分連續曲線),內存上升到一定程度后,JVM 拋出了 OOM 錯誤,沒有繼續申請堆內存。看來這種方式也是有效果的。不過,仔細觀察容器的內存占用情況,可以發現容器所使用的內存僅為不到 300M,而我們對于這個容器的內存配額限制為 512M,也就是還有 200M+ 是閑置的,并不會被 JVM 利用。這個利用率,比起上文中直接設置-Xmx256m的內存利用率要低 : ( 。推測是因為 JVM 并不會感知到自己是部署在一個 docker 容器里的,所以它把當前的環境當成一個物理內存只有 512M 的物理機,按照比例來限制自己的最大堆內存,另一部分就被閑置了。


關于Docker容器中怎么部署Java微服務問題的解答就分享到這里了,希望以上內容可以對大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關注億速云行業資訊頻道了解更多相關知識。

向AI問一下細節

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

AI

丽江市| 吉隆县| 砚山县| 西峡县| 玉田县| 随州市| 开远市| 海兴县| 枣强县| 南陵县| 万安县| 丰宁| 合山市| 桃源县| 桂东县| 宁津县| 阿合奇县| 承德县| 翁牛特旗| 读书| 类乌齐县| 确山县| 商丘市| 兴隆县| 靖边县| 方城县| 澎湖县| 苍南县| 富宁县| 松桃| 岳西县| 基隆市| 高邮市| 扶风县| 铅山县| 扎兰屯市| 临海市| 连州市| 定西市| 东至县| 紫金县|