@gaoxiaoyunwei2017
2017-09-22T11:19:11.000000Z
字数 5911
阅读 650
北哥
跟大家分享的主题是饿了么服务化的演进,主要是下面几个部分内容:
- 饿了么技术挑战最大领域: 订单 ---> 运单
- 饿了么订单挑战
- 饿了么运单挑战
- 外卖 vs. [衣住行]之技术挑战
- 服务化架构演进
- 服务化架构内关系
- 服务化架构演进阶段
饿了么在最近三四年发展的非常快,十位数的增长。在这个十位数的增长过程中,后台发生了巨大的变化,从十万单级别到百万单到千万单我们做了很多工作。
同时在这么迅速的增长过程中,对饿了么的技术挑战也是非常高的。简单的来说,它包含了订单+运单,或者等于京东+顺丰全包了,而且在运输过程中的处理时间要求比顺丰高很多很多。
因此,对于订单量是一个巨大的性能挑战,对于运单量就是处理时效上的挑战。
为了达到高性能和高时效的要求,我们在过去几年做了很多方面的改造工作。
美好生活触手可得,通过互联网做一个外卖到底有多复杂呢?大家在手机软件上做一个点击购买很简单,但是后面我们的工作是比较复杂的。
食客做一个购餐点击,只是生成了订单,后台还要确认,商家再点击接单,花一段时间把餐做好打包后,就会通知我们取餐,然后再生成一个运单,又要求限时送达,所以有运单的分配,配送员在配送过程中,还有轨迹位置点的上报,以及在配送过程中实际上还会每隔间隔时间会有一个状态的上报,如果发生一些突发情况,还需要重新调度,就会有一个重新的指令发给骑手,直到配送完成。
所以,从食客浏览到配送完成,时间上慢的话1个小时,快的话也就是几十分钟。比京东+顺丰一单要两三天完成,速度上要高得多。
在整个流程设计中,除了一般的正向流程以外,还有一些对于出错或者是一些异常的,这些补偿流程。所以,这个流程是涵盖了整个电商的全链路。
上图是我们内部业务处理的一些流程。大家在使用饿了么可能注意到或者遇到过这种情况,如商家超时无接单或者配送过程中超时会自动赔偿,这些都是很多流程中的各种状态和步骤。
在饿了么系统里面,对于每天千万单的交易量是有挑战的。同时我们也跟阿里做了一些合作,也参加过秒杀活动,在秒杀的时候我们也会面对处理过很多次瞬时的流量高峰。
所以,在整个这种对于高时效高性能要求的系统里面,我们会面临分布式业务的挑战。这也是我们从一个PHP开发的单独的网站做成分布式化和微服务化。比如降级、熔断、限流等等。
上图是订单处理监控图。
上图是运单处理监控图。
订单:高并发、瞬时冲击、517、秒杀
策略
:全链路监控 (含开放平台)、降级、熔断、限流难点
:限流守门,不仅仅是技术上挑战实战
:分区错峰、多步延迟、攻击应对延伸
:实时订餐领域每天都面临两次大的瞬时冲击,再加上秒杀活动,不仅技术压力大,商户、配送、客服压力都很大。。。那么,有没有可能在产品形态或用户引导上做些创新?
上面是我们面临的订单业务挑战。
运单:快、准、全
快
:客人第一反应,肯定是快准
:客人长期期望,基本是准
全
:覆盖挑战最大,模型为王
运单四大模型
:网格、定价、调度、路径运单技术挑战
:机器学习、各种算法策略
上面是我们面临的运单业务挑战。
- 每日订单:8M/天,峰值订单:9M+/天
- 每秒订单:常规 500/秒,活动 15K+/秒
覆盖城市 1400+
每日配送:3.5M/天
峰值配送:4.5M+/天
平均人效:35/天
配送人数:自营 6K,团队 100K,注册众包 2.9M
逻辑数据中心:6 (4 IDC + 阿里云 + 其他云平台)
- 服务器节点:18K+
- SLOC:50M+ (master/default-only)
- App ID:1400+
饿了么覆盖全国上千个城市,每天千万单的级别,每秒钟峰值订单上百万。同时,有四个自建IDC,后面会提到,我们在其中两个IDC已经做了多活的第一个阶段双活,还有大数据的IDC。另外我们还做了业务导向,就是业务的一个导流,业务导流的模块是用阿里云的。
我们现在物理机+虚拟机已经有18000台了,做了分布式和多活。现在的APP ID,其实就是分拆开的各种模块,已经有1400多个。开发人员已经超过1200人,分别工作在1400个不同的模块,大的模块可能部署数百个服务器,小的模块可能只有两三个虚拟机。这就是一个完整的电商包括物流所涵盖的所有工作内容。
核心角色挑战,尤其开放平台技术挑战
- 用户 (含企业订单/团餐/拼单/开放平台)
- 商户 (含直营连锁/加盟连锁/开放平台)
- 骑手 (含团队/众包/自营/开放平台)
淘宝
:用户/商户为主,[骑手]走开放平台
携程
:用户/商户为主,基本没有[骑手]
滴滴
:用户/[骑手]为主,基本没有商户
在互联网行业里面,我们自己感觉到我们解决的技术挑战还是排在前几位的。
比如淘宝还是电商这部分,它对物流,特别是我们这种要求30分钟内送达的物流,他也是通过风投来扶持我们的发展。
像传统的去哪儿、携程,他们每天的订单量比我们可能要小一个数量级,我和朋友在私底下互相交流过,他们对这个挑战是没有这么高的。
当然,我们现在的体量跟滴滴差不多,但是滴滴比我们相对简单一点,因为滴滴把人跟车撮合后,在后续跑单过程中的状态、追踪和处理是不管的。我们对骑手配送的状态实际上是在管在调度的。
因此,对于我们这种情况,有个自我的感觉,就是我们解决了电商里很大的一个技术难度,而且按照我们创始人所讲的,我们还创造了物流的一个新模式,叫即时配送。现在是属于订餐,可以帮你在30分钟内送到,还可以送药,可以有一个商超、生鲜也可以在30分钟送到。
我们有一个新的目标,就是不管你订什么东西,都可以在30分钟内帮你送到,送一个钥匙也好,送一个文件也好,只要有人发出这个需求,只要在这个范围内,30分钟内送达。
整个这个工作的背景是我们最近做了分布式服务化和双活。
饿了么在两年多前,整个网站是一个PHP的系统。所以,从一个大而全的PHP改造成这样子,我们这里所有的有关中间件和一些支持的组件全部是我们自己开发的。
饿了么外围模块用了Java。实在找不到那么多人,有一些模块被迫的用Java,用Java的人更多了。
分布式服务化业内是阿里做的比较早,我们是借鉴了阿里平台端的一些信息自己来做。
这是分布式服务架构的内在关系走向。
这是我们这三年来工作的一个演进图。我们是基于这个业务的容量和发展,把每个模块挑选出来,先用python加中间件,用python去部署,至于部署十个,还是几十个,就是根据业务负载情况了。一个一个模块这样的改写,然后再把PHP那部分传出来。这是跟大家分享的一个既满足业务增长需求,又能够把整个所有流程,从订餐到商家到物流全在一起的程序。
我们也做了分库分表,而且还做了一个多活。我们每年以100%,200%的量增长。当时考量了一下,如果今年不做多活,如果到年底一个机房的规模过大了,导致机房都会有困难,基于上面原因考虑推动我们做多活。多活是在5月上旬上线了,还比较顺利,比较成功。对今年年底再增加一两倍的业务量心里就有底了。
这是改造前的情况,所有的东西都是PHP,PHP确实还是挺好用的,开发也方便,调试也方便,特别是开发起来比较快。
这是我们改造后的一个简图。一个一个的模块,再到订单处理,再到商家的处理等等,通过前面讲的,先改造重写一个块,然后再把它Thrift化。和PHP被完全Thrift化后,后端就变成了一个API网关,我们用java又重写了一个API网关。PHP现在有几个还在用,只做一个Thrift的转义,其实没有什么需要再维护的。
这是改造完后,我们一个稍微细化点的结构图。这个图上还多了一点,就是我们自己开发的一个分布式服务架构中必须的服务注册和服务发现的环节。它的一个中央环节是靠服务注册,服务发现。前面所说的服务的负载分担等等,有很大的工作是靠服务注册,服务发现的环节来做的。
右边的这些一个个分布式服务的模块,它们作为消费者的时候,会去服务注册的环节查询这个信息,查到生产者在哪里?哪个运营?实际上是服务发现根据生产者的心跳状态,以及生产者的负载情况,来动态派发的,这个派发也只是信息的一个指向,找到生产者以后,消费者跟它们之间是互相直接访问的,这是服务模块互相之间的常规工作情况。
中间几个环节是API Router。它下面有做物流的,也有做订单的等等。我们大量的业务负载是靠集群跟踪的,包括我们的一些商品,店家的信息。
前端的订购到商家的订单,到运单,每个环节大家都看得出来,它是一个异步的状态。订单处理跟运单处理互相没有关联,所以我们是一个重度的MQ用户。最近我们重写了一个MQ,上面有一半的业务量。
右边是各个服务组件,访问MQ,或者访问数据库的中间件,它有一个分布式服务的一个调动环节。我们用Go语言重写了一个GoProxy,是一个可以集中做配置动态更新的一个集群化的Proxy,因为Proxy配置变动必须写配置文件。
对于微服务的发展,由于我们是从PHP发展过来的,对PHP的服务治理理念是一个实践者,觉得这是业内的一个总结,跟大家分享一下。就是我们的所有服务模块,都是松偶合的,每个模块可以独立开发,独立部署,独立测试,然后通过SOA的服务注册发现中间件,使它动态的联动起来。
- 引擎功能:分布式系统的配置管理、服务发现、断路器、智能路由、微代理、控制总线等
- 分布式服务:
- 模块间访问采用Thrift RPC的方式,开发者不用关注网络与报文格式,像写单机程序一样开发分布式软件服务。
- 服务高可用性:
- 负载自动均衡、熔断与容错,对于单机故障、服务过载、局部网络波动等状况自动应对(限流),服务有高可用性。
- 支持多种语言:
- 支持Python/Go/C++/Java/PHP语言,编程语言中立,兼具开发和运行效率。
- Web管理界面:
- Web化的管理界面,在web界面完成配置、发布、监控、日志、降级等所有操作。
- Docker镜像安装(开发中):
- 需要复杂部署的服务器都采用docker镜像的方式安装,使得部署非常容易。
- 目的:SOA架构/Microservice Architecture,就是基于微服务的架构。简单来说,微服务的目的是有效的拆分应用,实现敏捷开发和部署.
- 业务BU领域划分
- 按照业务而不是技术来划分组织
- 一系列的独立的服务共同组成系统
- 单独部署,跑在自己的进程里
- 做有生命的服务而不是项目
- Smart endpoints and dumb pipes(强内聚弱耦合)
- 自动化运维(DevOps)
- 容错
这是我们最近大半年做的一个多活平台架构。我们做了一个API Router部件,这个模块部署在云上面的,云相对比较容易扩展。这里面还会基于我们用户分区分配的策略。因为API Router 会去全局数据中心获取负载状态,可以被下发注入命令。比如说我们现在切换,基本上在一分钟内,一分钟内其实有一个控制中心,会给我们部署几十个,上百个 API Router,这是用户流量导向及控制的环节。控制环节有一个部件,注入导流的指令。
中间那部分就是分布式服务化的组件,是无状态的。
做双活多活里面,数据是关键的关键,一个是最外侧的负载的一个指控导向,一个是最底层的有状态的数据的一个同步复制,这个是最为核心的关键点。数据的同步复制这部分,基于对数据复制技术的研究后,我们自己用Java开发的。
数据的同步复制,有好几个环节。DAL是原有数据库分库分表的这部分,这部分还是老样子,不用动。但是有一些策略控制,会跟GZS有一定的关联。
最主要的就是开发的数据库辅助部件DRC,它也是可以被GZS进行控制,进行不同的数据库之间同步。我们有好几百套数据库集群,数据库集群之间的复制,是有一个系统来做这个事,但是又不能一个一个去部署,对管理上就容易出差错。因此,它也有一个中央控制的环节来去做数据不同的双向复制,双向复制有一些细节,比如怎么对步长的一个区别,防止不同的库之间,万一程序出错,是不是可以基于某一个信息,可以把数据复制再重跑一遍,以及怎样防止循环复制,A写给B了,B那边又给传回来了,这些都是数据库复制里面的典型的几个难题。还有就是大规模集群的时候,怎么部署和控制中央复制部件,使得我们能够控制几百套数据库。
在整个多活的设计里面,有一小部分是全局强一致性的业务,这些业务主要是整个庞大的业务后台管理部件。比如GZS里面负责登记管理整个集群的工作状态信息和配置信息,这些信息数据随着模块程序的部署和有一些服务的变动而变更的。这几个小数据库我们做了一个单独的区域,这个区域是架构上的定义,这些数据库是主备结构,平时一个机房为主,另一个机房为辅,随时可以切换。所以,一旦某个机房出问题,可以通过全局控制,转写到另外一个机房,另一个机房是始终可读的。
在多活设计里面,还有一些后台的业务作业。到晚上有一些支付清算,还有一些商户旧的数据更新。这里面我们识别出来有两类作业,一类作业是可以两个数据库分别跑,各做各的,没有什么问题。另一类作业可能需要有一定的全局性。比如说一些商家开店关店的状态信息等等,这些数据会在一个数据中心跑,然后再通过DRC复制到另外一个中心去。
这是我们改造前后的一些基础组件和工具。
以上就是我们在过去两三年所做的,从PHP发展到一个SOA的架构,又做了多活的技术架构的演进。