饿了么:日订单量超900万的架构设计及演进之路

网站在刚开始的时候大概只是一个想法:一个产业的模型,快速地将它产生出来。“快”是第一位的,不需要花太多精力在架构设计上。在网站进入扩张期才需要对架构投入更多的精力来承载网站在爆发时的流量。

饿了么成立已经8年,现在日订单量突破900万,我们也有了较为完善的网站架构。

一、网站基础架构

初期,我们使用了能够更容易拓展SOA的框架。我们用SOA的框架解决两件事情:

1. 分工协作

网站初期,程序员可能就1~5个,那时大家忙同一个事情就可以了。彼此之间的工作都互相了解,往往是通过“吼”的方式就把问题解决了。

但随着人员的增加,这种方式显然是不行的,不可能一个人更新了代码再把其他人的所有代码重新上线一遍吧?于是就要考虑分工协作的问题。

2. 快速扩展

看一下我们的现状,中间是我们整个架构的体系,右侧是和服务化相关的一些基础,包括基础的组件或者服务。

先说语言,我们原来的网站是在PHP上的,后来慢慢转型。

WebAPI主要做一些HTTPS卸载、限流,还有安全校验等一些通用的和业务逻辑无关的操作。

Service Orchestrator是服务编排层,通过配置的方式实现内外网的协议转换、服务的聚合裁剪。

架构图右边是一些围绕这些服务化框架的辅助系统,比如说用于定期执行一个任务的Job系统。我们有将近快1000个服务,这些系统怎么监控?所以必须有一套监控系统。刚开始只有30多个人时,我们更擅长的是跑到机器上去搜一下Log,但到了900多人时,你不可能都到机器上去搜一遍Log,需要有个集中式的日志系统。其它的系统这里就不一一赘述了。

罗马不是一天建成的,基础架构是个演进的过程。我们精力有限,那先做什么呢?

二、服务拆分

当网站变大了,原来的架构跟不上发展的节奏了。我们要做的第一件事情就是:

把大Repo拆成一个小Repo,把大服务拆成小服务,把我们的集中基础服务,拆分到不同的物理机器上去。

光是服务拆分用了一年多的时间才做完,这是一个比较漫长的过程。

这个过程中,首先要对API做一个很好的定义。因为一旦你的API上线之后,再做一些修改的成本是相当大的。会有很多人依赖于你的API,很多时候你也并不知道有谁依赖于你的API,这是一个很大的问题。

然后再把一些基础服务抽象出来。很多原来的服务其实是耦合在原来的业务代码里面的。比如说支付业务,业务很单一时,紧耦合的代码没有关系,但是扩展出的越来越多的业务都需要支付服务时,你每一个业务(比如说支付的功能)都要去做一个吗?所以我们要把这些基础服务抽离出来,比如支付服务、短信服务、推送服务等。

拆服务看似很简单、没什么价值,但这恰恰是我们刚开始就要做的事情。其实在这个时期,前面所有的那些架构都可以往后拖,因为不做架构调整其实不会死人,但是拆服务你不做的话,真的会死人。

服务拆分必定是一个漫长的过程,可这实际是一个很痛苦的过程,也需要很多配套系统的系统工程。

三、发布系统

发布是最大的不稳定因素。很多公司对发布的时间窗口有严格的限定,比如说:

  • 每周只有两天可以发布;
  • 周末是绝对不可以发布的;
  • 业务的高峰期绝对不允许发布;
  • 等等……

我们发现,发布的最大问题在于发布上去之后没有简单可执行的回退操作。回退操作到底是谁来执行,是发布人员就可以执行,还是需要专人来执行?如果是发布人员的话,发布人员并非24小时在线工作,出了问题找不到人怎么办?如果是有专人来执行回退,而又没有简单、统一的回退操作,那这个人需要熟悉发布人员的代码,这基本上不可行。

所以我们就需要有发布系统,发布系统定义了统一的回退操作,所有服务必须遵循发布系统的定义回退操作。

在饿了么对接发布系统是对所有人的强制要求,所有的系统必须全部接入发布系统。发布系统的框架很重要,这个东西其实对于公司是很重要的一件事情,需要放到第一优先级的队列里面去考虑。

四、服务框架

紧接着就是饿了么的服务框架,把一个大的Repo拆分成一个小的Repo,把一个大的服务拆成一个小的服务,让我们的服务尽量独立出去,这需要一套分布式服务框架来支撑。

分布式服务框架包含的服务注册、发现、负载均衡、路由、流控、熔断、降级等功能,这里就不一一展开了。前面已经提及,饿了么是多语言的生态,有 Python的,也有Java的,我们的服务化框架对应也是多语言的。这对我们后来一些中间件的选型是有影响的,比如说DAL层。

五、DAL数据访问层

当业务量越来越大的时候,数据库会变成一个瓶颈。

前期可以通过提升硬件的方式来提升数据库的性能。比如:

  • 升级到一个有更多CPU的机器;
  • 把硬盘改成 SSD 的或者更高级一点的。

但硬件提升终归是有一个容量限制的。而且很多做业务的小伙伴,写代码的时候都直接操作数据库,发生过很多次服务一上线数据库就被打爆的情形。数据库被打爆掉了之后,除非等待数据库恢复,没有任何其它机会可以恢复业务。

如果数据库里面数据是正常的,业务其实都可以补偿出来。所以我们做DAL服务层的时候,第一件事情是限流,其它的东西可以放一放。然后做连接复用,我们Python框架用的多进程单线程加协程的模型。

多进程之间其实是不可以共享一个连接的。比如:一台机器上部署了10个 Python进程,每个进程10个数据库连接。再扩展到10台机器上,就有1000个数据库连接。对数据库来说,连接是一个很昂贵的东西,我们DAL层要做一个连接复用。

这个连接复用讲的不是服务本身的连接复用,而是说DAL层上的连接复用,就是服务有1000个连接到DAL层,经过连接复用后对数据库可能只是保持着十几个连接。一旦发现某个数据库请求是一个事务的话,那么DAL就帮你保留这个连接的对应关系。当这个事务结束之后,就把数据库的连接,放回到共用池里面去,供其他人使用。

然后做冒烟和熔断。数据库也可以熔断的。当数据库发生冒烟时,我们会杀掉一些数据库的请求,保证数据库不至于崩溃。

六、服务治理

服务框架之后,涉及服务治理的问题。服务治理其实是一个很大的概念。首先是埋点,你要埋很多的监控点。

比如有一个请求,请求成功了或者失败了,请求的响应时间是多少,把所有的监控指标放到监控系统上面去。我们有一个很大的监控屏幕,上面有很多的监控指标。有专门小组72小时去盯着这个屏幕,如果有任何曲线波动了,就找人去解决。另外是报警系统,一个监控屏幕展示的东西总是有限的,只能放那些很重要的关键指标。这个时候就需要有报警系统。

罗马不是一天建成的,基础架构更是一个演进的过程。我们的资源和时间总是有限的,作为架构师和 CTO 来说,如何在这种有限的资源下,产出更重要的东西?

我们做了很多系统,觉得自己做得很不错了,但实则不是,我感觉我们又回到了石器时代,因为问题越来越多,需求也越来越多,总感觉你的系统里还缺点什么东西,想做的功能也一大堆。

这些问题涉及我们做事的一个原则:东西够用就好,但是要能够未雨绸缪,做一定的超前规划。

原文发布于微信公众号 - JAVA高级架构(gaojijiagou)

原文发表时间:2018-07-24

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏EAWorld

微服务模式系列之二:微服务架构

译者评论: 微服务架构大家已经耳熟能详,但是我认为这篇文章最有价值的是这段: 但这类解决方案中也存在着以下弊端: 开发者必须应对创建分布式系统所产生的额外的复杂...

36050
来自专栏about云

Kubernetes, Kafka微服务架构模式讲解及相关用户案例

问题导读 1.微服务有什么特点? 2.本文介绍了哪些案例? 3.你认为事件驱动的微服务、容器、Kubernetes和机器学习结合可以有哪些应用? 随着当今...

18530
来自专栏一个会写诗的程序员的博客

基于NodeJS的全栈式开发(基于NodeJS的前后端分离)【转】

随着不同终端(Pad/Mobile/PC)的兴起,对开发人员的要求越来越高,纯浏览器端的响应式已经不能满足用户体验的高要求,我们往往需要针对不同的终端开发定制的...

1.5K20
来自专栏云计算D1net

云技术如何改变业务灾难恢复计划?

尽管业务灾难恢复计划转向云计算,但传统灾难恢复(DR)的关键要素,如位置和测试仍然很重要。 在过去几年中,人们已经逐渐放弃了一种被动的业务恢复计划,那就是采用...

30660
来自专栏韩伟的专栏

如何提高程序员的生产率(上)

一、硬件资源 1) 办公环境 ? 大部分开发团队都不把座椅家具视为一个非常重要的问题。拥有宽敞的桌面的环境,可以在桌上放置更多的东西:本子、笔、杯子、书本、打...

45460

云原生应用的成熟度模型探讨

原文地址:https://dzone.com/articles/cloud-native-application

540100
来自专栏小程序

关于微信小程序,看这一篇就够了

简单来说,微信小程序是在微信上一种不需要下载安装即可在线使用的应用,用完直接退出,也无须安装、注册与卸载,大家担心的手机安装太多应用的问题也终于可以缓解啦~

12320
来自专栏精讲JAVA

前后端分离实践的架构设计

前后端分离的项目开发策略已经不是什么新鲜东西了,网上介绍这方面的文章非常多。我自己是在14年的时候接触到的,对这种开发策略一直爱不释手,不管新老项目都会首先用前...

17130
来自专栏腾讯大数据的专栏

HBase在腾讯大数据的应用实践

前言随着腾讯产品与技术的发展,几乎任何一个与用户相关的在线业务的数据量都在亿级别,每日系统调用次数从亿到百亿,对海量数据的高效插入和快速读取变得越来越重要。而传...

37760
来自专栏13blog.site

Java开源博客My-Blog之docker容器组件化修改

前言 5月13号上线了自己的个人博客,《Docker+SpringBoot+Mybatis+thymeleaf的Java博客系统开源啦》,紧接着也在github...

39470

扫码关注云+社区

领取腾讯云代金券