关于过气网红编程语言Ruby,我们此前曾发过一篇文章去回顾其大受追捧的过往,并讨论了它每况愈下的生存状态。不过人气并不能直接说明语言质量差,一方面RubyonRails(用Ruby写的开源Web应用程序框架)仍是实现原型设计演示的好方法,能帮助开发者在几天之内更稳妥地构建起最小可行性产品,另一方面,市场对于Rails和Ruby开发者还是存在刚性需求。 近期,GitLab就发布了一篇文章阐述它们坚持使用RubyonRails的原因。全球有许多流行网站都是基于Rails构建的,尽管今天Rails有日落西山之势,但技术选型还得图个合适。从GitLab的角度看,他们本身没有复杂的运行体系,也不需要用微服务,在这样的情况下,RubyonRails对他们而言反而是最佳选择。RubyonRails胜在哪 2004年7月,Rails的创始人DavidHeinemeierHansson从37signals公司的项目管理工具Basecamp分离出RubyonRails,并且以开源方式发布。 David曾在一个采访中回顾他创造RubyonRails的心路历程,其中最大的影响来自他使用PHP与Java的深度经验。一方面,他不喜欢Java那种冗长、僵化、导致JavaWeb框架既复杂又难以使用的设计方式,但他赞赏Java良好的结构完整性。另一方面,他喜欢PHP易于上手的友好特性,但也发现PHP过于混乱,难以提供顺畅的项目开发轨道。 当时的情况就是,必须在两种都不够好的方案中做选择:要么是易于上手却混乱不堪,要么是结构良好却难以使用。这种困境不禁让人联想起服务器级操作系统(例如稳定却难以使用的Unix)和客户端操作系统(例如简便易懂却经常崩溃的Windows和MacOS)间的经典难题。 当初人人都觉得现实就是这样残酷,只能陷入二选一的艰难抉择。但后来NeXT在Unix的坚实基础之上却开发出一套漂亮、易用且流畅的GUI。如今,服务器级Unix不仅能够运行起漂亮的GUI桌面,甚至还能搭载在大部分手机、智能手表当中。 所以事实证明,易用性和稳定性之间并不是非此即彼的关系。Web框架中的易用性和混乱性也是如此明明是两条并行的车道,为啥非得纠缠在一起? 所以,David看到的一个理想的平衡点是:既平易近人、又结构良好的Web框架。凭借其扎实、支持元编程的Samlltalk特性,再加上良好的Unix集成效果,Ruby证明了自己完全可以在配合Rails之后成为那个正确答案。 回到GitLab本身,当联合创始人DmitriyZaporozhets在决定开发自己的版本控制服务器软件的时候,他其实也是PHP开发背景,但他没有坚持自己熟悉的方法,而是选择了Rails。 对此,SidSijbrandij(GitLab联合创始人现任CEO)表示了肯定:Dmitry的判断是有先见之明(或许也有偶然性),但不管怎么说,GitLab也因此发展得不错。这里的部分原因可归功于Rails在良好架构与平易近人之间找到了平衡。我们不需要微服务 在1971年发表的文章《关于将系统分解为模块时,所应遵循的标准》中,DavidL。Parnas将模块化系统的优势总结如下: 有望缩短开发时间,因为各独立小组可以在每个模块上工作,彼此之间几乎不需要沟通。有望对单一模块做出重大变更或改进,且不影响其他模块。有望每次只学习系统中的一个模块。 FredBrooks在后来的《人月神话》中也强调了减少沟通需求的重要意义,认为额外的沟通开销正是在项目后期再增加人手,反而会进一步拖慢项目进度的主要原因之一。 SidSijbrandij认为,模块化虽然受到高度追捧,但也往往神秘莫测。因此,设计师们只能从当今世界上规模最大的软件系统中汲取灵感万维网。考虑到万维网的基本特性,它只能选择模块化构建方式。 使用独立的进程组织本地软件系统,再使用REST架构风格将各微服务组合起来,这样确实有助于通过操作系统强制划定模块边界。虽然这是种行之有效的严格模块化实现方式,但对应的成本也相当沉重。 SidSijbrandij进一步说道,目前分布式系统也面临着类似的实现挑战与高昂成本,人们迟迟找不到在分布式计算中保障性能与可靠性的有效方法。 简而言之,为了保证性能与可靠性,我们只能把原本以纳秒为衡量单位、且永不失败的函数调用,替换成以毫秒甚至秒为衡量单位、而且随时可能失败的网络调用。而且我们经常需要在几乎没有工具支持的情况下,跨多项服务开展跟踪,于是故障诊断变得更加困难。只有相当成熟的DevOps组织才能成功运行起微服务架构。总之,请大家明确一点我们不是谷歌,我们可能搞不定那么复杂的大规模运行体系。 而且即使是真能管理起来,还有另一个问题要注意:架构本身的复杂度,是不是已经超出了问题本身的原始复杂度。微服务并不能降低复杂性,所以想象中的模块化改进最终带来的很可能只是一团永远理不清头绪的乱麻。模块化单体架构 凭借着良好架构加平易近人、再加高效操作,Rails帮助GitLab开发出了模块化单体架构。模块化单体与分布式架构完全相反:它强调程序应该具有良好的结构、架构以及更高的模块化水平,其中每个进程都能稳定运行且尽可能保持简单。 SidSijbrandij表示,虽然将GitLab构建成单体最符合项目预期,但对于具体结构取舍也绝不能太过教条。总之,架构要为需求服务,而非需求为架构服务。 虽然Rails确实能帮助GitLab有效达成目标,但它也有一些缺点,特别是在性能方面。所幸的是,GitLab大多数代码库中只有极小一部分需要重视性能。所以我们用Go自己编写了gitaly守护进程以处理实际git操作,并使用PostgreSQL处理非repo持久性数据。SidSijbrandij坦言道。 SidSijbrandij表示,模块化单体架构把GitLab的核心开放(OpenCore)商业模式从理论真正转化为现实。尽管Rails本身并不能实现这一点,这是那些出色的贡献者和工程师们完成的,但Rails还是为这些成功奠定了基础。 开源运动的圣经《大教堂与集市》里提到,为了发挥开源的真正优势,贡献者必须能够随时访问源代码。另一方面,为了在接收各种贡献的同时保持架构完整性,就需要在开放组件和封闭组件之间划开定清晰的分界线、保证代码结构良好。 如此一来,有些人可能会想问,GitLab为什么不开发一套合适的插件接口呢?或者干脆建立基于微服务的服务接口?对于这类问题,SidSijbrandij的回答是坚决的:没必要。因为这些方法不仅会在部署和集成层面,显著提升源代码轻微改动的实现难度,同时也会带来过于严格的架构实施约束。谁能预测出未来一切可能的扩展点?根本不可能,我们也压根不打算给自己找这个麻烦。 凭借着这些无聊的模块化单体,用户及其他第三方开发商一样能为核心产品做出贡献、并帮助社区积累起巨大的影响力,同时保持着无与伦比的创新速度与可扩展性。或许在GitLab看来,有时候,平平淡淡才是真。 参考链接: https:about。gitlab。comblog20220706whywerestickingwithrubyonrails https:corecursive。com045davidheinemeierhanssonsoftwarecontrarian