在阿里云ECS上同时运行多个Spring Boot应用是常见需求。以下是详细步骤和最佳实践:
1. 环境准备
# 安装Java环境
sudo yum install -y java-1.8.0-openjdk-devel
# 验证安装
java -version
2. 应用配置(关键:端口分离)
方法一:通过application.yml配置不同端口
# app1/application.yml
server:
port: 8081
spring:
application:
name: app1-service
# app2/application.yml
server:
port: 8082
spring:
application:
name: app2-service
# app3/application.yml
server:
port: 8083
spring:
application:
name: app3-service
方法二:通过启动参数指定端口
# 启动命令示例
java -jar app1.jar --server.port=8081
java -jar app2.jar --server.port=8082
java -jar app3.jar --server.port=8083
3. 目录结构规划
/opt/springboot-apps/
├── app1/
│ ├── app1.jar
│ ├── application.yml
│ └── logs/
├── app2/
│ ├── app2.jar
│ ├── application.yml
│ └── logs/
├── app3/
│ ├── app3.jar
│ ├── application.yml
│ └── logs/
└── scripts/
├── start-all.sh
├── stop-all.sh
└── status.sh
4. 创建启动脚本
单个应用启动脚本 (start-app1.sh)
#!/bin/bash
APP_NAME="app1"
JAR_NAME="app1.jar"
APP_PORT=8081
LOG_DIR="/opt/springboot-apps/app1/logs"
PID_FILE="/var/run/${APP_NAME}.pid"
cd /opt/springboot-apps/app1
case "$1" in
start)
if [ -f $PID_FILE ]; then
echo "$APP_NAME is already running..."
exit 1
fi
nohup java -jar $JAR_NAME
--server.port=$APP_PORT
--logging.file.name=$LOG_DIR/${APP_NAME}.log
> $LOG_DIR/nohup.out 2>&1 &
echo $! > $PID_FILE
echo "$APP_NAME started on port $APP_PORT"
;;
stop)
if [ ! -f $PID_FILE ]; then
echo "$APP_NAME is not running"
exit 1
fi
kill $(cat $PID_FILE)
rm $PID_FILE
echo "$APP_NAME stopped"
;;
restart)
$0 stop
sleep 2
$0 start
;;
status)
if [ -f $PID_FILE ]; then
PID=$(cat $PID_FILE)
if ps -p $PID > /dev/null; then
echo "$APP_NAME is running (PID: $PID)"
else
echo "$APP_NAME is not running (stale PID file)"
rm $PID_FILE
fi
else
echo "$APP_NAME is not running"
fi
;;
*)
echo "Usage: $0 {start|stop|restart|status}"
exit 1
;;
esac
批量管理脚本
# start-all.sh
#!/bin/bash
APPS=("app1" "app2" "app3")
for app in "${APPS[@]}"; do
echo "Starting $app..."
/opt/springboot-apps/scripts/start-${app}.sh start
sleep 3
done
echo "All applications started!"
5. 使用Systemd服务管理(推荐)
创建systemd服务文件
# /etc/systemd/system/app1.service
[Unit]
Description=App1 Spring Boot Application
After=syslog.target
[Service]
Type=simple
User=root
WorkingDirectory=/opt/springboot-apps/app1
ExecStart=/usr/bin/java -jar app1.jar --server.port=8081
Restart=always
RestartSec=10
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=multi-user.target
管理服务
# 启用服务
sudo systemctl enable app1.service
sudo systemctl enable app2.service
sudo systemctl enable app3.service
# 启动服务
sudo systemctl start app1
sudo systemctl start app2
sudo systemctl start app3
# 查看状态
sudo systemctl status app1
sudo systemctl status app2
sudo systemctl status app3
# 查看日志
sudo journalctl -u app1 -f
6. Nginx反向X_X配置
# /etc/nginx/conf.d/apps.conf
upstream app1 {
server 127.0.0.1:8081;
}
upstream app2 {
server 127.0.0.1:8082;
}
upstream app3 {
server 127.0.0.1:8083;
}
server {
listen 80;
server_name your-domain.com;
location /app1/ {
proxy_pass http://app1/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location /app2/ {
proxy_pass http://app2/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location /app3/ {
proxy_pass http://app3/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
7. 防火墙配置
# 开放必要端口
sudo firewall-cmd --permanent --add-port=80/tcp
sudo firewall-cmd --permanent --add-port=8081-8083/tcp
sudo firewall-cmd --reload
# 或使用iptables
sudo iptables -A INPUT -p tcp --dport 80 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 8081:8083 -j ACCEPT
8. 监控和维护
资源监控脚本
# monitor.sh
#!/bin/bash
echo "=== Spring Boot Applications Status ==="
ps aux | grep java | grep -v grep
echo -e "n=== Network Ports ==="
netstat -tlnp | grep java
echo -e "n=== Memory Usage ==="
free -h
echo -e "n=== Disk Space ==="
df -h /opt/springboot-apps
9. 最佳实践
-
内存分配:为每个应用设置合适的JVM参数
java -Xms512m -Xmx1024m -jar app.jar -
日志轮转:配置logback或log4j2的滚动策略
-
健康检查:确保每个应用都有/actuator/health端点
-
安全考虑:
- 使用非root用户运行应用
- 配置合理的文件权限
- 定期更新依赖
-
备份策略:定期备份应用jar包和配置文件
通过以上配置,你可以在同一台ECS实例上稳定运行多个Spring Boot应用。建议根据实际业务需求调整资源配置和监控策略。
CLOUD技术博