众善之源 or 万恶之源?详析微服务的好与坏

【CSDN 编者按】微服务是近年来的一个热点话题。他与 API 挂钩,就像是躯干输水管道的接口,看似格格不入影响美观,实际上作用难以估量。

编译 | 弯月  责编 | 张文

头图 | CSDN 下载自视觉中国

出品 | CSDN(ID:CSDNnews)

什么是微服务?

微服务是一种软件架构风格,以专注于单一责任与功能的小型功能块为基础,利用模块化的方式组合出复杂的大型应用程序,各功能块通过 API 相互通信

普通的 Web 应用程序只需要一个进程就可以处理所有请求(姑且不谈负载均衡的问题),你需要运行的程序包/软件只有一个,其中包含了所有逻辑。

然而,微服务就不同了,其中包含多个不同的进程,每个进程仅服务一小部分请求。每个进程都需要运行一个单独的程序包,而且只包含自己所需的代码。

微服务不是一个新概念。微服务的模式只不过是更高层的面向对象编程:应用程序体系结构。它经常利用 HTTP API,尤其是 RESTful,这并非偶然,这实际上是面向对象原则应用到了 API 设计中

在使用面向对象编程的时候,你将代码分割成类。每个类代表解决方案的一个组件,具有特定的作用。而且每个类只能处理自己的数据。听起来是不是很熟悉?

 

微服务的两大原则

在设计类的时候,你需要遵循两大主要原则:高内聚与低耦合。

  • 高内聚:尽可能类的每个成员方法只完成一件事(最大限度的聚合)。

  • 低耦合:减少类内部,一个成员方法调用另一个成员方法。

微服务也一样。良好的面向对象设计也可以成就优秀的微服务设计。

微服务的分割方式与面向对象完全一样,你需要遵守高内聚低耦合。你知道如何按照正确的方式将代码分割成类,同样在分割微服务的时候也不能随意。

类的设计不合理会导致维护和管理难度加大,因为代码被分散到不同的文件中。同样,随意分割的微服务应用程序也会导致代码分散到不同的进程中。

 

为什么应该将应用程序分割成微服务?

两个对象的交互非常简单,只需调用一个对象的方法即可。一切都在一个程序中。

然而,各个微服务位于不同的进程内,甚至在不同的机器上。你必须通过网络,使用 API 通信。

微服务会增加复杂度!因此,必须有足够的理由才值得考虑微服务。你不能只是为了追求潮流,或单纯为了好玩,而采用微服务。随意分割的微服务引发的管理问题一点都不好玩。

实际上,分割微服务的理由和设计 API 的理由一样。API 有很多优势,比如隐藏所有实现细节,这在有些情况下非常关键。

3.1 实现规模伸缩,以应对流量不均匀

假设你有一个超市的应用程序。你有一个库存微服务,只负责显示库存商品的数量。还有一个视觉识别微服务,使用 GPU 根据特定的图片来检测商品。

某一天,你收到了大量的库存 API 调用,但是视觉识别 API 的请求却很少,那么你需要扩展库存微服务。但是,你不需要增加 GPU 资源。

如果所有的服务都囊括在一个计算机或应用程序中,那么你需要扩展所有的服务,包括上面的 GPU 资源,这势必会造成浪费。

3.2 容错能力

假设你有一个银行的应用程序。某一天,转账微服务不断宕机,原因可能是由于某个临时的错误,也有可能是新引入的 bug。

在这种情况下,没有必要让整个银行应用程序都下线。也许有的顾客压根没注意到,因为他们只想查看余额或取钱。

3.3 单独部署

如果你想添加新功能或修复bug,则只需要正确部署相应的微服务即可。构建和部署的时间相对更短。

只不过,你可能需要将微服务放在不同的计算机上,放在不同的位置上。

3.4 完全隔离

你可以完全隔离各个微服务。你可以使用不同的数据库(SQL和noSQL),或不同的技术。这可以给你很大的自由度。

当然,容错能力或需求等其他方面的要求会相对更严格。

3.5 不同的要求

有些服务需要执行繁重的计算,比如机器学习,你需要GPU、相应的库等等;而有些服务则没有这样的要求。

有些服务用 Python 实现更好,而有些则更适合 Java。

有时,所有服务都使用同一种语言或库,可能会产生一些冲突。而有时,你迫切需要两个特定的版本来完成两个不同的任务。

再或者,你可能希望使用两种不同的云产品,来托管两个截然不同的服务。

在上述这些情况下,你需要分割应用程序。但是,请千万牢记两大主要原则:高内聚与低耦合。

 

单体架构

如果你的系统具有高耦合性,则可以考虑使用单体架构。

单体架构的依赖关系更加清晰,并且不需要复杂的编排或分布式系统来跟踪错误、共享数据、收集日志、同步调用、安全的网络交互等等。

如果面向对象编程不适合你的应用程序,RESTful 设计也不合适,那么微服务必然也行不通。

如果你的应用程序需要服务一长列 API 调用,而且后一个 API 需要用到前一个的结果,那么微服务也不是理想的选择,因为这会造成网络延迟。

如果你的应用程序是需要用户交互的单个过程,那么就是过程式。

如果 API 调用之间需要共享状态,每个组件都不是独立的,而且遇到错误就会造成整个队列的阻塞,那么分割应用程序几乎没有任何好处。

 

单体架构并不意味着混乱

有人认为单体架构就是一堆无序的代码,他们认为微服务模式是分割的、有秩序的代码的唯一方式。然而,实际情况并非如此。

代码的设计不需要依赖于进程的划分。其实面向对象编程也不是按进程划分的。如果你正确地拆分代码,并建立清晰的层次结构,妥善管理依赖关系以及文件,也可以实现相同级别的内聚和解耦。

另外,你还可以将 API 分割成不同的包、模块、控制器等等,然后通过一个进程来提供服务,或者你也可以按照构建时或运行时将它们拆分成微服务。

 

总结

如果你在正确的环境中,出于正确的原因,通过正确的方式使用微服务,那么它们可以帮助你解决问题,并提高性能或节约成本。

但是,你不能将它们视为所有问题的唯一解决方案。因为它们也有可能成为万恶之源。

参考链接:https://medium.com/swlh/stop-this-microservices-madness-8e4e0695805b

已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 代码科技 设计师:Amelia_0503 返回首页