写点什么

Shopify 是如何迁移到模块化单体架构的?

  • 2019-08-09
  • 本文字数:1323 字

    阅读完需:约 4 分钟

Shopify 是如何迁移到模块化单体架构的?

Shopify 高级工程师 Kirsten Westeinde 在 Shopify Unite 2019 大会上讨论了Shopify向模块化单体架构的演变。这包括使用设计收益线(design payoff line)来决定何时进行此更改,如何实现更改,以及为什么将微服务排除在目标架构之外。


一个关键的结论是,单体不一定是一个糟糕的架构,它具有许多优点,比如单个测试和部署管道。在项目开始时,当必须快速交付新特性时,这一点特别有用。只有在跨越了“设计收益线”时,也就是糟糕的设计阻碍特性开发的那一点,才应该开始改进架构。就 Shopify 而言,改进其架构并不意味着转向微服务,而是转向模块化单体架构。这结合了单体(例如单个测试和部署管道)和微服务(例如代码模块化和解耦)的优点。


Westeinde 认为,单体架构是一个很好的项目起点,他说:“其实,我建议新产品和新公司开始时使用单体架构。”她列举了其中的一些优点:


  • 一个项目包含所有代码;

  • 只有一个代码库,测试和部署都很简单;

  • 所有数据都可用,无需跨服务传递;

  • 一组基础设施。


由于这些优点,Shopify 一开始只是一个小型的 Ruby on Rails 单体,随着时间的推移,逐渐发展成为一个非常大的代码库。当这种情况发生时,它意味着 Shopify 开始变得不可维护,并且因此很难交付新特性。例如,更改一段代码会对看似无关的代码造成意想不到的副作用,并且构建和测试应用程序花费的时间太长。


Westeinde 援引 Martin Fowler 的设计耐力假说(design stamina hypothesis)解释说,是时候重构他们的架构了——一旦功能开发被糟糕的设计所阻碍,设计收益线就会被跨越,这意味着投入资源来修复它是有意义的。


最初,Shopify 将微服务视为一种可选的、更易于维护的架构。然而,由于分布式系统的复杂性,它被排除在外,取而代之的是更易于维护的单体架构:


我们意识到,我们喜欢单体所有的东西,代码都在一个地方,而且向一个地方部署。我们遇到的所有问题都是由代码中不同功能之间缺乏界限所直接导致的。


Westeinde 解释说,他们意识到他们的设计目标是提升系统的模块化,比如使用微服务,同时保持一个单一的可部署单元,像一个单体。为了实现这一点,Shopify 采用了模块化的单体模式。这使得代码之间有了边界,但要使代码都在同一个位置并且部署到同一个位置。迁移路径如下:


  • 代码重组:最初,代码的组织方式类似于典型的 Rails 应用程序,顶层部件以技术组件命名,如控制器。这被更改为基于业务功能进行组织,如“账单”和“订单”,从而更容易定位代码。

  • 隔离依赖关系:每个业务组件彼此隔离,然后通过公共 API 供外部使用。他们内部开发了一个名为 Wedge 的工具,它跟踪每个组件的隔离情况。它构建一个调用图,然后计算出哪些调用(比如跨组件的调用)违反了规则。

  • 强制边界:一旦每个组件都实现了 100%的隔离,它们之间就有了强制的边界。其思想是,当代码试图访问它没有显式依赖的组件的代码时,就会出现运行时错误。以这种方式声明依赖关系也将使它们在依赖关系图中可视化。


最后,Westeinde 解释说,这个例子很好地说明了架构如何根据业务需求发展:


良好的软件架构是一项不断演化的任务,而应用程序的恰当解决方案完全取决于你的操作规模。


完整的演讲可以在网上观看,也有相应的博客文章


原文链接:


How Shopify Migrated to a Modular Monolith


2019-08-09 08:002728
用户头像

发布了 897 篇内容, 共 633.4 次阅读, 收获喜欢 1622 次。

关注

评论

发布
暂无评论
发现更多内容

从解决Github TimeOut到经典面试题:从输入URL到浏览器显示页面发生了什么?

秦怀杂货店

GitHub TCP 网络 HTTP DNS

透过 3.0 Preview 看 Dubbo 的云原生变革

阿里巴巴云原生

容器 运维 云原生 dubbo 应用服务中间件

python编译器中出现了绿色波浪线,光标放上去出现的提示是什么意思?

Emotion

C 语言性能优化:循环条件i<=n与i!=0的性能差异

1

有道技术岗大揭秘!这么幸福的生活,真的是熬夜掉发Top1的职业吗?

有道技术团队

招聘

Flink 执行引擎:流批一体的融合之路

Apache Flink

flink

阿里面试官:Android开发真等于废人?已拿offer附真题解析

欢喜学安卓

android 程序员 面试 移动开发

这个GItHub上的Java项目开源了,2021最全的Java架构面试复习指南

Java 程序员 面试

定义结构体访问结构成员的三种方法

Emotion

行业资讯 | Android WebView 致安卓应用闪退,mPaaS 助你规避这波 Bug

蚂蚁集团移动开发平台 mPaaS

android webview mPaaS 离线包 UC内核

活动 | Apache Pulsar Meetup 欢迎报名

有道技术团队

活动

报名倒计时 | 有道技术沙龙,聊聊明星语音背后的故事

有道技术团队

活动

可能是绝唱!阿里资深工程师深度解读Netty底层核心源码

Java架构追梦

Java 源码 架构 面试 Netty

为了跳槽刷完1000道Java面试真题,没想到老板直接给我升职了

Java 程序员 架构 面试

Go Mysql Driver 集成 Seata-Golang 解决分布式事务问题

阿里巴巴云原生

Java 微服务 云原生 seata Go 语言

实现跨生态互联,区块链赋能智能家居新体验

旺链科技

区块链应用 智能家居

字节抖音iOS客户端实习 123hr面 面经

iOSer

ios 字节跳动 面试 抖音

被MySQL慢日志查询搞废了?3分钟教你快速定位慢查询问题!

观测云

云计算

我在阿里实习做开源

阿里巴巴云原生

阿里巴巴 云原生 dubbo 个人提升 中间件

力扣(LeetCode)刷题,简单题(第13期)

不脱发的程序猿

面试 LeetCode 28天写作 算法面经 3月日更

为什么python中程序的结果会一直输出,需要怎么解决

Emotion

单账户实时记账能力达2万笔每秒 蚂蚁启用新一代高性能记账引擎

DT极客

程序员去大公司面试,小程序FMP优化实录,已拿offer入职

欢喜学安卓

android 程序员 面试 移动开发

LeetCode题解:92. 反转链表 II,迭代,JavaScript,详细注释

Lee Chen

算法 大前端 LeetCode

OpenKruise 如何实现 K8s 社区首个规模化镜像预热能力

阿里巴巴云原生

Serverless 容器 云原生 k8s 调度

实习就参与“服务过亿用户的项目”,是什么体验?

阿里巴巴云原生

开发者 云原生 调度 应用服务中间件 Go 语言

Go Storage存储包封装

非晓为骁

storage Go 语言

困扰一周的奇葩bug:重复相似代码多,导致单片机程序跑飞

不脱发的程序猿

28天写作 硬件设计 嵌入式软件 单片机 3月日更

一周信创舆情观察(3.15~3.21)

统小信uos

百度直播消息服务架构实践

百度Geek说

手机 直播 移动端

2021最新分享三面百度提前批(Java开发岗)面经 已拿Offer

比伯

Java 编程 架构 面试 程序人生

Shopify 是如何迁移到模块化单体架构的?_架构_Andrew Morgan_InfoQ精选文章