|设计:苏子馨
工程师如何对待开源
概述
那么如何选择开源软件? 这么多开源软件中,如何根据个人需求和业务需要来选择合适的开源项目来进行投入,是需要综合考虑的。
选择了开源软件之后又如何进行定制和长期维护? 这也是一个很大的问题。因为在企业内部开发软件,跟个人开发软件不一样的是,维护一个计算机软件系统的成本远远大于开发该系统或软件的成本。选择开源软件之后,如何从长期的视角进行定制和修改,后续的长期维护如何进行,才能做到高效和节省成本,业内有很多很好的经验,也有不少不太成功的案例成为教训。
最后回到个人,工程师的成长是在不断的学习和实践中进行的。如何来利用开源来提升自己能力,扩大自己的眼界,提高自己技术口碑和业内影响力,对于工程师本人也是非常重要的。
1工程师如何选择开源软件
2工程师如何定制和维护开源软件
3工程师个人成长如何利用开源
1.如何选择开源软件
首先要明确对开源软件的态度,在现阶段是不可能离开对开源软件的使用的。 使用开源软件有各种各样的风险,包括开源合规、安全、效率的问题。 简化为一句:在企业内部使用开源软件,需要遵守该企业对开源软件的内部规定,包括如何引入和如何维护,以便达到高效、安全、合规的使用。
回到具体如何选择特定的开源软件的问题上,有如下几个纬度可以进行参考:
● 根据需求
● 根据技术发展趋势
● 根据软件采纳周期的不同阶段
● 根据开源软件的成熟度情况
● 根据项目的质量指标
● 根据项目的治理模式
1.1根据需求来选择开源软件
选择开源软件,首先要明确需求,即选择这个开源软件的目的究竟是什么。 工程师选择一个开源软件,究竟是它用来做什么的,是用来进行个人学习的; 还是用来满足 ToB 客户的需求的;还是用来满足内部服务开发的需求的。 这三个不同的目的下,选择开源软件的导向完全不一样。 (注意:后两个场景是需要先考虑企业开源合规的需求的,参见第三章)
先说说选择开源软件来进行个人学习,那么需要看看个人学习的具体目的究竟是什么。 是想学习一种比较流行的技术来完善个人的技术知识结构扩大个人技术视野;还是想看看相应的开源技术项目的具体实现,来作为内部项目技术开发的参考;还是想为了下一份工作进行有针对性的技术准备。不同的目的会导致不同的选择。针对前者,显然是什么技术最流行选什么,自己缺什么选什么;针对第二种目的,一般是对该技术领域的知名开源软件或者创新性软件进行有针对性的选择,即某个特性是我当前需要的,或者是我当前项目实现不好的,我需要看看别人是如何实现的。最后一种,显然是按照下一份工作的职位需要和技术栈要求进行准备,并根据技术栈要求的门槛高低进行选择。但是注意,从个人需求出发选择开源软件,一般都需要写个小项目练练手,比如一个 Demo 程序或者一个测试服务,因为不用考虑后续的长期维护,所以尽可以按照个人的想法和个人研发习惯进行各种练习,不用遵循企业内部的开发流程和质量要求,也不用考虑该开源软件的稳定性和 区成熟度等情况,只需要尽情的学习和参考代码就好了。
然后看下一个需求,选择开源软件进行研发的软件是需要提供给客户的,往往可能还是以私有云的方式进行交付。基于此类需求来选择开源软件,注意做好平衡,即客户的需求和企业自身技术规划或产品的长期规划需要。以私有云方式进入客户的 IDC 环境,是需要跟客户开发和运行环境的上下游项目进行集成的。这时候要看客户的需要,可能某些客户对开源软件有特定的要求,例如要求使用 HDFS 而且是某个特定版本。对这类指定软件名字和指定版本的要求,有可能是因为客户当前比较熟悉这个版本,也有可能是因为之前其他软硬件供应商提供的软件和版本,指定的目的是方便集成和后续的使用与维护。如果这种需求是符合企业项目或者产品的长期发展需求的,则是可以完全满足的。如果甲方非常强势,除了满足他的要求之外没有别的办法,那就选择客户所指定的软件和版本好了。但是如果跟自身项目或产品的长期发展需求不一致,而且具体项目或者版本是可以跟甲方进行协商的,那么需要跟客户协商出一个双方都能接受的结果出来,即选择特定的开源软件和版本既要做到客户满意并买单,又要做到自身的交付成本可控,还要做到符合自身项目或者产品的长期发展需要。
例如客户使用 Java 的某个老版本,但是企业的 toB 交付的软件要求使用 Java 的较高版本。那么需要跟客户协商,要么切换到企业希望的版本上,还需要帮助客户完成已有系统的升级工作;要么只能降低自身软件的 Java 版本需求,可能还需要对某些自身代码进行修改,还可能对软件中的某些依赖组件进行修改。这个场景下是带有很多客观约束条件下的选择,是需要跟客户,自身的产品经理和架构师一起协商的。
最后,如果场景是为了满足内部服务的需求,即选择开源软件来搭建的服务是给内部业务或者最终用户来使用的,常见于国内各大互联 公司的互联 服务系统和各种手机上的 App。这时候项目的开发和维护方有较大的自主权,跟 toB 的交付业务完全不一样。此时选择开源软件,就一定要综合考虑开发和维护成本,还要考虑使用该服务的业务所处的阶段。
(1)如果提供的服务是给创新业务使用的,创新业务一般都是试错业务,随时需要根据市场情况的变化和当前执行的状态进行调整,很可能三个月后这个项目没了,即被取消了。这种情况下 “糙快猛” 的开发方式是比较合适的,不用太多考虑系统的可维护性和可扩展性,就用研发团队最熟悉的软件技术栈,然后用底层技术支撑团队比如基础架构团队提供的成熟而且经过验证后的底层基础技术平台就可以,最重要是尽快把系统搭建出来,然后随着产品进行快速的迭代。这个时候需要尽量降低现有研发运维团队的学习成本和开发成本,不用太多考虑可维护成本,因为需要糙快猛的把系统堆出来,验证产品需求和商业模式是最重要的,时间最重要。如果发现有市场机会,就快速跟进,站稳脚跟之后可以采用省时间但是费资源的方式(俗称 “堆机器”)来进行扩展,或者采用 “边开飞机边换引擎” 的模式进行重写都是比较划算的。对于处于创业阶段的企业或者项目来说,速度胜过一切。
(2)但是如果选择开源软件搭建出来的计算机软件系统或者服务,是需要长期维护的,比如是给公司内成熟业务使用的,或者是针对公司内成熟平台的缺点进行系统升级并要替代原有产品的,那么在满足业务需求的前提下,考虑系统的可维护性变成最重要的事情。选择对应的开源软件,它是否成熟,是否稳定;二次开发是否友好;运维成本是否比较合算即比较省机器和带宽;运维操作是否方便,例如常见的扩容和缩容操作是否可以高效、自动、无损地完成;Upstream 到上游开源 区是否容易等等,这些都成为需要重点考虑的事情。这种情况下,开发一个系统的成本,可能只占整个系统生命周期内的成本的 1/10 不到。所以在满足需求的前提下,重点考虑可维护性。
1.2根据技术发展趋势来选择开源软件
如上图所示,现代计算机软件或者服务的研发,是一个不断运行的循环和迭代过程。从市场分析开始,然后进入到创意阶段,再到编码阶段,最后到上线阶段完成应用的部署和生效,上线之后根据得到的数据反馈,继续进行分析。这个循环迭代的过程,显然对于一个身处竞争激烈的行业的企业来说,迭代的速度越快越好,同时也需要具备快速弹性、低成本伸缩的能力,即产品方向对了,那么赶紧进行系统扩容,承接快速增长的流量,做到快速增长;如果产品方向不对,需要赶紧缩容,把相关硬件和人力资源节省出来,投入到新的试错方向上去。身处同一个行业内的企业,如果企业 A 能以更低的成本,更快的速度地进行各种产品和策略的迭代,显然它是能比迭代速度慢,成本高的企业 B 是有更好的竞争优势的。
现在的开源软件数量非常多,几乎每一个分类下面都有很多的开源项目。针对某一个具体的需求,如何进行选择?一个建议是根据技术趋势进行选择。即现在的计算机系统迭代的方式是 Agile(敏捷) + Scale(扩展)。显然,能够支持计算机系统进行快速迭代,并能够很方便进行低成本弹性伸缩的开源软件是值得进行长期投入的。而对一个新的开源软件的学习和使用,学习者是希望该软件的学习门槛越低越好。一个流行的开源软件,内部实现可以尽可能的复杂,但是对于用户来说一定是需要用户友好的。不然即使创新度再好,易用性不好,只有极客才能学习和掌握,创新的鸿沟是很难跨越的。
例如 Docker 的出现之后,以极快的速度风靡全球,非常多的工程师喜欢上了 Docker。就是因为 Docker 的特性,在传统的容器系统之上增加了新特性,包括把应用程序和底层依赖库封装为一个容器镜像,容器镜像有版本,而且可以通过集中的镜像仓库进行存储和大批量分发。Docker 首先解决了长期困扰工程师的开发、测试、上线环境标准化的问题,能够支持开发者进行快速的迭代。同时使用了统一的镜像仓库来进行镜像的分发,而且底层采用了轻量级虚拟机即容器的技术,可以非常快的被拉起,所以采用 Docker 的系统可以很方便的进行弹性扩展。同时,因为把应用 App 封装在一个镜像里面,可以在逻辑上根据 Domain Model 的设计原则进行更好的抽象和复用。显然,这样的技术是值得每一个开发计算机系统的工程师学习和掌握的。因为他能带来极大的方便。相反,在 Docker 产生之前,虽然 Control Group(简称 cgroup) + Namespace 的技术早就已经出现,并早就集成在 Linux 内核中,Google 的 borg 相关的论文早就已经发表,但是一般的技术研发团队不是很容易就能驾驭容器并把容器系统在公司内部大规模进行部署的。印象中 borg 论文出现后,国内只有 BAT 级别的互联 公司,才有一小撮精英研发团队来研发和使用容器管理系统,例如百度负责 Matrix 系统研发的团队,阿里负责 Pounch 系统研发的团队,腾讯也有一个小团队负责容器系统的研究。但是除了那一小部分团队,更多的工程师因为相对较难的学习难度而没有把容器大批的用起来。而 Docker 这种技术,就是非常好的顺应了敏捷和弹性扩展的技术趋势,而且提供了非常好的用户易用性,然后一出场就被非常多的工程师迅速使用上了,而且成为市场的默认标准。
这些顺应潮流的开源软件是值得选择和投入的。
另外一个例子是 Spark,Spark 的出现解决了 MapReduce 在分布式计算过程中因为需要频繁进行 IO 操作导致的性能比较低下的问题,同时在易用性上有较大的提升,所以才取代了 MapReduce 在分布式计算领域内的主流地位。
1.3根据开源软件采纳周期的不同阶段进行选择
软件作为智力活动的产物,他有他的生命周期,一般用软件的技术采纳曲线表示。
开源软件也是软件的一种,也都是遵循软件的技术采纳规律的。如下图所示:
一个开源软件从创建到衰亡一般会经过 5 个阶段。 从创新期(Innovators,占比 2.5%),到早期采纳期(Early Adopters,占比 13.5%),然后跨越鸿沟(chasm),进入到早期大众期(Early Majority,占比 34%),再进入后期大众期(Late Majority,占比 34%),最后进入衰退期(Laggards,占比 16%)。绝大部分的开源创新项目,没有能成功的跨域鸿沟,即从早期采纳阶段进入到早期大众阶段,就消亡掉了。 所以,如果是选择一个需要长期使用并维护的开源项目,选择处于早期大众或者后期大众状态的项目是比较理智和科学的。
当然如果只是个人想学习一个新的东西,可以看看处于创新者状态的开源项目,或者看看处于 “早期采纳者” 状态的项目。
注意不管是从长期研发系统的角度,还是从个人学习的角度,都不要再去看处于衰退期(Laggards)的项目了。 例如现阶段即 2022 年,是不用再去选择 Mesos,Docker Swarm 之类的项目了。自从 Kubernetes 成为容器调度技术分类的默认标准,这两个项目就已经处于衰退期,他们的母公司都已经放弃了。这个阶段如果还投入较多精力来开发和维护,除非真的是非常强势的甲方要求,把钱砸在工程师面前逼的不得不用才会选择。
同学们可能会问,从哪里可以看到这些技术采纳度曲线?
InfoQ,gartner,thoughtworks 每年都会更新他们各自的技术采纳度曲线并公布出来, 大家可以在 上搜索一下,看看他们各自的技术采纳图是什么,然后结合一些业内的经验,得出自己的判断。
例如:
https://con.infoq.cn/conference/technology-selection?tab=bigdata
从这里能看到 2022 年 InfoQ 对 BigData 领域各种流行技术的判断。
从上图可以看出,Hudi、Clickhouse、Delta Lake 等开源软件还处于创新者的阶段,即在工业界采纳还比较少,对于想学习新项目的同学是可以重点关注的。但是现在这些开源软件还不适合应用在需要长期维护的成熟应用场景里面。
注意这些知名科技媒体的技术采纳曲线是每年都在更新的,在进行参考的时候别忘了注意一下发表的时间。
1.4根据开源软件的成熟度情况选择开源软件
还有一点,即根据开源软件本身的成熟度来选择开源。 即从这个开源软件是否定期发布,是否处于一个多方维护的状态(即使一个公司的战略发生了变化不再继续维护了,还有其他的公司在长期支持),是否文档比较齐全等多个维度来进行成熟度的评估。
对于开源软件的成熟度模型,开源 区有很多度量开源项目的成熟度模型,其中 Apache 开源软件基金会的项目成熟度模型是比较有名的。
可以参考这里:
https://community.apache.org/apache-way/apache-project-maturity-model.html
按照这个 Apache 开源软件基金会制定的开源项目成熟度模型,他把一个开源项目的评估纬度,分为 7 个维度:
● Code(代码)
● License and Copyright(软件许可证和版权)
● Release(发布)
● Quality(质量)
● Community( 区)
● Consensus Building(共识共建)
● Independence(独立性)
每个纬度又有几个考察项。
例如针对 Independence(独立性),又有两个考察项,其一是看这个项目是否独立于任何公司或者组织的影响,其二是看贡献者在 区内活动是代表他们个人,还是作为公司或者组织的代表出现在 区并进行活动的。
Apache 基金会 Top Level 的项目即顶级项目,在毕业阶段都会从这些维度进行综合的判断。只有各方面都达标的项目,才会被允许从 Apache 基金会的孵化状态中毕业而成为成为 Top Level 的项目。这也是逼着个人比较喜欢 Apache 顶级项目的原因。
另外,OpenSSF 项目的 Criticality 评分(参见:
https://github.com/ossf/criticality_score)也是一个不错的参考指标,它会度量一个项目的 区贡献者数量、提交频度、发版频度、被依赖的数量等指标,来判断一个开源软件在开源生态中的重要程度。这里就不详细展开了,有兴趣的同学可以参考它的资料,个人认为是一个值得参考的方向,但是这个评分还处于早期阶段,距离理想状态还比较远。
1.5根据项目的质量指标来进行选择
很明显,有些开源软件的代码质量是比其他开源软件的质量好。 有的时候需要从项目的质量情况来选择开源软件。这个时候,我们需要查看一些被业内广泛证明比较有效的指标。
其中 MTTU 是被知名开源供应链软件供应商 SonaType 所推荐的指标。它在它著名的供应链年度 告里面提到MTTU。参见:
https://www.sonatype.com/resources/state-of-the-software-supply-chain-2021
MTTU(Mean Time to Update):即开源软件更新它依赖库的版本的平均时间。举个例子来说,某开源软件 A 依赖于开源库 B,假设 A 的当前版本是 1.0,依赖 B 的版本是 1.1。某天开源库 B 的版本从 1.1 升级到了 1.2,然后一段时间之后,开源软件 A 也发布了新版本 1.1,其中把对 B 的依赖版本从 1.1 升级到了 1.2。这个时间间隔,即从开源版本 B 的版本升级到 1.2 的时间点距离开源软件 A 的新版本 1.1 的发布时间,称之为 Time to Update,反映出来的是开源软件 A 的研发团队,根据依赖库的更新周期,同步更新它的依赖版本的能力。Mean Time to Update 是指这个软件的平均升级时间。数值越低表明质量越好,表明该软件的负责人在很快速的升级各种依赖库的版本,在及时修复各种依赖库引起的安全漏洞问题。
据 SonaType 的统计,业内开源软件的更新升级时间 MTTU 越来越短。 据它的统计,在 Maven 中心仓库上的 Java 类开源软件,2011 年平均的 MTTU 为 371 天,2014 年平均的MTTU为302 天,2018 年平均的 MTTU 是 158 天,而 2021年平均的MTTU 时间是 28 天。能看出来,随着开源软件库更新频率的加快,使用它们的软件也随着加快了更新版本的速度,MTTU 相对 10 年前,时间缩短到原来的 10/1 以下。
当然 MTTU 只有项目质量的一个间接纬度。 历史上是否爆出重要高危安全漏洞,修复响应是否快速及时,等等也是作为开源项目质量评价的重要维度。
某些大厂的安全部门,会不断评估开源软件的安全情况,把某些屡屡发生高危安全漏洞,但是修复不及时的开源软件设定为不安全软件,列入到内部的开源软件黑名单中对内公示,并要求各个业务研发团队不再使用这些软件,实在因为研发和人力问题不能迁移到新的软件系统的情况也需要把这些老服务迁移到一个相对封闭的 络环境中,减少风险可能造成的损失。这个时候,显然应该需要遵守公司的安全规定,不再使用黑名单上的开源软件。
1.6从开源软件所属于的开源 区治理模式角度来考虑
还有一个维度,即从这个开源项目的 区治理模式来考虑,适用于需要长期进行开发和维护的项目。
区治理模式(Governance Model)主要是指该项目或者 区是如何做决定的以及由谁来做决定。 具体表现为: 是所有人都可以做贡献吗还是少数几个? 决定是通过投票的方式产生的,还是通过权威?计划和讨论是否可见?
常见的开源 区和开源项目的治理模式有如下三种:
● 单一公司主导:特点是软件的设计、开发和发布都由一个公司来控制,也不接受外部贡献。开发计划和版本计划不对外公开,相关讨论也不对外公开,版本发布时候才对外公开源码。例如 Google 的 Android 系统。
● 独裁者主导(有个专有名词 “Benevolent Dictatorship”,翻译为 “仁慈的独裁者”):特点是由一个人来控制项目的发展,他有强大的影响力和领导力,一般都是该项目的创始人。例如 Linux Kernel 由 Linus Torvalds 来负责,Python 之前由 Guido Van Rossum 来主导。
● 董事会主导:特点是有一拨人构成项目的董事会来决定项目的重大事项。例如 Apache 软件基金会的项目由该项目的 PMC 决定,CNCF 的基金会的决策是 CNCF 董事会来负责(很多技术决定授权给了 CNCF 董事会下的技术监督委员会)。
个人意见和经验,根据该开源软件背后的开源 区的治理方式来进行选择优先级的排序如下:
● 优先选择 Apache 毕业项目(因为这些项目的知识产权情况清晰,而且至少有三方在长期维护)
● 次优选择 Linux 基金会等其他开源基金会的重点项目(因为 Linux 基金会的运营能力很强,每个重点项目后面往往都有一个或者多个大公司在支持)
● 小心选择一个公司主导的开源项目(因为该企业的开源战略随时可能会调整,很有可能不再持续支持该项目,例如 Facebook 就是一个弃坑很多的公司)
这是个人推荐的选择同类开源软件项目的优先级顺序,仅仅代表个人观点,欢迎讨论。
2.如何定制和维护
把一个开源软件引入到企业内部后并用来进行开发和长期维护,就出现了如何定制和维护的问题了。 首先要明确,开源软件引入到企业内部之后是需要定制的。 因为如下几个理由:
1、开源软件往往都是适用于通用场景,考虑的情况比较多,需要支持各种各样的使用场景。但是引入到企业内部之后,往往只需要针对企业特定的场景。所以针对这些特定场景进行优化,例如对全部功能进行剪裁,去掉跟本场景无关的特性,针对特定场景进行性能调优和参数优化等,往往能取得更好的性能,例如可以抗更多的流量,节省机器成本的效果是惊人的。这也是常见的定制方法。
2、开源软件进入企业内部要经过开发并长期运营,是需要满足该企业的各种内部的服务运维规范的。例如业务上线,是需要有完整的日志和监控,比如需要提供服务健康检查接口,还需要有流量调度等容错处理。这些都是需要进行定制修改的。
3、开源软件还需要对接企业内部的上下游系统,例如如果该软件的正确运行需要依赖底层的分布式存储和分布式计算系统来完成基本功能,是需要对接企业内部已有的存储系统或者计算系统的;企业内部的底层虚拟机系统或者容器调度系统,往往有部分修改和优化,对接起来也是需要进行修改的;所以这个时候需要进行定制修改。
4、特殊场景下的需求定制,在企业应用场景下使用该开源软件往往会遇到特定的问题,可能会碰到 Bug,这些都需要 Bugfix 和新增特性来支持。
2.1如何对开源软件进行定制和修改
对此,笔者建议有几个基本原则: 不动开源软件的核心代码,尽量使用该开源软件已有的插件机制;或者在外围改;定期升级到开源 区的稳定版本。
很多开源软件在设计之初,就留下了不少扩展机制,方便后续开发者进行功能扩展和特性增加。例如几个最著名的开源软件 Visual Studio Code,Firefox Browser 就提供了 Extension 机制,很多开发者根据自身需求开发对应的插件,并把插件提交到官方支持的插件市场里面。普通用户在安装完成主要程序后,还可以浏览插件市场,寻找和选择自己需要的插件进行安装。 另外像 Kubernetes,也在多个地方提供了扩展机制,例如核心调度器哪里提供了定制化的 scheduler,可供开发个性化的调度策略;底层的存储和 络都
声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!