把我的单体架构还给我! - Craig Kerstiens


感觉现在是微服务炒作周期的高峰期,看到一篇博客文章“如何将我的巨石迁移到150个服务”。现在我经常听到更多的反击:“我不讨厌我的巨石,我只关心事情保持高效”。我们实际上看到了一些从微服务迁移回单体的案例。当你从一个大型应用程序转到多个小型服务时,你需要解决许多新事物,这里是你现在要重新访问的所有简单事项的简要说明:

1. 设置是复杂的
使用后台进程设置基本数据库和应用程序是一个非常明确的过程,我在Github上有自述文件,当我开始一个新项目时,通常会在一个小时或者几个小时内启动并开始运行。至少在初始环境中一个新工程会在第一天完成。当我们冒险进入微服务时,开始时间暴长。是的,我们现在有像K8这样的码头工人和编排器来帮忙,但是从开始到运行K8s集群,一个新工程师花费的时间比几年前看到的要大几个数量级。对于许多初级工程师来说,这是一种非常复杂的负担。

2.理解我们的系统需要很长时间
让我们暂时留在初级工程师的角度。回到我们有单体应用程序时,如果你有一个错误,你有一个清晰的堆栈跟踪,看看它来自哪里,可以直接进入调试。现在我们有一个与另一个服务对话的服务,它在消息总线上排队,另一个服务处理时我们才有一个错误。我们必须拼凑好所有这些部分,以最终了解服务a版本11和服务q预期版本12如何整合,现在,调试和理解更加复杂。

3. 如果我们无法调试它们,也许我们可以测试它们
持续集成和持续开发现在开始变得普遍。我现在看到的大多数新应用程序都会使用新的自动构建和运行测试,并且需要在提交之前通过并查看测试。这些都是很好的流程,对许多公司来说都是一个很大的转变。但是现在要真正测试我的服务,我必须提出我的应用程序的完整工作版本。那么现在我们可以教我们的CI系统如何调出所有这些系统来实际测试事情是否正常。这可能需要太多的努力,所以我们只是单独测试每个部分,我确信我们的足够符合规格,API很干净,因为服务失败是孤立的现象,不会影响其他服务。

4.所有的权衡都是有充分理由的,对吗?
迁移到微服务有很多原因。我听说过更灵活,扩展团队,提高性能,为您提供更具弹性的服务。我们在开发实践和工具方面投入了数十年的现实,这些工具仍在不断成熟。在我的日常生活中,我与来自不同背景的很多人一起工作。通常我们谈论扩展,因为它们遇到了单个节点Postgres数据库的限制。我们的大多数谈话都侧重于扩展数据库
一个有趣的趋势是看到越来越多的反应:“我们对我们的单体应用程序感到满意。”通往微服务的道路可能是好处大于付出的努力坎坷,但是否值得呢?

来自Hackernews的评论

1. 我不会责怪作者,我不确定为什么你会从微服务开始,除非你想表明你可以构建一个微服务应用程序;而巨石单体可以更快速,更轻松地进行设置。
随着一个组织成长并且软件扩大时,单体系统开始变得笨拙时,走向微服务才是有意义的。微服务在工程和组织层面是有优势的。
一个由三名工程师组成的团队协调负责25个微服务听起来很疯狂。一个由三十人组成的团队将一个单体切分成10个微服务,三个人组成一个团队,分成10个团队,每个团队负责维护一项服务,这是你想要的微服务方案。

2. 可能更喜欢推理出每个有界上下文的边界,并根据该分析选择适当数量的服务。
当然,根据互联网上陌生人的建议会将应用程序分成任意行,这些陌生人从未见过应用程序并且不了解产品/业务领域,这不是解决问题的合理方法。

3. 你一定做错了。在我工作的公司中,我们显然已经通过有界上下文分离了微服务,从而使它们完全分离。

4. 解耦是关键  ,当你必须跨多个服务进行事务回滚提交时,这就表明这些服务没有分离,耦合在一起了,表示你做错了。
每项服务都应完全独立,无需更改其他服务即可部署和回滚。
如果您正在进行API更改,那么您必须开始讨论API版本控制并在客户端迁移时支持API的多个版本,等等。

5. 我不认为Martin Fowler在撰写第一篇微服务文章时意识到他偶然发现了一个政治问题的技术解决方案。他只是看到它的工作,并希望分享。

6.微服务很有趣。
从技术上讲,它们不会增加复杂性。
但它们能够实现真正强大的功能:手段的连续性,责任的连续性,以及小团队完全掌握开发和运营解决方案的方式。
基本上,组织在处理小团队(大约十几个人,披​​萨规则)时往往非常有效,这种方式信息很容易流动,点对点通信而不需要协调员。
但是,有了这样的架构,应该更加重视接口(又称API)。必须编写详细的合同(甚至设定为政策):
* API保持稳定多长时间?
*如何弃用?使用Vn和Vn-1方案?
*如何记录?
*有什么限制?(性能,通话费率等)?

7. 我在某种程度上同意作者。
许多人认为,通过将他们的单体分解为服务,他们就拥有微服务了。不,你没有。你有一个分布式的单体而已。
你可以独立部署服务吗?不能?那你就没有微服务。你能改变一个微服务数据存储并部署它吗?如果要更改数据表结构,而且必须部署多个服务,那它们不是微服务。
所以,你拿一块巨石单体,然后分解它,添加一个消息代理,集中记录,也许在K8上部署它们,然后你就实现微服务了吗?......什么都没有。这不能够帮助企业。更复杂,需要管理更多东西,可能会出错。
每个愚蠢的hello world应用程序现在都需要8GB内存和自己的DB。所以你也增加了成本。并且没有完成任何CI / CD管道以及理智的开发和部署实践。
它有时也用于代替团队协作。现在每个人都可以用他们自己的语言编写自己的东西,而无需与其他人交谈合作,但是合作仍然需要,你只是正在积累你自己对其一无所知的技术债务而已。你可以打破接口和假设,你的单体甚至不会编译运行,哦哦,现在没人理解你的系统如何工作了。
如果您正在使用微服务正确地设计系统,那么在生产中进行工作和管理可能是一个梦想。但这需要每个团队的良好团队合作以及团队之间的良好协作。你还需要一种不同的心态。

8. 是否有推荐的处理跨多个服务的事务边界的方法?当涉及现实世界时,它基本上归结为现在你最终具有一致的分布式系统,如果其中一个调用失败,则没有通用的有效方法来展开对多个服务的更改。

9. 我得出结论:微服务适用于分工很重要的大型组织,但对于小型开发团队来说,它实际上会使事情变得更糟。
曾经只是一个函数调用现在成为一个API调用。现在,您需要管理多个CI / CD构建和脚本。
它增加了大量的开销,并且花费更少的时间来提供核心价值。
无服务器架构和应用程序平台似乎可以纠正大量的开销和挫败感,同时仍然提供微服务的大部分好处。

10. 在我看来,ESB的问题是紧密耦合; 所有这些分布式系统彼此了解并相互依赖。解决方案是在形式化接口/合同/模式时实现松耦合,其设计可实现版本控制并强制进行优雅演进。ESB的现代版本是基于事件架构(注意:这可能并不意味着事件溯源)基于分布式构建:将事件仅追加到日志上,这种日志可在理想情况下直接使用数据库事务日志。

11. 就我个人而言,困扰我的不是单体对微服务的矛盾,而是有态服务与无状态服务选择。
如果服务不能采用本地状态,则会产生不必要的设计开销。例如,在没有本地状态的情况下,您无法在两个服务之间实现完全一次的语义。如果用消息队列替换本地状态,则只需将1-network-1-disk op转换为5-network-3-disk op,并引入了大量其他问题。

12.针对“我们的大多数谈话都侧重于扩展数据库。“观点,我认为现代微服务设计背后的一个新兴原则是将您的数据模型分解为隐藏数据库的单独服务。然后,您可以将数据更改发布到事件流。这有助于避免返回数据库的请求。我认为与重度缓存(例如redis / memcache)相比,这是一种更好的方法。
我绝对同意微服务不是解决存在的每一个工程问题的银弹,但150个微服务的夸张是一个吸管人的论点。
我遇到的Kubernetes / docker系统的主要烦恼是集群的稳定性和对pod的健康状况的可见性。这两个问题都是我的组织决定从头开始构建我们自己的Kubernetes,这已经证明是一项重大任务。
如果我创办自己的公司并希望开发使用微服务,我可能会使用现有的现成容器云服务提供商(例如亚马逊/谷歌/微软)。我认为这是一种更好的方法,而不是“建立一个单体,然后再提升并转变为微服务”。

13. 我注意到欧洲中心主义架构和以美国为中心的架构之间存在很大差异。美国似乎更青睐象牙塔,以RDBMS为中心的系统,欧洲一直致力于领域驱动设计,事件风暴,无服务器和事件驱动架构。
单体设计适用于简单的系统,但随着复杂性和规模的增加,相关成本也会增加。
我目前正在使用DDD,微服务和公共云,因为复杂的系统可以更好地服务。

14. 微服务是一种时尚,而且名字也很差。SOLID原则和松耦合才是长期设计的基础。