×
技术社区 >  技术博客 >  OceanBase云平台 (OCP) 容器化部署中的Supervisor进程守护机制解析

OceanBase云平台 (OCP) 容器化部署中的Supervisor进程守护机制解析

OceanBase云平台(OCP)作为OceanBase分布式数据库的全生命周期综合运维管理平台,其核心服务以Java进程形式运行在容器环境中,这带来了进程稳定性、高可用性和自动化运维的全新需求。本文通过分析,展示OCP容器中Supervisor的进程守护机制。

一、OCP 容器进程概述

OCP 云平台的本质是一个运行在容器中的Java进程,具体表现为 ocp-server-4.4.1-20260212105850.jar 这样的 jar 包执行体。
在容器环境中,该Java进程通过特定的JVM参数配置运行,以满足企业级应用对性能和稳定性的高要求。

  1. # 登录 ocp 容器
  2. # docker exec -it ocp sh
  3. # 查看容器中的JAVA进程
  4. # ps -ef|grep -v grep|grep java
  5. admin 12 133 2.3 745050368 25132288 ? Sl 14:51 5:16 /usr/lib/jvm/java-17/bin/java
  6. -server -XX:+UseZGC -Xms14336m -Xmx14336m -Xss512k -XX:MetaspaceSize=1024m -XX:MaxMetaspaceSize=1024m
  7. -Xlog:gc*,gc+stats=off,safepoint=off:file=/home/admin/ocp-server/bin/../log/gc.log:time:filecount=2,filesize=50M
  8. -XX:+ExitOnOutOfMemoryError -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/home/admin/ocp-server/bin/../log/
  9. -Dfile.encoding=UTF-8
  10. --add-exports=java.xml/jdk.xml.internal=ALL-UNNAMED
  11. --add-opens=java.base/java.io=ALL-UNNAMED
  12. --add-opens=java.base/java.lang.reflect=ALL-UNNAMED
  13. --add-opens=java.base/java.lang=ALL-UNNAMED
  14. --add-opens=java.base/java.math=ALL-UNNAMED
  15. --add-opens=java.base/java.net=ALL-UNNAMED
  16. --add-opens=java.base/java.nio.charset=ALL-UNNAMED
  17. --add-opens=java.base/java.nio=ALL-UNNAMED
  18. --add-opens=java.base/java.nio.file=ALL-UNNAMED
  19. --add-opens=java.base/java.security=ALL-UNNAMED
  20. --add-opens=java.base/java.text=ALL-UNNAMED
  21. --add-opens=java.base/java.time.format=ALL-UNNAMED
  22. --add-opens=java.base/java.time=ALL-UNNAMED
  23. --add-opens=java.base/java.util.concurrent.atomic=ALL-UNNAMED
  24. --add-opens=java.base/java.util.concurrent=ALL-UNNAMED
  25. --add-opens=java.base/java.util.regex=ALL-UNNAMED
  26. --add-opens=java.base/java.util.stream=ALL-UNNAMED
  27. --add-opens=java.base/java.util=ALL-UNNAMED
  28. --add-opens=java.base/sun.net.www.protocol.https=ALL-UNNAMED
  29. --add-opens=java.base/sun.net=ALL-UNNAMED
  30. --add-opens=java.base/sun.nio.cs=ALL-UNNAMED
  31. --add-opens=java.base/sun.nio.fs=ALL-UNNAMED
  32. --add-opens=java.base/sun.security.jca=ALL-UNNAMED
  33. --add-opens=java.base/sun.security.ssl=ALL-UNNAMED
  34. --add-opens=java.base/sun.security.util=ALL-UNNAMED
  35. --add-opens=java.base/jdk.internal.util=ALL-UNNAMED
  36. --add-opens=java.logging/java.util.logging=ALL-UNNAMED
  37. --add-opens=java.rmi/sun.rmi.transport=ALL-UNNAMED
  38. -Daliyun.rass.enabled=false
  39. -jar /home/admin/ocp-server/bin/../lib/ocp-server-4.4.1-20260212105850.jar --bootstrap

二、Supervisor 在容器环境中的价值

在传统的物理机或虚拟机部署中,系统服务通常由systemd或init系统管理。然而,在Docker容器环境中,每个容器默认只运行一个前台进程,当这个进程退出时容器也随之终止。对于OCP这样的复杂企业级应用,需要确保其核心Java服务在意外崩溃时能够自动恢复,同时还需要管理可能存在的其他辅助进程。这种需求催生了在容器内部引入进程管理工具的必要性,而Supervisor正是这一场景下的理想选择。

Supervisord 是一个用 Python 编写的进程控制系统,用于在类 Unix 系统(如 Linux)上监控和管理后台进程,确保它们守护的进程在意外退出时自动重启‌ 。

2.1 Supervisor 的基本原理与架构

Supervisor 是一个 C/S(客户端/服务器)架构的工具。在此架构中:‌‌

  1. supervisord‌:是‌服务端(server)守护进程‌,也是整个系统的核心。它负责启动配置中指定的子进程,响应客户端的命令,监控子进程状态,并在其崩溃或退出时按策略自动重启,同时负责记录子进程的标准输出和错误输出。
  2. ‌supervisorctl‌:是‌命令行客户端(client)工具‌,为用户提供了一个与 supervisord 交互的接口。通过它,用户可以查看进程状态、启动、停止、重启进程或重新加载配置文件。‌‌

2.2 Supervisor主要功能与特点

Supervisord 的设计宗旨在于简化多进程管理,其主要功能包括:

  1. 进程守护与自动重启‌:这是其核心功能。当被管理的进程意外崩溃或退出时,supervisord 可以自动将其重新启动,确保服务的高可用性。其 autorestart 参数允许精细控制重启行为(如仅在非预期退出时重启)。
  2. 统一管理界面‌:通过一个统一的配置文件(及包含的子配置文件)和一套简单的命令,即可管理多个不同的后台进程,无需为每个进程单独编写复杂的守护脚本。
  3. 集中化的日志管理‌:supervisord 可以捕获并重定向所有被管理进程的 stdout(标准输出)和 stderr(标准错误)到指定日志文件,方便问题排查和日志轮转。
  4. 进程状态监控与控制‌:用户可以通过 supervisorctl status 命令或启用 Web 管理界面(通过配置 [inet_http_server] 部分),实时查看所有进程的运行状态(如 RUNNING, STOPPED),并对其进行启动、停止、重启等操作。
  5. 进程分组管理‌:支持将多个进程定义为一个组([group: x]),从而可以一次性启动、停止或重启整个组内的所有进程。

2.3 Supervisor与OCP的集成模式

查看容器中 supervisord 进程信息,发现 supervisord 进程是通过 /usr/bin/supervisord -c /etc/supervisor/supervisord.conf 命令启动而来,其父进程号为 1。

  1. # ps -ef|grep -v grep|grep -i supervisor
  2. root 1 0 0 14:51 ? 00:00:00 /bin/bash -c chmod u+s /usr/sbin/clockdiff; setcap 'cap_net_raw+ep' /usr/sbin/clockdiff; /usr/bin/supervisord -c /etc/supervisor/supervisord.conf
  3. root 9 1 0 14:51 ? 00:00:04 /usr/bin/python2 /usr/bin/supervisord -c /etc/supervisor/supervisord.conf

在OCP的容器化部署中,Supervisor被配置为容器的1号进程(PID 1),这意味着它伴随着容器的启动而启动,并负责管理容器内的所有其他进程。通过分析OCP容器的启动命令可以发现,容器入口点是一个包含多个命令的bash脚本,其中最后一步就是启动 supervisord 服务:

  1. # docker ps -f "name=ocp" --no-trunc --format '{{.Names}} {{.Command}}'
  2. ocp "/bin/bash -c 'chmod u+s /usr/sbin/clockdiff; setcap 'cap_net_raw+ep' /usr/sbin/clockdiff; /usr/bin/supervisord -c /etc/supervisor/supervisord.conf'"

这种设计确保了Supervisor作为容器生命周期管理器,当它退出时整个容器也会终止,从而实现了对容器内所有进程的统一管控。

三、OCP进程守护的具体实现机制

3.1 Supervisor配置文件

# ls -l /etc/supervisor
drwxr-xr-x 2 admin admin   22 2月  12 11:21 conf.d
-rw-r--r-- 1 admin admin 1009 2月  12 11:19 supervisord.conf

# ls -l /etc/supervisor/conf.d/
-rw-r--r-- 1 admin admin 369 2月  12 11:19 ocp.conf

主配置文件/etc/supervisor/supervisord.conf)定义了Supervisor服务本身的全局设置,包括日志文件路径、PID文件位置、日志级别等关键参数。特别值得注意的是nodaemon = true这一配置,它使supervisord以前台模式运行,这是容器环境中确保supervisord作为1号进程的必要条件。

程序配置文件/etc/supervisor/conf.d/ocp.conf)专门定义OCP Java进程的管理规则。该配置文件包含了进程名称、启动命令、工作目录、运行用户、日志文件路径等关键信息。确保了OCP进程在意外退出时能够自动重启,这是实现高可用性的核心机制。

3.1.1 主配置文件示例

  1. # cat /etc/supervisor/supervisord.conf
  2. [unix_http_server]
  3. file = /dev/supervisor.sock ; (the path to the socket file)
  4. [supervisord]
  5. logfile = /home/admin/logs/ocp_supervisord.log ; (main log file;default $CWD/supervisord.log)
  6. logfile_maxbytes = 50MB ; (max main logfile bytes b4 rotation;default 50MB)
  7. logfile_backups = 10 ; (num of main logfile rotation backups;default 10)
  8. loglevel = info ; (log level;default info; others: debug,warn,trace)
  9. pidfile = /run/supervisord.pid ; (supervisord pidfile;default supervisord.pid)
  10. nodaemon = true ; (start in foreground if true;default false)
  11. minfds = 1024 ; (min. avail startup file descriptors;default 1024)
  12. minprocs = 200 ; (min. avail process descriptors;default 200)
  13. [rpcinterface:supervisor]
  14. supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface
  15. [supervisorctl]
  16. serverurl = unix:///dev/supervisor.sock ; use a unix:// URL for a unix socket
  17. [include]

3.1.2 ocp程序配置文件示例

  1. # cat /etc/supervisor/conf.d/ocp.conf
  2. [program:ocp-server]
  3. process_name = %(program_name)s_%(process_num)02d <-- 程序名称:ocp-server:ocp-server_00
  4. command = /home/admin/ocp-server/bin/ocp-server --bootstrap <-- ocp 启动命令
  5. directory = /home/admin <-- 执行命令前切换的目录
  6. user = admin <-- 启动用户
  7. numprocs = 1
  8. stopsignal=INT
  9. killasgroup = true
  10. stdout_logfile = /home/admin/logs/ocp-server.%(process_num)s.out
  11. stderr_logfile = /home/admin/logs/ocp-server.%(process_num)s.err
  12. redirect_stderr = false

3.2 ocp 进程守护的实践验证

当手动终止OCP的Java进程(kill -9)后,观察发现该进程会被自动重新拉起,且进程ID发生变化。这一现象正是Supervisor的 autorestart 机制在起作用,它持续监控被管理进程的状态,一旦发现进程异常退出,便根据配置策略重新启动该进程。

  1. # kill -9 12 <--- 杀掉ocp进程
  2. # ps -ef|grep -v grep|grep java <-- 发现ocp进程重新拉起,进程号由原来的12,变为29796
  3. admin 29796 9 99 15:02 ? 00:00:31 /usr/lib/jvm/java-17/bin/java -server -XX:+UseZGC -Xms14336m ...

进一步分析进程关系可以发现,OCP Java进程的父进程正是 supervisord 进程(PID 9),而 supervisord 的父进程是容器的1号进程(PID 1)。这种进程层级关系清晰地展示了Supervisor作为进程管理器的角色定位。

  1. # ps -ef|grep -v grep|grep supervisor
  2. root 1 0 0 14:51 ? 00:00:00 /bin/bash -c chmod u+s /usr/sbin/clockdiff; setcap 'cap_net_raw+ep' /usr/sbin/clockdiff; /usr/bin/supervisord -c /etc/supervisor/supervisord.conf
  3. root 9 1 0 14:51 ? 00:00:08 /usr/bin/python2 /usr/bin/supervisord -c /etc/supervisor/supervisord.conf

四、Supervisor 运维操作

Supervisor提供了 supervisorctl 命令行工具,能够方便地查看和管理被监控的进程。通过supervisorctl手动停止的进程不会自动重启,这与进程意外崩溃时的自动重启行为形成对比。这种差异化的行为控制为运维操作提供了灵活性,既保证了生产环境的高可用性,又支持了必要的维护操作。

4.1 查看 ocp 进程

  1. # supervisorctl status
  2. ocp-server:ocp-server_00 RUNNING pid 29796, uptime 0:22:49

4.2 停止 ocp 进程

  1. # supervisorctl stop ocp-server:ocp-server_00
  2. ocp-server:ocp-server_00: stopped
  3. # supervisorctl status
  4. ocp-server:ocp-server_00 STOPPED Mar 05 03:25 PM
  5. # ps -ef|grep -v grep|grep java
  6. 使用supervisorctl停止的进程,不会自动拉起。

4.3 启动 ocp 进程

ocp 进程启动后,监测 8080 端口,成功监听后,ocp 才能对外提供服务。

  1. # supervisorctl start ocp-server:ocp-server_00
  2. ocp-server:ocp-server_00: started
  3. # supervisorctl status
  4. ocp-server:ocp-server_00 RUNNING pid 101997, uptime 0:00:07
  5. # ps -ef|grep -v grep|grep java
  6. admin 101997 9 99 15:27 ? 00:00:30 /usr/lib/jvm/java-17/bin/java -server -XX:+UseZGC -Xms14336m ...
  7. # netstat -tnlp|grep 8080
  8. tcp6 0 0 :::8080 :::* LISTEN

精选推荐