技术分享

SpringBoot 2.3.0 新特性来了,还不快学一波

Spring Boot 2.3 已经发布一个月了,这两天才想起来尝一尝鲜儿。除了常规的升级外,很大部分的升级是针对 Docker 的,让你不得不相信,Docker 容器化微服务已然大势所趋。还没有用过的同学,再不下手就晚了。

此次升级主要包括如下几个方面,接下来就跟着我一起来尝一尝吧。

1.jpg







准备工作

为了说明 Spring Boot 2.3 的新特性,必须创建一个项目,以便试验。

创建一个项目并启动

1、创建一个 Spring Boot 项目,可以到 https://start.spring.io/ 上创建,也可以使用 IDEA 自带的功能创建。选择版本 2.3.1,JDK 还是选择亲爱的 Java 8,引入 Web 和 Actuator 两个依赖包。




2.jpg




有一点要注意一下,在我写本文的时候,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,说明项目启动成功




3.jpg




更好的 Docker 支持

如果不使用 Docker 呢,那就直接打成 jar 包,使用如下命令

mvn package spring-boot:repackage




4.jpg




然后就可以把这个 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 等。




5.jpg




为什么前面要说 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,直接打开设置,在里面加上代理就可以了(别问我代理怎么搞,问我就是没有代理)。

6.jpg

好了,通过上面一顿猛如虎的操作,再次运行命令

mvn spring-boot:build-image

根据你的网速,等上一段时间,就会出现下面的结果,说明镜像创建成功了。



7.jpg



之后你可以使用 docker images命令查看。这时间也是醉了,40 years ago。



8.jpg



使用此镜像启动容器

使用命令直接启动容器。

docker run -it -p8080:8080 play:0.0.1-SNAPSHOT

然后访问 8080 端口,得到正确的返回结果,说明启动成功了。



9.jpg



Docker Image 的一个特点是,每个层都是前一层变化的增量。有一个工具叫做 dive,可以清楚的查看分层结构里面包含的内容。具体安装和使用请自行搜索。

使用 dive 查看的一个小技巧,因为镜像层包含的指令很多,所以我们选择只查看相对于上一层的增量内容,使用 Ctrl+L组合键。

10.jpg



然后按 Tab进入视图,然后按 Ctrl+U,去掉没有更改的选项,也就是只看变化的部分。



11.jpg


然后上下箭头可以切换层查看,比如下面这个图展示了一个 18 M 的层相对于上一层的变化内容,可以看出来这个层实际上就是应用程序层,包含了很多当前应用程序的类和第三方依赖包等。

12.jpg