ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

开源矿机管理系统OpenRig:从零构建自托管监控与自动恢复架构

开源矿机管理系统OpenRig:从零构建自托管监控与自动恢复架构 做矿场运维这行时间越久越觉得真正让人头疼的往往不是矿机本身而是管理矿机的那套工具。商业面板按月付费、按卡收费功能看似齐全可真要接入自己写的告警、自己想做的自动恢复策略就会发现处处都是墙。所以我用了大概三周时间用开源组件从零搭了一套完全攥在自己手里的矿机管理系统代号就叫 openrig。这篇文章会把整体设计、技术选型、核心功能实现和部署细节都摊开讲适合小中型矿场、多机架玩家也适合想摆脱商业面板锁定的运维团队参考。1. OpenRig 是什么从需求倒推出来的设计1.1 商业矿池面板的四个痛点先说说我为什么放着现成的商业面板不用非要自己折腾。第一是费用和规模的矛盾。商业面板大多按矿机数量或者显卡数量阶梯计价机子少的时候看着不贵机架一多每个月就是一笔固定开销。更难受的是有些功能比如自定义策略、开放 API都被放在更高的付费档位里等于你想省事反而要被多收钱。第二是数据不透明。面板上显示的温度、算力、拒绝率很多是经过厂商处理的你看不到原始采样数据。一旦想针对某张卡做精细分析比如显存温度震荡、功耗曲线异常商业面板往往不给原始数据导出逼着你另外写采集脚本。第三是策略被锁死。自动重启、温度预警、算法切换这些功能都依赖厂商预设的模板。想加一条“显存温度连续十分钟超过 96 度就先降频再重启”的规则可以要么加钱要么等版本更新。最要命的是有些面板的自动逻辑是黑盒你不知道它什么时候重启了矿机也不知道为什么。第四是闭源风险。面板本身不开源一旦厂商调整协议、关闭服务或者现场环境需要离线运行整个机架的管理就会立刻失效。1.2 OpenRig 的定位与设计目标我想要的系统其实很简单自托管、全开源、可离线运行并且在协议层完全开放。它不是一个大而全的商业产品更像是一个“矿机管理框架”我把底下所有模块都做成了可以独立替换的组件。初始设计目标定得很明确新矿机接入不超过 5 分钟断网后矿机端仍然能按最后策略运行故障后可以在 30 秒内自动重启挖矿进程并且所有采集指标全部落到自己的数据库里。这几条听起来不复杂但真正实现起来每一步都有不少细节要抠。2. 系统架构与关键技术选型2.1 整体架构采集、汇聚、控制三层OpenRig 在架构上分成三个清晰的层次采集层、汇聚层、控制层。采集层跑在每一台矿机上是一个轻量级 Agent 进程。它的职责是轮询本机挖矿内核暴露的 API 接口把温度、功耗、算力、拒绝率等指标读出来然后标准化成统一格式上报。Agent 同时负责接收控制指令比如重启内核、切换算法、调整风扇转速。汇聚层是服务端集群由消息中间件、后端 API、数据库和前端面板组成。消息中间件负责接收海量的指标数据后端 API 做指令下发和业务逻辑处理数据库存时序指标和配置前端面板负责展示和操作。控制层实际上就是后端 API 加规则引擎。它根据采集上来的指标结合你预设的阈值和策略决定是否下发控制指令。这个分层的好处是哪怕后端 API 挂了矿机端的 Agent 依然能按照本地缓存策略继续跑不会因为服务端故障导致算力中断。在实际部署里我用这几样组件来承载对应职责EMQX 作为 MQTT Broker负责采集数据的接入和指令下发。Go 写的后端服务负责 API、规则引擎、任务调度。TimescaleDB 存储时序指标PostgreSQL 的生态也可以直接用。Redis 做短时的状态缓存和分布式锁。React 加 TypeScript 写前端控制台。矿机端 Agent 用 Python 写成方便快速迭代后续也可以换成编译型语言。2.2 为什么要用 MQTT 来传监控数据很多朋友问我监控数据用 HTTP 轮询不就行了确实可以但矿场这个场景有其特殊性单机几十张卡指标每 5 秒采集一次一次上报的数据量非常小但数量很大。如果每台矿机都用 HTTP 不停地打接口连接建立的额外开销和负载就上来了。MQTT 的优势在于它本身就是为大量低频消息设计的。矿机 Agent 与 Broker 保持长连接上报数据就是一个很小的 PUBLISH 消息没有 HTTP 头这些冗余。而且 MQTT 的 Last Will 机制特别适合矿场监控矿机异常断电时Broker 能立刻感知连接断开推送离线事件比“因为没数据所以判断离线”要快太多。最重要的是MQTT 天然支持一个 Topic 树结构。我可以把每台矿机的数据按rigs/{rig_id}/metrics这样的路径组织控制指令走另一个rigs/{rig_id}/control方向前端订阅特定 Topic 就能实时看到数据变化不需要后端额外做长连接推送。2.3 数据模型一台矿机一张“体检表”设计数据模型时我没有把矿机指标单纯看成一串数字而是当成一张动态更新的“体检表”。每台矿机有一份静态配置表记录矿机 ID、Agent 版本、所在机架、控制端口、对应的挖矿模板。动态指标单独存时序表包括采集时间、GPU 索引、核心温度、显存温度、核心频率、显存频率、功耗、算力、效率等字段。这样静态配置和动态数据分离查询历史趋势时只需要扫时序表效率高很多。设备状态我划分为三种在线、关联路径缺失、离线。在线是指 Agent 持续上报心跳关联路径缺失是指 Agent 在线但挖矿内核 API 无响应常见于内核崩溃离线就是 MQTT 连接断开。这个划分很重要因为很多故障其实发生在矿机没宕机、只是挖矿进程挂了的场景。2.4 安全边界设计自托管系统最容易被忽视的就是安全。OpenRig 的安全边界我做了三层。第一层是网络隔离。服务端只暴露必要端口后端 API 在用反向代理前加上 HTTPS矿机 Agent 和 Broker 之间通过网络策略限制禁止矿机直接访问数据库。第二层是认证。Agent 连接 Broker 时使用独立账号密码后端签发短期 Token 给控制台登录使用。所有控制指令都要求携带 Agent 端的随机挑战码防止中间人伪造重启指令。第三层是操作审计。每一次重启、切换算法、改配置的操作都会追加到审计日志表里我可以在面板上随时查到是谁在什么时间对哪台矿机做了什么操作。3. 核心功能拆解与实现细节3.1 矿机接入与自动注册矿机接入流程的目标是“零手工运维”。我给每台新矿机准备了一个一次性注册码在服务器后台生成一个码贴到矿机配置里。Agent 启动后先带着这个码去请求注册接口服务端验证通过后给这台矿机分配正式 ID 和 Token。注册完成之后Agent 立刻从服务端拉取该矿机对应的挖矿模板。模板里包含挖矿内核路径、矿池地址、钱包地址、超频参数这些信息。也就是说矿机本身不需要预装任何挖矿配置重装系统之后只要装上 Agent、填上注册码一切环境都由服务端下推。这一步省掉了很多重复劳动。以前每台机器我都要手动编辑配置文件、核对矿池地址还经常出现钱包地址填错导致算力白跑的情况。现在注册即配好错了也能在面板上一键修正。3.2 指标采集算力、温度、功耗、拒绝率指标采集是 OpenRig 最重要的基础能力。不同型号的挖矿内核 API 返回格式不一样所以 Agent 里做了解析器层每种内核对应一个解析器统一输出标准化字段。以常见的矿机程序为例它的本地 API 端口返回 JSON 格式包括每张卡的当前算力、核心温度、功耗。Agent 轮询的频率我设成 5 秒一次这个频率足够捕捉温度陡升又不会给内核 API 造成太大压力。采集到数据后Agent 会先做一层轻量处理过滤掉明显异常的值比如 -1 度这样的占位符计算最近一分钟的平均算力再把这些处理后的数据打包成一条消息通过 MQTT 上报。这样做的好处是服务端拿到的数据已经是相对平滑的指标画出来的趋势图不会到处是毛刺。功耗这一项很多新手会忽略。对家用电源来说整机功耗和单卡功耗的换算经常让人对不上账。OpenRig 里我记录的是内核程序报的单卡功耗同时 Agent 也通过读取系统功耗传感器记录整机功耗两套数据分开存这样哪张卡异常耗电一眼就能从面板上看出来。3.3 告警、熔断与自动恢复机制告警和自恢复是我最看重的一部分也是和商业面板差距最大的地方。在 OpenRig 里规则引擎支持这样几条典型的故障规则核心温度超过 95 度持续 2 分钟触发高温告警。显存温度超过 100 度持续 3 分钟触发降频指令。算力低于理论值的 80%持续 5 分钟触发挖矿进程重启。MQTT 连接断开5 秒内触发离线通知。内核 API 无响应30 秒内触发全机断电重启。这些规则都配置在服务端Agent 本地也会缓存一份简化版本。即使服务端不可用Agent 也能根据本地缓存的阈值做基本的自我保护比如温度过高时直接重启内核不需要等服务端下发指令。自动重启策略我做成了分级处理先尝试通过内核 API 软重启比如发送重启指令软重启失败就由 Agent 直接结束挖矿进程再拉起还不行就重启整台机器。这个分级策略避免了“一有小问题就把机器重启一遍”的粗暴做法毕竟频繁冷重启对硬件寿命是有影响的。3.4 算法切换与利润调度OpenRig 的算法切换逻辑本质上是“按外部收益指标变化选择当前最优挖矿算法”。这个功能和商业面板里的自动切换类似但我做成了完全可控的调度器。调度器定时去读取第三方利润热度接口拿到不同算法当前的单位算力收益排名。然后结合矿机显卡型号和当前功耗算出一个预估的每瓦收益。如果新算法比当前算法的预估收益高出一定比例并且持续了一段时间才触发切换。为了安全切换前系统会先拉取新模板检查模板可用性然后把新旧算法跑一个短时间的并发对比。对比结束后根据实际收益决定是否切换。这个机制能有效避免因为接口数据抖动导致矿机频繁切换超频参数也因此在每个模板里独立管理。4. 实操从零部署一套 OpenRig4.1 服务端快速部署服务端我用 Docker Compose 编排所有组件打包成容器部署时只需要在服务器上执行几条命令。git clone https://your-git-host/openrig/deploy.git cd deploy cp .env.example .env # 编辑 .env配置数据库密码、JWT 密钥等 docker compose up -d如果你没有现成的 Git 仓库也可以把整份部署目录直接拷到服务器上。服务端首次启动后需要初始化数据库docker compose exec api openrig-admin init-db docker compose exec api openrig-admin create-admin --username admin --password 你的密码这样一个最小可用的服务端就跑起来了。对于机柜数量不超过 30 台的小型矿场单台 4 核 8G 的服务器已经完全够用。指标数据默认保留 30 天可以根据磁盘空间调整保留周期。4.2 Agent 端安装与注册Agent 端安装我写成了一个脚本系统里只需有 Python 3.9 以上版本即可。curl -fsSL http://your-server/static/install_agent.sh | bash脚本会完成这几个动作下载 Agent 程序、创建系统服务、生成配置文件框架。接下来只需要编辑配置文件[server] endpoint your-server:8883 company_code your_company [rig] register_code xxxx-xxxx-xxxx network_timeout 30保存后启动服务再看服务端面板这台矿机就会出现在“待审批”列表里。审批通过后Agent 会从那台服务器拉取挖矿模板整个过程不需要 SSH 上去手改挖矿配置。4.3 接入主流挖矿内核OpenRig 的模板机制设计成“内核类型 参数”的组合。新增一种内核时只需在面板上创建一个模板选择内核类型、填矿池地址、钱包地址、内核启动参数、单卡配置和超频参数。以常见的 GPU 内核为例模板配置大致长这样{ kernel_type: teamredminer, pool_address: stratumtcp://example-pool:3333, wallet: your_wallet_address, parameters: [--fan_control50], oc_settings: { core_clock: 1400, memory_clock: 2100, power_limit: 120 } }模板创建后可以批量应用到一组矿机比如按机架分组应用。Agent 收到新模板后会先校验配置合法性再重启挖矿进程。这样做的好处是调参不用再挨台机器敲命令改完模板统一下发一分钟内全部生效。4.4 仪表盘与告警通知配置仪表盘是平时看得最多的界面。我用 React 写了一个简洁的概览页包含整体算力趋势、在线矿机数、平均温度、最近告警列表。每台矿机的详情页可以查看单卡温度、功耗、算力、内核运行时长并直接执行重启、切换模板、追加控制指令这些操作。告警通知我接入了通用 Webhook 模式。不管是钉钉群、企业微信还是其他支持 Webhook 的平台把地址填到配置里就能收到消息。通知格式是一条纯文本加一个跳转链接点击直接跳到对应的矿机详情页。配置项里我还加了一个静默时段。比如凌晨三点的温度高告警不想被连续打扰可以把静默时段设为三点到七点只记录告警不推送通知。这个功能看似不起眼实际用起来非常舒服。5. 真实踩坑记录与排障速查表5.1 我踩过的五个坑第一个坑是时间同步。矿机上如果系统时间不准Agent 上报的时间戳就会出现偏差时序数据画出来的趋势图全是错位的。我后来在 Agent 启动时强制做一次时间同步并周期性检查时间偏移超过 60 秒就告警。第二个坑是 MQTT 半连接。矿机异常断电再恢复后经常出现网络层已经恢复、但 MQTT 连接还挂在半开状态的问题。Agent 进程还在实际上已经断开服务端却以为在线。解决方式是在 Agent 里加了一个心跳自检如果连续 3 次心跳发送失败就主动重连 Broker。第三个坑是挖矿内核占用控制端口。有些内核默认占用了 Agent 也需要用的端口尤其是重启内核后端口释放不及时导致 Agent 误判为内核崩溃。我给 Agent 的端口探测加上了重试机制并且把端口占用检测放到矿池模板下发之前。第四个坑是数据库写入放大。指标每 5 秒一次30 台矿机各自 8 张卡数据量积攒起来非常可观。如果不做批量写入数据库负载会非常高。后来我把写入改成缓存批量提交每五秒合并一次上报数据再用单条批量 SQL 插入负载瞬间降了下来。第五个坑是挖矿进程重启后拿到的是脏环境。内核用的是同一批超频参数但偶尔重启后参数没生效算力跑不满。最后我在 Agent 的重启流程里加入了“等待内核就绪—检查算力—未达标则再次重启”的闭环。5.2 常见问题速查表症状可能原因排查与解决矿机显示离线但本机系统正常MQTT 半连接或防火墙阻断检查 8883 端口连通性重启 Agent 服务面板有上报数据但无温度曲线采集字段模板与矿机型号不匹配在面板上更新该矿机的内核解析器版本自动重启无效模板配置里内核路径错误查看 Agent 日志核对模板下发内容告警一直触发阈值设太低或静默时段未配置调高阈值或设置静默时段算力切换过于频繁利润热度接口数据抖动提高切换判定持续时长增加新旧算法对比期5.3 几个调优心得时间序列数据的存储保留可以按时间做降采样。原始 5 秒级数据保留 3 天分钟级聚合数据保留 30 天更早的只留小时级聚合。这样查询历史趋势仍然能看到整体走向磁盘占用却少了非常多。采集频率不是越高越好。对普通矿场来说10 秒一次已经足够5 秒是一次冗余的激进值。如果矿机数量很大可以考虑把采集频率调成 10 秒再对告警类指标用 Agent 侧秒级检测这样兼顾精细度和负载。自动恢复逻辑里每一级操作之间要加入延迟等待。比如先软重启等 90 秒让内核重新初始化并报告算力算力恢复后才算成功。时间给太短容易误判成失败触发更高级别的重启动作反而把正常的流程打断。我个人在实际操作中的体会是自建这套系统的最大价值不是省钱而是把“矿场怎么跑”的决策权完全拿回到了自己手上。从采集指标的第一行代码到控制指令下发的每一条链路每一个环节都能被审查、被改动、被优化。这套体系用久了以后你会对自己机架上的每一张卡的状态、每一次异常的前因后果都有非常清晰的判断不再依赖厂商给的“平均数据”和“自动处理”。如果你也打算搭一套类似的系统我的建议是从最小闭环开始先只做指标采集和展示把链路跑通后再逐步加入自动恢复和算法切换这样每一步都有清晰验证翻车的概率会低很多。
返回列表