大厂开源之殇

本轮开源之风吹起迄今数年,最大的影响还是越来越多的商业公司开始探索开源方法能够如何改变自己的经营策略。

开源策略循序渐进分成使用、参与和发起。在发起开源项目实践一线的,一个是打着开源旗号的创业公司,另一个就是大型企业尤其互联网企业(大厂)。

前者我在过去的文章里已经详细讨论了他们的动机、面临的风险和应对策略。

本文将关注大厂发起的开源项目的共同特点,讨论围绕这样的开源项目聚拢起来的企业研发团队、市场运营团队、用户开发者之间常见的认知失配问题。值得说明的是,这些问题虽然是大厂开源常见的问题,却不是大厂开源独有的问题,对其他开源项目的建设也有参考意义。

用户不买账:我要怎么用起来?

首当其冲的问题,是大厂开源的软件,离开了内部需求和重度集成的基础平台之后,很难为其他用户场景产生价值。

通常,大厂开源的软件,来自于基础架构团队剥离其提供服务的核心,例如微服务中间件的核心框架、日志收集和分析系统、配置中心和监控系统等等。这些软件开发之初,是为了服务企业内部业务对基础软件的需求。

企业内部的需求是特定的,而且往往倾向于把业务的需求推到基础平台来解决,随着集成程度的增强,边际成本不断降低。例如,内部平台上有一个配置中心,其他所有的软件启动时都默认环境里有这样一个配置中心,从中取得对应的参数做初始化。例如,内部平台有一套监控系统,有一套日志上报和分析的流程,这些逻辑都很容易侵入到其他组件当中。

这就导致大厂一旦要开源,经常是一股脑的把整个基础平台都打包开源出来。BAT 开源的软件当中,被当做拳头产品的,很多是这类全家桶式套件开源。

  • 字节跳动的 CloudWeGo 是 Golang 和 Rust 的微服务中间件套件;
  • 阿里巴巴的 SOFAStack 是 Java 的微服务中间件套件;
  • 腾讯捐赠到 Linux Foundation 的 TARS 是 C++ 为主的微服务中间件套件;
  • 字节跳动的 KubeWharf 是云原生应用管理套件。

这些套件,往往你很难单独拿其中一个跑起来,而是需要把全家桶都部署起来才能用上其中任何一个功能。

这样,用户选择这个套件的时候,就需要每个被全家桶带进来的软件都能较好的解决其对应领域的问题,否则就是浪费,很难过内部审查这关。然而套件开发都是针对大厂内部的需求,对于外部用户的定制化需求很容易无法满足,而又因为高度集成实际就是耦合而不好扩展,最终在大厂之外难以被用户用起来。更有甚者,有些功能用户压根不需要,但是大厂内部的业务是需要的,大厂内部的基础平台的部署又是标准化的,用户时常会发现全家桶里有毫无价值但是又需要吃资源的组件。

此外,在软件诞生的企业里,部署运维这个全家桶套件的流程往往是经年累月磨合出来的,有很多的故事和康威定律的结果,这样的历史在其他任何用户那里都是不存在的。运维的难题是定制化以外的另一个阻止用户使用的重要原因。

那么,大厂开源之前,把软件之间的依赖解耦,做好封装和模块化,不可以吗?

这样做是很有难度的。ByConity 是字节跳动基于 ClickHouse 改出来的一个号称云原生数仓的软件。它的核心架构依赖 FoundationDB 和 HDFS 这两个服务,虽然这两个服务对应的软件是开源的,用户理论上可以自己起起来,但是纵览整个编译和部署的手册,我相信没有几个人能够真的跑起来。

可以想象,在字节跳动内部有一个云平台,直接提供了相应的服务和自动配置的深度集成逻辑。这样看来,ByConity 不仅是云原生的,几乎是火山引擎云原生的,离开了这个平台,该软件的使用成本急剧上升。这样开源出来的软件,用户自己都跑不起来,何谈后续的反馈和参与呢?

无独有偶,阿里巴巴开源的 PolarDB-X 也对如何跑起来只字不提。虽然我们知道它是一个 MySQL 的魔改版本,但是毕竟会为了这个软件而来的人,想知道的肯定是如何利用那些独特的功能。我看到 PolarDB-X 的 Wiki 页面讲了不少技术设计、理想和参数手册,但是到底怎么跑起来,还是不知道。可能这些功能在阿里云上对应的产品里已经被很好的集成并提供给客户,但是对于拿到这个开源版本的用户来说,他能使用这个软件为自己带来什么价值呢?

当然,大厂开源也有把开源软件自己的产品化做得好的。

例如阿里巴巴捐赠到 ASF 的 Dubbo 项目,就以其充分的组件化和插件化,得到了社群生态良好的集成。同样是微服务中间件,Dubbo 的核心足够小,而且没有对其他软件服务过硬的依赖,用户可以先跑起来解决一个特定的问题,再在使用过程里逐渐添加或自己开发集成做增强。最终,扩展和集成对接口的需求回流到上游,扩展和集成本身共享到社群,这样的正循环帮助 Dubbo 灵活地服务各种不同的微服务场景。

同样,腾讯开源的影响力标杆 ncnn 有一个完整的 HowTo 列表,告诉用户怎么在各种环境下跑起来,生成用户内容。通过用户内容的传播聚集人气,并在解决一个又一个用户问题的正循环里不断打磨软件的成熟度。

NCNN 的起步指南

ApolloKvrocks 是另外两个来自企业的有口皆碑的开源项目,前者孵化于携程,后者来自美图。它们后来都脱离了大厂的开源体系,独立运营,在面对真正的用户需求时较好地解决了问题,从而得到了用户的信赖,也就有了源头活水。

开发者晕头转向:我该如何参与?

大厂开源之初,经常会想象项目一呼百应,开发者蜂拥而至,社群生态一片繁荣的景象。然而,项目实际开源之后,真实情况常常是门可罗雀,只有公司员工在提交代码,甚至 commit 都是从内部同步出来的,堪称只读开源。

除了没有回答好软件对用户有什么价值,用户到底要怎么用起来的问题,导致从根本上失去源头活水以外,另一个可观的社群增长阻碍,是由于内外流程失配带来的开发者难以参与的问题。

我在《企业如何实践开源协同》当中提到的第一点就是需要建立内外共享的工作流。否则,如果在设计开源方案的时候,没有把共享工作流考虑在内,即使代码公开,大部分开发流程也会保持在企业内部。如果开发者不是企业员工,则根本无法参与。

在实际接触了许多企业开源项目的需求之后,我能理解企业内部总是需要一个响应客户问题和解决研发排期的流程,但是在这样的背景下,为了良好的社群协作,仍然需要一个完整的、同企业内部流程啮合的开源工作流。

这里的核心原则是对社群参与设置的检查点,开发者需要有能力做自我检查。典型的场景是开发者提交一个补丁以后,在合并之前需要走哪些步骤,他心里应该是有数的。

腾讯开源的数据处理方案 InLong 项目,在 Apache 的流程模板加持下,从合作开发到软件发布,都是有迹可循的。其官网上仔细地记录了如何参与和如何发布的文档。进一步地,腾讯内部的数据处理系统也跟随开源版本发布,仅在内部对紧急问题做 hotfix 处理,所有的信息尽可能脱敏公开到社群,公共的改动会 upstream first 的推到上游分支。

谷歌开源在相当一段时间里都饱受恶名,因为它们几乎没有响应过任何外部参与者提交的补丁。不过,我在 Protobuf 的参与体验却不算差。Protobuf 的 CI 流程虽然依赖于内部系统,但是其结果会报告到 GitHub Pull Request 的 Check Status 上,所以开发者至少可以知道自己是否通过了测试。同时,Protobuf 的 CI 日志是可以公开访问的,我在贡献 Ruby 模块的时候,就通过自己读测试日志排查问题,数次避免了需要等待内部员工告诉我哪里出错了。

许多运行不良的大厂开源项目,往往是完全不考虑外部参与者的旅程体验,只是简单地维持先前内部研发的流程能工作即可。

TiDB 项目虽然不是大厂开源,但是从来自大厂的工程效能团队接手项目基础设施之后,整体的考虑方式也出现了相应的症状。

例如,在 PR-39440 里,他们试图在 TestCase 里加上某个测试必须对应某个内部系统 ID 的做法。这对于外部参与者来说完全是不可理解的,也不知道在自己正常改代码加测试,到底要怎么跟一个自己看也看不见,整个流程都与自己无关的内部系统关联上。通常,如果工程效能团队想要掌握一些指标,是可以在开源的工作流之上,通过分析测试的报告,提供内部的关联信息元数据,从而以对外界透明的方式来完成相同的需求。然而,对于设计工作流之初就没有考虑过开源协同的人来说,假设所有人都是我的同事,大家都工作在同一个上下文,才是熟悉的味道。

其他许多大厂开源项目甚至没有可以当做例子的内容,因为其开发过程完全和开源协同不沾边,也不在任何一个开放的代码协作平台上进行,你只能看到有 commit 神秘地被同步出来,没有任何解释,自然也无从参与。

上面说的是工作流上的问题,我在《共同创造价值》里提过,开发者参与协同的两大问题,除了知悉工作流解决怎么做的问题,还有可以做什么的问题。

大厂开源很多时候还是按照原先的产品计划和研发流程来进行,从未想过社群可以如何参与,自己又可以如何借助社群的力量提升软件的质量和增长软件的生态。

虽然开源之初,大厂的决策者就预想了开发者蜂拥而至的场景,但是要么根本没有想过这些人为何而来,如何引导他们参与,要么干脆假设这就是一批不用发薪水的员工,应当服从公司安排,接受任务指派,按时按量按质完成工作。

显然,社群成员不是你的免费员工,他们为开源软件和社群努力,而不是为公司努力。

为了正确引导外部开发者的参与力量,ClickHouse每年都会发布自己的 RoadMap 计划,大致告诉开发者今年要做什么。每当有一个新的想法和设计,也会尽可能地分享到社群,打开沟通的渠道。虽然大多数时候,功能还是由当初的 Yandex 或现在的 ClickHouse.com 的员工完成,但是一个打开的窗口允许参与者留言评论和理解整个需求的来龙去脉。

一般来说,社群成员是不能代替你完成软件产品的功能设计的,企业开源的项目仍然是企业项目,企业里的团队需要把控项目前进的方向。因此,企业视角里社群成员真正能够规模化地产生价值的地方,是功能初步交付后在各种使用场景的打磨,以及软件易用性和准确性的改进。

让你的社群成员知道你完成了什么功能,预期是什么样的,有助于激励他们试用起来。试用的过程会发现很多问题,引导和鼓励他们解决这些问题,是开启社群参与飞轮的第一步。

如果开发者来到你的社群,发现既不知道能做什么,尝试提交一些简单的改动,也完全搞不明白整个开发的流程,以及对 PR 被 Review 和被合并没有任何预期,那么开发者是不会对社群产生任何信赖感,也就不会留在社群的。

过度营销:KPI 导向的恶果

最后一个水面上的问题,也是无须多加分析就已经被广泛认知的问题,就是开源项目时 KPI 导向的过度营销,反过来妨碍了最初的影响力目标。

第一种过度营销,是夸大软件产品的价值。这一点我们在前面谈到“用户不买账”的问题时已经提到过,软件很可能没有解决什么普遍的用户问题,重度依赖大厂内部的业务假设和基础平台,用户用不上。这种情况下鼓吹开源软件如何解决大厂内部的问题,并自大地认为我能“降维打击”其他所有业务,最终用户用不起来,自然对你嗤之以鼻。

第二种过度营销,是为了人气指标提出一些零门槛的打卡任务,这一点其实跟“开发者晕头转向”紧密相关。由于工作流不透明,产品发展方向仅内部可见,不满足“共同创造价值”的前提条件,整个社群参与度非常低,堪称门可罗雀。这个时候,为了解决开源之初定下的 star 数和参与者人数的指标,运营团队乃至研发团队一起推出改拼写、改 linter 报错、改空白符等等零门槛活动,还发小礼品和大肆宣传,让真正想投入的开发者耻与之为伍,起到了反向的宣传作用。

第三种过度营销,是形式主义地搞出各种流程和机构。这其实是一种船货崇拜,即类似 Apache 和 Kubernetes 这样成功的项目,都搞了项目管理委员会、技术治理委员会、社区大使等等机构和角色,我们抄一套,是不是也就成功了?

很显然,在前面两个问题没有回答之前,软件的价值和整体的参与路径不清晰,搞出这些机构来往往是项目团队的角色扮演游戏和自我感动。漩涡在 BeyondStorage: why we fail 中对 BeyondStorage 社群为用户提供价值之前就沉迷于设计各种流程和机构做了深刻的反省。从用户和开发者视角来看,这个软件产品啥价值还没证明呢,就“封”了一群委员、委员长、秘书长、主席,到底是一个开源软件社群,生产软件我们好用起来和做反馈,还是一个官僚主义严重的团伙,主要职责是开会和弄文件的?

开发者关系:一种解决方案

上面介绍了大厂开源常见的三类问题,如果仔细看,会发现它们都跟软件产品研发团队相关。用户场景的问题需要产品定义,开发流程需要跟内部研发流程协同,市场营销的问题,也需要结合开发者的特点做相应的调整。

直接的结论可能是增加研发团队的职能,但是先驱者踩出来的实践可能是在企业当中设置一个开发者关系团队。对于有许多开源或待开源项目需要协调的大厂来说,还需要一个开源办公室来处理安全、合规和治理问题。

《开发者关系:方法与实践》介绍了一种开发者关系团队在企业当中充当开发者和产品研发部门信息枢纽的模式图:

开发者关系团队的定位

开发者关系团队了解开发者的特点,掌握社群当中开发者关注的内容,通过向产品研发部门提供开发者反馈,共同制作出开发者友好的 RoadMap 和使用说明。StreamNative 的开发者关系团队和研发团队紧密合作,推动 Apache Pulsar 网站 Getting Started 章节和 Landing Page 的改造,使得用户更好的了解 Pulsar 如何解决他们的问题,以及如何快速的在自己的环境上启动和试用 Pulsar 系统。

开发者关系团队熟悉开发者工作的方式,关注和协调社群当中的开发活动,通过不断改进工作流和促进消息流通,提升社群飞轮产生价值的速度和质量。在我开始处理 Pulsar 社群的开发者输入以后,Pulsar 主仓库的 Open Issue 和 PR 数量分别减少了 1000+ 个和 200+ 个。Issue 首次响应时间预期收敛到一周以内,大量的使用型问题在正确流转到对应核心研发之后迅速得到解答,许多明显易用性的问题补丁能够更快得到合并,而不是因为“不够重要”而被长期搁置。

开发者关系团队是不同于市场运营团队的内容出口,后者面向的群体是潜在客户(2B)或大众(2C),开发者关系的内容面向对象是开发者(2D)。开发者有其独特的内容喜好,开发者关系团队通过发布场景应用指南、软件使用教程、样例程序、线下会议和 workshop 等形式接触开发者,在开发者心智中建立起务实有效的技术品牌。