1. 项目概述
作为一名长期奋战在一线的Java开发者,我深知将SpringBoot应用部署到生产环境的重要性。Ubuntu作为最流行的Linux发行版之一,凭借其稳定性和丰富的软件生态,成为企业级Java应用部署的首选平台。本文将分享我在实际项目中总结的SpringBoot应用部署全流程,涵盖从环境准备到服务管理的每个关键环节。
2. 环境准备与配置
2.1 服务器基础环境
推荐使用Ubuntu 20.04 LTS或22.04 LTS版本,这两个版本都提供长期支持且稳定性经过验证。在开始部署前,确保:
- 完成系统更新:
sudo apt update && sudo apt upgrade -y- 安装必要工具:
sudo apt install -y curl wget unzip net-tools注意:生产环境建议禁用root直接登录,配置SSH密钥认证。可通过
sudo nano /etc/ssh/sshd_config修改PermitRootLogin为no。
2.2 Java环境安装
2.2.1 JDK版本选择
当前主流选择有:
- OpenJDK 17(LTS版本,推荐新项目使用)
- OpenJDK 11(另一个LTS版本,存量项目常用)
- Amazon Corretto(AWS优化版本)
安装OpenJDK 17:
sudo apt install -y openjdk-17-jdk验证安装:
java -version2.2.2 环境变量配置
虽然Ubuntu会自动配置Java路径,但显式设置更可靠:
echo 'export JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64' >> ~/.bashrc echo 'export PATH=$JAVA_HOME/bin:$PATH' >> ~/.bashrc source ~/.bashrc3. 应用部署实战
3.1 应用打包与传输
推荐使用SpringBoot Maven插件打包:
mvn clean package -DskipTests生成的jar文件通常位于target目录下。传输到服务器的几种方式:
- SCP命令(适合小文件):
scp target/your-app.jar user@server:/var/www/java-app/- SFTP客户端(如FileZilla)
- 代码仓库直接拉取(需配置部署密钥)
3.2 运行应用
基础启动命令:
java -jar /var/www/java-app/your-app.jar生产环境推荐添加JVM参数:
java -Xms512m -Xmx1024m -XX:+UseG1GC -jar your-app.jar常见问题:遇到"no main manifest attribute"错误,检查pom.xml是否配置了spring-boot-maven-plugin。
3.3 数据库配置(MySQL示例)
安装MySQL 8.0:
sudo apt install -y mysql-server安全初始化:
sudo mysql_secure_installation创建应用数据库:
CREATE DATABASE app_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; CREATE USER 'app_user'@'localhost' IDENTIFIED BY 'StrongPassword123!'; GRANT ALL PRIVILEGES ON app_db.* TO 'app_user'@'localhost'; FLUSH PRIVILEGES;在application.properties中配置:
spring.datasource.url=jdbc:mysql://localhost:3306/app_db spring.datasource.username=app_user spring.datasource.password=StrongPassword123! spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver4. 生产级优化配置
4.1 系统服务管理
创建systemd服务文件/etc/systemd/system/java-app.service:
[Unit] Description=Java Application Service After=syslog.target network.target [Service] User=appuser Group=appgroup WorkingDirectory=/var/www/java-app ExecStart=/usr/bin/java -Xms512m -Xmx1024m -jar /var/www/java-app/your-app.jar SuccessExitStatus=143 Restart=always RestartSec=10 StandardOutput=syslog StandardError=syslog SyslogIdentifier=java-app [Install] WantedBy=multi-user.target关键参数说明:
User/Group:建议使用非root用户运行Restart=always:确保应用崩溃后自动重启StandardOutput:将日志输出到系统日志
启用服务:
sudo systemctl daemon-reload sudo systemctl enable java-app sudo systemctl start java-app4.2 Nginx反向代理配置
安装Nginx:
sudo apt install -y nginx配置/etc/nginx/sites-available/your-domain.com:
server { listen 80; server_name your-domain.com; location / { proxy_pass http://127.0.0.1:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; # WebSocket支持 proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; } # 静态资源缓存 location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ { expires 30d; add_header Cache-Control "public, no-transform"; } }启用配置:
sudo ln -s /etc/nginx/sites-available/your-domain.com /etc/nginx/sites-enabled/ sudo nginx -t sudo systemctl restart nginx4.3 日志管理方案
4.3.1 Logback配置示例
logback-spring.xml配置:
<configuration> <property name="LOG_PATH" value="/var/log/java-app" /> <property name="LOG_FILE" value="${LOG_PATH}/application.log" /> <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> <file>${LOG_FILE}</file> <encoder> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern> </encoder> <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"> <fileNamePattern>${LOG_PATH}/application.%d{yyyy-MM-dd}.%i.log.gz</fileNamePattern> <maxFileSize>100MB</maxFileSize> <maxHistory>30</maxHistory> <totalSizeCap>2GB</totalSizeCap> </rollingPolicy> </appender> <root level="INFO"> <appender-ref ref="FILE" /> </root> </configuration>4.3.2 日志轮转配置
创建logrotate配置/etc/logrotate.d/java-app:
/var/log/java-app/*.log { daily missingok rotate 30 compress delaycompress notifempty create 0640 appuser appgroup sharedscripts postrotate systemctl kill -s HUP java-app.service >/dev/null 2>&1 || true endscript }5. 高级部署技巧
5.1 多环境配置管理
使用Spring Profile管理不同环境配置:
- 创建配置文件:
application-dev.properties application-prod.properties- 启动时指定profile:
java -jar your-app.jar --spring.profiles.active=prod5.2 健康检查与监控
- 启用Actuator端点:
management.endpoints.web.exposure.include=health,info,metrics management.endpoint.health.show-details=always- 配置Prometheus监控:
<dependency> <groupId>io.micrometer</groupId> <artifactId>micrometer-registry-prometheus</artifactId> </dependency>5.3 安全加固措施
- 禁用敏感端点:
management.endpoints.web.exposure.exclude=env,beans- 添加Basic认证:
spring.security.user.name=admin spring.security.user.password=securepass- 配置HTTPS:
sudo apt install -y certbot python3-certbot-nginx sudo certbot --nginx -d your-domain.com6. 常见问题排查
6.1 内存问题排查
查看JVM内存使用:
jstat -gc <pid> 1000 5生成堆转储:
jmap -dump:format=b,file=heap.hprof <pid>6.2 启动失败排查
查看最近日志:
journalctl -u java-app --no-pager -n 1006.3 性能优化建议
- JVM参数优化示例:
-XX:+UseG1GC -Xms2g -Xmx2g -XX:MaxGCPauseMillis=200 -XX:ParallelGCThreads=4 -XX:ConcGCThreads=2- 连接池配置(HikariCP示例):
spring.datasource.hikari.maximum-pool-size=20 spring.datasource.hikari.connection-timeout=30000 spring.datasource.hikari.idle-timeout=600000在实际部署过程中,我发现最容易出问题的环节是文件权限配置。建议专门为应用创建用户组,并确保所有相关目录(如日志目录、上传目录)都有正确的权限设置。另外,对于需要长时间运行的服务,使用tmux或screen可以防止SSH断开导致服务终止,但这只是临时方案,最终还是要配置为系统服务。