php发展

注册

 

发新话题 回复该主题

脉坤饿了么技术往事上 [复制链接]

1#

作为一个互联网创业公司,饿了么从初创到壮大,在移动互联网时代,业务量和技术团队的体量经历了10倍增长,这其中的经历,是互联网领域许多创业公司技术团队的一个缩影。在这里把我们成长过程中的体会和教训记录下来。

饿了么的技术体系,经历了以下四个阶段:

1、核心系统Allinone的早期架构;2、以系统领域化拆分、业务系统和中间件等基础设施分离为基础的全面服务化的架构;

3、随着自动化平台、容器调度体系成熟,治理从传统运维向DevOps转变的基础设施体系;4、多数据中心体系基础上的CloudReady架构成型。

在这期间,业务的快速增长,大大小小的事故,组织结构的变化、融合,团队的工程师文化和技术栈背景,不同技术理念的冲突,交织在一起,互相冲击、影响着架构变迁。

第一阶段:Allinone

这是饿了么技术体系早期的样子,技术联合创始人带着一群Geek,从0到1,搭建了最早的技术体系,支撑了百万级的单量。

这个阶段,业务一路狂奔,技术拼命追赶业务,唯快不破。

技术栈以Python为主,兼有部分PHP的系统,单机多应用的混布模式,应用发布、系统运维基本上是开发工程师敲命令行完成。核心的业务系统,商户、用户、交易都共享一个codebase,建立在一个名为zeus的系统下。短时间内业务飞速增长,在线数据库已经支撑不了ETL的需求,大数据体系、数仓开始建立。

大数据所在的上海数据中心,在线业务系统所在的北京数据中心开始搭建,这两个数据中心见证了我们架构的变迁,直到后来整体上云,最早的时候,技术团队40多人,有时候需要创始人跑到机房里面搬服务器。

系统跟不上业务发展速度的时候,核心系统经历过一些间歇性宕机的尴尬阶段。一些刚刚开始开拓的业务系统,也经历了系统刚上线就连续宕机,不得不临时放慢业务的阶段。但是这个过程也有收获,很多开发工程师线上排障能力非常强,脚本玩得很溜。

这个时期的工程师经常一人身兼数职,前端、后端、开发、测试、运维部署,对业务的理解也很深刻,甚至身兼技术和产品的角色。

收获和教训——文化的重要性

早期饿了么有一个鲜明的特点,就是大家都非常有担当,开放且包容。推卸、逃避责任的事情很少发生。虽然当时很多事故回过头来看比较严重,但是,组织对技术人员成长中的错误也相对包容。整个团队比较扁平,上下级之间的技术争论是常有的事情,但是都能就技术论技术。

饿了么的工程师文化氛围还是挺强烈的:工程师想着服务器的资源利用率能不能再压榨一下;在决定大规模使用Redis之前,会去读Redis的源码;很多方案,都是找个吧台和白板快速讨论,快速达成共识,落地上线。可能也是这个氛围,吸引到很多相同味道的人,形成了技术团队的文化。技术团队创始人最初形成的文化能延续下来,是这个团队从最初的几十人发展到上千人,还保有凝聚力和执行力的基础。

第二阶段:拆迁和基建

技术系统架构影响了业务交付效率,那么就需要重构甚至重建系统;如果是组织结构的不合理,阻碍了系统架构的迭代,成为业务发展瓶颈,那么就需要调整组织结构。

打个比方,如果说业务系统是赛车,那么基础设施就是跑道。基础设施也是这个阶段我们建设的重点,为承接将来业务快速增长打下基础。

这个阶段我们面临几个问题:

Python为主的技术栈,现有的工程师单兵作战能力都很强,但是当时市场上的兵源严重不足。

Allinone的系统,各业务领域没有划分,业务模块之间代码交错,影响到了交付效率,需要给业务快速发展松绑。

基础设施和业务系统开发没有分开,身兼数职的开发工程师,在基础设施运维、中间件开发、前后端业务系统开发各个方面,各有长短。

传统的手工上线、部署、运维、监控模式——SSH到服务器上手工执行脚本,效率低下,事故发生时恢复时间长,发布后难以回滚。

成建制

随着业务量迅速增长,业务系统日渐复杂,技术团队也随之扩张,当时人才市场上Java工程师还是比Python的工程师来源多,有更大的选择余地,因此,以Java为主的多个领域开始逐步壮大,形成了Python和Java两大技术栈体系。

大前端、移动端、多个领域的后端业务应用、运维、中间件、风控安全、大数据、项目管理等多个角色分工,不同角色的工程师做自己擅长的事情。在这个阶段,系统和组织形成了业务开发、运维、共享组件及中间件几个体系架构。

业务系统

1、业务领域划分

单体架构的系统开始按照领域拆分。Allinone的系统,通过划分业务领域,各个领域的技术骨干认领掉所负责的领域,组织结构相应调整,才很艰难的完成了划分。导购、搜索推荐、营销、交易、金融、公共服务、商户商品、商户履约、客服,新建的物流运单、分流、调度等系统,大数据数仓,逐步识别出自己领域、子领域及相应模块。在这个过程中,也有一些骨干在接手所负责领域后,没有在第一时间重视人力资源,导致交付能力不足,成为业务发展的瓶颈。从技术骨干再到技术团队负责人这一转变过程中,很容易被忽略的就是团队的人员结构。

2、系统拆分

随着各自领域内的需求快速迭代,系统也迅速膨胀,相互之间的依赖、领域边界也开始变得错综复杂。原来可以“闭环”的,现在需要交互了,甚至原来可以直接动其他领域的代码提PR,访问别人的数据库,现在都不行了。从单体到领域切分服务,改变原有的思维方式,导致很多不适应,也走了一些弯路:导购域为了性能,自己落了一份商户商品数据缓存供商品查询,从而需要理解商户端领域的业务,订阅这类主数据的变更,而商户端的这部分数据就没有办法收口,缓存的新鲜度保障、底层数据结构变更、系统重构都比较麻烦;交易域麻烦也不少,一些领域为了不依赖交易,自己冗余了大部分的订单数据;物流履约领域则是下游存在多份运单数据冗余,导致领域职责没有收口,带来很多一致性问题,系统的复杂度也随之增加,系统交互和沟通成本也上升了。

而另一个极端,则是系统拆得过散,频繁的互相调用依赖,把本该高内聚的系统拆成低内聚了。订单和物流都经历了过度的异步化带来的痛苦,故障恢复时间过长,复杂性和排障成本增加。这段时间,领域边界的分歧也是一个头疼的事情。

体会和教训——康威定律、技术文化

订单履约体系里面,有一个隶属于商户域的团队,负责推单系统,该系统主要职责是承接商户呼叫配送,并将订单推送到物流运单中心。因为想减少对订单系统的依赖,以防订单系统挂了,无法履约,开发团队冗余了很多订单的数据,为此,要同时考虑订单和运单的正向、逆向,自身的可用性,系统也被设计得比较复杂。

在这个过程中,一旦有项目涉及到物流和推单系统交互,两个团队就经常发生领域边界的分歧,涉及到一些从订单取数的场景,物流团队认为,“这部分逻辑我不应该理解,你们应该从上游系统取到推给我们”,而这个隶属于商户域的团队则认为,“这部分不是推单的领域内的数据,而且推单系统自己也用不到,物流需要应该自己去取”。

类似问题反复出现,反复讨论,消耗掉大家很多时间,而且可见的将来还会发生。链路过长也带来稳定性隐患。最终,负责订单域的团队,来负责推单系统,订单领域内的逻辑可以闭环,这个问题就迎刃而解了。

所以,涉及到两个领域边界的时候,一旦相似问题反复出现,我们可能要考虑一下康威定律。

关于争论:系统设计阶段的激烈争论是非常合理的,充分的讨论会大大减少方案出现硬伤的概率,开发阶段也少受返工之苦。技术讨论围绕技术合理性,就事论事的展开,不要因为技术以外原因推脱或者权威说得算,讨论完大家才能很坦然的接受决定,最重要的是,参与的工程师都能充分理解最终方案的利弊和取舍,落地不会有偏差,出了问题不推诿。这也是很多团队技术氛围吸引人的一个地方,文化不是口号,是日常的这些细节和实践。

运营体系

1、团队负责软件交付的业务运维、负责底层操作系统和硬件交付的系统运维、负责数据库的DBA、稳定性保障团队,相继成立。

2、监控告警集群实例的数量急剧扩张,登录到服务器上查看日志的运维模式已经不现实,也被基于遥测的监控体系所替代。随着7*24小时的NOC团队(故障应急响应)建立,基于ELK的监控体系也搭建起来,将核心指标投到了监控墙上。

体会和教训:监控告警机制的意义

互联网应用到了一定复杂度以后,庞大的集群,尤其容器化之后,IP动态分配,日志数量巨大,日志数据繁杂而离散,监控和排障需要借助的是和卫星排障一样的思路——遥测。日志系统要支持聚合和查询,监控需要实时收集采样各种指标、监控面板可以随时查看系统当前健康状况、告警机制第一时间发现系统冒烟。

有一次出现了一个问题,从监控面板上看一切正常,后来发现根因是一个int32溢出的bug,导致下单失败,但是,为什么监控看不出来?因为代码里面把异常吞掉了,调用返回成功,而我们核心指标用的是下单接口的成功调用量指标和一些异常指标。

经过关键指标的治理,我们的监控面板

分享 转发
TOP
发新话题 回复该主题