部署Spring Boot应用
SpringBoot 应用可直接打包成 Jar、War,运行时执行 java -jar *.jar/*.war
。但将其“解压”并以不同的方式运行也往往是一种优势,这在启动时(取决于jar的大小)实际上比从一个未“解压”的归档文件中运行要稍快一些。
创建应用目录:
1 2 3
| # 创建应用解药目录 mkdir -p app_dir unzip app_name.jar -d app_dir
|
运行应用
1 2 3 4
| # 进入应用目录 cd app_dir # 运行应用 java -Xms1g -Xmx1g -Dfile.encoding=UTF-8 org.springframework.boot.loader.WarLauncher --spring.profiles.active=hunkier --server.port=8083
|
此时SpringBoot应用在命令行前台运行,当键盘按下 control + C 结束时,应用程序也停止运行。
需要应用一直在后台一直运行,不受命令行退出影响。
方便应用启动和停止等操作,可将命令写成 shell 脚本 api_service.sh,内容如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
| #!/bin/bash #cat /etc/init.d/api_service # # Provides: hunkier # Required-Start: $network $local_fs $remote_fs # Required-Stop: $network $local_fs $remote_fs # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: The SpringBoot control shell # Description: Start or stop the SpringBoot application #
#应用名称 NAME="API_SERVICE"
# springboot 激活的配置文件 PROFILE="hunkier" # web 应用服务端口 PORT=8083 # 应用部署目录 APP_DIR="/data1/webserver/api_service_${PORT}" #日志配置文件 LOGGING_CONFIG="${APP_DIR}/config/logback-spring.xml" # 日志目录 LOG_DIR="${APP_DIR}/logs" # 日志文件 LOG_FILE="${LOG_DIR}/${PORT}.log" # JVM 参数 VM_OPTIONS="-Xms1g -Xmx1g -Dfile.encoding=UTF-8" # springboot 参数 SPRING_OPTIONS="--spring.profiles.active=${PROFILE} --server.port=${PORT} --logging.config=${LOGGING_CONFIG} --logging.pattern.path=${LOG_DIR}" JAVA_HOME="/Library/Java/JavaVirtualMachines/jdk1.8.0_311.jdk/Contents/Home" JAVA_BIN="${JAVA_HOME}/bin/java"
# 引入系统环境 source /etc/profile
# 进入应用目录 #cd $APP_DIR # 创建日志目录 if [ ! -d $LOG_DIR ]; then mkdir -p $LOG_DIR fi
# 创建日志文件 if [ ! -f $LOG_DIR ]; then touch $LOG_FILE fi
Info_font_prefix="\033[32m" && Error_font_prefix="\033[31m" && Info_background_prefix="\033[42;37m" && Error_background_prefix="\033[41;37m" && Font_suffix="\033[0m"
RETVAL=0 check_running(){ PID=$(ps -ef |grep ${APP_DIR} |grep $PORT |grep java |grep -v "tail" |grep -v "grep" |grep -v "init.d" |grep -v "service" |awk '{print $2}') if [[ ! -z ${PID} ]]; then return 0 else return 1 fi } do_start(){ check_running if [[ $? -eq 0 ]]; then echo -e "${Info_font_prefix}[信息]${Font_suffix} ${NAME}_${PORT} (PID ${PID}) 正在运行..." && exit 0 else ulimit -n 51200 # cd ${APP_DIR} do_info nohup $JAVA_BIN -cp ${APP_DIR} ${VM_OPTIONS} org.springframework.boot.loader.WarLauncher ${SPRING_OPTIONS} >> $LOG_DIR/${PORT}_nohup.log 2>&1 & check_running if [[ $? -eq 0 ]]; then echo -e "${Info_font_prefix}[信息]${Font_suffix} ${NAME}_${PORT} 启动成功 !" else echo -e "${Error_font_prefix}[错误]${Font_suffix} ${NAME}_${PORT} 启动失败 !" fi fi } do_stop(){ check_running if [[ $? -eq 0 ]]; then kill -9 ${PID} RETVAL=$? if [[ $RETVAL -eq 0 ]]; then echo -e "${Info_font_prefix}[信息]${Font_suffix} ${NAME}_${PORT} 停止成功 !" else echo -e "${Error_font_prefix}[错误]${Font_suffix} ${NAME}_${PORT} 停止失败 !" fi else echo -e "${Info_font_prefix}[信息]${Font_suffix} ${NAME}_${PORT} 未运行 !" RETVAL=1 fi } do_status(){ check_running if [[ $? -eq 0 ]]; then echo -e "${Info_font_prefix}[信息]${Font_suffix} ${NAME}_${PORT} (PID ${PID}) 正在运行..." else echo -e "${Info_font_prefix}[信息]${Font_suffix} ${NAME}_${PORT} 未运行 !" RETVAL=1 fi } do_tail(){ echo "tail -1000f ${LOG_FILE}" tail -1000f ${LOG_FILE} } do_log(){ echo "tail -f ${LOG_FILE}" tail -f ${LOG_FILE} } do_restart(){ do_stop do_start } do_console(){ do_start do_log } do_info(){ echo "APP_NAME: ${NAME}" echo "APP_DIR: ${APP_DIR}" echo "APP_PORT: ${PORT}" echo "spring 激活配置:${PROFILE}" echo "日志目录: ${LOG_DIR}" echo "JAVA_HOME: ${JAVA_HOME}" echo "VM_OPTIONS: ${VM_OPTIONS}" echo "SPRING_OPTIONS: ${SPRING_OPTIONS}" $JAVA_BIN -version } case "$1" in start|stop|restart|status|log|tail|console|info) do_$1 ;; *) echo "使用方法: $0 { start(启动) | stop(停止) | restart(重启) | status(状态) | log(日志) | tail(日志) | console(启动并查看日志) | info(配置信息)}" RETVAL=1 ;; esac exit $RETVAL
|
启动、停止命令
1
| ./api_service.sh start/stop/status
|
在 Unix/Linx 服务 作为 init.d 服务安装
1
| sudo ln -s api_service.sh /etc/init.d/api_serice
|
一旦安装完毕,可以用通常的方式启动和停止该服务
1
| service api_service start/stop/staus
|
为了更好的管理日志文件需要定制 logback 相关配置,以下为 logback-spring.xml 文件内容:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
| <?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="10 seconds"> <contextName>logback</contextName>
<springProperty scope="context" name="logging.pattern.path" source="logging.pattern.path"/> <springProperty scope="context" name="server.port" source="server.port"/>
<conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter" /> <conversionRule conversionWord="wex" converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter" /> <conversionRule conversionWord="wEx" converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter" /> <property name="CONSOLE_LOG_PATTERN" value="${CONSOLE_LOG_PATTERN:-%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"> <filter class="ch.qos.logback.classic.filter.ThresholdFilter"> <level>debug</level> </filter> <encoder> <Pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</Pattern> <charset>UTF-8</charset> </encoder> </appender>
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> <file>${logging.pattern.path}/${server.port}.log</file> <encoder> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern> <charset>UTF-8</charset> </encoder> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <fileNamePattern>${logging.pattern.path}/${server.port}-%d{yyyy-MM-dd}.%i.log.gz</fileNamePattern> <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"> <maxFileSize>100MB</maxFileSize> </timeBasedFileNamingAndTriggeringPolicy> <maxHistory>365</maxHistory> </rollingPolicy> <filter class="ch.qos.logback.classic.filter.LevelFilter"> <level>info</level> <onMatch>ACCEPT</onMatch> <onMismatch>DENY</onMismatch> </filter> </appender>
<root level="info"> <appender-ref ref="FILE" />
</root>
</configuration>
|
参考资料:
springBoot deployment:
https://docs.spring.io/spring-boot/docs/current/reference/html/deployment.html#deployment.efficient.unpacking
Accessing Command Line Properties:
https://docs.spring.io/spring-boot/docs/current/reference/html/features.html#features.external-config
Profiles:
https://docs.spring.io/spring-boot/docs/current/reference/html/features.html#features.profiles
Logback Extensions:
https://docs.spring.io/spring-boot/docs/current/reference/html/features.html#features.logging.logback-extensions