通常情况下,默认的单体应用会被逐步淘汰,让位于解耦和容器化的微服务架构,但如果你有意识地构建一个单体应用呢?
译自 Monoliths: A Space Odyssey to Better Developer Experience,作者 Sarah Morgan。
这篇文章是系列文章的第一篇。
除了描绘了一个迷人但具有杀人倾向的 AI 的电影《2001: A Space Odyssey》外,该影片最为人记忆深刻的或许是其巨大的石碑。这些貌似突然出现的完美光滑、深邃如夜空的石板,引导着史前的猿猴,以及后来的一支先进的宇航员队伍,向前触摸并试图理解它们,窥视它们可能包含的秘密。
电影刻意对这些石碑的意义保持模糊。它并没有提供具体的真相,而是反映了人类的雄心壮志和成长,呈现给任何可能观察它们的人。
开发者对于单体应用(monoliths)有一个不同的概念。虽然同样神秘且引人注目,但通常缺乏完美的比例和无与伦比的表面处理,软件单体讲述了一个团队通过代码重构、关键人员的雇佣和离职,以及业务需求的重大变化来设计和发展应用的故事。
与电影中石碑的模糊不同,软件中的单体故事只有两种走向:
起初,人们对你的单体应用的离世并不经常感到伤感。微服务简化了你在整个应用中范围重大或破坏性变更影响的方式,你的同行喜欢他们可以用除 JavaScript 之外的任何语言开发新的 API。再次,每个人都开始感觉自己是贡献者,编写新功能并解决复杂的优化难题,而不是坐在为旧单体的每个主要版本发布而进行数小时会议的情况。
你的单体的消亡使得围绕组织开发人员和工程师方面的一些小问题变得平稳,但它也引入了一些最初你没有完全考虑到的新的技术要求。你开始思考:我们花在重构和配置基础设施,然后处理微服务的挑战的所有时间,鉴于我们面临的工程问题的复杂性,这一切都是必要的吗?
选择微服务是因为你认为它能解决你的技术问题,但实际上它更适合解决组织和协作问题,而你的公司几乎肯定没有这些问题。通过让你的单体应用消亡,你在系统中引入了许多不必要的复杂性,比如:
如 Kelsey Hightower 警告的那样,你从“编写糟糕的代码到构建糟糕的基础设施”,寻找你希望从一开始就拥有的工程纪律。或者,正如Basecamp的CTO和Ruby on Rails的创作者David Heinemeier Hansson所说,你增加了不必要的复杂性:“在几乎所有情况下,用网络调用和服务分区替换方法调用和模块分离,而这一切都在一个一致的团队和应用程序中进行,简直是疯狂的。”
现在,在这个“疯狂”中,你开始后悔自己没有保留单体应用。也许,如果你是幸运的少数人之一,就像 Twilio 内的 Segment 团队一样,你可以尝试用一种有意图的新型单体应用:一个你有意识构建的单体。
这个故事的开始也有两种方式:
随着你继续沿着单体的道路前进,这种架构成功扩展,因为你意识到了常见的担忧和误解。
“开发者不喜欢在单体应用中工作。”虽然没有官方的调查表明开发者更喜欢哪种方式,但只要单体应用保持性能良好,开发者在单一代码仓库中的工作体验往往更简单。通过按文件夹和调用分隔服务,而不是基础设施即代码、不同语言和不同代码仓库,你甚至可以将重大变更同步到单一的拉取请求中,以提高速度和质量。
当 Segment 团队转向有意识的单体应用时,他们在共享库中进行的改进从一年的 32 次增加到了接下来的短短六个月的 46 次。
“单体应用就是一个没人能理解的黑盒。” 很多人也对微服务有同样的看法。
“单体应用很慢。” 单体应用并不是垂直扩展的理想选择,但它们可以独特地快速。数据传输保持在进程内存中,比起机器间通信更便宜和更快,并且不必经过分布式服务的编排逻辑。当需要进行水平扩展时,你可以依赖具有更可预测性能和成本的服务,比如 AWS EC2,而不是依赖无服务器选项。此外,有许多应用性能监控工具,比如 Scout APM,专门设计帮助你识别优化机会,甚至到特定代码行。
“单体应用需要进行更多的测试。” 这似乎是个好问题。正如 Hightower 所建议的那样,编写基础设施并不是解决编写糟糕代码问题的方法,这通常归结为编写不好的测试,或者不够多的测试。
“你不能使用新的(云原生)技术!”是的,单体应用可能无法在最新的无服务器或容器编排潮流上运行,但你仍然有选择。例如,你可以部署一个服务网格,比如 Linkerd 或 Istio,通过 mTLS 将你的单体应用连接到外部服务。你可以通过负载均衡器和多云部署来提高可伸缩性,或者将你的应用连接到 OpenTelemetry Collector,将日志、指标和跟踪发送到当今众多的可观测性解决方案之一。
了解这些误解及其现实,你还可以实施应对构建单体应用的真正挑战的策略:
关键在于,你不是因为单体应用是默认选择而构建单体应用。即使是最出于良好意图的单体应用也可能走向失败。你是有意图地构建单体应用,因为它解决了你组织当前存在的一级工程问题。因为你仍然可以将你的应用全部理解在脑海中。因为你不想一旦微服务不再流行,就意识到你对所构建的东西了解甚少,然后不得不从头开始。
有意图地构建一个单体应用并亲自体验吧:几乎每次单体应用都是正确的选择。
单体应用的最大优势之一在于,谁能从微服务架构导致的成本飙升中获益最多。请继续关注我们系列的第二篇文章,但在那之前,给你一个提示:这个人不是你。