安装 Supervisord

# Ubuntu/Debian
sudo apt update && sudo apt install -y supervisor

# CentOS/RHEL
sudo yum install -y supervisor
sudo systemctl enable supervisord
sudo systemctl start supervisord

验证安装

sudo supervisorctl status
ps -ef | grep supervisord

配置 Java 服务

创建配置文件 /etc/supervisor/conf.d/my-java-app.conf

[program:my-java-app]
# 基础配置
command=java -Xms512m -Xmx1024m -jar /opt/app/my-app.jar
directory=/opt/app
user=appuser
autostart=true
autorestart=true
startsecs=30
startretries=3

# 日志管理
stdout_logfile=/var/log/my-java-app/stdout.log
stdout_logfile_maxbytes=50MB
stdout_logfile_backups=10
stderr_logfile=/var/log/my-java-app/stderr.log
stderr_logfile_maxbytes=50MB
stderr_logfile_backups=10

# 环境变量
environment=JAVA_HOME="/usr/lib/jvm/java-11-openjdk",SPRING_PROFILES_ACTIVE="prod"

# 进程管理
stopsignal=INT
stopwaitsecs=30
killasgroup=true

高级配置选项

# 资源限制
priority=500                ; 进程优先级
numprocs=1                  ; 进程数量

# 安全控制
umask=022
serverurl=AUTO

# 事件通知
events=PROCESS_STATE_FATAL  ; 配置事件触发告警

服务管理命令

# 重新加载配置
sudo supervisorctl reread
sudo supervisorctl update

# 服务控制
sudo supervisorctl start my-java-app
sudo supervisorctl stop my-java-app
sudo supervisorctl restart my-java-app

# 查看状态
sudo supervisorctl status my-java-app
sudo supervisorctl tail -f my-java-app stderr

批量操作

# 启动所有服务
sudo supervisorctl start all

# 停止所有服务
sudo supervisorctl stop all

# 重启所有服务
sudo supervisorctl restart all

Prometheus 监控集成

# 在supervisord.conf中启用HTTP接口
[inet_http_server]
port = 0.0.0.0:9001
username = monitor
password = yourpassword

告警规则示例

# Prometheus alert.rules
groups:
- name: java-service-alerts
  rules:
  - alert: JavaServiceDown
    expr: up{job="my-java-app"} == 0
    for: 2m
    labels:
      severity: critical
    annotations:
      summary: "Java服务 {{ $labels.instance }} 已宕机"
      description: "服务 {{ $labels.job }} 已停止响应超过2分钟"

自定义健康检查

# 在Java应用中添加健康接口
@RestController
public class HealthController {
    @GetMapping("/health")
    public String health() {
        return "OK";
    }
}

# Supervisord配置健康检查
[program:my-java-app]
healthcheck=curl -fs http://localhost:8080/health || exit 1
healthcheck_interval=60

日志管理方案

创建 /etc/logrotate.d/my-java-app

/var/log/my-java-app/*.log {
    daily
    rotate 30
    compress
    delaycompress
    missingok
    notifempty
    create 640 appuser appuser
    sharedscripts
    postrotate
        /usr/bin/supervisorctl signal HUP my-java-app >/dev/null 2>&1 || true
    endscript
}

ELK 集成方案

# 修改Supervisord日志输出为JSON格式
stdout_logfile=/var/log/my-java-app/app.log
stdout_logfile_format=json

多实例部署

[program:my-java-app]
process_name=%(program_name)s_%(process_num)02d
numprocs=4
command=java -jar /opt/app/my-app.jar --server.port=808%(process_num)02d

依赖服务控制

[group:app-group]
programs=my-java-app,redis-server,mysql-server

[program:redis-server]
command=/usr/bin/redis-server

[program:mysql-server]
command=/usr/bin/mysqld_safe

自定义启动脚本

#!/bin/bash
# /opt/app/start-app.sh

# 检查端口占用
if netstat -tln | grep -q ':8080'; then
    echo "Port 8080 already in use!"
    exit 1
fi

# 启动Java服务
exec java -jar /opt/app/my-app.jar

对应Supervisord配置:

command=/bin/bash /opt/app/start-app.sh

安全加固措施

# 创建专用用户
sudo useradd -r -s /bin/false appuser
sudo chown -R appuser:appuser /opt/app
sudo chmod 750 /opt/app

[inet_http_server]
port = 127.0.0.1:9001  ; 仅允许本地访问

[program:my-java-app]
priority=100          ; 降低CPU优先级
minfds=1024           ; 最小文件描述符
minprocs=200          ; 最小进程数

故障排查指南

# 查看详细日志
sudo supervisorctl fg my-java-app

# 检查启动错误
journalctl -u supervisord -n 50 -f

# 手动测试启动
sudo -u appuser java -jar /opt/app/my-app.jar

# 检查端口冲突
ss -tlnp | grep java

自动恢复策略

[program:my-java-app]
autorestart=true
startretries=5
exitcodes=0,2          ; 只有退出码为0或2时重启
stopasgroup=true       ; 停止整个进程组

性能优化建议

command=java -server -Xms2g -Xmx2g -XX:+UseG1GC -XX:MaxGCPauseMillis=200 -jar /opt/app/my-app.jar

Supervisord 调优

[supervisord]
minfds=65535           ; 最大文件描述符
minprocs=2000          ; 最大进程数

一键部署脚本

#!/bin/bash
# deploy-java-with-supervisor.sh

APP_NAME="my-java-app"
APP_JAR="/opt/app/my-app.jar"
APP_USER="appuser"
JAVA_OPTS="-Xms2g -Xmx2g -XX:+UseG1GC"

echo "开始部署Java服务托管..."

# 1. 创建用户和目录
sudo useradd -r -s /bin/false $APP_USER
sudo mkdir -p /opt/app /var/log/$APP_NAME
sudo chown $APP_USER:$APP_USER /opt/app /var/log/$APP_NAME

# 2. 创建Supervisor配置
sudo tee /etc/supervisor/conf.d/$APP_NAME.conf > /dev/null <<EOF
[program:$APP_NAME]
command=java $JAVA_OPTS -jar $APP_JAR
directory=/opt/app
user=$APP_USER
autostart=true
autorestart=true
startsecs=30
stdout_logfile=/var/log/$APP_NAME/stdout.log
stderr_logfile=/var/log/$APP_NAME/stderr.log
environment=JAVA_HOME="/usr/lib/jvm/java-11-openjdk"
EOF

# 3. 重载配置
sudo supervisorctl reread
sudo supervisorctl update

echo "部署完成!使用以下命令管理服务:"
echo "启动服务: sudo supervisorctl start $APP_NAME"
echo "查看状态: sudo supervisorctl status"

更多推荐