SpringBoot项目jar、war方式的部署
一、jar形式部署
java -jar xxxxxx.jar
这种方式的启动,linux只会短暂的运行该项目,当退出控制台后会自动关闭该项目。
nohup java -jar xxxxxxx.jar >日志文件名.log 2>&1 &
命令详解:
- nohup:不挂断地运行命令,退出帐户之后继续运行相应的进程。如果未安装请执行 yum install coreutils 。
-
>日志文件名.log:是nohup把command的输出重定向到当前目录的指定的“日志文件名.log”文件中,即输出内容不打印到屏幕上,而是输出到”日志文件名.log”文件中。不指定文件名会在当前目录创建nohup.out,如果当前目录的 nohup.out 文件不可写,输出重定向到 $HOME/nohup.out 文件中。如果没有文件能创建或打开以用于追加,那么 Command 参数指定的命令不可调用。
- 2>&1:2就是标准错误,1是标准输出,该命令相当于把标准错误重定向到标准输出么。这里&相当于标准错误等效于标准输出,即把标准错误和标准输出同时输出到指定的“日志文件名.log”文件中。
- &:让该作业在后台运行。
shell
平时我们用的最多的shell来启动、停止项目。
启动方法:app.sh start 会自动生成catalina.log(文件名称可以自行修改脚本) 文件可供查阅日志
查阅实时日志方法:tail -f catalina.log
停止方法:app.sh stop 会杀掉当前目录下的服务进程
重启方法:app.restart 平滑重启服务
查询状态:app.status
app.sh内容如下:
#!/bin/bash version="6.6.6"; appName=$2 if [ -z $appName ];then # 搜索目录下的jar,还是一个项目一个文件夹,一个文件内有jar包和该sh文件 appName=`ls -t |grep .jar$ |head -n1` fi ## 后台启动项目 自动生成 catalina.log日志文件 function start() { count=`ps -ef |grep java|grep $appName|wc -l` if [ $count != 0 ];then echo "Maybe $appName is running, please check it..." else echo "The $appName is starting..." nohup java -jar ./$appName -XX:+UseG1GC -XX:+HeapDumpOnOutOfMemoryError -Xms512M -Xmx4G > catalina.log 2>&1 & fi } ## 停止项目 function stop() { appId=`ps -ef |grep java|grep $appName|awk '{print $2}'` if [ -z $appId ];then echo "Maybe $appName not running, please check it..." else echo "The $appName is stopping..." kill $appId fi } ##重启项目(平滑启动) function restart() { # get release version releaseApp=`ls -t |grep .jar$ |head -n1` # get last version lastVersionApp=`ls -t |grep .jar$ |head -n2 |tail -n1` appName=$lastVersionApp stop for i in {5..1} do echo -n "$i " sleep 1 done echo 0 backup appName=$releaseApp start } function backup() { # get backup version backupApp=`ls |grep -wv $releaseApp$ |grep .jar$` # create backup dir if [ ! -d "backup" ];then mkdir backup fi # backup for i in ${backupApp[@]} do echo "backup" $i mv $i backup done } ## 查看项目当前状态 function status() { appId=`ps -ef |grep java|grep $appName|awk '{print $2}'` if [ -z $appId ] then echo -e "\033[31m Not running \033[0m" else echo -e "\033[32m Running [$appId] \033[0m" fi } function usage() { echo "Usage: $0 {start|stop|restart|status|stop -f}" echo "Example: $0 start" exit 1 } case $1 in start) start;; stop) stop;; restart) restart;; status) status;; *) usage;; esac
二、war形式部署
要使用war形式部署,首先就要打包成war。
pom依赖 剔除内置的tomcat
<!-- web 剔除内置的tomcat, 部署时才用剔除,开发可用内置的--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <exclusions> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> </exclusion> </exclusions> </dependency> <!--添加servlet-api的依赖--> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> <scope>provided</scope> </dependency>
pom依赖,配置启动类
<build> <plugins> <!-- 添加spring的插件, 就可以直接通过 mvn spring-boot:run 运行了 --> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <mainClass>com.linhw.example.AppClient</mainClass> </configuration> <executions> <execution> <goals> <goal>repackage</goal> </goals> </execution> </executions> <!--在这里添加 springloader plugin,热部署 --> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>springloaded</artifactId> <version>1.2.8.RELEASE</version> </dependency> </dependencies> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> </plugins> </build>
修改启动Application文件继承SpringBootServletInitializer,实现configure方法
@EnableDiscoveryClient @SpringBootApplication public class AppClient extends SpringBootServletInitializer { public static void main(String[] args) { SpringApplication.run(AppClient.class, args); } @Override protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) { return builder.sources(AppClient.class); } }
修改pom的打包方式
<packaging>war</packaging>
打包后,把target目录下的war包放到tomcat的webapps目录下,启动tomcat,即可自动解压
如果使用的是tomcat7会报java.lang.NoClassDefFoundError: javax/el/ELManager,这可能是因为el-api的版本太低了。在tomcat的lib里面添加javax.el-api-3.0.0.jar即可解决。
访问地址:localhost:{tomcat端口号} /重命名的war包名/xxxx,这里要特别注意,端口是tomcat的端口号
三、优雅停服(针对jar)
首先我们不能使用kill-9。如果加了-9,那么系统就不会给JVM调用 shutdown hook 的机会,也就无法完成资源清理了。也不能使用kill -6 否则无法调用到移除eureka的方法。
spring-boot-starter-actuator中提供了/shutdown的方式来优雅的停止服务,所以在pom.xml中必须加入以下依赖:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency>
并在全局配置文件中开启shutdown:
#启动所有端点, 也可以设置部分启动, 如:env,beans。默认是health, info management.endpoints.web.exposure.include=* ## 启用shutdown,优雅停服功能,配置actuator的优雅关闭 ## actuator 组件监听shutdown请求地址的时候,要求请求的method必须是POST ## shutdown的请求地址是使用:@PostMapping或@RequestMapping(method=RequestMethod.POST) management.endpoint.shutdown.enabled=true
服务启动后,可以通过linux的curl命令发送POST请求的方式优雅的停止服务。编写脚本,可命名为:shutdown.sh,内容:
curl -X POST host(ip):port(端口)/actuator/shutdown # curl -X POST 192.168.178.5:8888/actuator/shutdown # 返回:{"message":"Shutting down, bye..."}