Skip to content

Latest commit

 

History

History
469 lines (370 loc) · 10.6 KB

File metadata and controls

469 lines (370 loc) · 10.6 KB

SimpleScheduler 快速使用指南

� 核心概念

SimpleScheduler 采用预定义服务模式

  1. 服务定义:在 config/services.json 中预先定义所有可用的服务
  2. 任务提交:客户端只需指定 serviceId 和对应的 payload 参数
  3. 队列执行:任务按队列和并发规则自动调度执行

这种设计确保了安全性可控性,避免客户端执行任意代码或调用。

�🚀 立即开始

1. 启动服务器

yarn dev

服务器将在 http://localhost:3005 启动。打开浏览器访问主页查看系统状态和可用服务列表。

2. 查看可用服务

访问 http://localhost:3005 或运行:

curl http://localhost:3005/api/v1/services

你会看到预定义的服务列表,例如:

  • example-web-api - 调用外部 Web API
  • example-script - 执行本地脚本
  • file-generator - 生成文件

3. 提交第一个任务

使用预定义的服务 ID 提交任务:

curl -X POST http://localhost:3005/api/v1/schedule \
  -H "Content-Type: application/json" \
  -d '{
    "serviceId": "example-web-api",
    "payload": {
      "url": "https://httpbin.org/json",
      "method": "GET"
    },
    "queue": "default"
  }'

响应示例:

{
  "jobId": "550e8400-e29b-41d4-a716-446655440000"
}

4. 查询任务状态

curl http://localhost:3005/api/v1/status/550e8400-e29b-41d4-a716-446655440000

5. 实时监听任务(SSE)

curl -N http://localhost:3005/api/v1/stream/550e8400-e29b-41d4-a716-446655440000

你将看到类似这样的实时事件流:

data: {"eventType":"status_update","data":{"status":"RUNNING","timestamp":"2025-11-12T07:00:01.000Z"}}

data: {"eventType":"log","data":{"message":"Calling GET https://httpbin.org/json"}}

data: {"eventType":"result","data":{"status":"COMPLETED","result":{"slideshow":{"author":"Yours Truly","date":"date of publication","slides":[...],"title":"Sample Slide Show"}}}}

📝 常见任务示例

调用外部 API(使用预定义服务)

curl -X POST http://localhost:3005/api/v1/schedule \
  -H "Content-Type: application/json" \
  -d '{
    "serviceId": "example-web-api",
    "payload": {
      "url": "https://api.github.com/users/octocat",
      "method": "GET",
      "headers": {
        "User-Agent": "SimpleScheduler"
      }
    },
    "queue": "default"
  }'

执行本地脚本(使用预定义服务)

首先,确保你的脚本是安全且可执行的:

# 创建一个简单的测试脚本
echo '#!/bin/bash' > /tmp/test.sh
echo 'echo "Hello from SimpleScheduler!"' >> /tmp/test.sh
echo 'date' >> /tmp/test.sh
chmod +x /tmp/test.sh

然后提交任务:

curl -X POST http://localhost:3005/api/v1/schedule \
  -H "Content-Type: application/json" \
  -d '{
    "serviceId": "example-script",
    "payload": {
      "command": "/tmp/test.sh",
      "args": [],
      "cwd": "/tmp"
    },
    "queue": "default"
  }'

使用不同的队列

# 高优先级队列(并发 10)
curl -X POST http://localhost:3005/api/v1/schedule \
  -H "Content-Type": "application/json" \
  -d '{
    "serviceId": "example-web-api",
    "payload": {"url": "https://httpbin.org/delay/1", "method": "GET"},
    "queue": "high-priority"
  }'

# 低优先级队列(并发 2)
curl -X POST http://localhost:3005/api/v1/schedule \
  -H "Content-Type": "application/json" \
  -d '{
    "serviceId": "example-web-api",
    "payload": {"url": "https://httpbin.org/delay/5", "method": "GET"},
    "queue": "low-priority"
  }'

查看所有队列状态

curl http://localhost:3005/api/v1/queues

响应:

{
  "queues": [
    {
      "name": "default",
      "concurrency": 5,
      "pendingJobs": 0,
      "runningJobs": 2
    },
    {
      "name": "high-priority",
      "concurrency": 10,
      "pendingJobs": 3,
      "runningJobs": 5
    },
    {
      "name": "low-priority",
      "concurrency": 2,
      "pendingJobs": 10,
      "runningJobs": 2
    }
  ]
}

🔧 自定义服务

重要:所有服务必须在服务器启动前在配置文件中定义。

1. 添加新的 Web 服务

编辑 config/services.json,添加新服务定义:

{
  "id": "weather-api",
  "type": "WEB_SERVICE",
  "description": "获取天气信息(OpenWeatherMap)",
  "parameters": {
    "city": "string",
    "units": "string"
  },
  "output": "JSON"
}

重启服务器后使用:

curl -X POST http://localhost:3005/api/v1/schedule \
  -H "Content-Type: application/json" \
  -d '{
    "serviceId": "weather-api",
    "payload": {
      "url": "https://api.openweathermap.org/data/2.5/weather?q=London&units=metric&appid=YOUR_API_KEY",
      "method": "GET"
    },
    "queue": "default"
  }'

注意

  • 服务定义中的 parameters 是用于文档说明,实际执行时 WebServiceExecutor 会使用 payload 中的 urlmethodheadersbody 等字段
  • 修改配置文件后需要重启服务器

2. 添加新的本地工具服务

编辑 config/services.json

{
  "id": "database-backup",
  "type": "LOCAL_TOOL",
  "description": "备份 PostgreSQL 数据库",
  "parameters": {
    "database": "string",
    "outputPath": "string"
  },
  "output": "FILE"
}

重启服务器后使用:

curl -X POST http://localhost:3005/api/v1/schedule \
  -H "Content-Type: application/json" \
  -d '{
    "serviceId": "database-backup",
    "payload": {
      "command": "/usr/local/bin/backup.sh",
      "args": ["mydb", "/backups/mydb_$(date +%Y%m%d).sql"],
      "cwd": "/var/lib/postgresql"
    },
    "queue": "default"
  }'

3. 服务配置最佳实践

推荐做法

{
  "id": "email-notification",
  "type": "WEB_SERVICE",
  "description": "发送邮件通知(通过 SendGrid API)",
  "parameters": {
    "to": "string",
    "subject": "string",
    "body": "string"
  },
  "output": "JSON"
}

这样定义清晰表明了:

  1. 这个服务的用途
  2. 需要哪些参数
  3. 返回什么类型的结果

客户端提交任务时只需关注 payload:

curl -X POST http://localhost:3005/api/v1/schedule \
  -H "Content-Type: application/json" \
  -d '{
    "serviceId": "email-notification",
    "payload": {
      "url": "https://api.sendgrid.com/v3/mail/send",
      "method": "POST",
      "headers": {
        "Authorization": "Bearer YOUR_API_KEY",
        "Content-Type": "application/json"
      },
      "body": {
        "personalizations": [{"to": [{"email": "user@example.com"}]}],
        "from": {"email": "noreply@example.com"},
        "subject": "Hello",
        "content": [{"type": "text/plain", "value": "Test"}]
      }
    },
    "queue": "default"
  }'

🔐 安全注意事项

🔐 安全注意事项

服务预定义的重要性

为什么要预定义服务?

  1. 防止任意代码执行:客户端不能执行未授权的命令或调用
  2. 访问控制:只有配置文件中定义的服务才能被使用
  3. 审计追踪:所有可执行的操作都在配置文件中明确定义
  4. 参数验证:每个服务都有明确的参数要求

命令执行安全

LocalToolExecutor 有多层安全保护:

  • 服务白名单:只能使用预定义的 serviceId
  • 命令白名单:只允许字母、数字、下划线、连字符、点、斜杠
  • 禁用 shell:使用 spawn 而非 exec,防止命令注入
  • 禁止危险字符:管道符 |、分号 ;、反引号 `$

推荐做法

  1. 专用脚本目录:将可执行脚本放在专用目录(如 /opt/scheduler/scripts/
  2. 使用绝对路径:配置文件中使用完整的绝对路径
  3. 最小权限原则:以非特权用户运行服务器
  4. 容器隔离:考虑使用 Docker 容器运行任务

生产环境配置示例

// config/services.json - 生产环境推荐配置
{
  "id": "backup-database",
  "type": "LOCAL_TOOL",
  "description": "PostgreSQL 数据库备份",
  "parameters": {
    "database": "string"
  },
  "output": "FILE"
}

对应的客户端调用(只能调用预定义的备份脚本):

curl -X POST http://localhost:3005/api/v1/schedule \
  -H "Content-Type: application/json" \
  -d '{
    "serviceId": "backup-database",
    "payload": {
      "command": "/opt/scheduler/scripts/backup-db.sh",
      "args": ["production_db"],
      "cwd": "/var/backups"
    },
    "queue": "default"
  }'

## 🐛 调试技巧

### 1. 查看服务器日志

服务器会输出详细的日志:

[ConfigManager] Loaded 3 service definitions [JobManager] Created job abc-123 for service example-web-api in queue default [Queue:default] Enqueued job abc-123 [TaskExecutor] Executing job abc-123 for service example-web-api (WEB_SERVICE)


### 2. 检查任务状态

```bash
# 获取任务详情
curl http://localhost:3005/api/v1/status/{jobId} | jq

3. 监控队列

# 持续监控队列状态
watch -n 1 'curl -s http://localhost:3005/api/v1/queues | jq'

📊 性能优化

调整并发数

编辑 config/queues.json

[
  {
    "name": "default",
    "concurrency": 10 // 增加并发数
  },
  {
    "name": "bulk-tasks",
    "concurrency": 50 // 大批量任务
  }
]

清理策略

server/plugins/init.ts 中调整清理间隔:

// 每 30 分钟清理一次
cleanupService.start(1800000)

// 或手动触发清理(通过添加 API)

🎯 完整工作流示例

# 1. 批量提交任务
for i in {1..10}; do
  curl -X POST http://localhost:3005/api/v1/schedule \
    -H "Content-Type: application/json" \
    -d "{
      \"serviceId\": \"example-web-api\",
      \"payload\": {
        \"url\": \"https://httpbin.org/delay/$i\",
        \"method\": \"GET\"
      },
      \"queue\": \"default\"
    }" \
    -s | jq -r '.jobId' >> job_ids.txt
done

# 2. 监控所有任务
while read jobId; do
  (curl -N "http://localhost:3005/api/v1/stream/$jobId" &)
done < job_ids.txt

# 3. 等待所有任务完成
wait

echo "所有任务已完成!"

💡 最佳实践

  1. 使用有意义的服务 IDuser-registration-emailservice-1 更好
  2. 合理分配队列:将快速任务和慢速任务分开
  3. 设置超时:避免任务无限期运行
  4. 监控存储:定期检查 .data/ 目录大小
  5. 日志记录:保留重要任务的日志用于审计

🔗 相关资源


需要帮助?查看完整文档 README.md 或提交 Issue!