SpringBoot 2.3.0 新特性來了,還不快學一波
Spring Boot 2.3 已經發布一個月了,這兩天才想起來嘗一嘗鮮兒。除了常規的升級外,很大部分的升級是針對 Docker 的,讓你不得不相信,Docker 容器化微服務已然大勢所趨。還沒有用過的同學,再不下手就晚了。
此次升級主要包括如下幾個方面,接下來就跟著我一起來嘗一嘗吧。
準備工作
為了說明 Spring Boot 2.3 的新特性,必須創建一個項目,以便試驗。
創建一個項目并啟動
1、創建一個 Spring Boot 項目,可以到 https://start.spring.io/ 上創建,也可以使用 IDEA 自帶的功能創建。選擇版本 2.3.1,JDK 還是選擇親愛的 Java 8,引入 Web 和 Actuator 兩個依賴包。

有一點要注意一下,在我寫本文的時候,Spring Boot 2.3.1 還不能從中央倉庫下載,需要添加 Spring Boot 官方的里程碑倉庫。
<repositories>
<repository>
<id>spring-milestone</id>
<name>Spring Milestone Repository</name>
<url>https://repo.spring.io/milestone</url>
</repository>
</repositories>
2、在 pom 文件中引入 Maven 插件
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.3.1.RELEASE</version>
</plugin>
</plugins>
</build>
3、添加一個 Controller,做測試用。
@RestController
public class PlayController {
@GetMapping(value = "play")
public String play(){
return "hey, play with me!";
}
}
4、啟動項目
mvn spring-boot:run
5、訪問 http://localhost:8080/play,說明項目啟動成功

更好的 Docker 支持
如果不使用 Docker 呢,那就直接打成 jar
包,使用如下命令
mvn package spring-boot:repackage

然后就可以把這個 Jar
包部署到服務器了,當然這個過程可能是用自動化部署工具實現的,不如 jenkins 或者自研系統。
之前 Docker 打包方式
拋開公司(尤其是大廠)里成熟的自動化部署流程不談,我這里說的是一般性小廠或者是個人項目。
如果你在之前的版本就已經用 Docker 方式,那基本上都是自己寫 Dockerfile ,然后自己寫腳本使用 Dockerfile 打鏡像包,或者使用 Maven
插件,比如 dockerfile-maven-plugin
。
Cloud Native Buildpacks
如果你了解 Dockerfiles 的話,那你肯定了解用 Dockerfiles 構建鏡像的過程,需要你創建一個 Dockerfile 文件然后在里面寫上構建鏡像所需的一系列動作,而 Cloud Native Buildpacks 則無需配置類似的過程文件,很大程度上減輕了開發者的工作,提高了效率。這還不是最重要的,最重要的是它提供了更高層次的抽象能力,使鏡像的分層更加清晰,并且合理有效的利用層緩存,這樣一來,當我們對應用程序進行修改之后,再次構建鏡像時的速度飛快,比如我們的應用只改了幾行代碼,那當我們使用 Buildpacks 構建鏡像時,只需要在應用程序層進行重新構建,其他層使用緩存就可以,也就是只對變化了的層重新構建。
Spring Boot 2.3 Docker 方式
首先要確保你本地已經正常啟動了 Docker 服務。
Spring Boot 2.3 官方的 Docker Maven 插件,從此不用再借助第三方了。我們前面創建項目的時候已經引入了這個 Maven 插件。
此插件不僅提供了打鏡像包的功能,還有其他的常用功能,比如 run、repackage 等。

為什么前面要說 Cloud Native Buildpacks 呢,不是跑題啊,是因為 Spring Boot 2.3 生成 Docker 鏡像包的方式就是集成了 Cloud Native Buildpacks。
那我們就打個鏡像包試一下吧
mvn spring-boot:build-image
你以為馬上就能看到成果了嗎,還是太年輕。
大中華區開發者怎么了
對于中國的開發者來說,打包這一步不會太順利,原因大家都很清楚。不出意外的話,應該會出現這樣的錯誤,不出錯可能才是意外。
[ERROR] Failed to execute goal org.springframework.boot:spring-boot-maven-plugin:2.3.1.RELEASE:build-image (default-cli) on project play: Execution default-cli of goal org.springframework.boot:spring-boot-maven-plugin:2.3.1.RELEASE:build-image failed: Docker API call to 'localhost/v1.24/images/create?fromImage=gcr.io%2Fpaketo-buildpacks%2Fbuilder%3Abase-platform-api-0.3' failed with status code 500 "Internal Server Error" and message "Get https://gcr.io/v2/: net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)" -> [Help 1]
出現這個問題的原因是因為 Buildpacks 調用 Docker API 創建鏡像的方法,要訪問 https://gcr.io ,從上面 pull 一些基礎鏡像下來,這是 Google 的 Google Cloud ,是 Google 的容器倉庫,然而對于中國的開發者來說,這個地址是 404 的。
所以我們要加個系統級別代理,或者專門為 Docker 配置代理。我是在 Docker 中配置的代理,系統代理的影響太大。我本機安裝的是 Docker Desktop,直接打開設置,在里面加上代理就可以了(別問我代理怎么搞,問我就是沒有代理)。
好了,通過上面一頓猛如虎的操作,再次運行命令
mvn spring-boot:build-image
根據你的網速,等上一段時間,就會出現下面的結果,說明鏡像創建成功了。
之后你可以使用 docker images
命令查看。這時間也是醉了,40 years ago。

使用此鏡像啟動容器
使用命令直接啟動容器。
docker run -it -p8080:8080 play:0.0.1-SNAPSHOT
然后訪問 8080 端口,得到正確的返回結果,說明啟動成功了。

Docker Image 的一個特點是,每個層都是前一層變化的增量。有一個工具叫做 dive,可以清楚的查看分層結構里面包含的內容。具體安裝和使用請自行搜索。
使用 dive 查看的一個小技巧,因為鏡像層包含的指令很多,所以我們選擇只查看相對于上一層的增量內容,使用 Ctrl+L
組合鍵。
Tab
進入視圖,然后按 Ctrl+U
,去掉沒有更改的選項,也就是只看變化的部分。然后上下箭頭可以切換層查看,比如下面這個圖展示了一個 18 M 的層相對于上一層的變化內容,可以看出來這個層實際上就是應用程序層,包含了很多當前應用程序的類和第三方依賴包等。