十多年研发、架构经验老司机的技术选型哲学
扫描二维码
随时随地手机看文章
不谈具体技术,从更高层面看,技术选型应该怎么做?
写在前面
技术选型是一个很热门的话题,最近我看到自己的微信朋友圈有好几篇关于技术选型的文章,读者对这类主题的热情很高。在技术组织内部,技术人员经常会面临技术选型问题,有时候,技术选型还常常牵扯好几波干系人,相互之间还会产生争议,有的甚至还可能发展到派系斗争的地步。即便像我自己,已经有十几年研发和架构经验的老司机,不管是工作还是业余,有很大部分时间的思考都是深陷在 A 技术和 B 技术的利弊权衡之中,不能自拔。无论如何,技术选型说小了关乎项目和团队成败,说大了关乎企业业务的发展,不可小觑。
本文所表达的技术选型理念应该是与具体技术无关的,但是由于我个人的背景更偏向互联网后端的研发和架构,所以本文的视角更偏向后端技术的选型。
软件的本质
复杂性近年,云计算、微服务、容器和 DevOps 等新技术和理念层出不穷,技术人员对各种新技术的追捧热情也空前高涨,各种新技术微信讨论群也如雨后春笋般冒了出来。这是一个好现象,说明我们的开发人员多了,技术环境也日趋成熟,有点百花齐放的感觉。同时也让我有一点担忧,我担忧的是纯技术和工具论的抬头,也就是太过专注技术,认为技术可以搞定一切,反而忽略了软件研发的本质复杂性。回想当年,自己也曾是这样的技术狂热分子,EJB 刚出来的时候,我为 EJB 摇旗呐喊,Spring 出来的时候,我也曾一度是该技术的死忠,简单认为这些技术是银弹可以帮助解决所有的复杂性问题。
1986 年,人月神话的作者 Brooks 就提出,软件的本质复杂性(Essential Complexity)存在于复杂的业务领域中(用技术的话讲是业务领域建模复杂性),技术仅是辅助工具,它解决的问题是帮助将业务领域问题映射转换成软件实现,只解决次要复杂性(Accidental Complexity)。
作者同时指出,由于软件本质的复杂性,真正的银弹并不存在;也断言在十年内,没有任何一项技术或者方法可使软件工程的生产力提高一个数量级。30 年前作者提出的论断,今天依然闪烁智慧的光芒。人月神话已经出了 40 周年纪念版了,堪称软件工程的圣经,建议所有从事软工行业的朋友学习。除了业务和技术,我还想强调软件的本质复杂性同时隐含在企业的人、组织、流程和管理中,不容忽视。
架构师只有深刻理解软件的本质复杂性,才能站在解决实际业务问题的角度,更好的做出技术选型,否则易陷入唯技术工具论的陷阱。
使用成熟的技术
大部分公司都是商业组织,不是科研机构或者纯软件研发机构。商业组织使用技术是为了解决当下的业务问题,他们更应该使用成熟稳定的技术。
如下图,技术的使用有明显的生命周期,早期有创新者和早期使用者采用,我把这个阶段称为试水趟坑期,也就是说这个阶段技术不是很成熟稳定的,虽然尝新者可能占据一定的技术领先优势,但是他们常常需要以踩坑填坑作为代价;如果这项技术经过早期验证则会跨越鸿沟进入早期大众阶段,这个阶段技术会逐渐走向成熟,处于上升期,坑逐渐被填平,技术被大众所采纳;之后技术缓慢经过末期大众阶段,最终走向滞后期,一直到生命周期的结束退出历史舞台。
技术选型的一大智慧是不要盲目追求新技术,老老实实采用成熟稳定的技术,让那些喜欢追新的人去踩坑😊,等这项技术跨越鸿沟,进入早期大众阶段,你再择机投入,这样最保险和高效。当然作为技术人员,对新技术保持敏锐,提前预研是完全 OK 的,但是投入生产的话还是成熟稳定第一。
少即是多
一项新技术既有学习成本,又有维护(定制、监控、管理和运维)成本,新技术引入很容易,学好用好运维好却很难。一个不严格把控技术栈数量的公司,开发人员常常会各自为政,随意引入新技术,造成技术栈散乱,学习和维护成本高,技术栈知识无法共享,技术体系无法建立等问题,严重的会极大影响研发效率和业务规模化能力。
以我本人专注的后端基础框架领域为例,技术栈散乱还会直接影响系统稳定性,因为技术组件和工具太多,无法统一埋点和建立完善的监控体系。当业务量发展到一定规模,技术栈散乱还会给系统扩容跨机房迁移等带来巨大障碍。
在一些成熟的互联网公司,比如国内的阿里,国外的 Netflix 和 eBay 等公司,这些公司虽然财力和资源丰富,但是他们的核心技术栈(比如主流开发语言,框架和数据存储等)的数量同样是受到严格把控的。
新技术引入的基本原则就是少即是多,能不引入新技术尽量不要引入新技术,确实需要引入的话,也要有相应的新技术引入管理流程(一般由公司的技术或者架构委员会制定和把控)。
技术的先决条件
技术引入常常是有一些先决条件的,比方说最近比较热的微服务架构,按照马丁福勒的说法,微服务有如下先决条件:
快速的环境提供能力(Provisioning)能力(通常指 IAAS 层能力),
基本的监控能力
快速的发布能力
初步的 DevOps 文化
马丁特别指出“你必须长足够高才能考虑微服务”,在这些先决条件没有满足之前,直接推行微服务会面临巨大落地挑战。
同样,容器技术的引入对应用也是有要求的(参考附录 18.1 ~ 12 Factor App),而 DevOps 研发模式的引入不仅对基础技术和架构,研发人员技能,甚至组织架构和企业文化都是有很高要求的,在没有满足先决条件前,这些新技术或研发模式都会面临巨大的落地挑战。
作为管理者或者架构师,在引入一项新技术之前,要充分调研了解新技术的先决条件,不能盲目引入。对于确实需要引入但是目前还不满足先决条件的,需要做好阶段性规划,先打好基础,再适时引入新技术。
来自大公司的技术
大公司采用的技术,未必适合中小公司。大公司有足够的资源、人力和时间,可以投入一些前沿和重量级的技术(在 BAT 级别公司,为重量级技术投入几十甚至百人以上的研发团队是很正常的事),但是中小公司资源有限,不能盲目跟风,应该选择和自己发展阶段相适应的技术,否则不仅不能帮助业务发展,反而会给业务发展带来阻碍。
技术的文化特性
技术常常带有文化特性的,在国外流行的技术,在国内未必流行。一个例子是如 Scala 这样的函数式语言,Scala 在国外互联网公司是有一定流行度的(Twitter、Linkedln 等),国内虽然有不少簇拥者,但是始终只是小众,无法流行,究其原因,国外很多大学教授的第一门编程语言是采用函数式语言的(例如美国 Berkeley 大学的 CS61A 是基于 Scheme 函数式语言),国内大学几乎清一色采用 C/C++/Java 等命令式语言作为第一门编程语言。也就是说函数式语言在国外是有文化基础的,所以容易流行,国内没有这样的文化基础,所以难以流行。
我们在选型的时候,尽量采用在国内有文化基础,已经落地开花的技术,盲目追求国外新技术有可能文化不适应反而难于落地。
同样的,在 A 公司流行的技术,在 B 公司也未必流行。比方说 BAT 三家公司所采用和后面演化出来的技术栈就明显不同,这同样和三家公司不同的业务领域和文化基因有关系。我们在做技术选型的时候,也要考虑公司的文化特性,如业务模式、已有技术生态和开发人员技能等现实情况。
开源还是第三方软件提供商的技术
互联网时代,传统的企业软件供应商开始明显地走下坡路,企业越来越多的采用开源技术来开发他们的业务系统,开源软件具有如下优势:
成本,商业软件一般有昂贵的 license 费用;
避免供应商绑定 (vendor lockin);
灵活的定制能力,现代企业需要灵活的软件定制能力以应对快速变化的用户需求,商业闭源软件常常缺乏这种能力;
社区和生态,投资具有良好社区和生态的开源技术是企业技术选型的最佳实践。
即使是开源软件,这里面有一个很重要的闭环问题。有些开源软件是一线互联网公司成功落地后再开源出来的,比如阿里的 dubbo,点评的 CAT,这些公司本身有场景,内部大量使用,也就是说内部已经形成反馈闭环,开源出来和社区又形成了一个更大的反馈闭环。有一些第三方软件供应商提供的开源软件,其实他们本身是没有业务场景的(或者场景非常有限),主要靠社区使用后才能形成反馈闭环,对于这类开源软件的使用需要谨慎,如果选择的话,可能需要一起帮忙踩坑形成社区反馈闭环。
使用能掌控的技术
技术和武器一样,并不是说越先进越好。就像航空母舰和 F117 这样的尖端武器,确实非常厉害,但是掌握和部署运维这些武器的成本非常之高,如果你的团队没有足够的能力运维和掌控这样的武器,那么这些武器摆在家里充其量只能是摆设,不能形成战斗力,有时甚至还会拖累业务。
在大数据领域重量级武器尤其多(Hadoop, HBase, Spark, Storm…),很多产品既消耗机器资源,部署和运维也非常复杂,如果某种重量级武器被应用在关键业务上,一旦出问题,团队能不能 hold 住是要重点考虑的,否则可能会死得很难看。架构师需要根据业务阶段规模,团队规模和技能水平,综合评估后再考虑引入,如果团队能力还不足以掌控某种重量级技术,则可以先从轻量级技术开始。
剑要交给懂得挥舞
它的人同一种技术,不同的人使用,可能会得出完全相反的结论。比如 Cassandra 这种 NoSql 分布式数据库,在 Netflix 有比较成功的应用,Netflix 从 2010 开始将系统迁移到 AWS 云中,并开始将大部分业务数据从传统 Oracle 数据库迁移到 Cassandra 上,Netflix 的前架构总监 Adrian Cockcroft 把他们技术升级的一大成功功劳归结为采用了 Cassandra 这种天然支持跨数据中心的分布式数据库。但是,在 2012 年时候,Digg 在网站改版升级过程中也试图将传统 Mysql 数据库迁移到 Cassandra Nosql 数据库,结果导致 Digg 网站问题频发,最后技术副总裁 John Quinn 主动卷铺盖走人。事后,有人将问题归结为 Cassandra,这就是著名的 Digg 使用 Cassandra 遭遇滑铁卢事件。有人在 Quora 上发帖提问“Is Cassandra to blame for Digg v4’s technical failures?”[附录 18.2],回帖中有知情人士出来澄清:把 Digg 网站升级失败归结为 Cassandra 完全是转移注意力(red herring),背后的真正原因是工程管理和架构的问题(poor engineering management and architecture),简单讲就是人的问题。
我曾经在 2013 年左右在携程框架部工作,当时有一个很重要的框架产品叫分布式数据访问层 DAL,很多团队都跃跃欲试要做,但是当时的 CTO 一直没有正式启动这个项目,理由是没有合适的人。这个事情拖了有一年之久才找到合适的人,这个项目才启动并逐步落地,现在已经是携程框架的关键基础设施,承载携程大部分数据库访问流量。
对于一些重量级的,处于业务关键链路上的产品,如果它重要但不紧急的话,一定要找到并交给能搞定它的人。把一个重要产品交给一个不合适的人,不仅不能解决问题,后续还常常会制造问题。设想一下业务的关键链路上的某个关键产品质量不过关,问题频发,但是业务已经跑在上面无法简单替换,这是让人很无奈的事情,很多架构老司机对此场景应该深有体会吧。
浪费是创新的副产品
即使在同一个公司中,在主流技术栈的基础上,不同团队适当引入一些不同的技术栈,比如一个公司主流的技术栈是 Java,有些前端团队会尝试用 Nodejs 开发应用,有些大数据团队会采用 Python 开发应用(Python 里头有很多数据分析库)。这些做法和第二点提出的少即是多并不矛盾,根据业务场景的需要,适当引入一些互补的技术栈,适度冗余可以促进团队创新。
再举个例子,阿里在发展的过程中,曾经发展出两套技术体系,一套是淘宝体系,一套是 B2B 体系。有一段时间内,两套体系并行发展,团队之间既竞争也相互借鉴,形成一个良性竞争的技术生态。据说 Dubbo 最早就是 B2B 搞出来的,淘宝后面又搞了一套 HSF(未开源),Dubbo 和 HSF 之间相互借鉴所以功能比较类似,阿里在 2014 年上市前对技术栈进行了整合,集团统一使用 HSF,Dubbo 则继续活跃在开源社区,成为中国开源软件的一个传奇,它的成功一方面源自阿里技术的沉淀,另一方面也是 B2B 和淘宝相关团队思路碰撞融合的结果。
技术的宗教信仰很多技术人员对他们投入时间最多最熟悉的技术栈比较热衷,有些甚至能上升到宗教信仰的程度,不同派系还会有相互鄙视的情况出现(据说 PHP 是最被鄙视的语言),有的还会发展到派系争斗的地步。之前我在一家互联网公司,在容器 PaaS 平台选型上出现了两个派系,分别被戏称为 K 党和 M 党,K 党主张引入谷歌推的 Kubernetes,M 党主张基于 Mesos 做定制,两拨人都非常坚持互不相让,争得不可开交。
其实我个人对技术的宗教信仰是非常排斥的,它是一种技术视野狭隘的表现,技术本身没有绝对的好坏之分,只有适用场景和利弊之分。但是,技术的宗教信仰是一种客观存在,有经验的架构师在做技术选型时需要考虑这一层面的因素。
通过背书做技术选型
和一线资深的架构师或者技术专家交流,获取技术选型的专家建议,是一种比较靠谱的技术选型策略。专家是一种背书,他们踩坑无数才成为专家,对很多技术有一手的实战经验,是真正 know how 的人,所以他们给出的建议一般都比较接地气。
大公司是一个很好的背书,比方说 Google,当初它推出 Kubernetes 的时候,其实我一开始看过架构设计之后是对这个产品嗤之以鼻的。但是 Google 的强大背书和号召力摆在那里,用户深信 Google 用脚投票,一开始架构设计不好不是根本性问题,只要有足够的用户形成社区闭环,这个产品就会不断长好长大。目前 K8S 已经基本垄断了容器 PaaS 平台市场,它的成功很大程度归结为 Google 公司的背书影响力。所以,绑着技术型大公司这个背书做技术选型,大概率不至于大错(当然不是绝对)。
Github 上的星的数量也是一个重要的技术选型参考,同时还有项目代码和文档更新频度(尤其是近期),这些指标直接反应开源项目的社区活跃度和生命力。
实践出真知
实际评估一项技术时,最靠谱的做法还是详细研究其文档,做一些样例和测试,对性能有要求的则必须实际做充分压力测试获得真实性能数据。对于开源的产品,如果处在业务的关键链路上,则建议把代码拉下来通读梳理一把,深入理解其内部设计和架构,有的还需要根据企业业务场景适当做一些定制。
通过初步评估,仍需要寻找一定数量非关键试点项目(pilot project)做试水躺坑,经过初步生产验证,才可以考虑逐步扩大生产普及的规模。
实践出真知,对于那些长期在一线实战和积累的架构师,他们最终将获得良好的技术选型的 sense 和对新技术的敏锐性。
技术的落地
简单回顾下我国辽宁号航母的历史:1999 年中国购买了瓦良格号,于 2002 年 3 月拖回大连港,2005 年 4 月开始由中国海军继续建造改进,2012 年 9 月正式更名辽宁号,交付中国人民解放军海军,2013 年 11 月,辽宁舰从青岛远赴中国南海展开为期 47 天的海上综合演练,标志着辽宁号航母开始具备海上编队战斗群能力。我国前前后后花费超过 10 年才让辽宁号航母初步形成战力能力。
技术和武器一样,你引入一个技术是一码事,真正落地形成战斗力或者说产生业务价值完全是另外一码事。技术一般有落地周期:引入,定制改造,小规模试点,再到逐步扩大生产规模,这个周期可长可短,对于一些基础性和重量级的技术,或者涉及大规模遗留系统升级改造的技术,一般周期比较漫长(可能时间跨度长达 1 年甚至几年),对于这类技术的引入和落地,架构师需要高屋建瓴,通盘考虑,制定落地计划,分阶段推进技术的落地。
定制、自研还是购买
这个问题比较复杂,很难一概而论,和企业的业务和团队规模,架构甚至文化等诸多因素有关系。我个人遵循的两个简单原则分别是:
如果不是你最擅长,也提供不了差异化的竞争优势的技术则直接用开源或者购买。小心 Not Invented Here 症状,避免重复造轮子,始终牢记达成业务目标才是重点。
当企业的业务和团队规模达到一定阶段,对于处在业务关键链路上的核心技术,必须要有一定的定制甚至自研能力。创业公司尽量用开源或者购买云服务,验证业务模式是第一优先;当你的业务模式获得验证,业务和团队达到一定规模,则需逐步考虑对核心业务链路上的技术进行定制甚至自研;如果你成长到接近 BAT 那个量级,那么大部分核心技术必然是定制甚至自研的,否则无法支撑那个规模。
写在最后
本文仅限个人经验视角,技术选型理念仅供参考借鉴。每个企业的具体上下文(业务场景,团队组织,技术架构等)各不相同,每个架构师的背景经验也各不相同,大家要结合实际自己做出选型,没有最好的技术,只有相对较合适的技术。另外,好的技术选型是相互借鉴甚至 PK 出来的,欢迎大家讨论,给出自己的技术选型思考。