完整目录:
由于管理的服务越来越多, 导致机器上的定期任务越来越多, 然后任务越多, 问题也很多
- 每个人写的脚本语言可能都不一样, 有人写的python, 有人写的shell, 有人写的go, 然后python的版本也不统一
- 每个脚本的日志, 执行结果等信息, 有的人存在本地, 有的人写的发邮件
- 每个脚本没有版本管理
- 没有一个统一的平台查看我们到底有多少个定期任务, 跑在什么服务器上, 是用做什么功能
所以决定自己用Go写一个跨语言的定期任务调度器, 需要实现的功能
- 跨语言
- 可以存任务的输出日志, 记录任务的执行结果
- 可以让用户在前端手动的执行任务
- 可以暂停任务, 删除任务
- …
第一个要解决的问题, 就是跨语言问题
如果放在服务器上直接运行任务, 那么带来的问题非常多
- 我们需要针对不同的任务, 创建非常多文件夹, 如果任务是python, 那么我们还需要创建很多虚拟环境, 然后安装不同任务的依赖
- 如果涉及到任务的删除, 那么需要直接操作服务器去删除文件夹
- 我们需要在服务器上安装很多语言环境, 比如go, python等等
所以思考下来, 决定用Docker来实现任务的执行, 好处如下
- 服务器上不需要安装任何语言环境
- 执行任务不会影响到宿主机, 不会有太大的安全风险
坏处是shell脚本的定期任务放在容器里执行毫无意义
所以后期我们需要支持远程调用定期任务, 比如在一台机器上运行一个http服务, 使用token作为认证, 然后定期任务服务器通过http api方式调用这台机器来实现shell脚本的执行
第二个要解决的问题, 就是脚本的存储问题
最开始的想法是, 让用户上传一个脚本来执行, 但是后面发现, 有许多定期任务就是需要2个,3个文件, 甚至他需要一些配置文件来执行, 所以文件上传问题非常多,并且涉及到定期任务脚本有更新时, 用户还需要来重新上传脚本
所以这里想到了一个办法
就是大家都把定期任务的脚本存放到git上存储,这样不仅实现了脚本的版本控制, 也解决了脚本的存储问题
但是这样也会带来一个新的问题, 为了安全, 我们不能在git上明文存储任何密钥, 密码等敏感数据
所以我们需要在前端创建任务时, 用json的格式填一些敏感信息作为环境变量传入到容器, 然后在任务脚本里使用获取环境变量的方式获取这种敏感信息
{ "ad_user": "xxxx", "ad_password": "xxxxx", "wechat_key": "xxxx" }
并且我们需要在存储这些敏感数据时使用加密存储, 在前端展示给用户时也需要进行脱敏处理
当然这里会有一些小问题
- 比如python, 用户需要在git仓库里导出自己的requirements, 然后我们构建容器时安装依赖
- 比如go, 用户需要带上go.mod文件, 然后我们构建容器时安装依赖
第三个问题, 就是任务的日志存储
为了方便的查看任务输出, 我们可以在脚本中使用log库直接打印日志到标准输出, 然后我们的定期任务调度器直接读取容器的日志, 这样就可以拿到任务的日志信息, 不用再用文件来存储日志, 我们也可以直接从前端看到定期任务的日志
但是这样有一个小问题
- 如果每一次执行任务都把任务的输出放到数据库中, 那么我们如何实现日志的过期与清理
所以后面想到了把任务日志存到redis里, 然后使用redis的ttl来实现日志的过期, 我们在数据库中只需要记录redis的key就可以读取到任务的日志输出了
超过存储期限的日志,在redis查不到, 我们可以给用户一个优雅的提示,显示日志过期
这两个核心问题解决以后, 就可以考虑我们需要解决的技术问题了
- 前端需要有一个cron组件, 可以选择执行时间
- 后端需要能解析cron表达式
- 后端需要能支持重启程序后, 重新把任务加载到内存中
- 需要学习怎么用Go去操作docker
发表回复