Sia-Minio Integration Postmortem

Michael Lynch

Sia 与 Minio 集成事后复盘

原文由 Michael Lynch 发布,订阅该博客

在谷歌工作期间,我学到的最宝贵的经验之一就是无责事后复盘的实践。出问题时,先等风波平息,再撰写一份分析事件经过的报告。报告会解释问题是如何发生的,并明确团队未来可以采取哪些具体措施来避免类似问题再次出现。

上周,我发现了一个非常适合做事后复盘的机会。一个通过赏金资助、为 Minio 集成 Sia 支持的项目刚刚正式完工,但它的耗时比预期多了好几个月,期间还经历了多次大规模重写。

Sia 是一项去中心化云存储技术。我之前写过相关文章,因为它是我最喜欢的技术之一。Minio 是一个开源的、兼容 S3 的文件服务器。两者集成后,用户现在可以使用任何兼容 Amazon S3 的备份软件,将数据备份到 Sia 网络。

这次集成意义重大,我计划在 Sia 十二月版本发布、软件趋于稳定后再撰写更多相关内容。在此期间,我认为这是一个对集成过程进行复盘的宝贵机会。我联系了 Nebulous Labs 团队,他们很赞同这个想法。我又联系了 Sia-Minio 集成代码的作者,他也非常支持,并同意与我共同撰写这份报告。Nebulous Labs 和 Minio 团队审阅并批准了报告的发布,完整报告如下:


Minio 集成赏金事后复盘

Nebulous Labs 事件 #1

日期:2017-12-01

作者

  • Michael Lynch - @mtlynch - Sia 博主、/r/siacoin 版主
  • David Gore - @dvstate - 开发者、赏金获得者

审阅者

  • David Vorick - @taek42 - 首席开发者,Nebulous Labs
  • Zach Herbert - @zherbert - 运营副总裁,Nebulous Labs
  • @harshavardhana - Minio 维护者

背景:什么是事后复盘?

事后复盘是一项从未按计划进行的近期经历中吸取教训的实践。

事后复盘坚持无责原则:我们要找出的是导致不良结果的流程问题,而不是要揪出或指责某个人。我们默认所有参与讨论事件的人员都是称职且出于善意的。

详情请见 SRE 一书中的《事后复盘文化:从失败中学习》

概述

7 月 19 日,Nebulous Labs 宣布悬赏 300,000 SC,征集一个可用的 Sia 与 Minio(开源的兼容 S3 的文件服务器)集成方案。开发者 David Gore(@dvstate)在五天后发布了概念验证,并在不到 10 天后获得了全部奖金。

而该集成又花了三个月才被合并到 Minio 仓库。为了让代码被 Minio 接受,需要对代码进行彻底重构,@dvstate 为此付出了大量额外工作,而这些工作并未得到赏金的正式补偿。

集成最终得以实现,但完成时不得不增加了赏金中未曾预料到的若干限制:

  • 仅支持有限的文件名字符白名单,比 Sia 本身允许的范围更严格。
  • 不支持分块文件传输。
  • 只有两个简单函数有自动化测试覆盖。

影响

这些事件最重大的影响,是与关键合作伙伴的集成被推迟了数月。Sia 获得 S3 兼容性是一个巨大的里程碑,但由于过程过于漫长,这一成就带来的震撼感似乎大打折扣。

过程中的波折也给外界留下了对 Sia 的负面印象:

  • 与 Sia 集成很困难,甚至用 Sia 的原生语言 Go 也需要重复造轮子。
  • 完成 Sia 赏金任务很困难,因为验收标准不明确。

经验教训

做得好的方面

  • Sia 成功集成到了 Minio 中。
  • Sia 社区成员使用多种 S3 客户端,在不同场景下参与了 Minio 集成的测试。

出现的问题

  • 关于功能和需求的沟通不畅,导致集成被多次重写。
  • Minio 维护者的评审与 PR 更新之间存在很长的延迟,有时甚至长达数周。
  • 由于在 Sia 集成 PR 审阅期间 Minio 代码库本身也在变更,@dvstate 不得不花费大量时间解决合并冲突。

侥幸之处

  • @dvstate 在 Nebulous 支付赏金后,仍自愿花费数月时间继续完善集成。
  • @dvstate 自费启动、配置并维护了一台 Sia 测试服务器供 Minio 测试使用。
  • Minio 维护者慷慨地投入时间,对同一个 PR 持续评审了数月。

时间线

  • 2017-07-19:Nebulous Labs 宣布推出一系列 Sia 赏金,首先是将 Sia 与 Minio 集成的赏金
  • 2017-07-24:@dvstate 发布概念验证集成
  • 2017-08-03:Nebulous Labs 向 @dvstate 颁发全部赏金
  • 2017-08-09:@dvstate 向 Minio 源码提交了 Sia 集成的首个 PR
  • 2017-08-09:@harshavardhana 要求 @dvstate 重写 PR,改用 BoltDB 替代 SQLite。
  • 2017-08-13:@harshavardhana 同意接受 Sia-Minio 集成。
  • 2017-08-16:@dvstate 完成 BoltDB 重写。
  • 2017-08-28:代码评审期间,@harshavardhana 要求 @dvstate 完全移除数据库,在不使用缓存层的情况下重写 PR。
  • 2017-09-26:在 PR 沉寂数周后,@zherbert@mtlynch 请求更新进展。
  • 2017-10-19:@dvstate 完成了移除缓存层的 PR 重写。
  • 2017-10-24:@harshavardhana 向 @dvstate 发送了一个补丁。
  • 2017-10-25:@dvstate 关闭原 PR 并新建一个 PR,以满足 Minio 的要求并整合 @harshavardhana 的补丁。
  • 2017-10-26 - 2017-11-21:@dvstate 搭建并自费提供了一台 Sia-Minio 测试节点,并向 @harshavardhana 开放访问。两人使用 Minio 网页应用、s3cmd 和 mc 命令行工具对集成进行了手动测试。
  • 2017-11-22:Minio PR 被合并。

发现的问题

需求不明确

赏金说明中对 Sia-Minio 集成的许多细节都未作定义。它只规定“用户必须能够使用 Minio 客户端上传/下载 Sia 文件”,却未提及 Minio 维护方的任何限制或要求。

此外,还有几位 Sia 用户通过 Sia Slack 的 #bounties 频道或私信联系 @dvstate 提出功能需求。由于没有权威的需求定义,@dvstate 担心如果忽略这些请求会失去获奖资格,于是实现了这些额外功能。

因此,@dvstate、Minio 维护者与 Sia 用户之间在以下问题上产生了混淆:

  • 哪些第三方库是可接受的
  • Sia 集成是否允许在文件系统上维护缓存以保存状态信息和元数据
  • Sia 集成是否必须实现分块文件传输
  • Sia 集成是否必须支持存储桶策略设置
  • 需要支持哪些 S3 客户端应用(例如 mc、s3cmd)
  • 需要何种程度的手动测试来证明功能可用
  • Sia 集成允许使用多少个 Sia 专属的环境变量
  • 需要多少测试覆盖率
  • 对 Minio 界面需要/允许做哪些改动
  • 对 Minio 文档需要做哪些改动

@dvstate 最终为了满足 Minio 维护方提出、而原始赏金说明中并未提及的要求,重写了三个截然不同的集成版本(第一版第二版第三版)。

建议的改进措施

  • 对于未来的 Sia 赏金,事先与第三方维护者共同确定需求,并将其纳入赏金的评奖标准。

  • 为赏金制定客观的验收测试。例如:

    1. 准备一台已部署 siad 且 allowance 为 500 SC 的服务器。

    2. 客户端使用以下命令启动 Minio:

      export MINIO_ACCESS_KEY=minioaccesskey
      export MINIO_SECRET_KEY=miniosecretkey
      ./minio gateway sia
      
    3. 客户端机器在 ~/test-data 文件夹中有 100 个大小从 1 KB 到 10 GB 不等的文件,总计不超过 4 TB,其中包含嵌套文件夹,深度最多为 3 层。

    4. 客户端机器成功执行以下命令:

      SERVER=insert.server.hostname # replace with actual server
      mc config host add minio-sia \
       "http://${SERVER}" minioaccesskey miniosecretkey S3v4
      
      mc mb minio-sia/sia-test-bucket
      
      # Upload test files.
      mc cp --recursive ~/test-data/* minio-sia/sia-test-bucket/
      
      # Download test files.
      mc cp --recursive \
       minio-sia/sia-test-bucket/* ~/test-data-downloaded/
      
    5. 下载文件的 SHA-1 哈希值与原始文件的 SHA-1 哈希值一致

  • 如果在赏金公告中发现歧义,应在整个竞赛期间持续更新公告,并通过变更日志标明修改内容。

  • 明确赏金的 issue 跟踪器是获奖要求的权威来源。

  • 赏金参赛者无需满足出现在官方赏金跟踪器之外的请求。

赏金按概念验证而非成功集成发放

Nebulous 在 Sia 核心开发者评审后、但在获得 Minio 维护者批准之前就发放了赏金。而赏金的真正目标是将代码集成到 Minio 仓库中,否则用户会不愿部署来自 @dvstate 那个无人维护的分支的代码。

Sia 很幸运,@dvstate 在职责结束后仍继续推进 PR,但赏金真正目标的完成不应依赖于获奖者的善意。

在赏金发放前,存在一种赢取奖金的紧迫感——要求的改动在几小时或几天内就能完成。赏金发放后,响应延迟就增加到了数周。

这是预期之中且合理的,因为 @dvstate 之后是以志愿者、尽力而为的方式在工作。Sia 能得到任何小于无限期的响应,已经算是幸运的了。

建议的改进措施

  • 按成功集成而非概念验证来发放赏金。
  • 将成功合并到目标仓库作为未来赏金的明确要求。

Minio 集成重复了 siac 命令行客户端的逻辑

Minio 集成代码中有 30-40% 只是用于实现 Sia API 的逻辑。这与 Sia 核心仓库中已有的代码重复,因为 siac 命令行客户端已经实现了相同的功能。

目前没有任何语言的官方 Sia API 绑定,包括 Sia 的原生语言 Go。

建议的改进措施

  • 为 Sia API 创建官方 Go 客户端库。以 siac 作为该库的参考客户端,并重构 Minio 集成以使用该库。
  • 对于未来需要非 Go 代码的赏金,要求提交方案为所需的 Sia API 功能创建一个独立于应用代码的库。

Minio 集成的测试覆盖率几乎为零

只有两个简单函数有测试覆盖,这使得难以检测对 Sia Minio 代码的改动是否会破坏 Minio 的功能。

建议的改进措施

  • 将自动化测试作为未来 Sia 赏金的必要要求。

评审期间的信息孤岛

关于 PR 所需改动的关键讨论都是私下进行的。除 @dvstate 和 @harshavardhana 之外,没有人能跟踪进展或协助推进 PR。

建议的改进措施

  • 按成功集成而非概念验证来发放赏金。
  • 要求讨论在集中的位置进行(例如赏金的 GitHub issue),以便所有赏金申请者都能获取相同的信息。

“先到先得”式赏金带来了逆向激励

赏金计划的规则写道:

赏金仅会向一份提交发放一次,除非另有说明,将发放给首个满足赏金全部标准的个人或团队。

这会激励赏金提交者以最小化实现成本来优化方案,从而不利于他们在可读性、可维护性或清晰文档上投入时间。

就 Minio 集成而言,代码虽然有详尽的文档,但缺乏测试,且将 Sia 逻辑与 Minio 逻辑混在一起,这可能会给未来的可维护性带来挑战。

这种制度也不利于协作或改进。如果一名开发者发布了解决方案,其他开发者就没有动力再去尝试,因为赏金很可能会归首个提交者。规则也未涵盖在他人方案基础上改进的路径,因此不存在改进他人提交成果的通道。

建议的改进措施

  • 采用无差别的“提交窗口”
  • 设定一个提交速度不重要的时间窗口(例如,赏金竞赛开始后前两周内收到的所有提交都同等对待)。
  • 申请者可以尽早提交,但允许他人 fork 并改进其作品(必须是实质性改进,而不仅仅是重命名几个符号)。在这种情况下,赏金由 Nebulous 酌情在贡献的开发者之间分配。
  • 初始提交窗口结束后,奖金归首个有效提交。

第三方验证的困难

Minio 团队此前没有任何 Sia 方面的经验。在 Minio 愿意合并 PR 之前,@dvstate 不得不自费搭建一台测试服务器,并与 Minio 维护者一起完成一系列此前未公布的手动验证步骤。

建议的改进措施

  • 对于未来涉及第三方集成的赏金,由赏金组织方负责验证解决方案,并协助第三方合作伙伴完成验证。
  • 为赏金制定客观的验收测试。(参见 “需求不明确”一节)。

本文章由 muse-spark-1.2-contributor 进行翻译

评论