在传统的 Web 应用程序开发中,工程师编写代码、编译、测试, 然后作为一个单元部署并提供功能服务。但是,如果一个网站有数以百万计的终端用户在持续使用,并且有成百上千的工程师在持续开发,这种方法就面临着很大的挑战了。
DoorDash 的平台就面临着类似的情况。起初,该平台是在单个大型代码库中开发的,2019 年,随着公司业务的增长,这种开发模型的缺点暴露了出来,开发人员的适应期越来越长,测试等待时间增加,开发人员的挫败感越来越强,应用程序的脆弱性越来越大。经过一番讨论,公司开始计划从单体迁移到 微服务架构 。
其实,工程团队已经在许多场景中使用了微服务,如流量高、业务重要、需要具备扩展性的 Web 服务。从根本上说,就是单体代码库的功能被分解成单独的、具有容错性的服务。最终,工程师管理的是一些相对较小的对象的生命周期,变更更容易理解了,也就更不容易出错。在部署频率和策略方面,这种架构很灵活。
2019 年底,在 DoorDash 做个变更需要全体总动员,甚至要暂停所有新特性的开发,以便公司可以专注于构建一个面向未来的可靠平台。虽然从单体中提取业务逻辑的工作仍在进行,但我们的微服务架构已经上线运行,为数以百万计的客户、商家和 Dasher(我们对送货司机的称呼)提供服务,他们每天都通过我们的平台下单、备货和配送。
业务增长
2013 年,DoorDash 涉足食品配送领域。那时,从工程师的角度来看,我们的任务是快速构建一个原型,通过电话和电子邮件这种基本的通信方式收集外卖订单并分发给一些企业。这个应用程序应该可以从客户那里接收订单,并将它们传达给餐馆,同时还要吸引 Dasher 接单并把食品送给客户。
起初,团队决定使用 Django (这以前是、现在仍然是一个一流的 Web 框架)构建 DoorDash Web 应用。事实证明,Django 很适合一个小型开发团队在短时间内构建最小可行产品。Django 还支持新特性的快速迭代,在早期,这非常有价值,因为业务逻辑一直在变。随着 DoorDash 的工程师越来越多,网站的复杂性越来越高,技术栈开始围绕 Django 强化。以敏捷性为首要目标,DoorDash 工程团队不断在这个单体系统上迭代,同时还要构建业务基础,扩展应用程序的功能。
在头几年,采用单体架构构建 Web 应用程序体现出了多方面的优势。主要的好处是,在单体上开发缩短了新特性上市时间。Django 为工程团队提供了一个前后端统一的框架,一个代码库,一种编程语言,一套共享的基础设施组件。在开始的时候,这种方法让 DoorDash 的 Web 应用程序走了很远,因为它让开发人员可以快速行动,把新特性提供给客户。由于整个代码库都在一个存储库中,所以可以通过重用组合模式将新增逻辑对接到已有的框架和基础设施上,加速开发。
不管是工程层面,还是操作层面,部署单个服务的成本都包含在里面了。我们只需要维护一个测试和部署管道,以及数量有限的云组件。例如,一个公共数据库支撑着后台大部分功能。
图 1:DoorDash 的原始架构,前端和后端都在一个 Django 应用程序中,数据访问基于单个 PostgreSQL 实例。
除了操作简单外,单体方法的另外一个好处是,当一个组件调用其他组件时不会产生服务间网络延迟成本。在单体部署时,不需要考虑组件间 API 向后兼容性、慢速网络调用、重试模式、断路器、负载分片策略以及其他常见的故障隔离做法。最后,由于所有数据都在一个数据库中