好久没写公众号文章了,一直想着等后面不忙了再写,但突然想起事情是忙不完的,所以还是决定一定要给自己留些时间去总结、去思考。(而且近客观事实上确实要没那么忙了,所以正好借此机会来做个总结。)是的,我们耗时了几个月,投入了数百人月,重构了一个很大的系统。在此期间,实践了很多本人的想法,也从中学习到了很多。今天的文章,就让我来讲述整个项目重构期间发生的故事,不光光讲技术,更要讲的是工程实践。
物联网因其影响范围之广吸引着各行各业的关注。当前物联网行业的发展在一个什么位置上呢?什么是物联网连接数呢?每一个在线物联网设备都算一个连接。所以物联网连接数也可以叫设备在线数。物联网连接数进一步细分,可以分为蜂窝连接数和非蜂窝连接数。非蜂窝连接,指的是蓝牙、Zigbee这类泛连接,这类连接一般出现在智能家居场景中,用于短距离通信。蜂窝连接,指的是通过通信服务运营商的蜂窝网络进行的连接,用于长距离通信。从全球来看,目前物联网连接数大概有100多亿,其中包括了蜂窝连接和非蜂窝连接。在物联网行业,目前非蜂窝连接还是占据大多数,大约占据70%-80%左右,蜂窝连接大约占据20%-30%。所以从全球来看,蜂窝连接大约在20-30亿左右。因为个人所在的行业,对蜂窝连接了解得比较多,当前中国物联网蜂窝连接数超过10亿。在这背后,承载着中国超过10亿物联网蜂窝连接的是各大运营商的物联网连接管理平台。而这其中,我们的物联网连接管理平台承载着将近3亿的连接。可以看出,各大运营商的物联网连接管理平台,是物联网时代名副其实的基础设施。物联网连接管理平台,就是本文的主角,就是我们重构的对象。物联网连接管理平台处于物联网系统中承上启下的位置
上图是物联网连接管理平台在物联网系统中的位置,以及它所具备的主要功能。简单介绍了一下系统背景,下面就开始我们的项目重构之旅吧。
1
开始
系统好好的,没人想着耗时耗力去重构,所以让我们投入了如此多的时间精力来做重构,起因是什么呢?起因是当前我们的物联网连接管理平台已经无法满足我们的业务增长需求了。是不是很官方的一句话?既然想做总结,想做思考,那肯定不能浮于表面。我下面就来深挖下之前的系统是如何无法满足我们的业务增长的。上述软件生命周期应该是适用于所有软件项目的,包括做软件外包的2B公司、做互联网产品的2C公司,只不过这些公司在每个阶段的投入或者关注度有所不同。对于一些小型的、刚起步的互联网公司,他们可能一开始有个Idea,然后团队讨论讨论就进入到实施阶段了。是的,你没看错,可能有时候还更简陋点,专业的团队都没有,就几个人罢了。实际上很多目前来看取得很大商业上成功的公司,其实一开始并没有做什么详尽的市场调研、规划,想做就做了,终也做成了,说无心插柳柳成荫可能不太合适,因为他们开始确实是想做成点什么,不过比起很多大公司详尽的市场调研、规划,终也没做成来讲,也有那么点意思。而对于一些专业的软件公司,特别是做2B项目的公司,首先他们的团队规模将会更大,专业度也会更强,他们的立项是伴随着软件合同的签订开始的,他们在规划阶段就会投入很大的精力,投入诸如项目范围、时间、人力的规划等,然后终进入到实施阶段。说了这么多,实际上终都是殊途同归,软件项目终都会来到维护阶段,该阶段也是软件项目生命周期中长的阶段。软件工程和其他项目有着很大的不同,其中大的不同在于维护阶段的不同。拿房地产来举例,开发商建好房子交付后,物业进场就进入了维护阶段,但不论怎么维护,当初建的时候是几栋几层楼,终还是几栋几层楼,物业不会把当初的六层小洋房维护成十几层的小高层。但软件工程的维护就不一样了,当初是个“小平房”可能过几年就维护成了“大教堂”,也可能终维护成了“大茅厕”。所以软件项目进入维护阶段,才是真正考验团队能力的时候。可维护性差,意味着新功能特性添加的困难,意味着糟糕的代码质量,意味着项目可靠性差,问题频发,意味着性能的不足。可维护性差,足以作为项目需要重构的大理由了。想想计算机的诞生才几十年,它对我们今天的社会生活产生的影响是多么的巨大。对于漫长的人类历史来说,几十年产生如此大的影响,不得不说它的发展是爆发性的。对于很多公司的业务发展也是一样的,短视频的爆发,自媒体的发展,直播带货也就是这两年。虽说我们的系统在建设之初就预留了一定的容量,但随着物联网的发展,当初预留的资源已经无法满足当前的业务需求了,而且当初的系统架构可扩展性也很差,导致即使增加资源也无法线性扩展。在我看来,物联网还远未达到爆发的程度,预则立,不预则废,为应对物联网可能迎来的爆发,需要一个可扩展的系统架构,从这一点看,重构也是必须要进行的了。对于分布式系统来说,可观测性对于问题的排查及定位的重要性不言而喻。日志、调用链、指标等监控内容,对于原有系统是部分缺失的,这也导致了问题的排查与定位的困难,鉴于以前系统的可维护性差,也很难给它添加上这些,所以需要重构了。当然除了上述问题之外,我们系统还有很多其他的问题,诸如代码质量差,文档缺失等等,当然我愿意把此类问题都归入到可维护性差上。鉴于目前系统存在的上述问题,我们决定开始重构。
2
项目规划阶段我们主要做的事有如下几个,范围规划、时间规划、团队组建以及各类规范的制定。我们经常说勿忘初心,在做什么事情之前一定要弄清楚自己为什么做,以及要把事情做成什么样子,这件事很重要。因为初心不同,事情的结局会大不相同。不知道自己为什么出发,走着走着就容易迷路。在盘点了当前系统存在的问题之后,我们决定启动新项目的重构。既然开始了,首先要确认的就是目标。新系统要重构成什么样子的呢?这是我们需要回答的个问题。经过我的思考加上霎那间的灵光一现,我确认了新系统重构的目标:高性能、高可靠、可扩展、可维护、可观测的下一代物联网连接平台。确认目标对于做事来讲真的是太重要了,在整个重构过程中,作为整个系统的架构师,我都在时不时的回过头来重新审视我们的目标。目标的确认,也让后面的项目决策有了很多的原则可指导。这在后面会不断得提到的。确认了目标之后,还需要确认时间,咱们要花多少时间去完成目标。毕竟不能无休无止地做下去,一定要有个时间。实际上时间的确认可长可短,毕竟可以加人力吗,人力多的话,时间就可以短一些,人力少做的时间就长一些。(但是随着项目的实施,后面我也发现了在时间规划上,软件项目并不是这样的,加人力,但拖慢了项目进度的事,也是遇到了。)在项目的时间规划上,还有一点要注意的就是要设立项目节点及里程碑,节点及里程碑的设立实际上就是把大的目标拆分成小的目标,对于团队的节点达成及激励都是有一定的作用的。团队组建有一点非常重要,就是分工,团队中一定要分工明确,因为分工可以让相关人员更专注于自己的领域,这样才能更专业,更有效率。分工明确了,职责也就明确了。切记合理的团队分工,是迈向成功的关键一步。系统架构组:负责系统整体架构,关键疑难问题解决,架构的持续优化;在规范方面,整个项目进行过程中,我们团队制定了代码规范、开发流程规范、接口规范、分支规范以及沟通规范等。具体的规范内容就不再贴出来了,但这里想说明的是规范的重要性,以及制定规范的几点注意事项。团队几十号人,后面将会构建几十甚至上百个微服务,没有规范就问你可不可怕。制定规范很重要,让团队所有的人都遵守规范更重要。下面要讲的就是规范制定的注意事项了。点需要注意的是,不要一言堂。各类规范当然得有一位主导人,负责规范的初版编写,毕竟不能所有的点都由团队所有人来讨论确定,没这个必要也没这个时间,但是终版的确定一定要经过团队所有人的讨论及确认,记住是所有人,所有需要遵守这个规范的人,哪怕是外包人员。**有参与感才有责任感,有责任感才会遵守规定。**这里从整个规范的讨论到终确认,需要开很多次会,花很多时间,但是这个时间跟团队不遵守这个规范或者根本不认可这个规范继而导致后面项目出现的各类问题所花费的处理时间相比,成本还是低的多的。第二点需要注意的是,规范要简单可行,贴合实际。想一想你自己都不想遵守的规范,别人为什么要遵守?第三点需要注意的是,规范要统一放在一个地方,方便查阅。整个项目中,我们的所有文档都是在线的,实际上这是我们的项目沟通规范。这样的好处是有一个地方可以统一管理各类规范,人手一个Word文档,后面文档更新了怎么办?这简直是一个分布式一致性问题了。统一放线上还可以方便后面新加入的团队成员阅读。项目的规划阶段我们就大概做了这么多事,没有一开始就着急去做设计、去编码,先把准备工作做好,后面会走的更快、更远。慢就是快。
3
实施
项目实施阶段,我们做了系统总体架构设计、微服务拆分设计以及启动系统的编码实现。在系统的总体架构设计及决策上,实际倒是没有花什么时间与精力,作为业内的主流架构,微服务架构是经历过实践检验的,并且生态环境也很完善。所以新系统采用微服务架构是团队的共识。当然微服务有利有弊,有它的优点也有它的挑战,这不在本文的讨论范围。确认了系统整体微服务架构,下面要做的就是微服务拆分了,在这上面还是花了些时间的。在微服务的拆分上,有一些基本的原则,比较常见的原则有:基于功能拆分的原则、按照服务变更频率拆分的原则、按照安全要求拆分的原则、按照性能拆分的原则等。但在我看来,微服务要想拆分得好,除了根据这些基本原则外,重要的一点就是架构师一定要对业务有非常深入的了解。这里不是指某一处业务,而是需要从全局视角,对整个系统的所有业务都有非常深入的了解。这对于一个复杂的系统来说,是一个不小的挑战,但我们的系统可不是一般的复杂。作为系统架构师,我花了两周时间,深入各个业务模块,与各个业务负责人及开发人员进行了深入的沟通,终也只能说是对整个系统的全局业务有了个基本的了解,远远没达到理解的程度。究其原因,并不是我不行,而是我们的业务真的不是一般的复杂。(有熟悉运营商业务的同学应该可以理解。)在梳理了两周之后,我决定不再耗费时间了,不如先做再说。首先,我们先确定了整个微服务拆分的总体指导原则:前期先粗粒度,不同服务有相同业务逻辑时,再拆分出单独服务。明显独立的服务,可以先拆分。有了原则之后,后续做事就有规则可循了,可见原则的重要性。基于上述原则,我们前期基于业务首先拆分出12大微服务群,每个微服务群终可能包含数个微服务,但前期是粗粒度,所以每个微服务群暂时都按照一个微服务来构建。微服务拆分初步完成,每个服务便开始轰轰烈烈地进入开发了。工程实施阶段时间长,遇到各种各样的问题也多,这期间的故事也很多。软件工程不同于其他项目,没有一个统一的限制或约束。比如建筑学,有力学为基础指导。这也导致了软件工程对于特定问题,解决方案之多,选型之多很容易在团队间产生分歧。对于特定问题,实际上每种方案都有各自的优缺点,在很多情况下都没有对错之分,可以说是用这种方案也行,用那种方案也行,都能解决问题。但终到底用哪个呢,这是需要有人来做出决策的,而且要能说清楚为什么要用这个而不用另一个。那么如何在有意见分歧的时候做决策,我个人的经验是你们的团队一定要有自己的原则,或者不妨说是团队负责人一定要有自己的原则。方案没有对错之分,选择哪一个就要依赖相应的原则了。举个例子,简单性原则是你们在构建系统时所遵循的原则,那么所有可能会引入复杂性的方案都可以被否掉了,虽然它们可能也符合一定的场景,但并不符合你们的原则。发生意见分歧没问题,但团队一定要有相应的原则来做指导。至于原则是怎么来的,很多情况下来源于团队的负责人,但一定要经过团队充分的讨论共同确认下来,有参与感才有责任感,这样大家才会去遵守相应的原则,才会认同你的决策。当然,这里额外说一句,可能有时候一些问题并没有明确的原则来指导,可能只是依靠自己的直觉,这时候你也需要有魄力去拍板,去让大家相信你的判断。如何让大家相信你的判断,并且按照你说得去做呢?这就依赖你的个人魅力了。想象一下我们现在在工地搬砖。总共有两万块砖,假设一个人一天搬两千块砖,那么一个人把所有砖搬完需要十天时间,两个人呢?五天。五个人呢?两天。这应该是没有什么问题的。但是在软件工程实施中,是这样吗?一个功能点,假如一个人实现要花十天时间,两个人呢,五天能完成吗?实际情况下,可能两个人花的时间要比一个人花的时间还要长。为什么会这样呢?究其原因还是软件项目的复杂性引起的。搬砖嘛,无非是从A搬到B,易上手。但软件开发就不是这么简单的了,新加入的人,上手前,规范要学、业务得培训、环境要熟悉,上手后,代码要Review、问题要修改等等。可以看出来,这一切的成本都是很高的,而且这是与专业水平高低无关的,当然专业水平高的人上手可能要快一点,但这些都是必不可少的需要学习的内容。当然讲这些并不是说加人成本高,不需要加人了,团队要发展,人员当然得扩充。讲这些只是为了说明,想要在短时间内通过人员增加来加快项目进度,是不现实也是无法实现的。一个人的精力和时间是有限的,我们不能一个人把所有事情都做了,所以要学会合理授权,把事情安排给别人去做。你把事情安排给别人去做,重要的是什么,是要把要做的事情给说清楚。我经常说要做重要但不紧急的事情,而不是做重要又紧急的事情,如果你有很多又重要又紧急的事情,你要反思反思是不是因为重要但不紧急的事情没做好。这里具体举例说明,你安排团队成员开发某个功能特性,一没详细的文档,二又描述的不清楚,整个过程也没有流程规范去监控去反馈,等要验收的时候才发现做的事情完全不是那么回事,到时候是又通宵又加班的去补救。在上面的例子中,哪些事情是重要但是不紧急的?一是详细的文档(包括功能文档、设计文档)、二是授权事情的详细描述、三是整个开发过程的流程规范制定。这些事情做好了,你觉得还会有后面紧急补救的事情吗?所以我们在授权别人做事的时候,一定要把事情给描述清楚,必要时候要多重复几遍。但这里有的人可能会说,费这么大劲讲清楚,还不如我自己做了。实际这里也要分情况的,对你比较放心的人,可能只要简单描述要做的事情是什么就够了,过程细节交给他去做,偶尔询问反馈下就行。而对不太放心的人,可能还需要额外把达成目标的具体步骤详细描述给他,过程中要经常询问反馈才行。沟通很难,而且对不同的人要有不同的沟通方法,但沟通确实很重要。要想实现一个大的目标,一定需要团队,把要做的事情安排下去,这在前面已经讲过了,要合理授权。不知道别人是否有这种情况,我有时候会有很多重要的事情要做,但又不放心下面的成员去做,担心他们做不好,而我又没有精力去做所有的事情,这就导致了很多重要的事情积压在我这里,知道它们重要,但又没法安排下去,这也导致了我很焦急。答案是培养。培养有两种方式,一种是培训学习式,另一种是实际指导式。种方式可以外出学习交流,也可以内部培训学习,都是学习的理论知识。第二种方式就是手把手指导了,耗费的精力会更大,但效果应该是好的。当然,还有一点比较重要的是,把所有重要的事情安排计划,你不必一次性把所有重要的事情都解决,我们总是在时间有限、资源有限的情况下做事的,把重要的事情枚举出来,安排计划,一个季度挑几个解决,重要的事情都排了计划了,这样就不会让人有焦急的感觉了。有时候,方案错了,修修改改并不能完全解决问题,相反可能会让系统越来越复杂,技术债越攒越多。我们已经做了这么多了,踩过这么多坑了,推倒重来不要怕,从头再来到走到现在的位置,花不了多少时间。行业的人,他对该行业的认识与普通人是不一样的。认识得越深入,越能知道其中的困难。业内分布式领域学者都会告诉你要规避分布式事务,更是要规避补偿,因为他能看到普通人看不到的困难之处。反观行业内一些公司或者说是团队,小作坊式的也要搞微服务、大数据,只能说他们连这件事难度有多大都没能力认清。当然我们不能畏畏缩缩,不敢前进,但也要结合实际,心存敬畏。成功的项目管理是要让相关利益方都收益。相关利益方这里包括投资者、管理层、项目团队成员、合作伙伴等。在说明人员的重要性时,更要说明的是我们要尊重所有人的利益,让所有人在项目中都能够有所收获。项目实施过程周期长,任务多,压力大。这期间肯定会有无数个让你崩溃的瞬间,所以一定要有强大的内心,要确信困难的时候就是接近成功的时候。还要不断地回过头来看看初心,当初为什么出发。还记得当初制定的目标吗?坚守它,实现它。
4
反馈
在项目实施过程中,我们要能及时发现风险,以便应对风险。工程反馈需要贯穿于整个项目实施过程中,方法其实就是开会。晨会、周会、月度会,虽然日常我本人也是很反对开会的,但是在项目实施过程中,会议是不嫌多的。虽然我们平时也会经常开会,但是想要开好一个会是不容易的。实时监控与反馈,需要贯穿于整个项目周期。监控与反馈可以帮助我们发现问题,进而解决问题。
5
我们做的所有事情,终的价值都体现在对别人产生影响上,都体现在改变世界上。不要觉得改变世界有多难,很多人可能都没有你能力强,但他们依然在改变着世界。看看你的书桌,看看你的厨房,看看那些影响着你学习,影响着你生活的小玩意,你能说这些小玩意的制造者没有改变世界吗?因为整个项目进行过程中,我们都遵循着持续开发、持续集成、持续测试、持续发布的原则,所以在终的项目交付上线的时候,并没有焦头烂额,手忙脚乱。终的上线也只是简单的切一下配置,仅此而已。这里还有一点需要注意的是,我们不要想着把所有问题都在个版本解决,这只会导致发布时间的无限延长。先发布,再完善,迭代起来。
6
Leader
单独拉出来讲是因为Leader是项目成功非常重要的因素。Leader可以说是整个项目团队的主心骨,所有棘手的问题、决策终都会来到他这边,等着他来处理。一个合格的Leader,心中一定有着项目必定成功的理念,而支撑着这一理念的是他的业务能力,他的自信,他的方法论。面对各种各样的问题,他该出手时就出手,有着兵来将挡,水来土掩,遇水搭桥,逢山开路的决心。面对质疑,他沉着冷静,不必急于争辩,用实际行动来证明对错。遇到这样的Leader,就跟了吧。
7
如果你做事的目的是为了获得奖赏、获得荣誉,那么整个过程中,你都会患得患失,终得不到它们也会很痛苦。而这些事情往往都很飘渺,而且不是由你自己决定的。如果你是发自内心的想做一件事,你便会享受整个过程,不计得失,专注于想做的事,终你会发现荣誉、财富反而都会随之而来。即使不来又有什么关系呢,你想做的事已经做了,这不就足够了吗。我们要经常听听自己内心的声音,追随自己的内心,在前进的路上不断成长。
写在后
软件工程确实是一个很复杂的工程,进入软件维护阶段才是真正考验团队能力的时候。高可靠、高性能、可维护、可观测、可扩展,可以作为分布式系统的通用建设目标。即使面对相同的问题,不同团队不同条件下也会有不同的解决方案,如何选择合适的解决方案,我们要有自己的原则。分工才会更专业,更有效率。合理的团队分工是迈向成功的步。时不时回过头看看自己为什么出发,当初的目标,还记得吗?坚守它,实现它。
聊技术,不止于技术。
在这里我会分享技术文章、管理知识以及个人的思想感悟,欢迎点击关注。