微服务-不是免费的午餐!


 ## 微服务-不是免费的午餐

这是Contino的 CTO Benjamin Wootton的来宾帖子,Contino是一家总部位于伦敦的咨询公司,致力于将DevOps和Continuous Delivery应用于软件交付项目。

微服务是一种软件体系结构,涉及将系统作为一组非常小的,颗粒状的,独立的协作服务进行交付。

尽管它们并不是一个新主意,但微服务在今年似乎已经爆炸式增长,文章,会议曲目和Twitter流都在抒情地表达了以这种方式构建软件系统的好处。

这种受欢迎程度部分是由于Cloud,DevOps和Continuous Delivery等趋势共同推动了这种方法的实现,部分是由于Netflix等公司的出色工作而来,这些公司非常明显地应用了这种模式以产生巨大效果。

首先让我说我是这种方法的粉丝。微服务架构具有许多非常实际和重大的好处:

服务本身非常简单,专注于做好一件事情。
可以使用最合适的最佳工具来构建每种服务;
以这种方式构建的系统本质上是松散耦合的。
在这种模式下,多个开发人员和团队可以彼此相对独立地交付;
它们是持续交付的重要推动力,可以频繁发布,同时保持系统的其余部分可用并稳定。
这就是说,微服务不是免费的午餐!

我目前正在参与设计基于微服务的系统,尽管各个服务非常简单,但是在管理这些服务和协调整个服务的业务流程方面,存在更高层次的复杂性。

微服务是在实践中很好的想法之一,但是当遇到现实时就会出现各种复杂性。出于这个原因,我想写这篇文章来捕捉其中的一些并纠正这种平衡。

重大运营开销

微服务架构带来了大量的操作开销。

在可能将整体应用程序部署到小型应用程序服务器群集的地方,您现在可以使用多种语言和环境使用数十个单独的服务来构建,测试,部署和运行。

所有这些服务都可能需要群集以实现故障转移和弹性,在您添加弹性后,您的单个整体系统将变成由40-60个进程组成的20个服务。

与提供相同业务功能的单个整体应用程序相比,用于在服务和资产之间进行连接的负载平衡器和消息传递层开始变得相当大!

生产所有这些需要高质量的监视和操作基础结构。保持应用程序服务器运行可能是一项全职工作,但是现在我们必须确保数十个甚至数百个进程保持正常运行,不要用完磁盘空间,不要死锁,保持高性能。这是一项艰巨的任务。

通过您的管道将大量的微服务以物理方式运送到生产中,还需要非常高度的鲁棒性以及发布和部署自动化。

当前,从操作的角度来看,没有太多的框架和开源工具来支持这一点。因此,推出微服务的团队可能需要在自定义脚本或开发上进行大量投资,以管理这些流程,然后再编写可提供业务价值的代码行。

对于模型,操作是最明显且最普遍的反对意见,尽管它很容易被该体系结构的支持者遗忘。

要求具备实质性的DevOps技能

在开发团队可能能够启动Tomcat群集并使之保持可用的地方,保持Microservices处于可用状态的操作挑战意味着您确实需要高质量的DevOps并释放嵌入在开发团队中的自动化技能。

您根本无法将以这种样式构建的应用程序扔给运营团队。由于基于微服务的应用程序非常紧密地集成到其环境中,因此开发团队需要非常专注于操作和生产意识。

惯用此体系结构还意味着许多服务也将需要自己的数据存储。当然,这些也可以是多语言的(最适合该工作的工具!),这意味着现在必须由对如何部署,运行,优化和支持少量NoSQL了如指掌的开发人员替换古老的DBA。产品。

拥有如此强大的DevOps配置文件的开发人员很难找到,因此如果您走这条路,您的招聘挑战就会变得更加困难。

隐式接口

一旦将系统分解为协作组件,就会在它们之间引入接口。接口充当合同,双方需要交换相同的消息格式并对这些消息具有相同的语义理解。

更改合同一侧的语法或语义,所有其他服务都需要了解该更改。在微服务环境中,这可能意味着简单的跨领域变更最终需要对许多不同的组件进行更改,所有这些组件都需要以协调的方式发布。

当然,我们可以使用向后兼容方法来避免其中的某些更改,但是您经常会发现,业务驱动的需求无论如何都禁止分阶段发布。例如,发布新产品线或外部强制性法规变更可能会迫使我们一起释放大量服务。由于集成点,与替代的整体应用程序相比,这代表了额外的发布风险。

如果我们让协作服务前进并变得不同步(也许以金丝雀的发布风格),则更改消息格式的效果将变得非常难以可视化。

再次,贝克特兼容性在这里并不是微服务传播者声称的万能药。

重复努力

想象一下,存在一项新的业务需求,即针对某个产品线以不同方式计算税额。我们有几种选择来实现这一目标。

我们可以引入一项新服务,并允许其他服务在需要时调用此服务。但是,这确实将更多潜在的同步耦合引入到系统中,因此我们不会轻易做出决定。

我们可以复制工作量,将税额计算添加到需要它的所有服务中。除了重复的开发工作之外,以这种方式重复执行通常被认为是一个坏主意,因为每个代码实例都需要进行测试和维护。

最后的选择是在服务之间共享资源,例如税收计算库。这可能很有用,但是它并不总是在多语言环境中起作用,并且引入了耦合,这可能意味着必须并行释放服务以维护它们之间的隐式接口。这种耦合实质上减轻了微服务方法的许多好处。

在我看来,这三个选项都是次优的,而不是一次编写代码并使之在整个应用程序中可用。我见过的以这种方式工作的团队倾向于选择2,复制业务逻辑,这违反了良好软件工程的许多原则。是的,这甚至发生在经过良好分解和设计良好的系统中-并不总是表明服务边界不好。

分布式系统复杂度

微服务意味着分布式系统。在以前可能有一个方法调用充当子系统边界的地方,现在我们引入了许多远程过程调用,REST API或消息传递,以将不同进程和服务器之间的组件粘合在一起。

分发完系统后,我们必须考虑很多以前从未考虑过的问题。网络延迟,容错,消息序列化,不可靠的网络,异步性,版本控制,我们的应用程序层中的不同负载等。

为其中一些编码是一件好事。向后兼容性和正常降级是我们可能无法在整体式替代方案中实现的良好属性,有助于保持系统正常运行,并且比整体式应用程序具有更高的可用性。

但是,这样做的代价是应用程序开发人员必须考虑所有以前不需要的所有事情。分布式系统更难以开发和测试一个数量级,因此与构建那种不性感的整体应用程序相比,门槛再次提高。

异步困难!

与上述观点有关,以微服务样式构建的系统可能比单片应用程序异步得多,它们依靠消息传递和并行性来提供其功能。

当我们将工作分解成真正独立的独立任务时,异步系统非常有用,这些任务可能在不同时间发生混乱。

但是,当事情必须在固有的异步体系结构中同步或事务发生时,事情变得复杂了,我们需要管理关联ID和分布式事务以将各种操作绑定在一起。

可测性挑战

如此众多的服务都以不同的步伐发展,并且不同的服务在内部推出了canary版本,因此很难以一致的方式重新创建环境以进行手动或自动测试。当我们添加异步性和动态消息负载时,测试以这种方式构建的系统变得更加困难,并且对将要发布到生产环境中的服务集充满信心。

我们可以测试单个服务,但是在这种动态环境中,服务的交互会出现非常细微的行为,很难对其进行可视化和推测,更不用说对其进行全面测试了。

惯用微服务需要减少对测试的重视,而将更多的精力放在监视上,因此我们可以发现生产中的异常并迅速回滚或采取适当的措施。我坚信这种方法-降低释放壁垒并倾向于连续交付以加快瘦肉交付。但是,由于花了数年时间应用测试自动化以在发布之前获得信心的人,降低此功能的任何事情都感觉要付出高昂的代价,尤其是在错误规避风险的环境中,错误可能会产生重大影响。

结论

这些是在构建和运行基于微服务的系统的早期阶段遇到的一些困难。

我仍然是这种方法的忠实拥护者,并相信在具有适当团队的适当项目下,采用这种架构是一种很棒的架构,在这种架构中,收益大于成本。

但是,在考虑像微服务这样的体系结构时,重要的是不要被这一类的炒作吸引,因为挑战和成本与收益一样真实。


文章作者: Jone
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Jone !
评论
 上一篇
整合测试 整合测试
整合测试如何在微服务架构中编写集成测试?编写集成测试需要大量的精力。与编写单元测试相比,它花费更多,并且要打开的锁数量要多得多。虽然我们仅通过单元测试保证服务的功能,但我们需要集成测试来保证与其他服务的通信。 当涉及集成时,难度级别会进一步
2019-04-16
下一篇 
Dockerfile 定制镜像 Dockerfile 定制镜像
从前面一节的docker commit的学习中,我们可以了解到,镜像的定制实际上就是定制每一层所添加的配置、文件等信息,但是命令毕竟只是命令,每次定制都得去重复执行这个命令,而且还不够直观,如果我们可以把每一层修改、安装、构建、操作的命令都
2018-08-21
  目录