源码面前,了无秘密 —- 侯捷
很多人的『开源』是一个比较时髦且有情怀的词汇,不少公司也把开源当做 KPI 或者是技术宣传的手段。但是在我们看来,大多数人开源做的并不好,大多数开源项目也没有被很好的维护。比如前一段时间微博上流传关于 Tengine 的讨论,一个优秀的开源项目不止是公布源代码就 OK 了,还需要后续大量的精力去维护,包括制定 RoadMap、开发新功能、和社区交流、推动项目在社区中的使用、对使用者提供一定程度的支持,等等。
目前我们在国内没看到什么特别好的文章讲如何运营一个开源项目,或者是如何做一个顶级的开源项目。TiDB 这个项目从创建到现在已经有两年多,从开发之初我们就坚定地走开源路线,陆续开源了 TiDB、TiKV、PD 这三个核心组件,获得了广泛的关注,项目在 GitHub 的 Trending 上面也多次登上首页。在这两年中,我们在这方面积累了一些经验和教训,这里和大家交流一下我们做开源过程中的一些感受,以及参与开源项目(至少是指 TiDB 相关项目)的正确姿势。
Open-source software (OSS) is computer software with its source code made available with a license in which the copyright holder provides the rights to study, change, and distribute the software to anyone and for any purpose.
—- From Wikipedia
本文讨论的开源是指开源软件,简而言之,开源就是拥有源代码版权的人,允许其他人在一定许可证所述范围内,访问源代码,并用于一些自己的目的。
最基本的要求就是其他人可以访问源代码,另外获取代码后能做什么,就需要一个专门的许可证来规范(可以是自己写的,也可以用一个别人写好的)。里面一般会规定诸如对修改代码、新增代码、后续工作是否需要开源以及专利相关的事项。
OK,我们写一个 main.py
里面有一行 print "Hello World!"
,再和某个许可证文件一起扔到 GitHub 上,我们就有一个满足最低要求的开源项目了。
很多人觉得代码是一个软件公司最宝贵的资产,把这些最宝贵的资产让别人免费获取,对你们有什么好处?如果对手拿走了你们的代码,另起炉灶和你们竞争怎么办?或者是用户直接获取源代码,用于自己的环境中,那你们如何收钱呢? 对一个技术型公司来说,最宝贵的资产其实是人,对一个开源项目来说,最核心的资产是一个活跃的开源社区以及他人对这个项目的认可。 我们从这两方面来看一下开源在这两方面的影响。
Branding 很明显,开源是一种非常好的 PR、Branding 的手段,大多数大公司做开源也是这个目的,可以以一种成本几乎为零的方式宣传企业名,树立技术型企业形象。一个知名且良好的企业形象,对于各个方面都很有好处。比如国外有一个知名的技术媒体叫 HackNews,我司的产品曾经多次登上其首页,获得了大量的关注。其实那几次都不是我们自己发的帖子,而是其他人关注到我们的产品,自行做的传播。
人才获取 人才招聘最大的难处就是如何鉴别这个人的能力,他是否能干活、是否是靠刷题通过了面试。如何能和这个人工作一段时间,看到他是如何完成日常工作,那么对于这个人的能力了解会更进一步。为了实现这个目的,传统的手段是 Some How 找到和这个人共事过的人,听取他的意见。这样做首先要看运气,有的时候要转几层关系才能找到这样的人,并且不一定得到的是正确、真实的答案。 但是如果这个人已经给你的项目贡献了一些代码,并且代码质量比较高、贡献过程中和你的沟通很顺畅,那么一方面说明这个人软硬实例都不错,另一方面说明这个人对你做的事情很有兴趣。TiDB 有大量的正式、实习员工都是从 Contributor 中转化来的,以至于我们担心别把所有的人都招进来,社区没了 :) 。
社区贡献 可以这么说,如果没有开源社区,整个互联网都不会是现在这样。想象一下如果没有 Linux、MySQL、GCC、Hadoop、Lucence 这些东西,那么整个互联网的基础技术栈将不复存在(当然,肯定会出现另外一套东西,但是可能不会像开源的这套这么完善)。无数的开源社区贡献者贡献自己的力量,共同维持这样一个互助互利的社区,支撑社会技术进步。 我们也从开源社区中获得了很多支持,包括大家报的问题、提的建议以及来自全球一百四十多名贡献者提交的代码。随着项目的发展,我相信社区贡献代码的比例会持续提升。
提升项目质量 当一个项目以开源方式运营时,代码质量是项目的脸面,大家无论是在提交代码的时候,还是在 Comment 别人的 PR 的时候,都会非常谨慎,因为你的一举一动全世界都能看到,毕竟谁也不想人前露怯是吧。
对基础软件的意义 对于一个数据库这样的基础软件,最重要的就是正确性、稳定性和性能。前两点尤其重要,要保证这两点,一方面需要在开发和测试过程中尽可能提高质量,另一方面广泛的使用也非常重要。只有当你的产品有足够多的人试用,甚至用于生产环境,才可能有足够多的问题反馈以及产品建议。开发人员能做的测试毕竟是有限的,很多场景、环境或者是业务负载是我们想象不到的。来自实际用户的问题反馈有助于我们提升产品质量,来自用户的建议有利于我们提升产品易用性。只有长期在生产环境中运行过的基础软件的,才算是合格的基础软件的。
所以我们认为开源是基础软件的大趋势,无论是 Hadoop、MySQL、Spark 这样的知名产品,或者是 Linux 基金会、Apache 基金会、CNCF 基金会这样的巨头,都证明了这个观点。国内目前大公司比较热门的开源项目,也都集中在基础软件领域,比如百度的 Brpc、Palo、Tera,以及腾讯的 PaxosStore。
这里简单讲一下我们开源的几个 Repo 都是做什么:
大家可以在 GitHub 上浏览我们的代码,看到我们完整的开发过程。
PingCAP 攻城狮小申典型的一天:
8:00 起床,先登录 Slack 看一下昨晚定时跑的测试任务是否结果正常,然后关注一下 Slack 上各种 Channel 以及微信群、邮箱是否有什么重要的消息
9:00 洗漱完+吃完早饭,逗一会可爱的女儿(也可能是被女儿逗),然后去上班
9:30 到达公司,开始干活。
* 打开电脑看看 GitHub 上面有什么新的 Issue
* 看看自己的 PR 有没有被别人 Comment,如果有 Comment 的话,尽快解决;如果还没人看的话,at 一下相关的同学,求 Review
* 看看有没有别人的 PR 需要自己 Review,特别是 at 自己的那些 PR
* 带上耳机开始写点代码
* Slack 有人 at 我,赶紧回复一下
* Slack 上我关注的 Channel 中有人在讨论问题,我很感兴趣,加入进去讨论一会
* 同事要做一个新的 Feature,写了设计文档,我点进去看了一遍提了几个 Comment
12:00 肚子可耻的饿了,呼朋唤友去吃饭,路上顺便讨论讨论技术以及八卦
13:00 吃饭归来,看看邮件、Slack、微信留言,处理一下紧急的事情
13:30 小睡一会
14:00 小睡结束,接一杯咖啡,开始下午的工作,键盘敲起来。。。。。
15:30 参与同事的设计评审会议,通过视频会议系统和远程的同事一起讨论设计方案,拍板后开干
16:30 休息一下,然后继续敲代码、Review PR
18:00 大部分同事已经去吃饭了,我准备开车回家吃饭去
20:30 吃完饭,收拾完,没什么事情,打开电脑看一会邮件、Issue、PR
22:30 休息一会,准备洗澡睡觉
首先你需要根据自己的诉求、商业模式等选择一个开源协议,常见的有 GPL 、BSD、Apache 和 Mit ,这些开源协议的区别在阮一峰老师的 如何选择开源许可证? 这篇博客中解释的很清楚了,推荐大家阅读。
协议选定之后,再选择一个代码托管平台,目前的标准选择是 GitHub,注册一个 GitHub 账号,申请一个 Orgnization 之后,就可以开始用了,如果不需要私有 Repo 的话,那么不需要交任何费用。
开始代码开发,提交第一次 Commit,完成 Readme 的撰写(一个好的 Readme 真的很重要)。
后续的开发都需要通过 Pull Request 进行,最好不要直接 Push Master。一个严肃的项目需要把 Master 加入 Protected Branch,禁止直接 Push。
为了保证后续的代码提交都是 Work 的,最好在 GitHub 中集成至少一个 CI 服务,常用的有 TravisCI、CircleCI (最近一段时间 CircelCI 似乎总是出问题)。然后在 PR 的设置页面上要求 PR 通过了 CI 才能合并。
如果有人试用项目时发现一些问题,会通过 Issue 反馈,所以需要关注 Issue ,尽快给予回复。另外将 Issue 通过 Label 分门别类是一个好的实践,便于大家快速搜索、分类 Issue。比如我们会将一部分简单些的 Issue 标记为 Help Wanted,如果有新加入社区的同学想要开始贡献代码,那么这些 Issue 就是不错的起点。
当参与的人越来越多,那么会有一部分人开始贡献代码,Maintainer 需要 Review 其他人的 PR,保证能项目自身的代码质量要求、编码风格一致。
最后一点,一个好的项目需要配备完善的文档,帮助大家使用项目。包括架构、简要介绍、详细介绍、FAQ、使用范例、接口文档、安装部署以及最佳实践等等。这点也是大多数项目所忽略的。
最简单的参与方式是试用开源项目,这也是开源最大的一个好处,所有人都可以随时试用,相当于有很多人帮助项目作者做测试。毕竟如果只有作者自己做测试,遇到的环境、场景、应用方式会比较单一,总有一些你想像不到的地方会出问题。所以每一个测试出来的问题都很宝贵,我们都会尽可能快的评估和回复。
试用过程中大家可能会遇到各种问题,特别是文档中没有提及的问题,反馈问题的最佳方式是在 GitHub 上新建 Issue,这样所有的人都可以看到,而且通过 Issue 来反馈我们也会更重视一些,有人会定期扫一遍未处理的 Issue。当然,建立 Issue 之前先搜索是否和已有的 Issue 重复是个好习惯。
在 Issue 中尽可能详细的描述清楚遇到的问题,以及一个可操作的复现步骤,包括所用 Binary 的版本、部署方式、客户端以及服务的日志、操作系统的日志(如 dmesg 的输出)。如果不能复现,也尽可能详细地提供 Log。这些对开发人员追踪 Bug 会非常有用。
如果对项目有什么建议,也可以通过新建 Issue 来反馈, 我们一般会给出是否会支持,如果要支持的话,大概会在什么时候支持。
当你使用 TiDB 遇到问题或者需要新的 Feature,而觉得自己有能力 Fix 或者是当前官方还没有精力 Fix 时,可以尝试自己修改代码,解决问题。
目前 TiDB 项目的 Contributor 有 140 多个,分散在全球十几个国家。其中不乏深度参与的用户。
如果是小的功能或者是简单的 Bug Fix,可以在相关的 Issue 下面吼一声,让大家知道你在做这个事情即可,这样不会有人做重复的工作。如果做的过程中遇到了什么问题,也可以在相关的 Issue 中和 Maintainer 讨论。
如果要做的是比较大的功能,那么最好先和官方做一轮讨论,然后写一个尽可能详细的 Design,讨论 OK 后,开始开发。
在开源项目中总能或多或少的发现奇葩的 Issue,比如 这个:
看到这个 Issue 真的是震惊了。