如何在阿里云ECS上同时运行多个SpringBoot应用?

在阿里云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. 最佳实践

  1. 内存分配:为每个应用设置合适的JVM参数

    java -Xms512m -Xmx1024m -jar app.jar
  2. 日志轮转:配置logback或log4j2的滚动策略

  3. 健康检查:确保每个应用都有/actuator/health端点

  4. 安全考虑:

    • 使用非root用户运行应用
    • 配置合理的文件权限
    • 定期更新依赖
  5. 备份策略:定期备份应用jar包和配置文件

通过以上配置,你可以在同一台ECS实例上稳定运行多个Spring Boot应用。建议根据实际业务需求调整资源配置和监控策略。

未经允许不得转载:CLOUD技术博 » 如何在阿里云ECS上同时运行多个SpringBoot应用?