我在微服务世界中看到的灾难

2021-06-13 23:04:20

当Martin Fowler'关于MicroServices的帖子于2014年出来时,我工作的团队已经建立了面向服务的架构。那篇文章和随后的炒作进入了世界上几乎每个软件团队。 " Netflix OSS Stack"那是最酷的事情,允许全世界工程师利用Netflix'在分布式系统中的课程。超过六年后,如果我们现在调查软件工程就业,他们大多数人都谈到了一个微服务和#39;建筑学。

在2010年代的最早部分,许多组织对其软件开发周期遭受挑战。人们使用其他50,100或200名工程师,努力开发环境,重质QA流程和编程部署。虽然马丁福勒' s"连续交货"书籍棚在许多团队中,他们开始意识到他们的雄伟的巨石正在为他们创造组织问题。因此,微服务对软件工程师进行了吸引力。它更具挑战性,在大项目中延续持续交付或部署而不是从它开始。

所以球队开始旋转三,十,一百个微服务。他们中的大多数人使用" json overt http" - 其他人可能会说依赖于这些组件之间的远程呼叫的API。人们知道HTTP协议很好,它似乎是将墨底转换成较小的碎片相对简单的方法。此时,团队开始在不到15分钟的时间内将代码部署到生产中。没有更多的"哦,团队突破了CI管道,我可以和#39; t部署我的代码"它感到很棒!

尽管如此,大多数工程师忘记了在软件架构中解决组织问题' S水平,他们也介绍了很多复杂性。分布式系统贫困变得越来越明显,并且对于这些团队来说很快就会出现头疼。即使对于已经在他们已经存在的客户/服务器架构的公司提供了客户/服务器架构,它一旦它们在其系统中有10个以上的移动碎片就在其脸上爆炸。

为了获得重大的建筑变革,不为免费来。团队开始意识到共享数据库是一个单点故障。然后,他们意识到分离他们的域名创造了一个全新的世界:最终的一致性是一件事。当你&#39的服务时何时何地呢?问题和问题的数量开始堆积。通过寻找错误,事件,数据一致性问题等,突破了高速发展步伐的承诺。另一个问题是工程师需要集中日志和可观察性解决方案,以跨越几十种服务来发现并纠正这些缺陷。

有能力每天创建新服务,带来开发商的爆炸'创造力。一个新功能? BAM,Let'开始服务!突然,20名工程师的团队正在维持50家服务。这个'每个人多于一个服务!代码的问题通常是它rots。维护每项服务都是成本的。想象一下,在您的服务中传播库升级'舰队。想象一下,这些服务在不同的时间点开始,具有不同的架构以及业务逻辑与使用的框架之间的一些纠缠。那个' sananas!当然,有方法可以解决这些问题。他们中的大多数人都在那些日子里拿回来,其他人在FTES工作中成本很多。

另一个嗅觉是当有人告诉我,在服务中部署新功能a也需要部署 - 同时 - 在服务B中,或者人们开始编写服务以生成CSV。为什么有人会介绍网络跳跃以产生全球已知的文件格式?谁将保持这种情况?一些团队患有服务性。甚至比那更糟糕,它在发展时产生了很多摩擦。一个人不能只是在他们的IDE中调查一个项目,但它需要同时打开多个项目来了解所有这些混乱。

嘿,joão。能打扰你几分钟吗?我们需要修复我们的开发环境!人们一直在抱怨他们,这是'工作!

问题交叉不同的尺寸。移动开发人员未在开发环境中开发一个功能,或者在开发环境中或后端开发人员,他们想要尝试他们的服务DIDN' t打破任何业务流程。如果有人想在生产之前测试在移动应用程序中的整个流程中,它也是有问题的。

在云提供商中旋转200个服务是多少钱?你能做到吗?您还能旋转运行它们所需的基础架构吗?

这样做是多少时间?如果移动工程师开始开发一个功能,那么在给定版本中的一套服务,以及在完成时,将有十个新版本部署到生产中?

测试数据怎么样?您是否有所有服务的测试数据?这是船队的一致性,所以用户和其他实体匹配吗?

如果您' re开发多租户,多区域应用程序,那么配置和功能标志如何?您如何与生产保持同步?如果默认值改变了什么?

这是冰山一角。人们可以想到将工程权力投入这个问题。它可能有效。但是,我' D挑战大多数组织都有规模要做。做得对令人震惊和昂贵。

正如您可以想象的那样,端到端测试对开发环境具有类似的问题。之前,使用虚拟机或容器创建新的开发环境相对容易。使用Selenium创建一个测试套件,通过业务流程并断言他们在部署新版本之前正常工作是相当简单的。在微服务之后,即使我们可以解决所有上述环境和#39;在设置环境中的问题时,我们也无法声明系统是否已再次工作。至多,我们可以说明具有特定版本的服务运行的系统和给定配置在特定时间点工作。那个巨大的差异!

说服人们非常难以说服我们不能超过一些这些测试。并且它是不够在持续积分流中运行它们的'他们应该连续运行。他们应该违反生产并相应地产生警报。我分享了无数次Cindy Sridharan' s文章"生产中的测试,安全的方式"试图让人们了解我的观点。

在保持数据一致性的同时,在整体上轻松出路是继续使用共享数据库。它不会增加操作负荷,并且可以轻松地逐步切片。但是,它也具有相当大的缺点。除了一个明显的单点失败,击败了一些面向服务的建筑''更多。您每项服务创建用户吗?您是否具有细粒度的权限,因此服务A只能从特定表中读取或写入?如果有人无意中删除指数怎么办?我们如何知道有多少服务使用不同的表?缩放怎么样?

解开所有这一切都成为一个全新的问题。从技术上讲,考虑到数据库倾向于最终的软件,它可能不是微不足道的。使用数据复制解决问题 - 是Kafka,AWS DMS或其他 - 创建您的工程团队需要了解数据库细节以及如何处理重复的事件,等等。

API网关是面向服务的架构中的典型模式。他们'重新有助于从前端消费者分离后端。它们在实现系统中实现端点聚合,限速或身份验证时也有益。最近,该行业一直倾向于前端架构,其中这些网关为每一个前端消费者 - iOS,Android,Web或桌面应用程序部署 - 使他们的进化彼此分离。

与这个世界上的一切一样,人们开始为它创造新的创造性用例。有时它'是一个小的黑客,使移动应用程序向后兼容。突然,你有你的" API Gateway"作为一个失败的单点 - 因为人们发现更容易在一个地方处理身份验证 - 以及它内部的一些意外业务逻辑。而不是拥有一只巨大的交通,现在你有一个自制的春天启动服务才能获得所有的春天启动服务!什么可能出错?工程师很快意识到这是一个错误,但随着许多自定义,有时他们不能替代这件作品以无规定,级别友好的。

API Gateways灾害的罪魁祸首是在消耗没有分手或返回大规模响应的端点时出现的。或者当您在没有后退机制的情况下进行聚合时,使一个单个API调用刻录到网关。

分布式系统始终处于部分故障模式。在罐头和#39; T联系服务B时会发生什么?我们可以重试我们的要求,对吗?但这会及时导致我们走下兔子洞。使用断路器,然后使用断路器的团队,然后将HTTP调用的超时增加到下游的服务。虽然这可能是一个正常的反应来购买我们一些时间来解决问题,但它会产生二阶效应。现在,所有这些请求使您的断路器会取消,因为它们' re the loce在那里有更多时间。如果有流量增加,越来越多的请求将被排队,导致比您想要修复的情况更差。我看到工程师努力了解队列理论以及为什么有超时的地方。当团队开始讨论他们的HTTP客户端和Whatnot时,就会发生同样的事情。在配置那些本身的时,基于肠道的设定值可能会使您设置为显着的中断。

从失败中恢复时棘手的事情是并非所有这些都是相等的。在某些情况下,我们可能希望消费者能够宽容。但这意味着我们应该主动决定在每个故障情景中做些什么。消费者是个体化吗?我可以重试这个电话吗?我看到许多工程师忽略了这些,因为它' s"一个边缘案例",以稍后实现它们具有大规模的数据完整性问题。

即使您设置了回退机制,重试甚至比所有这些都剧烈。想象一下,您的移动应用程序中有五百万用户,您的留言总线更新用户偏好'停止工作一会儿。您为该案例设置了一个抵押机制,该机制调用用户'首选项通过HTTP API服务。我猜你知道在哪里我去了。现在,这项服务突然出现了大量的交通飙升,可能无法应对所有流量。它甚至更糟糕的是:您的服务可能能够获得所有这些新请求,而是如果重试机制不受指数退避和抖动,您可能会遇到来自您的分布式拒绝服务移动应用程序。

如果我告诉过你我只写了关于灾难的一小部分我看到了什么? 🤣分布式系统很难掌握,最近大多数软件工程师都始终暴露于它们。

好事是,许多灾难我谈到了有良好的答案,行业创造了更好的工具,使他们由榴景以外的组织制定。

我仍然喜欢分布式系统,我仍然认为微服务是组织问题的好解决方案。但是,当我们考虑到&#34的故障时,问题来自于"边缘案例"或者我们认为永远不会发生在我们身上的事情。这些边缘案例以一定的规模变成新的正常,我们应该应对它们。