SimpleScheduler 采用预定义服务模式:
- 服务定义:在
config/services.json中预先定义所有可用的服务 - 任务提交:客户端只需指定
serviceId和对应的payload参数 - 队列执行:任务按队列和并发规则自动调度执行
这种设计确保了安全性和可控性,避免客户端执行任意代码或调用。
yarn dev服务器将在 http://localhost:3005 启动。打开浏览器访问主页查看系统状态和可用服务列表。
访问 http://localhost:3005 或运行:
curl http://localhost:3005/api/v1/services你会看到预定义的服务列表,例如:
example-web-api- 调用外部 Web APIexample-script- 执行本地脚本file-generator- 生成文件
使用预定义的服务 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"
}curl http://localhost:3005/api/v1/status/550e8400-e29b-41d4-a716-446655440000curl -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"}}}}
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
}
]
}重要:所有服务必须在服务器启动前在配置文件中定义。
编辑 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 中的url、method、headers、body等字段 - 修改配置文件后需要重启服务器
编辑 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"
}'推荐做法:
{
"id": "email-notification",
"type": "WEB_SERVICE",
"description": "发送邮件通知(通过 SendGrid API)",
"parameters": {
"to": "string",
"subject": "string",
"body": "string"
},
"output": "JSON"
}这样定义清晰表明了:
- 这个服务的用途
- 需要哪些参数
- 返回什么类型的结果
客户端提交任务时只需关注 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"
}'为什么要预定义服务?
- 防止任意代码执行:客户端不能执行未授权的命令或调用
- 访问控制:只有配置文件中定义的服务才能被使用
- 审计追踪:所有可执行的操作都在配置文件中明确定义
- 参数验证:每个服务都有明确的参数要求
LocalToolExecutor 有多层安全保护:
- ✅ 服务白名单:只能使用预定义的 serviceId
- ✅ 命令白名单:只允许字母、数字、下划线、连字符、点、斜杠
- ✅ 禁用 shell:使用
spawn而非exec,防止命令注入 - ❌ 禁止危险字符:管道符
|、分号;、反引号`、$等
推荐做法:
- 专用脚本目录:将可执行脚本放在专用目录(如
/opt/scheduler/scripts/) - 使用绝对路径:配置文件中使用完整的绝对路径
- 最小权限原则:以非特权用户运行服务器
- 容器隔离:考虑使用 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
# 持续监控队列状态
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 "所有任务已完成!"- 使用有意义的服务 ID:
user-registration-email比service-1更好 - 合理分配队列:将快速任务和慢速任务分开
- 设置超时:避免任务无限期运行
- 监控存储:定期检查
.data/目录大小 - 日志记录:保留重要任务的日志用于审计
需要帮助?查看完整文档 README.md 或提交 Issue!