spring boot介绍

Spring Boot目前流行的java web应用开发框架,相比传统的spring开发,spring boot极大简化了配置,并且遵守约定优于配置的原则即使0配置也能正常运行,这在spring中是难以想象的。spring boot应用程序可以独立运行,框架内嵌web容器,使得web应用程序可以像本地程序一样启动和调试,十分的方便,这种设计方式也使得spring boot应用程序非常适合容器化进行大规模部署。生态方面,spring boot提供了非常丰富的组件,目前流行的java web框架基本都有spring boot版本,生态十分庞大,是目前java web开发最好的方案。

spring boot部署问题

Springboot应用程序有两种运行方式

以jar包方式运行

以war包方式运行

两种方式应用场景不一样,各有优缺点

jar包运行

通过maven插件spring-boot-maven-plugin,在进行打包时,会动态生成jar的启动类org.springframework.boot.loader.JarLauncher,借助该类对springboot应用程序进行启动。

优点

本地无需搭建web容器,方便开发和调试。

因为自带web容器,可以避免由于web容器的差异造成不同环境结果不一致问题。

一个jar包就是全部,方便应用扩展。

借助容器化,可以进行大规模的部署。

缺点

应用过于独立,难以统一管理。

数据源无法通过界面进行管理。

应用体积过大。

修改web容器相关配置较为困难,需要借助代码实现。

war包运行

以war包方式运行,通过maven插件spring-boot-maven-plugin进行相关配置后,最终生成一个可运行在tomcat,weblogic等java web容器中的war包。

优点

可以借助web容器管理界面对应用进行管理。

可以管理JNDI数据源。

web容器配置较为灵活,配置和程序分离。

应用体积较小,甚至可以借助web容器的包管理功能(比如weblogic Library)进一步减小应用大小。

缺点

本地需要搭建web容器,对本地环境要求更高点,学习成本也响应更高。

调试较为困难,需要借助web容器。

无法兼容所有web容器(比如spring boot2.x无法运行在weblogic 11g上)。

部署较为困难(比如和weblogic有较多的类冲突)

在实际的项目中,并没有哪一种方式是最好的,根据客户不同的需求制定不同的部署方案,比如有些客户比较看中管理功能,要求数据源和tomcat相关配置必须由管理员进行管理,那么选择war包方式,有些客户希望借助容器化进行大规模部署,那么jar方式更适合。不管选择哪种方式,在部署时都会遇到下面的问题

如果需要打war包,那么不仅是pom文件需要修改,应用程序也要做相应的改动,改动完后,应用程序就无法本地运行,需要打完包后将配置信息修改回来,这样不仅麻烦,还容易出错。

不管是war包还是jar包,如何管理不同环境的配置文件,保证不会出错,虽然spring boot有提供spring.profiles.active配置设置不同的环境,但一方面需要人为修改配置文件,只要是人为的就有可能出错,另一方面,客户有时出于安全考虑不会提供生产环境配置信息,那么这时候就无法指定prifiles.active。

如何将多个spring boot模块打包在一起。

jar包需要配合容器化才能发挥出最大的优势,如果没有容器,spring boot jar包就是一个玩具,随处运行的jar包,缺少统一管理,是达不到生产的要求,那么如果从jar包到容器也是一个问题。

早期碰到这些问题,都是人工解决,不仅效率十分低下,部署一次都需要十几分钟,而且很容易出错,一百次出错一次算是概率低了,但是生产出错一次都是重大事件,所以我们也在思考如何通过自动化解决以上问题,如何将开发和部署分离,开发人员只关心开发,开发完提交代码,打包和部署都是后台透明的完成。以下就是我们的解决方案。

打包war包打包问题解决

spring boot打war包的步骤如下

在pom.xml中将打包方式改为war。


<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"> ... war ...
设置spring-boot-starter-tomcat范围为provided
org.springframework.boot spring-boot-starter-tomcat provided
修改spring boot的启动类,继承SpringBootServletInitializerpublic class DemoApplication extends SpringBootServletInitializer{ @Override protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) { return builder.sources(DemoApplication.class); }}

每打包一次都要修改pom.xml和启动类,打包完再修改回来,十分的繁琐,因为,我们提出以下整改方案

从pom.xml复制一个pom-war.xml文件,将pom-war.xml修改为war包配置

在根目录下(除了src目录外都可以)复制一份启动类的代码,修改为war包的配置方式。

编写shell脚本进行打包。

shell脚本打包过程为

  1. 备份当前启动类的java代码。

  2. 将war包启动类的代码替换掉当前启动类的代码。

  3. maven指定pom-war.xml文件进行打包。

  4. 打包结束后恢复启动类文件。

以下就是参考脚本


app-war.sh#!/usr/bin/env bash
v1=src/main/java/com/definesys/demo/DemoApplication.javav2=war/DemoApplication.javav3=war/DemoApplication-bak.java
cp -rf $v2 $v1
mvn clean package -Dmaven.test.skip=true -f war-pom.xml
#recoverycp -rf $v3 $v1

通过预先配置好pom文件和启动类文件,开发人员只要运行app-war.sh脚本无需修改任何文件即可生成war包。

更优的方案

以上方案pom文件和启动类文件都需要预先准备好,未实现完全的自动化,通过优化方案做到完全自动化。

脚本可以通过find命令搜索以*Application.java结尾的文件,作为启动类文件,读取文件名获取类名,通过字符串替换方式动态生成war包启动类文件。

在pom.xml中用注释设置好锚点,脚本通过替换锚点动态生成pom.xml文件。

如果不希望通过锚点实现,可以借助更高级的脚本语言,比如python对xml进行解析,再动态生成xml。

多模块打包

这里的多模块指的是maven中的多模块,项目工程中的代码多模块,一个项目按功能划分模块后,在创建工程时一般也按照功能层面上的模块进行创建,这样避免一个模块代码过于庞大,也利于任务的分工,但打包却更麻烦了。

每个模块都是独立的spring boot程序,整合到一个包的时候会出现多个启动类,多个配置文件冲突的问题。

每个模块有引用相同的依赖,依赖包版本升级后,需要每个pom文件都做修改。

通过优化项目结构解决以上问题

父项目的pom指定spring boot的依赖和公共的依赖。

创建一个spring boot的子项目,作为启动项目,我们称为start项目。

其余子项目为普通的java maven项目,parent设置为第一步创建的spring boot父项目。

start项目的pom引用其他子项目的依赖。

本地调试可以直接运行start的启动类,ide会自动编译其他模块并引用。

打包可以在父项目上进行install后再进入start项目进行打包,脚本参考如下


mvn clean installcd startmvn clean package

目录结构如下


.├── pom.xml├── role│ ├── pom.xml│ └── src│ ├── main│ │ ├── java│ │ │ └── com│ │ │ └── definesys│ │ │ └── demo│ │ │ └── controller│ │ │ └── RoleController.java│ │ └── resources├── start│ ├── pom.xml│ ├── src│ │ ├── main│ │ │ ├── java│ │ │ │ └── com│ │ │ │ └── definesys│ │ │ │ └── demo│ │ │ │ └── DemoApplication.java│ │ │ └── resources│ │ │ └── application.properties└── user ├── pom.xml └── src └── main ├── java │ └── com │ └── definesys │ └── demo │ └── controller │ └── UserController.java └── resources

start项目包含包含启动类和配置文件,pom文件引用其余子项目。


start pom.xml
<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">
blog0915 com.definesys.demo 1.0-SNAPSHOT
4.0.0 start

com.definesys.demo user 1.0.0

com.definesys.demo role 1.0.0

org.springframework.boot spring-boot-maven-plugin

父项目parent为spring boot,引用spring boot相关依赖和各个子项目公共的依赖

父项目 pom.xml


<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"> 4.0.0 pom
user role start

org.springframework.boot spring-boot-starter-parent 2.1.2.RELEASE

com.definesys.demo blog0915 1.0-SNAPSHOT

org.springframework.boot spring-boot-starter-web

所有非start的子项目需要指定版本号并且父项目都设为根目录项目。

子项目 pom.xml

<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">        blog0915        com.definesys.demo        1.0-SNAPSHOT    4.0.0    role    1.0.0

所有子项目的包路径前缀必须一样,并且以start项目作为基本路径。

配置文件问题

spring boot提供spring.profiles.active指定配置文件,但生产环境有时候客户出于安全考虑不提供配置信息给开发人员,而是预先将配置文件上传到服务器指定路径,程序需要在运行时去引用该配置文件,如果运行环境是kubernetes,则会提供一个config map作为配置文件,这时候就要求spring boot程序读取外部配置文件。

这里讨论的是线上环境配置文件方案,本地调试参考子模块打包相关内容,可以将配置文件统一写在start项目中。

jar包外部配置文件读取

jar运行可以通过指定参数spring.config.location引用外部文件,命令参考如下:


java -jar start-1.0-SNAPSHOT.jar --spring.config.location=/Users/asan/workspace/config

config目录存放properties配置文件

可以通过配合spring.profiles.active参数可以指定目录下配置文件,如:


java -jar start-1.0-SNAPSHOT.jar --spring.profiles.active=prod --spring.config.location=/Users/asan/workspace/config

则会读取/Users/asan/workspace/config/appliction-prod.properties文件作为配置文件。

war包外部配置文件读取

以tomcat为例,需要在tomcat启动时指定-Dspring.config.location参数,可以设置服务器环境变量CATALINA_OPTS达到目的。可以编辑用户 prifile文件


export CATALINA_OPTS=/Users/asan/workspace/config

同样,也可以通过-Dspring.profiles.active指定配置文件名称。

容器化

spring boot借助容器化,可以如虎添翼,发挥出更大的威力,也只有通过容器化,才能体会到spring boot开发的高效。通过以上的介绍,你可以很顺利的打好一个jar包或者war包,那么可以通过编写dockerfile文件进行镜像的构建。spring boot在构建镜像时有两个地方需要考虑时区问题,基础镜像的时区默认是UTC,比北京时间早8小时,需要指定镜像时区。

配置文件问题,需要指定外部配置文件(根据项目具体情况选择)。


app-jar-dockerfile.DockerfileFROM openjdk:8-jdk-alpine
MAINTAINER definesys.com
VOLUME /tmpADD start-1.0-SNAPSHOT.jar app.jarRUN echo "Asia/Shanghai" > /etc/timezoneEXPOSE 8080ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","--spring.config.location=/Users/asan/workspace/config","/app.jar"]app-war.dockerfile.DockerfileFROM tomcat
MAINTAINER definesys.com
ENV CATALINA_OPTS -Dspring.config.location=file:/middleware/config/ADD start-1.0-SNAPSHOT.war /usr/local/tomcat/webapps/app.jarRUN echo "Asia/Shanghai" > /etc/timezoneEXPOSE 8080

EOF部署

早期我们采用的是以下部署过程

首先构建测试环境的镜像,上传到镜像仓库,应用重新部署。

接着构建UAT环境的镜像,上传到镜像仓库,应用重新部署。

最后构建生产环境的镜像,上传到镜像仓库,应用重新部署。

每一次发布都是一个新的镜像,但这种方式有个问题就是如何保证前一个环境验证没问题,后一个环境就一定没问题,因为两个镜像是不一样的,虽然可能两次构建都是基于同一版本代码,但因为是重新构建,中间可能因为各种原因,如maven包版本更新等,无法保证两次构建就是完全一样的镜像。因此我们优化了构建的流程,如下:

所有的环境都是用同一个镜像,环境之间只有配置文件不同,文件通过configmap或者外部配置文件方式进行挂载,这样保证了配置文件没问题的前提下,每个环境的程序一定是一样的。

jenkins自动打包部署

打包和部署在本地进行也是有问题的,本地jdk版本取决于个人电脑,甚至有黑客污染jdk导致编译的class文件自带后门,个人电脑环境也是随着用户不同操作可能改变,构建出来的包不能保证是稳定的包。因此需要一个远程服务器用于打包和部署,能够实现从源码到镜像过程。jenkins是一个基于java开发的持续集成工具,通过配置插件和编写脚本实现程序从代码到制品再到线上运行的过程。jenkins在spring boot开发中主要完成了以下工作。

通过gitlab插件实现源代码的获取。

基于以上介绍的脚本,实现从源码到制品的过程。

通过docker工具实现从制品到镜像的过程。

通过kubectl工具,实现从镜像到上云的过程。

jenkins在构建镜像时需要借助docker工具,但jenkins本身也是有docker版本的,所以就面临着docker in docker的问题,这里选择的方案是用二进制文件安装jenkin而非镜像方式,虽然丧失了docker的便利性,但可以简化docker方案,降低集成的复杂度。

总结了很多有关于java面试的资料,希望能够帮助正在学习java的小伙伴。由于资料过多不便发表文章,创作不易,望小伙伴们能够给我一些动力继续创建更好的java类学习资料文章,
请多多支持和关注小作,别忘了点赞+评论+转发。右上角私信我回复【03】即可领取免费学习资料谢谢啦!

SpringBoot 打包部署最佳实践相关推荐

  1. Mendix基于腾讯云部署最佳实践

    本实践由腾讯云与西门子数字化工业软件授权发布,未经允许不得转载. 1.  概述 本文档介绍了西门子企业级应用开发平台Mendix应用快速托管到腾讯云容器服务(简称TKE)的最佳实践.该方案仅用于非生产 ...

  2. SAP(HANA+S/4)上云基础环境部署最佳实践

    简介:为提高客户服务水平及集团管理效率,客户选择了SAP解决方案.但是同时也对客户的IT基础设施提出了更多的要求.对此我们针对SAP上云基础设施选型.云原生产品.灾备方案设计,云上安全环境设计总结出了 ...

  3. SpringBoot打包部署成Windows服务的详细步骤

    SpringBoot打包部署成Windows服务的详细步骤 1.SpringBoot 1.1 pom.xml 1.2 项目代码 1.2.1 项目结构 1.2.2 Controller的代码 1.2.3 ...

  4. 【部署】SpringBoot 打包部署/共享依赖包(分布式开发集中式部署微服务)精简jar包

    精简jar包 将项目跟第三方依赖分开 [部署]SpringBoot 打包部署/共享依赖包(分布式开发集中式部署微服务) 1 修改pom <build><plugins>< ...

  5. SpringBoot打包部署到环境

    [问题] 之前一直用SpringBoot做一些小项目,想打包部署在环境上,总是少依赖包jar.百度下可以通过Spring Boot Maven plugin插件,把Maven配置的依赖包都打到项目包里 ...

  6. k8s停止服务_Kubernetes 服务部署最佳实践(二) 如何提高服务可用性

    引言 上一篇 文章我们围绕如何合理利用资源的主题做了一些最佳实践的分享,这一次我们就如何提高服务可用性的主题来展开探讨. 怎样提高我们部署服务的可用性呢?K8S 设计本身就考虑到了各种故障的可能性,并 ...

  7. 跨 AZ 部署最佳实践之 Zookeeper

    作者:焦振清 跨 AZ 部署是实现服务高可用较为有效的方法,同时也极具性价比.如果实现了跨 AZ 部署,不仅可以消除服务中的单点,同时还可以逐步建设如下能力:服务隔离,灰度发布,N+1 冗余,可谓一举 ...

  8. 跨AZ部署最佳实践之Elasticsearch

    作者:焦振清 跨AZ部署是实现服务高可用较为有效的方法,同时也极具性价比.如果实现了跨AZ部署,不仅可以消除服务中的单点,同时还可以逐步建设如下能力:服务隔离,灰度发布,N+1冗余,可谓一举多得.因此 ...

  9. Swagger - SpringBoot整合Swagger最佳实践

    总结 Swagger UI部分有两种,一种是官方提供的名为swagger-ui,访问路径为/swagger-ui.html,一种是萧明同学提供的swagger-bootstrap-ui,访问路径为/d ...

最新文章

  1. python中创建列表[]和list()哪个效率快?为什么快?快多少呢?
  2. Troubleshooting Open Cursor Issues
  3. C# DateTime 格式
  4. 高并发-【抢红包案例】之三:使用乐观锁方式修复红包超发的bug
  5. python写游戏棋牌游戏_使用python实现简单五子棋游戏
  6. 移动互联网与传统互联网体验上的区别及功能测试要点(总结自《大话移动APP测试》)...
  7. 万丰科技机器人排名_机器人系统集成“7宗最”
  8. spring源码:BeanFactoryPostProcessor和BeanDefinitionRegistryPostProcessor的区别
  9. 科大讯飞语音接口调用实现语音识别
  10. 余世伟视频笔记----如何塑造管理者的性格魅力领袖根性之积极和大度
  11. EM310指令集及使用
  12. MQL5: 通过反向持仓来平仓
  13. 火车运煤问题(马车运草)问题
  14. 算法刷题打卡第34天:有效的井字游戏
  15. Python3-标准库概览
  16. 利用python进入数据分析之数据规整化:清理、转换、合并、重塑(二)
  17. SLAM 三维传感器 点滴
  18. 抖音取名,抖音打造人设(取名,头像,简介...):国仁楠哥
  19. 2022最新<浙江>教师资格证报考条件
  20. IIS发布网站,报错404找不到文件或者目录

热门文章

  1. 结合iconworkshop,创建ribbon界面
  2. vivado2018.3创建一个流水灯(基于创龙k7核心开发板)
  3. 莱鲍迪甙A(Reb A)的全球与中国市场2022-2028年:技术、参与者、趋势、市场规模及占有率研究报告
  4. 【ESP 保姆级教程】疯狂EspNow篇 —— 案例:ESP8266 + EspNow简单实剖析底层实现原理
  5. Emoji 表情符号 处理
  6. 有关python方面的论文_有关python基础知识的文章推荐5篇
  7. 微信小程序动态绑定style样式
  8. PLSQL - Months_Between的理解和使用
  9. MySQL procedure详解
  10. join方法 js 单字符串会报错_javascript/js换行出错拼接字符串的方法