Spring Boot
使⽤了内嵌容器,因此它的部署⽅式也变得⾮常简单灵活,⼀⽅⾯可以将
Spring Boot
项⽬打包
成独⽴的
Jar
或者
War
包来运⾏,也可以单独打包成
War
包部署到
Tomcat
容器中运⾏,如果涉及到⼤规模
的部署
Jinkins
就成为最佳选择之⼀。
Spring Boot
默认集成
Web
容器,启动⽅式和普通
Java
程序⼀样,
main
函数⼊⼝启动,其内置
Tomcat
容
器或
Jetty
容器,具体由配置来决定(默认
Tomcat
)。
相关配置
多环境配置
在这⾥将介绍⼀下
Spring Boot
多环境配置⽂件,在我们开发过程中必定会⾯临多环境的问题,⽐如开发环
境、测试环境、⽣产环境,在不同的环境下会有不同的数据库连接池等配置信息。如果都写在⼀个配置⽂件
中,在不同的环境下启动需要⼿动修改对应的环境参数,这种⽅式容易出错且不够优雅。
Spring Boot
⽀持多
配置⽂件的使⽤,只需要启动时指定对应的配置⽂件即可。
⾸先在
pom.xml
中添加相关配置:
<profiles>
<profile>
<id>dev</id>
<properties>
<env>dev</env>
</properties>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
</profile>
<profile>
<id>test</id>
<properties>
<env>test</env>
</properties>
</profile>
<profile>
<id>pro</id>
<properties>
<env>pro</env>
</properties>
</profile>
GitChat
</profiles>
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
<excludes>
<exclude>application-dev.properties</exclude>
<exclude>application-pro.properties</exclude>
<exclude>application-test.properties</exclude>
</excludes>
</resource>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
<includes>
<include>application-${env}.properties</include>
</includes>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
在
Spring Boot
中多环境配置⽂件名需要满⾜
application-{profifile}.properties
的格式,其中
{profifile}
对应环境
标识。在
resources
⽬录下创建以下三个⽂件。
pplication-dev.properties:开发环境
application-test.properties:测试环境
application-prod.properties:⽣产环境
不同的配置⽂件对应不同的环境,启动的时候通过参数设置来启⽤不同的配置,开发过程中在
application.properties
⽂件中通过
spring.profifiles.active
属性来设置,其值对应
{profifile}
值,⽣产中使⽤
--
spring.profifiles.active=dev
参数来控制加载某个配置⽂件。
配置项介绍
对
Server
的⼏个常⽤配置做个简单说明:
# 项⽬ contextPath,⼀般不⽤配置
server.servlet.context-path=/myspringboot
# 错误⻚,指定发⽣错误时,跳转的 URL
server.error.path=/error
# 服务端⼝
server.port=6060
# session最⼤超时时间(分钟),默认为30
server.session-timeout=60
# 该服务绑定 IP 地址,启动服务器时如本机不是该 IP 地址则抛出异常启动失败,只有特殊需求的情况下才
配置
# server.address=192.168.0.6
如果使⽤的是
Tomcat
还可以进⾏以下的配置:
# tomcat 最⼤线程数,默认为 200
server.tomcat.max-threads=600
# tomcat 的 URI 编码
server.tomcat.uri-encoding=UTF-8
# 存放 Tomcat 的⽇志、Dump 等⽂件的临时⽂件夹,默认为系统的 tmp ⽂件夹
server.tomcat.basedir=/tmp/log
# 打开 Tomcat 的 Access ⽇志,并可以设置⽇志格式
#server.tomcat.access-log-enabled=true
#server.tomcat.access-log-pattern=
# accesslog ⽬录,默认在 basedir/logs
#server.tomcat.accesslog.directory=
# ⽇志⽂件⽬录
logging.path=/tmp/log
# ⽇志⽂件名称,默认为 spring.log
logging.file=myapp.log
以上的配置都为可选,在默认情况下都可不配置,项⽬中根据实际的使⽤情况来调整。
项⽬打包
打成 jar 包
内嵌容器技术的发展为
Spring Boot
部署打下了坚实的基础,内嵌容器不只在部署阶段发挥着巨⼤的作⽤,
在开发调试阶段也会带来极⼤的便利性,对⽐以往开发
Web
项⽬时配置
Tomcat
的繁琐,会让⼤家使⽤
Spring Boot
内嵌容器时有更深的感触。使⽤
Spring Boot
开发
Web
项⽬,不需要关⼼容器的环境问题,专
⼼写业务代码即可。
内嵌容器对部署带来的改变更多,现在
Maven
、
Gradle
已经成了我们⽇常开发必不可少的构建⼯具,使⽤
这些⼯具很容易的将项⽬打包成
Jar
或者
War
包,在服务器上仅仅需要⼀条命令即可启动项⽬,我们以
Maven
为例来进⾏演示。
Maven
默认会将项⽬打成
jar
包,也可以显示指出打包⽅式。
<groupId>com.neo</groupId>
<artifactId>spring-boot-package</artifactId>
<version>1.0.0</version>
<!--指定打包⽅式-->
<packaging>jar</packaging>
Maven
打包会根据
pom
包中的
packaging
配置来决定是⽣成
Jar
包或者
War
包。
pom.xml
同⽬录下,执⾏以下命令:
cd 项⽬跟⽬录(和 pom.xml 同级)
mvn clean package
## 或者执⾏下⾯的命令
## 排除测试代码后进⾏打包
mvn clean package -Dmaven.test.skip=true
- mvn clean 是清除项⽬ target ⽬录下的⽂件
- mvn package 打包命令,可以和 mvn clean ⼀起执⾏
在使⽤
Maven
进⾏打包的时候,会⾃动对
test
包下⾯的测试⽤例进⾏测试,测试⽤例失败会给出错误提
示,并停⽌打包,可以利⽤这个功能来做项⽬的⾃动化测试,检测基本功能是否正确,也可以选择不执⾏这
些测试⽤例,启动时添加参数
-Dmaven.test.skip=true
。
打包完成后
jar
包会⽣成到
target
⽬录下,命名⼀般是
“
项⽬名
+
版本号
.jar”
的形式。
启动
jar
包命令:
java -jar target/spring-boot-package-1.0.0.jar
这种⽅式,只要控制台关闭,服务就会停⽌,⽣产中我们⼀般使⽤后台运⾏的⽅式来启动
:
nohup java -jar spring-boot-package-1.0.0.jar &
设置
jvm
参数:
java -Xms10m -Xmx80m -jar spring-boot-package-1.0.0.jar &
也可以在启动的时候选择读取不同的配置⽂件:
java -jar spring-boot-package-1.0.0.jar --spring.profiles.active=dev
gradle
如果使⽤的是
gradle
,使⽤下⾯命令打包:
gradle build
java -jar build/libs/mymodule-0.0.1-SNAPSHOT.jar
Spring Boot
⽀持在启动的时候添加定制,⽐如设置应⽤的堆内存、垃圾回收机制、⽇志路径等。
打成 war 包
打成
war
包也⾮常的简单,但需要添加⼀些额外的配置。
(
1
)
Maven
项⽬,修改
pom
包
将
<packaging>jar</packaging>
改为
<packaging>war</packaging>
(
2
)打包时排除
Tomcat
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
在这⾥将
scope
属性设置为
provided
,这样在打包产⽣的
war
中就不会包含此
jar
。
(
3
)注册启动类
在项⽬的启动类中继承
SpringBootServletInitializer
并重写
confifigure()
⽅法:
@SpringBootApplication
public class PackageApplication extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder applicat
ion) {
return application.sources(PackageApplication.class);
}
public static void main(String[] args) {
SpringApplication.run(PackageApplication.class, args);
}
}
最后执⾏:
mvn clean package -Dmaven.test.skip=true
会在
target
⽬录下⽣成:项⽬名
+
版本号
.war
⽂件,复制到
Tomcat
服务器中启动即可。
打包成功输出的内容:
Results :
Tests run: 3, Failures: 0, Errors: 0, Skipped: 0
...
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 29.290 s
[INFO] Finished at: 2017-11-26T15:19:43+08:00
[INFO] Final Memory: 36M/354M
[INFO] ------------------------------------------------------------------------
gradle
如果使⽤的是
Gradle
,基本步骤和
Maven
类似,
build.gradle
中添加
war
的⽀持,排除
spring-boot-starter
tomcat
:
...
apply plugin: 'war'
...
dependencies {
compile("org.springframework.boot:spring-boot-starter-web:2.1.0.RELEASE"){
exclude mymodule:"spring-boot-starter-tomcat"
}
}
...
再使⽤构建命令:
gradle build
war
会⽣成在
build\libs
⽬录下。
部署运维
单个项⽬
简单粗暴
直接
kill
掉进程再次启动
jar
包:
ps -ef|grep java
##拿到对于 Java 程序的 pid
kill -9 pid
## 再次重启
Java -jar xxxx.jar
当然这种⽅式⽐较传统和暴⼒,建议⼤家使⽤下⾯的⽅式来管理。
脚本执⾏
如果使⽤的是
Maven
,需要包含以下的配置:
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<executable>true</executable>
</configuration>
</plugin>
如果使⽤是
Gradle
,需要包含下⾯配置:
Spring Boot {
executable = true
}
启动⽅式:
(
1
)可以直接
./yourapp.jar
来启动
(
2
)注册为服务
也可以做⼀个软链接指向你的
jar
包并加⼊到
init.d
中,然后⽤命令来启动。
init.d
例⼦
:
ln -s /var/yourapp/yourapp.jar /etc/init.d/yourapp
chmod +x /etc/init.d/yourapp
这样就可以使⽤
stop
或者是
restart
命令去管理你的应⽤了。
/etc/init.d/yourapp start|stop|restart
或者
service yourapp start|stop|restart
如果是打包成独⽴的
war
包部署到
Tomcat
中,就按照
Tomcat
的相关命令来重启。当然以上只是单个项⽬
部署,假设我们有
1000
多个项⽬,如果再按照这种⽅式来打包上传启动的话,整个平台部署完成估计需要
⼏个⼩时,并且⾮常容易出错。在⼤量部署应⽤时,给⼤家介绍另外⼀款⾃动化部署神器
Jenkins
。
批量部署
Jenkins
是⽬前持续构建领域使⽤最⼴泛的⼯具之⼀,它是⼀个独⽴的开源⾃动化服务器,可⽤于⾃动化各
种任务,如构建、测试和部署软件。
Jenkins
可以通过本机系统包以
Docker
的⽅式部署项⽬,甚⾄可以通过
安装
Java Runtime Environment
的任何机器独⽴运⾏。
Jenkins
可以很好的⽀持各种语⾔(如
Java
、
C#
、
PHP
等)项⽬构建,也完全兼容
ant
、
maven
、
gradle
等
多种第三⽅构建⼯具,同时跟
svn
、
git
能⽆缝集成,也⽀持直接与知名源代码托管⽹站,⽐如
GitHub
、
Bitbucket
直接集成。
说直⽩⼀点
Jenkins
就是专⻔来负责如何将代码变成可执⾏的程序包,将它部署到⽬标服务器中,并对其运
营状态(⽇志)进⾏监控的软件。⾃动化、性能、打包、部署、发布、发布结果⾃动化验证、接⼝测试、单
元测试等关于我们打包测试部署的⽅⽅⾯⾯
Jenkins
都可以很友好的⽀持。
Jenkins
搭建部署分为四个步骤:
- 第⼀步,Jenkins 安装
- 第⼆步,插件安装和配置
- 第三步,Push SSH
- 第四步,部署项⽬
具体的安装部署过程可以参考我博客上的⽂章:
使⽤
Jenkins
部署
Spring Boot
。
在这⾥主要看⼀下使⽤
Jenkins
部署
Spring Boot
的脚本。
DATE=$(date +%Y%m%d)
export JAVA_HOME PATH CLASSPATH
JAVA_HOME=/usr/java/jdk1.8.0_131
PATH=$JAVA_HOME/bin:$JAVA_HOME/jre/bin:$PATH
CLASSPATH=.:$JAVA_HOME/lib:$JAVA_HOME/jre/lib:$CLASSPATH
DIR=/root/xxx
JARFILE=xxx-1.0.0-SNAPSHOT.jar
if [ ! -d $DIR/backup ];then
mkdir -p $DIR/backup
fi
cd $DIR
ps -ef | grep $JARFILE | grep -v grep | awk '{print $2}' | xargs kill -9
mv $JARFILE backup/$JARFILE$DATE
mv -f /root/Jenkins-in/$JARFILE .
java -jar $JARFILE > out.log &
if [ $? = 0 ];then
sleep 30
tail -n 50 out.log
fi
cd backup/
ls -lt|awk 'NR>5{print $NF}'|xargs rm -rf
⾸先导⼊相关环境变量,然后根据⽇期对项⽬进⾏备份,
kill
掉正在执⾏的
Spring Boot
项⽬,将推送过来的
项⽬包放到对应⽬录下,使⽤
java -jar
命令来启动应⽤,最后将启动⽇志打印出来。
使⽤
Jenkin
之后,部署项⽬的步骤如下:
- push 代码到 Github(或者 SVN) 触发 WebHook
- Jenkins 从仓库拉去代码
- Maven 构建项⽬、单元测试
- 备份项⽬,停⽌正在运⾏的项⽬
- 启动应⽤
- 查看启动⽇志
使⽤
Jenkin
前期做⼀些简单的配置,后期当发布项⽬时只需要点击项⽬对应的发布按钮,就可以将项⽬从版
本库中拉取、打包、发布到⽬标服务器中,⼤⼤简化了运维后期的部署⼯作。
查看应⽤运⾏配置
可以根据
Java
⾃带的
jinfo
命令:
jinfo -flags pid
来查看
jar
启动后使⽤的是什么
gc
、新⽣代、⽼年代分批的内存都是多少,示例如下:
Attaching to process ID 5589, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.131-b11
Non-default VM flags: -XX:CICompilerCount=2 -XX:InitialHeapSize=16777216 -XX:MaxHe
apSize=262144000
-XX:MaxNewSize=87359488 -XX:MinHeapDeltaBytes=196608 -XX:NewSize=5570560 -XX:OldS
ize=11206656
-XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseParallelGC
- -XX:CICompilerCount:最⼤的并⾏编译数
- -XX:InitialHeapSize 和 -XX:MaxHeapSize:指定 JVM 的初始和最⼤堆内存⼤⼩
- -XX:MaxNewSize:JVM 堆区域新⽣代内存的最⼤可分配⼤⼩
- XX:+UseCompressedClassPointers: 压缩类指针
- -XX:+UseCompressedOops: 压缩对象指针
- -XX:+UseParallelGC:垃圾回收使⽤ Parallel 收集器
总结
Spring Boot
项⽬⽀持在不同环境下指定不同配置⽂件启动,⽅便开发⼈员在各个环节部署。
Spring Boot
因
为使⽤了内嵌容器,因此极⼤的优化了项⽬的部署难度,我们可以根据配置将
Spring Boot
打包成
Jar
或者
War
部署,单个项⽬可以使⽤命令⾏或者脚本的形式部署项⽬,如果涉及⼤量应⽤的部署运维,建议使⽤
Jenkins
发布
Spring Boot
项⽬,使⽤
Jinkins
可以以图形化的形式批量部署
Spring Boot
应⽤。