{"repo":"135a/NanoJob","free":true,"listed":false,"github":"https://github.com/135a/NanoJob","clone":"git clone https://github.com/135a/NanoJob.git","description":"基于 Go + MySQL + Redis 的轻量分布式任务调度引擎，核心接口兼容 XXL-Job 执行器协议","language":"Go","stars":41,"topics":["cloud-native","distributed-systems","golang","scheduler"],"license":null,"category":"workflow-automation","readme_excerpt":"NanoJob 基于 Go + MySQL + Redis 的分布式任务调度引擎（学习型项目），核心接口兼容 XXL-Job 执行器触发协议。 简介 NanoJob 用 Go 从零实现了分布式任务调度的核心链路，砍掉了边缘功能，保留时间轮 + XXL-JOB 适配器这两个差异化卖点： 层 实现 说明 :--- :--- :--- 存储 MySQL 任务配置、触发时间、执行日志（ nanojob job / nanojob log 两张表） 选主与注册表 Redis 选主用 SETNX + TTL 自研锁；执行器心跳 SET key EX 90 过期自动摘除 调度内核 单层内存时间轮 + 圈数计数 1s 滴答 × 60 槽， 仅 Leader 运行 触发协议 XXL-Job HTTP 协议 /run 触发、 /api/callback 结果回调、 /api/registry 心跳 任务 ID MySQL 自增 天然全局唯一，替代雪花 + WorkerID 池 定位：学习分布式调度、Redis 选主、写收敛与容错设计。存储层（MySQL/Redis）暂为单实例，应用层多副本 HA。 项目思维导图 架构 启动方法 准备 - Go 1.26+ - MySQL 8+ 与 Redis（单实例即可） 环境变量（可选，多引擎差异化时用） 配置以 conf.json 为基准，以下环境变量可 覆盖 关键字段（docker-compose 三引擎就是靠它让每台引擎互不相同）： 环境变量 覆盖的配置字段 说明 :--- :--- :--- NANOJOB DSN mysql.dsn MySQL 连接串（连哪台库） NANOJOB REDIS ADDR redis.addr Redis 地址（选主锁 + 注册表共用） NANOJOB ADVERTISE ADDR api server.http.advertise addr 本节点对外地址 = 选主锁持有值 + 重定向目标， 多引擎必须各不相同 方式一：Docker Compose（MySQL + Redis + 3 引擎） 一条命令拉起：MySQL（3306）、Redis（6379）、三个 Go 引擎（8081/8082/8083）。停止中间某一台引擎，另两台会自动重新选主接管——可直接观察故障转移日志。 注意 ：引擎之间用容器服务名互通（如 nanojob1:8080 ）。浏览器访问 localhost:8081 8083 时，若写请求落在 Standby，重定向 Location 是容器内地址、浏览器解析不了 —— 想从浏览器验证\"重定向\"效果，把对应引擎的 NANOJOB ADVERTISE ADDR 改成 http://localhost: 即可。 方式二：源码启动 引擎启动时自动做两件事：① 若 nanojob 库不存在则创建（库名取自 mysql.dsn ）；② 确保 nanojob job / nanojob log 两表存在（ CREATE TABLE IF NOT EXISTS ，幂等）。建库建表 SQL 以独立 .sql 文件管理在 core/store/sql/ 下，随二进制 go:embed 嵌入。 注入种子任务 可视化大盘 引擎不托管静态页面。双击打开 ui/index.html （通过 API + CORS 读写），可新增任务、查看每行任务的 下次触发时间 与 执行日志 。 前端在 ui/index.html 顶部 API ENGINES 数组里配置 全部引擎地址 ，请求按顺序尝试：当前引擎挂","default_branch":null,"files":null,"tree":[],"storefront":"/r/135a","claimed":false,"request_supported":{"post":"https://gitbuyer.com/r/135a/NanoJob/request-supported","requests":0},"note":"indexed from public GitHub; nothing is for sale on this page. Clone it from GitHub. Paid listings live at /search."}