<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                Docker 從 2013 年發展到現在,它的普及率已經可以和最常用的 MySQL 和 Redis 并駕齊驅了,從最初偶爾出現在面試中,到現在幾乎成為面試中必問的問題之一。如果再不了解 Docker 相關的知識點,可能就會與自己心儀的職位擦肩而過。所以本課時將會帶領你對 Docker 相關的知識做一個全面的認識。 我們本課時的面試題是,Docker 是什么?它有什么優點? #### 典型回答 Docker 是一個開源(開放源代碼)的應用容器引擎,可以方便地對容器進行管理。可通過 Docker 打包各種環境應用配置,比如安裝 JDK 環境、發布自己的 Java 程序等,然后再把它發布到任意 Linux 機器上。 Docker 中有三個重要的概念,具體如下。 * 鏡像(Image):一個特殊的文件操作系統,除了提供容器運行時所需的程序、庫、資源、配置等文件外,還包含了一些為運行時準備的配置參數(如匿名卷、環境變量、用戶等), 鏡像不包含任何動態數據,其內容在構建之后也不會被改變。 * 容器(Container):它是用來運行鏡像的。例如,我們拉取了一個 MySQL 鏡像之后,只有通過創建并啟動 MySQL 容器才能正常的運行 MySQL,容器可以進行創建、啟動、停止、刪除、暫停等操作。 * 倉庫(Repository):用來存放鏡像文件的地方,我們可以把自己制作的鏡像上傳到倉庫中,Docker 官方維護了一個公共倉庫 Docker Hub,你也可以點擊這里查詢并下載所有的公共鏡像。 ![](https://img.kancloud.cn/68/6d/686d25be1853473ad3e2d88f05d1b8f7_1822x958.png) 在 Docker 出現之前,我們如果要發布自己的 Java 程序,就需要在服務器上安裝 JDK(或者 JRE)、Tomcat 容器,然后配置 Tomcat 參數,對 JVM 參數進行調優等操作。然而如果要在多臺服務器上運行 Java 程序,則需要將同樣繁雜的步驟在每臺服務器都重復執行一遍,這樣顯然比較耗時且笨拙的。 后來有了虛擬機的技術,我們就可以將配置環境打包到一個虛擬機鏡像中,然后在需要的服務器上裝載這些虛擬機,從而實現了運行環境的復制,但虛擬機會占用很多的系統資源,比如內存資源和硬盤資源等,并且虛擬機的運行需要加載整個操作系統,這樣就會浪費掉好幾百兆的內存資源,最重要的是因為它需要加載整個操作系統所以它的運行速度就很慢,并且還包含了一些我們用不到的冗余功能。 因為虛擬機的這些缺點,所以在后來就有了 Linux 容器(Linux Containers,LXC),它是一種進程級別的 Linux 容器,用它可以模擬一個完整的操作系統。相比于虛擬機來說,Linux 容器所占用的系統資源更少,啟動速度也更快,因為它本質上是一個進程而非真實的操作系統,因此它的啟動速度就比較快。 而 Docker 則是對 Linux 容器的一種封裝,并提供了更加方便地使用接口,所以 Docker 一經推出就迅速流行起來。Docker 和虛擬機(VM)區別如下圖所示: ![](https://img.kancloud.cn/5f/78/5f783a35eafac24465e7206fc30f296f_1290x530.png) Docker 具備以下 6 個優點。 * 輕量級:Docker 容器主要利用并共享主機內核,它并不是完整的操作系統,因此它更加輕量化。 * 靈活:它可以將復雜的應用程序容器化,因此它非常靈活和方便。 * 可移植:可以在本地構建 Docker 容器,并把它部署到云服務器或任何地方進行使用。 * 相互隔離,方便升級:容器是高度自給自足并相互隔離的容器,這樣就可以在不影響其他容器的情況下更換或升級你的 Docker 容器了。 * 可擴展:可以在數據中心內增加并自動分發容器副本。 * 安全:Docker 容器可以很好地約束和隔離應用程序,并且無須用戶做任何配置。 #### 考點分析 通過此面試題可以考察出面試者是否真的使用或了解過 Docker 技術,然而對于面試官來說,最關注的是面試者是否了解 Docker 和 Java 程序結合時會出現的一些問題,因此這部分的內容需要讀者特別留意一下。 和此知識點相關的面試題還有以下這些: * Docker 的常用命令有哪些? * 在 Docker 中運行 Java 程序可能會存在什么問題? #### 知識擴展 * [ ] Docker 常用命令 我們在安裝了 Docker Disktop(客戶端)就可以用 docker --version 命令來查看 Docker 的版本號,使用示例如下: ``` $ docker --version Docker version 19.03.8, build afacb8b ``` 然后可以到 Docker Hub 上查找我們需要的鏡像,比如 Redis 鏡像,如下圖所示: ![](https://img.kancloud.cn/7b/f5/7bf5ff759ed77973aa9fba2414c5b32b_2622x1918.png) 接著我們選擇并點擊最多人下載的鏡像,如下圖所示: ![](https://img.kancloud.cn/10/ad/10adf055d2510123a4feb9d07b406075_2582x1802.png) 從描述中找到我們需要裝載 Redis 的版本,然后使用 docker pull redis@ 版本號來拉取相關的鏡像,或者使用 docker pull redis 直接拉取最新(版本)的 Redis 鏡像,如下所示: ``` $ docker pull redis Using default tag: latest latest: Pulling from library/redis Digest: sha256:800f2587bf3376cb01e6307afe599ddce9439deafbd4fb8562829da96085c9c5 Status: Image is up to date for redis:latest docker.io/library/redis:latest ``` 緊接著就可以使用 docker images 命令來查看所有下載的鏡像,如下所示: ``` $ docker images REPOSITORY TAG IMAGE ID CREATED SIZE redis latest 235592615444 13 days ago 104MB ``` 有了鏡像之后我們就可以使用 docker run 來創建并運行容器了,使用命令如下: ``` $ docker run --name myredis -d redis 22f560251e68b5afb5b7b52e202dcb3d47327f2136700d5a17bca7e37fc486bf ``` 查看運行中的容器,命令如下: ``` ¥ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 22f560251e68 redis "docker-entrypoint.s…" About a minute ago Up About a minute 6379/tcp myredis ``` 其中,“myredis”為容器的名稱,“6379/tcp”為 Redis 的端口號,容器的 ID 為“22f560251e68”。 最后我們使用如下命令來連接 Redis: ``` $ docker exec -it myredis redis-cli 127.0.0.1:6379> ``` 其他常用命令如下: * 容器停止:docker stop 容器名稱 * 啟動容器:docker start 容器名稱 * 刪除容器:docker rm 容器名稱 * 刪除鏡像:docker rmi 鏡像名稱 * 查看運行的所有容器:docker ps * 查看所有容器:docker ps -a * 容器復制文件到物理機:docker cp 容器名稱:容器目錄 物理機目錄 * 物理機復制文件到容器:docker cp 物理機目錄 容器名稱:容器目錄 * [ ] Docker 可能存在的問題 Java 相對于 Docker 來說顯然具有更悠久的歷史,因此在早期的 Java 版本中(JDK 8u131)因為不能很好地識別 Docker 相關的配置信息,從而導致可能會出現 Java 程序意外被終止的情況或者是過度創建線程數而導致并發性能下降的問題。 Java 程序意外終止的主要原因是因為,在 Docker 中運行的 Java 程序因為沒有明確指定 JVM 堆和直接內存等參數,而 Java 程序也不能很好地識別 Docker 的相關容量配置,導致 Java 程序試圖獲取了超過 Docker 本身的容量,而被 Docker 容器強制結束進程的情況(這是 Docker 自身的防御保護機制)。 過度創建線程是因為早期的 Java 版本并不能很好地識別 Docker 容器的 CPU 資源,因此會錯誤地識別和創建過多的線程數。比如 ParallelStreams 和 ForkJoinPool 等,它們默認就是根據當前系統的 CPU 核心數來創建對應的線程數的,但因為在 Docker 中的 Java 程序并不能很好地識別 CPU 核心數,就會導致創建的線程數量大于 CPU 的核心數量,從而導致并發效率降低的情況。 ParallelStreams 的基本用法如下: ``` List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9); numbers.parallelStream().forEach(count -> { System.out.println("val:" + count); }); ``` ParallelStreams 是將任務提交給 ForkJoinPool 來實現的,ForkJoinPool 獲取本地 CPU 核心數的源碼如下: ``` private static ForkJoinPool makeCommonPool() { // 忽略其他代碼 if (parallelism < 0 && // default 1 less than #cores (parallelism = Runtime.getRuntime().availableProcessors() - 1) <= 0) parallelism = 1; if (parallelism > MAX_CAP) parallelism = MAX_CAP; return new ForkJoinPool(parallelism, factory, handler, LIFO_QUEUE, "ForkJoinPool.commonPool-worker-"); } ``` 其中,“Runtime.getRuntime().availableProcessors()”是用來獲取本地線程數量的。 要解決以上這些問題的方法,最簡單的解決方案就是升級 Java 版本,比如 Java 10 就可以很好地識別 Docker 容器的這些限制。但如果使用的是老版本的 Java,那么需要在啟動 JVM 的時候合理的配置堆、元數據區等內存區域大小,并指定 ForkJoinPool 的最大線程數,如下所示: ``` -Djava.util.concurrent.ForkJoinPool.common.parallelism=8 ``` #### 小結 本課時我們介紹了 Docker 的概念以及 Docker 中最重要的三個組件:鏡像、容器和倉庫,并且介紹了 Docker 的 6 大特點:輕量級、靈活、可移植、相互隔離、可擴展和安全等特點;同時還介紹了 Docker 的常見使用命令;最后介紹了 Docker 可能在老版本(JDK 8u131 之前)的 Java 中可能會存在意外停止和線程創建過多的問題以及解決方案。 通過以上內容的學習相信你對 Docker 已經有了一個系統的認識,需要特別注意是 Docker 在 Java 老版本中可能出現的問題以及解決方案,這一點在面試中經常會被問到。 OK,這一課時就講到這里啦,恭喜你已經學習完了關于本系列的所有課程。如果你覺得課程不錯,從中有所收獲的話,不要忘了推薦給身邊的朋友哦,最后希望大家都有所提高、不斷成長,謝謝~
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看