# 服务插件规范

文档版本 内容修订 修订人 修订日期
V1.0 添加插件规范基本内容 王垚 2023-11-25
V1.1 增加 Hooks 描述 王垚 2024-01-12
V1.2 增加可视化配置规范描述 郭程豪 2024-02-22

# 基本要求

服务插件对对程序的编程语言没有强制要求,你可以选择合适的编程语言,但是有以下几点需要进行注意:

  1. 程序可以在目标设备上直接运行,如果依赖于运行环境的,可以在配置好运行环境后正常运行。
  2. 尽可能的不要依赖系统的动态链接库,如果使用了系统的动态链接库,需要确保在目标设备中也安装有对应的库。
  3. 如果程序依赖了动态库,可以使用相对路径,把动态库和程序放在一起。
  4. 如果程序时编译型(C、C++、Go 等)语言,需要先编译为可执行文件。
  5. 如果程序为解释型(Python、JS、Java 等)语言,需要声明解释器类型,或者将解释器和程序打包放在一起。
  6. 需要将程序和其必要的依赖放到一起。
  7. 服务管理仅支持 Windows、Linux 和 MacOS 等系统的电脑,不支持移动平台(Android、iOS)。
  8. 支持在国产操作系统上运行服务管理,如 银河麒麟、UOS 等。
  9. 不支持带GUI的程序,如 (WPF、Qt、Unity 等桌面程序)。
  10. 如果是 B/S 架构的程序,在服务端内置一个网页服务是可行的。
  11. 不支持以 nohup 模式运行的服务。

# 程序开发建议

  1. 程序数据建议存储在用户目录或者程序的相对目录下,不要存储到绝对路径中。
  2. 程序可以通过 HOMEUSERPROFILE 来获取当前的用户目录。
  3. 如果程序的配置和数据文件存储在程序的相对路径下,那么需要在描述文件的 datas 字段中声明,以防止更新程序时覆盖这些文件。
  4. 建议捕获程序结束信号,在程序结束前保存相关的数据,并关闭文件连接,以防止对数据文件造成损坏。
  5. 如果程序需要较长的时间来处理收尾事项,请调整 stop_timeout 的时间,以确保在程序停止时可以有更充裕的时间来处理,否则程序长时间无法停止,会被视为无响应,将会执行强制结束进程的逻辑。
  6. 程序内部可以启用任意数量的子进程,但不要启动一个和主进程没有父子关系的进程,服务管理无法正确判断这个进程的从属关系时,可能不会正确的关闭该进程。
  7. 程序不要以 nohup 模式运行。
  8. 程序不需要自己设置进程守护,服务管理本身带有进程守护功能。

# 描述文件规范

完整描述文件示例:

{
  "id": "",
  "interpreter": "node",
  "interpreter_self": "",
  "interpreter_args": [],
  "path": "./ccs_pro.js",
  "pkg": "com.sansi.ccs-pro",
  "version": "2.2.27",
  "log_file": "",
  "pid_file": "",
  "icon": "favicon.ico",
  "name": "通用中控",
  "description": "通用中央控制系统(CCS Pro)",
  "args": [],
  "auto_start": true,
  "auto_restart": true,
  "restart_max": 3,
  "restart_delay": 0,
  "cwd": "",
  "env_vars": [],
  "port": 3436,
  "port_type": "HTTP",
  "os": "",
  "arch": "",
  "is_match": true,
  "stop_timeout": 5000,
  "doc": "https://ccs-pro.sansi.io/",
  "api_doc": "http://{{currentIp}}:{{currentPort}}/docs/api/",
  "homepage": "http://{{currentIp}}:{{currentPort}}",
  "configs": [
    {
      "title": "服务端配置",
      "type": "json",
      "path": "{{home}}/Sansi/CCS-Platform/config/ccs-server.json",
      "schema": "{{app}}/config/ccs-server.schema.zh_CN.json"
    },
    {
      "title": "客户端配置",
      "type": "json",
      "path": "{{home}}/Sansi/CCS-Platform/config/ccs-editor.json",
      "schema": "{{app}}/config/ccs-editor.schema.zh_CN.json"
    }
  ],
  "datas": [
    "{{app}}/date/*", "{{app}}/config/app.json"
  ],
  "logs": [
    "{{app}}/logs/*"
	],
  "firewall_enable": true,
  "firewall_ports": [
    "3436"
  ],
  "hooks": [
  	{
  		"type": "HTTP",
  		"stage": "PreStop",
  		"timeout": 10000,
  		"data": {
				"http": {
					"method": "GET",
					"url": "http://{{currentIp}}:{{currentPort}}/test"
				}
  		}
  	},
    {
      "type": "HTTP",
      "stage": "PreUnInstall",
      "timeout": 10000,
      "data": {
        "http": {
          "method": "GET",
          "url": "http://127.0.0.1:1280/sansi/daemon/api/v1/daemon/config"
        }
      }
    }
  ]
}

# 字段说明

字段名称(json) 字段类型 默认数值 参考数值 字段说明
id string QwOUYfIY 程序ID (自动生成,无法通过更新 config 修改)
interpreter string node / java / python 执行器,例如 python3、node、java,默认为空,可以支持选择执行器
interpreter_self string ./bin/node.exe 服务自身提供的执行器
interpreter_args []string [] ["-jar","-Dfile.encoding=utf-8"] 执行器参数,例如 "-jar","-Dfile.encoding=utf-8"
path string ./app.js 程序路径 (无法通过更新 config 修改)
pkg string com.sansi.demo 程序唯一标志符号 (无法通过更新 config 修改)
version string "1.0.0" 1.0.0 程序版本号 (无法通过更新 config 修改)
log_file string "/logs.log" "" 日志文件位置 (无法自定义,无法通过更新 config 修改)
pid_file string "/pid" "" pid 文件 (无法自定义,无法通过更新 config 修改)
icon string ./icon.png 程序图标
name string XX服务 程序名称
description string 提供XX功能的服务 程序描述
args []string [] ["--port", "8080"] 程序参数
auto_start *bool true true 自动启动,install 和 daemon 启动后自动启动该应用
auto_restart *bool true true 自动重启
restart_max *int 3 3 重启最大次数, 0 表示不限制次数
restart_delay *int 0 1000 重启延迟时间,单位毫秒(ms)
cwd string "./" 程序工作目录
env_vars []string [] ["KEY=sdfsdfsss"] 环境变量
port int 3436 运行端口
port_type string HTTP / TCP / UDP / Websocket 运行端口类型
os string "" / windows / linux / darwin 支持的操作系统,为空则表示不限制操作系统
arch string "" / amd64 / arm64 支持的CPU架构,为空则表示不限制架构(amd64含义和 x64、x86-64 一致,但不能写 x64)
is_match bool true 操作系统和架构是否适配(自动计算,无需设置)
stop_timeout *int 5000 0 停止服务时的超时等待时长。单位毫秒
doc string https://ccs-pro.sansi.io/ 当前服务的文档, 可以用 currentPort 表示当前服务的 IP,currentPort 表示当前服务的端口
api_doc string https://ccs-pro.sansi.io/ 当前服务的接口文档,可以用 currentPort 表示当前服务的 IP,currentPort 表示当前服务的端口
homepage string https://ccs-pro.sansi.io/ 当前服务的主页地址,可以用 currentPort 表示当前服务的 IP,currentPort 表示当前服务的端口
configs []Config [] 见上方示例 程序配置信息列表,可以使用 app 表示当前程序目录,使用 home 表示当前程序可以获取到的用户目录。
datas []string [] ["/data/*",
"/config/conf.json"]
当前程序的数据列表,在升级程序时会保留该目录,适用于程序和数据在相对路径的情况
logs []string [] ["/logs/*"] 当前程序的日志列表,在升级程序时会保留该目录,适用于程序和数据在相对路径的情况
firewall_enable bool true true 是否启用防火墙
firewall_ports []string [] ["1234", "3456-3467", "8033"] 防火墙开放端口,入方向
hooks []Hook [] 见上方示例 各个阶段的回调属性

# Hooks

Hooks 服务运行各个阶段的回调属性,他目前仅支持 HTTP 调用,需要注意的是,他的 url 中支持 和 字段,currentIp 代表当前服务的 IP 地址, currentPort 代表当前服务的开启端口。

hook 单个条目如下:

{
  "type": "HTTP",
  "stage": "PreStop",
  "timeout": 10000,
  "data": {
    "http": {
      "method": "GET",
      "url": "http://{{currentIp}}:{{currentPort}}/test"
    }
  }
}

字段说明

字段 类型 含义 支持参数
type string Hook 类型 HTTP
stage int Hook 阶段 PreInstall, PostInstall, PreUnInstall, PostUnInstall, PreStart, PostStart, PreStop, PostStop, PreBackup, PostBackup, PreRestore, PostRestore
timeout int 本阶段超时时间(毫秒) 小于等于 0 会取默认数值 10 秒
data HookData Hook 数据 详情见下方
data.http HookDataHttp HTTP 类型数据 暂不支持带有 body 的调用
data.http.method string 请求方式 GET,POST,PUT,DELETE
data.http.url string 请求地址 支持 和 字段,currentIp 代表当前服务的 IP 地址, currentPort 代表当前服务的开启端口

# 可视化配置规范

下面是服务端的配置文件 default_config.png

可视化后端的效果 read_config.png

使用 schema.zh_CN.json 解释配置文件中的字段

schema.zh_CN.json 示例

[
  {
    "props": {
      "header": "中控服务端"
    },
    "formProps": {
      "labelWidth": "100px"
    },
    "fields": [
      {
        "name": "auth_enable",
        "component": "switch",
        "formProps": {
          "label": "开启用户认证:"
        },
        "inputProps": {}
      },
      {
        "name": "database",
        "component": "select",
        "formProps": {
          "label": "认证方式:"
        },
        "inputProps": {
          "options": [
            {
              "label": "内置数据库",
              "value": "nedb"
            },
            {
              "label": "用户认证服务",
              "value": "oauth"
            }
          ]
        }
      },
      {
        "name": "oauth_url",
        "component": "input",
        "formProps": {
          "label": "用户认证服务:"
        },
        "inputProps": {}
      }
    ]
  }
]

编辑 daemon.json,加载 schema.zh_CN.json 文件 config_schema.png

目录结构如下
file_path.png

默认解析器类型

component 支持字段属性 说明
input string 文本输入框
link string 链接
select string 内容选择器(单选)
switch boolean 开关按钮
date-picker string 日期选择器
time-picker string 时间选择器
color-picker string 颜色选择器
rate number 评分