Python 官方文档:入门教程 => 点击学习
目录关于spring Native Spring Native到底是什么 本篇概览环境信息新建名为spring-native-tutorials的Maven父工程
欢迎访问我的GitHub
个人的理解:Spring Native是Spring提供的、制作native image的技术方案,涉及到以下关键技术:
作为实战风格的文章,本篇主要内容是开发springboot应用再构建为native image,然后验证其功能和效果,本文由以下内容构成:
本次实战相关的环境信息如下:
源码下载 本篇实战中的完整源码可在GitHub下载到,地址和链接信息如下表所示(https://github.com/zq2599/blog_demos):
名称 | 链接 | 备注 |
---|---|---|
项目主页 | https://github.com/zq2599/blog_demos | 该项目在GitHub上的主页 |
git仓库地址(https) | https://github.com/zq2599/blog_demos.git | 该项目源码的仓库地址,https协议 |
git仓库地址(ssh) | git@github.com:zq2599/blog_demos.git | 该项目源码的仓库地址,ssh协议 |
这个git项目中有多个文件夹,本次实战的源码在spring-native-tutorials文件夹下,如下图红框所示:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<modules>
<module>webmvc</module>
</modules>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.0-SNAPSHOT</version>
<relativePath/>
</parent>
<groupId>com.bolinGCavalry</groupId>
<artifactId>spring-native-tutorials</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<properties>
<java.version>1.8</java.version>
<!-- springboot生成jar文件的文件名后缀,用来避免Spring Boot repackaging和native-image-maven-plugin插件之间可能存在的冲突 -->
<classifier/>
<!-- 构建镜像时的定制参数 -->
<native.build.args/>
<!-- 指定使用dmikusa/graalvm-tiny这个镜像作为构建工具,来构建镜像 -->
<builder>dmikusa/graalvm-tiny</builder>
<!-- spring cloud版本 -->
<spring-cloud.version>2020.0.2</spring-cloud.version>
</properties>
<!-- 插件管理 -->
<pluginRepositories>
<pluginRepository>
<id>spring-release</id>
<name>Spring release</name>
<url>https://repo.spring.io/release</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
<pluginRepository>
<id>spring-milestone</id>
<name>Spring milestone</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
<pluginRepository>
<id>spring-snapshot</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/snapshot</url>
<releases>
<enabled>false</enabled>
</releases>
</pluginRepository>
</pluginRepositories>
<!--仓库管理-->
<repositories>
<repository>
<id>spring-release</id>
<name>Spring release</name>
<url>https://repo.spring.io/release</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
<repository>
<id>spring-milestone</id>
<name>Spring milestone</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
<repository>
<id>spring-snapshot</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/snapshot</url>
<releases>
<enabled>false</enabled>
</releases>
</repository>
</repositories>
<!--依赖包版本管理-->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.experimental</groupId>
<artifactId>spring-native</artifactId>
<version>0.10.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<!--插件配置-->
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<classifier>${classifier}</classifier>
<image>
<builder>${builder}</builder>
<env>
<BP_NATIVE_IMAGE>true</BP_NATIVE_IMAGE>
<BP_NATIVE_IMAGE_BUILD_ARGUMENTS>${native.build.args}</BP_NATIVE_IMAGE_BUILD_ARGUMENTS>
</env>
<!--执行构建任务的镜像,如果在当前环境不存在才会远程下载-->
<pullPolicy>IF_NOT_PRESENT</pullPolicy>
</image>
</configuration>
</plugin>
<!-- aot插件,ahead-of-time transfORMations -->
<plugin>
<groupId>org.springframework.experimental</groupId>
<artifactId>spring-aot-maven-plugin</artifactId>
<version>0.10.0-SNAPSHOT</version>
<executions>
<execution>
<id>test-generate</id>
<Goals>
<goal>test-generate</goal>
</goals>
</execution>
<execution>
<id>generate</id>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
上述pom.xml有以下几处需要注意:
新建名为webmvc的子工程,pom.xml内容如下,可见内容很简单,就是常规依赖库和父工程配置的两个插件,一个负责执行AOT,一个负责构建镜像:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>spring-native-tutorials</artifactId>
<groupId>com.bolingcavalry</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>webmvc</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.experimental</groupId>
<artifactId>spring-native</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-core</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-websocket</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.tomcat.experimental</groupId>
<artifactId>tomcat-embed-programmatic</artifactId>
<version>${tomcat.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.experimental</groupId>
<artifactId>spring-aot-maven-plugin</artifactId>
<configuration>
<removeSpelSupport>true</removeSpelSupport>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
代码很简单,一个普通的springboot应用,带http接口:
package com.bolingcavalry.webmvc;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;
import java.time.LocalDateTime;
@SpringBootApplication
@RestController
public class WebmvcApplication {
public static void main(String[] args) {
SpringApplication.run(WebmvcApplication.class, args);
}
@ResponseStatus(HttpStatus.ACCEPTED)
@GetMapping("/status")
public String status() {
return "status";
}
@GetMapping("/")
public String hello() {
return "1. Hello from Spring MVC and Tomcat, " + LocalDateTime.now();
}
}
现在编码已完成,来构建docker镜像吧,进入父工程的pom.xml所在目录,执行以下命令:
mvn clean -U -DskipTests spring-boot:build-image
构建成功后输出信息如下(篇幅所限仅截取最后一小段),耗时4分25秒,期间笔记本风扇狂转:
..
[INFO] Successfully built image 'docker.io/library/webmvc:1.0-SNAPSHOT'
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Summary for spring-native-tutorials 1.0-SNAPSHOT:
[INFO]
[INFO] spring-native-tutorials ............................ SUCCESS [ 1.786 s]
[INFO] webmvc ............................................. SUCCESS [04:19 min]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 04:25 min
[INFO] Finished at: 2021-05-22T16:36:44+08:00
[INFO] ------------------------------------------------------------------------
[WARNING] The requested profile "nexus" could not be activated because it does not exist.
执行docker images命令,如下图,可见镜像已经生成:
查看镜像构成,可见每个layer都不大,共计七十多M:
(base) zhaoqindeMBP:~ zhaoqin$ docker history webmvc:1.0-SNAPSHOT
IMAGE CREATED CREATED BY SIZE COMMENT
b8ff54813ae0 41 years ago 69B
<missing> 41 years ago 452kB
<missing> 41 years ago 2.51MB
<missing> 41 years ago 57.2MB
<missing> 41 years ago 1.4MB
<missing> 41 years ago 268B
<missing> 41 years ago 17.3MB
镜像构建成功,可以验证基本功能了;
执行以下命令,创建一个临时容器(控制台结束后容器会被清理掉):
docker run --rm -p 8080:8080 webmvc:1.0-SNAPSHOT
控制台输出如下,79毫秒启动完成,真是一眨间的功夫:
(base) zhaoqindeMBP:~ zhaoqin$ docker run --rm -p 8080:8080 webmvc:1.0-SNAPSHOT
2021-05-22 09:34:57.578 INFO 1 --- [ main] o.s.nativex.NativeListener : This application is bootstrapped with code generated with Spring AOT
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.5.0-SNAPSHOT)
2021-05-22 09:34:57.586 INFO 1 --- [ main] c.b.webmvc.WebmvcApplication : Starting WebmvcApplication using Java 1.8.0_292 on 3529ec458896 with PID 1 (/workspace/com.bolingcavalry.webmvc.WebmvcApplication started by cnb in /workspace)
2021-05-22 09:34:57.586 INFO 1 --- [ main] c.b.webmvc.WebmvcApplication : No active profile set, falling back to default profiles: default
2021-05-22 09:34:57.661 INFO 1 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (http)
May 22, 2021 9:34:57 AM org.apache.coyote.AbstractProtocol init
INFO: Initializing ProtocolHandler ["http-NIO-8080"]
May 22, 2021 9:34:57 AM org.apache.catalina.core.StandardService startInternal
INFO: Starting service [Tomcat]
May 22, 2021 9:34:57 AM org.apache.catalina.core.StandardEngine startInternal
INFO: Starting Servlet engine: [Apache Tomcat/9.0.46]
May 22, 2021 9:34:57 AM org.apache.catalina.core.ApplicationContext log
INFO: Initializing Spring embedded WebApplicationContext
2021-05-22 09:34:57.669 INFO 1 --- [ main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 79 ms
May 22, 2021 9:34:57 AM org.apache.coyote.AbstractProtocol start
INFO: Starting ProtocolHandler ["http-nio-8080"]
2021-05-22 09:34:57.713 INFO 1 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path ''
2021-05-22 09:34:57.713 INFO 1 --- [ main] c.b.webmvc.WebmvcApplication : Started WebmvcApplication in 0.178 seconds (JVM running for 0.19)
2021-05-22 09:34:57.713 INFO 1 --- [ main] o.s.b.a.ApplicationAvailabilityBean : Application availability state LivenessState changed to CORRECT
2021-05-22 09:34:57.714 INFO 1 --- [ main] o.s.b.a.ApplicationAvailabilityBean : Application availability state ReadinessState changed to ACCEPTING_TRAFFIC
浏览器访问本机8080端口,如下图,应用基本功能正常:
再看看资源使用情况,命令是docker stats,如下可见,内存仅用了30M:
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
6ce6c66fb4de jovial_hertz 0.11% 30.69MiB / 3.844GiB 0.78% 1.49kB / 158B 4.31MB / 0B 18
我曾经在hub.docker.com上放了一个传统springboot应用制作的镜像bolingcavalry/hellojib:0.0.1-SNAPSHOT,现在拿来和Spring Native镜像对比一下,启动信息如下,耗时2036毫秒:
(base) zhaoqindeMacBook-Pro:~ zhaoqin$ docker run --rm -P docker.io/bolingcavalry/hellojib:0.0.1-SNAPSHOT
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.1.6.RELEASE)
2021-05-22 11:13:28.121 INFO 1 --- [ main] c.b.hellojib.HellojibApplication : Starting HellojibApplication on ffb32e5b68b9 with PID 1 (/app/classes started by root in /)
2021-05-22 11:13:28.128 INFO 1 --- [ main] c.b.hellojib.HellojibApplication : No active profile set, falling back to default profiles: default
2021-05-22 11:13:30.000 INFO 1 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (http)
2021-05-22 11:13:30.054 INFO 1 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2021-05-22 11:13:30.054 INFO 1 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.21]
2021-05-22 11:13:30.241 INFO 1 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2021-05-22 11:13:30.241 INFO 1 --- [ main] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 2036 ms
2021-05-22 11:13:30.715 INFO 1 --- [ main] o.s.s.concurrent.ThreadPoolTaskExecutor : Initializing ExecutorService 'applicationTaskExecutor'
2021-05-22 11:13:31.103 INFO 1 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path ''
2021-05-22 11:13:31.110 INFO 1 --- [ main] c.b.hellojib.HellojibApplication : Started HellojibApplication in 3.618 seconds (JVM running for 4.297)
2021-05-22 11:13:48.866 INFO 1 --- [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring DispatcherServlet 'dispatcherServlet'
2021-05-22 11:13:48.866 INFO 1 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Initializing Servlet 'dispatcherServlet'
2021-05-22 11:13:48.880 INFO 1 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Completed initialization in 14 ms
再用docker stats对比内存,传统springboot应用的容器消耗了三百多兆内存:
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
ffb32e5b68b9 eager_williamson 0.64% 356.3MiB / 3.844GiB 9.05% 3.46kB / 2.29kB 0B / 0B 31
6ce6c66fb4de jovial_hertz 0.11% 30.69MiB / 3.844GiB 0.78% 1.49kB / 158B 4.31MB / 0B 18
综上所述,Spring Native带来的优势是很明显的,不过请注意:2021年03月11日官方宣布的Spring Native只是beta版本,请不要用于生产环境!!!
在实际操作过程中,经常会遇到maven插件或者docker镜像下载失败的情况,除了多试几次,您还可以考虑将项目放到github上去,借助github action在云端完成镜像构建,具体操作请参考《用GitHub Actions制作Docker镜像》
不用开发,直接体验
我已将镜像上传到hub.docker.com,完整名称是bolingcavalry/webmvc:1.0-SNAPSHOT,如果您只想体验一下native image的效果可以直接下载该镜像使用;
以上就是Spring Native实战(畅快体验79毫秒启动springboot应用)的详细内容,更多关于Spring Native实战的资料请关注编程网其它相关文章!
--结束END--
本文标题: Spring Native项目实战(体验79毫秒启动springboot应用)
本文链接: https://lsjlt.com/news/127059.html(转载时请注明来源链接)
有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341
2024-03-01
2024-03-01
2024-03-01
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
回答
回答
回答
回答
回答
回答
回答
回答
回答
回答
0