技术选型背后的思考
笔者在工作经历中曾多次遇到关于技术选型的问题,而每一次的技术选型都无一例外的纠结、反复。经常出现的现象是,在项目推进的过程中多次反复修改技术选型,客观上造成了效率的降低,而当最终选定某一个选型时,又觉得这个结果似乎是显而易见的。为了避免反复纠结造成效率降低,笔者觉得有必要总结下选型中常见的思考方式,方便以后参考。
每一次技术选型都是在特定的需求场景下,结合各种各样的主观、客观因素,最初一个最优的选择。很多人觉得技术选型时只要选定的技术产品满足业务需求就可以了,但笔者经过多次观察发现,满足场景需求只是一个前提条件,真正令人纠结的点往往在需求本身之外。
下面按照三个部分梳理了选型中要思考的几个方向:技术特性、技术管理和取舍之道。
1 技术特性
了解各个技术选型的技术特性是一次选型的开始,也是必须做好的一部分工作。笔者经验性的发现,往往选型过程中的反复、纠结,都是由于一开始并没有真正体系化的将每一个选型理解透彻。还是延续上面的说法:了解一个技术是否能够满足场景需求只是一个前提条件,除此以外还要了解的还有很多。下面笔者将结合个人经验,一一说明。
1.1 满足场景需求
这个点其实是老生常谈了,做技术选型当然要首先考虑各个选型是否能够满足场景需求。但是这里面有几个容易被大家忽略的点,值得一提:
- 了解能否满足需求,更要了解是如何满足需求的
对于一些相对简单的需求,可能会有很多技术选型都可以满足。但是实现方式细节上的差异,会导致后期场景迭代过程中引入天翻地覆的变化。据一个比较蠢的例子,某团队需要一个消息队列,那么到底用kafka还是RocketMQ呢?消息队列是一个非常简单的需求,但是不同使用场景的迭代过程中的对消息队列的追加需求会越来越多。能否持久化、是否支持EXACTLY-ONCE模式、能否按时间戳复现消息、读多还是写多、是否支持事务等等,这些都会影响选型上的倾向性。 - 很多时候,所有技术选型都能满足“最低需求”,但是没有一个技术选型能“完美的满足需求”
需求不明确的初期,往往会发现:世界这么小,却能找到这么多满足的要求的技术。但需求逐渐细化后,又会发现:天下这么大,竟没有一个技术选型能完美满足所有需求。遇到这种问题,其实思路就两种:一种是“忍”,体现在凑合用或者绕开不完美的部分上;一种是“干”,那就是想办法进行开发。
1.2 完善的技术体系
当一个技术选型基本满足了场景需求后,作为一个技术人员,还要思考很多场景之外的问题。比如:
- 如何监控、运维
一个优秀的技术选型会在设计阶段就将运维和监控等考虑在内,方便技术使用者可以清晰的了解到系统的运行状态,方便问题的排查。这些配套的工具是否完善对于一个技术人员来说是至关重要的。个人觉得Flink之所以如此风靡,除了它的技术层面的成就外,也离不开它原生完备的监控运维可视化工具。 - 周边技术体系
一个大型的技术选型往往绑定了很多其他的小的技术选型,比如Flink绑定了RocksDB,很多google的开源技术都绑定了protobuf等。除了关注技术选型主体外,还要注意分析下主体以外绑定的其他选型是否能够很好的融入已有的技术体系。
1.3 机器资源评估
技术选型上线后,必然会引入机器资源的开销。不同的选型在性能上的表现可能千差万别。如:rt、cpu、内存占用、网络IO、磁盘IO、存储开销。这里重点要提到的是,上述指标不能单一的看某一项指标,而是要整体评估所有指标。
举例说明:
假设要对两个数据存储技术进行选型。线上一台机器有4T磁盘、500G内存、96核CPU、2GB/s网络带宽。技术选型A 磁盘占用1T,内存占用200G,满负载运行时CPU 40%,网络IO 1GB/s。技术选型B 磁盘占用0.5T,内存占用100G,满负载运行时CPU 20%,网络IO 2GB/s。
单从存储开销、内存占用、CPU上来看,B选型完胜。但是由于选型网络IO做的不好,导致IO成为瓶颈。如果考虑到docker混布的话,一台机器可以布署两个A实例,但是却只能布署一个B实例。由于网络IO的瓶颈效应,导致选型B的节省的存储开销无法体现在节省机器资源上。
1.4 技术产品的稳定性
要不要做第一个吃螃蟹的人?这是一个问题。
一千个读者眼中有一千个哈姆雷特,但是一千个开发工程师在上面这个问题上却只能给出两种答案:要或不要。新兴技术总是吸引人眼球,并勾引着技术人员的好奇心,让后者有一种先睹而后快的冲动;但是内心理性的小人又在反复揣摩,为了满足一时的好奇心搞出个故障被扣工资甚至跑路,把孩子的奶粉钱都搞没了到底值不值得。一个技术选型是否有长时间稳定运行的先例,这一点对于选型者至关重要,但是如果所有人都因这么想而不愿意尝试新技术,那又何来的长时间稳定运行的先例呢?
个人冒昧分析,抉择的关键在于业务场景是新兴业务或是长期稳定业务、选型失败的后果是否严重、新技术提供的增量价值是否能打动使用者等因素,这里因业务而已,不做结论性说明。
2 管理模式
在工作中完成一次技术选型,绝不能简单的仅仅从纯技术角度出发思考。一次看似偶然的选型会给后续工作带来方向性的影响,这里的影响指的不光是技术层面,更多的是管理层面。这就如同在公司一次公开的项目招标中,考虑绝不仅仅是解决方案本身的优劣,更重要的考量方案的成本是否符合预期,方案提供方的实力、诚信度,甚至还要从商业模式上去思考未来的合作方式是什么,等等。而这一切,都能在一次技术选型的过程中,得以体现。
下面就从几个主要阐述下选型中遇到的常见问题。
2.1 时间成本与人力成本
再决定技术选型时,除了机器资源等成本以外,一定不要忘记了,作为一个团队投入的还有时间成本和人力成本。在一些争分夺秒的项目中,哪种选型能够达到快速迁移的目的,几乎就可以确定哪种选型会胜出。如果不得不使用一个复杂的技术,而时间有十分紧迫,那么唯一的方式就是通过加大人力投入来实现。
是什么决定投入成本的规模呢?是收益。不仅仅是完成一个项目的短期收益,更要衡量用该技术手段带来的长远收益。因此会有一个有趣的现象,有时通过技术选型就能看出一个业务线的盈利能力。
2.2 维护团队
一个技术选型要长期、稳定、完全的在生产上服务,离不开背后的维护团队。一个维护团队小则可以对使用过程中遇到的疑难问题进行解答,大则可以临危受命解决技术选型引入的线上故障。因此,在进行技术选型时,要考虑如下几点:
- 是否有维护团队,团队是否稳定
在对比同是来源于公司内部的技术选型时,要调研技术选型背后的支持团队是否仍然稳定存在。一个稳定的支持团队至少说明了这个技术选型对公司十分重要,因此它出现的任何问题都会得到高度重视。 - 维护团队的技术能力与合作意愿
由于不同公司各种组织架构划分模式,导致并不是所有的维护团队都是具有强烈的合作意愿的。一般情况下,成熟稳定技术的维护团队在解决稳定性问题和技术答疑上积极性较高,而在支持新feature和使用教学上热情有限;新推广技术的维护团队在支持各种新feature的工作上有很强的合作意愿。 - 维护团队与自身团队关系是否密切
维护团队和自身团队的利益绑定关系是否牢靠,leader之间是否同出一门,这等等因素都会影响日后寻求帮助时的便利性。此间细节,往往会在不经意间影响业务的稳定性和迭代效率。
2.3 新feature的开发模式
在业务迭代过程中经常会出现对技术上新的feature需求,此时若需要在选型上进行开发,则需要寻找到一种技术开发团队的有效合作方式,常见合作方式有如下:
- 提需求
这种模式就是简单的提需求,由维护团队来开发,极大降低人力成本,但是可控性不强,如果和未还团队之间没有较强的利益绑定关系,很容易出现时间拖延的情况。同时,这种模式带来的另外一个问题就是,自身团队的成员对技术了解十分有限,难以获得成长。 - 共建
这种方式多见于新推广技术。业务团队提供具体的业务场景,技术团队进行技术抽象与打磨。在合作的同时,业务团队的成员也有机会参与到技术开发中,提升技术储备。这种方式是共赢的,但是对时机和人事环境的要求相对苛刻。 - 自主研发
可控性最强,团队技术储备增长最快。但需考虑是否存在重复建设,是否存在增量价值,能否孵化出有亮点的结果产出。
在笔者实际工作经历中曾遇到过如下一次选型。
选型一:基本满足业务需求,技术成熟,很多业务线都在用,但是技术内部对外是一个黑盒,而且是一个与本团队关系疏远的团队在维护
选型二:需要一定的开发才能满足业务需求,技术相对成熟,维护团队与本团队是兄弟团队
选型三:完全满足业务需求,是一个新型技术,团队有能力自主研发,但周边设施并不是十分完善,与选型一存在大量的重复建设
在选型过程中经历了各种纠结,最终由于不能重复建设而放弃了选型三,由于兄弟团队无法支持定制开发而放弃了选型二,归根结底还是选择了选型一。
3 取舍之道
选型的核心在于取舍,取舍也是体现一个技术人员技术视野和综合判断力的关键决定。笔者结合自身的一些思考,提出了以下经验性结论。
3.1 技术特性的取舍
如1.1节中提到的,很多时候会出现没有任何一个技术选型“完美满足”业务需求。此时除了进行定制开发一种思路外,还可以选择绕开问题,曲线超车。这里的“绕开”并不是逃避,而是集中把精力放在解决关键问题上,而对于不那么关键的瑕疵,可以有多种方式解决。
举个例子,加入现在有一个集群A,它进行计算后会将结果发往下游集群B,集群B收到计算结果后会将结果写入数据库。我们要在集群A到集群B的通信方式上进行一次选型。直观上,我们需要一个消息队列来连接集群A和集群B,集群A是生产者,集群B是消费者,并且需要考虑如何保证集群B的各个机器之间读到的消息不能重复。但是,如果我们手边并没有合适的消息队列选型,我们该怎么做呢?有两种方法可以推进解决这个问题:
- 继续寻找/定制开发
我们可以继续寻找合适的消息队列选型,或者选择自己开发一套合适的消息队列。这样时间成本上和人力成本上必须加大投入。 - 绕开问题
消息队列提供的能力不光是通信,还有持久化、保证顺序、EXCECTLY-ONCE等能力。但是假如我们业务场景并不需要这些附加能力,而是仅仅需要“通信”这一个功能,那么其实我们完全可以使用“rpc单向调用”来完成通信。集群A发送rpc请求,集群B收到请求后立刻返回一个空结果(反正集群A也不关心返回内容),然后进行些数据库操作。
上面提到的案例并不是鼓励大家绕开问题,事实上,如果所有的人都绕开问题,就不会出现如今这么多优秀的技术选型。我们要做的是:把精力放到核心问题上。如果开发一个消息队列是我们要解决的核心问题,那我们绝不能绕开它,而是要知难而上;但如果我们是要完成一次业务架构的选型,就不应该把过多的注意力放在细枝末节上。
3.2 技术管理的取舍
由于笔者并没有实际参与过管理岗位的工作,在这里只能从一个被管理者的视角给出一些观点。在工作中,解决历史遗留问题(俗称填坑),是最没有成就感的工作,而且“日后填坑”的成本远高于“当时填坑”。日积月累,只能通过“爆破”(整体重构)这种巨额成本的工作来解决历史遗留问题。看上去破旧不堪的系统仍然继续在线上运转,每天耗费大量人力用于维护系统正常,这些都是多次选型不慎引入的长久隐患。因此,笔者认为,在技术选型时,维护团队的稳定性、技术产品的稳定性等因素的重要性要远大于较低的迁移成本的重要性。
如果感兴趣,欢迎关注微信技术公众号
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。