[译] 模块化 vs. 微服务

模块化 vs. 微服务

使用模块化系统设计原则来避免微服务的复杂性。html

从单体式应用向微服务架构迁移已是老生常谈的话题了。除了过过嘴瘾,彷佛真的动手将单体式应用拆分红微服务也不是什么很困难的事。可是这种作法真的是大家团队的最佳选择吗?维护一个凌乱的单体式应用的确很伤脑筋,可是还有另外一种优秀但经常被人忽视的替代方案:模块化应用开发。本文将探讨这种替代方案,并展示其与构建微服务的关系。前端

模块化微服务

“经过微服务,咱们终于可以让团队独立工做了”或者“咱们的单体式应用实在太复杂了,它下降了咱们的工做效率”之类的话,只是让团队改用微服务架构的诸多缘由中的一小部分;还有一种说法是须要可拓展性与弹性。全部开发人员彷佛都渴望系统设计和开发的模块化。软件开发中的模块化能够总结为如下三个原则:java

  • 强大的封装性:隐藏了各个组件内部实现的细节,减小了不一样组件之间的耦合性。团队能够在系统的各个非耦合部分中独立地工做。
  • 定义良好的接口:你不可能隐藏组件内的全部东西(不然你的系统将毫无心义),所以有必要在组件之间定义良好且可靠的 API。任意一个组件均可以被符合接口规范的其它组件替换。
  • 显式依赖:模块化系统意味着不一样的组件须要在一块儿工做。所以你最好能有一种途径来表达(与验证)它们之间关系。

这些原则均可以用微服务架构来实现。只要作到对其它服务暴露定义明确的接口(一般是一个 REST API),就能以任意方式来实现一个微服务。它的实现细节是这个服务内部的事情,你能够改变这些实现细节而不影响整个系统。微服务之间的依赖关系一般在开发时是不明确的,这可能会致使在运行时服务编排失败。只能说在大多数微服务架构中,实现最后一条模块化原则还须要再接再砺。react

所以,微服务架构实现了重要的模块化原则,并带来了如下三点实实在在的好处:android

  • 团队可以独立地工做与扩张。
  • 微服务小巧、专注,下降了复杂度。
  • 服务能够在不会影响全局的状况下内部进行更改或者替换。

那么微服务架构的缺点是什么呢?当你从一个单体式(虽然有点臃肿)应用切换成微服务分布式系统的时候,给表操做带来了巨大的复杂性。忽然间,你发现你要不断地部署各类不一样的(多是由容器包装的)服务。这时,服务发现、分布式日志记录、跟踪等新的问题出现了。如今,你更加容易出现分布式计算的谬论形成的错误。接口的版本管理与配置管理成为你面对的主要问题。各类问题将数不胜数向你涌来。ios

事实证实,因为全部的微服务个体都须要联合起来实现业务逻辑,微服务之间的链接将变得无比复杂。看到这里,你应该意识到不能简单地将单体式应用拆分红微服务了。单体式应用中的“意大利面条式代码”问题重重,在其中再加上网络边界会将这些纠缠在一块儿的问题升级成彻头彻尾的痛苦。git

模块化的替代方案

这是否意味着咱们要么沉没在混乱的单体式应用中,要么淹没在使人抓狂的微服务复杂性中呢?其实,模块化也能够经过其它方式实现。在开发时最重要的是正确地规划项目边界并实施方案,咱们也能够经过建立一个结构良好的单体式应用来实现这一点。固然,这意味着咱们将尽量利用编程语言与开发工具的协助来实现模块化原则。es6

例如在 Java 中,有几个能够帮助你构建应用的模块系统。OSGi 是其中最著名的一个,不过随着 Java 9 的发布,Java 平台将加入一个原生的模块系统。如今模块做为一等结构(first-class construct),成为了语言和平台的一部分。Java 模块能够代表对其它模块的依赖,以及在强封装实现类的时候公开暴露接口。甚至 Java 平台自己(一个庞大的代码库)已经使用了新的 Java 模块系统进行模块化。你能够在我即将出版的书Java 9 Modularity中了解有关 Java 9 模块化开发的更多信息。(现早期版本已经发布)github

其它的语言也提供了相似的机制。例如,JavaScript 在 ES2015 规范中提供了一个模块系统。在此以前,Node.js 也为 JavaScript 后端提供了一个非标准的模块系统。然而 JavaScript 做为一种动态语言,对于强制接口(类型)与模块封装的支持仍是较弱。你能够考虑在 JavaScript 的基础上使用 TypeScript 来从新得到这些优势。微软的 .Net 框架与 Java 同样都有着强类型,但就强封装以及程序集(Assemblies)间的显式依赖而言,它与 Java 即将推出的模块系统并不相同。尽管如此,你能够经过使用 .Net Core 中标准化的反转控制模式(IOC)以及建立逻辑相关的程序集来实现良好的模块化架构。即便是 C++ 也在之后的版本中考虑添加模块系统。许多语言都在向模块化靠近,这自己就是一个显著的进步。数据库

当你有意识地使用你的开发平台的模块化特性时,你就能够实现以前说起的微服务的模块化优点。基本上模块系统越好,你在开发过程当中得到的帮助就越多。只要在不一样团队间的接触点定义好明确的接口,不一样的团队也能够独立进行不一样部分的工做。固然,在部署时仍是要将模块在一个单独的部署单元中组合起来。这样能够防止过于复杂,以及减小迁移到微服务所须要的开发与管理成本。诚然,这也意味着你不能使用不一样的技术栈来构建不一样的模块,但你的团队应该不会真的这么作吧?

模块设计

建立好的模块和建立好的微服务同样,都须要严谨的设计。一个模块应该基于其域的有界上下文建模(DDD)。选择微服务的边界是架构上重要的决策,一旦出错就可能要付出沉重的代价。相较而言,模块化应用程序模块的边界更容易修改一些。模块间的重构一般由类型系统和编译器支持。微服务边界的从新划分则涉及大量的进程间通讯(IPC),以确保运行时稳定性。老实说,你真的只用一次两次就能正确的划分好边界?

在许多方面,静态语言的模块为了定义明确的接口而提供了更好的结构。经过调用另外一个模块暴露的接口提供的方法,比去调用另外一个微服务的 REST 端点健壮性要强的多。REST+JSON 如今无处不在,但在没有编译器检查的状况下,它并无”类型良好的互通性“这个特色。而事实上,经过网络序列化(或者反序列化)数据并非无开销的,甚至这种传输方式更加逊色。此外,许多模块化系统容许你代表此模块对于其它模块的依赖关系,模块系统将不容许违背这些依赖关系的状况出现。而微服务之间的依赖关系只在运行时实现,致使系统难以调试。

模块也是代码全部权中的天然单位。一个团队能够负责系统中的一个或者多个模块,而只须要给其它团队提供模块的公共 API。在运行时,模块之间的隔离比微服务少,毕竟模块化单体式应用的全部模块都运行在同一个进程中。

毫无疑问,单体式应用的模块不可能像微服务同样有本身的数据。模块化应用内部的数据交流是经过定义良好的接口或者模块间的消息进行的,而不是经过共享数据存储进行。它与微服务最大的差异就是它的一切都发生在同一个进程中,所以一样不能低估最终的数据一致性问题。对于模块来讲,最终的一致性问题能够是一个策略问题,或者你也能够仅将数据”逻辑地“分开存储在同一数据库内并仍然使用跨域事务。而对于微服务来讲,这个问题别无选择:必须保证最终的一致性。

什么时候微服务才适用于你的团队?

那么什么时候迁移到微服务架构才合适呢?到目前为止,咱们主要关注的是如何经过模块化来解决复杂性问题。对于这一点,微服务与模块化应用均可以作到,只不过各有所难。

当你的团队有如同 Google 或者 Netflix 般的规模的时候,拥抱微服务是毋庸置疑的。你有能力去创建你本身的平台与工具库,而且工程师的数量排除了任何使用单体式解决方案的可能。可是大多数的组织都达不到这个规模。即便你认为你的公司有朝一日将成为一个市值十亿美圆的独角兽,在刚起步时使用模块化的单体式应用也无伤大雅。

另外一个拆分微服务的理由是:不一样的服务在实现上更适合使用不一样的技术栈。那么,你必须有足够的规模来吸引人才以解决这些迥然不一样的技术栈,并支持这些平台的运行。

微服务还能够作到独立部署系统的不一样部分,这在大多数模块化平台中很难(甚至不可能)实现。隔离部署增长了系统的弹性与容错能力。此外,每一个微服务的缩放特性能够是不一样的,能够部署不一样的微服务以匹配硬件。模块化的单体式应用能够进行水平缩放,可是只能将全部模块捆绑在一块儿同时进行拓展。虽然你能够经过这种方法获得不少好处,但这可能并非最好的解决方案。

总结

总之,最好的方案就是找到一个折中的点。这两种方案都有可取之处,须要根据实际环境、组织和应用自己进行选择。既然你能够在以后迁移成微服务架构,那为何最开始不直接使用模块化应用呢?若是你以前就已经划分好了模块边界,那也就不须要再去拆分你的单体式应用了。甚至你还能够在模块内部搭建微服务架构。那么问题就变成了:为何微服务必定要是“微”的呢?

即便你的应用刚从模块化应用转成微服务架构,服务也没必要非得很“微”才具有可维护性。在服务中应用模块化原则能让它们在复杂度的可扩展性上超越一般的微服务。如今这份蓝图中既有微服务也有模块,减小架构中的服务的数量能够节约成本;而其中的模块能够像构建单体式应用同样,构建和扩展服务。

若是你追求模块化的好处,请确保本身不要自嗨进入一种“非微服务不可”的心态。探索你喜好的技术栈中的同进程模块化功能或框架,你将会获得支持去真正的执行模块化设计,而不是仅靠着约定来避免“意大利面条式代码”。最后,请深思熟虑后再选择:你是否愿意接受引入微服务形成的复杂度成本。有的时候你别无选择,但更多的时候其实你能够找到更好的解决方案。


掘金翻译计划 是一个翻译优质互联网技术文章的社区,文章来源为 掘金 上的英文分享文章。内容覆盖 AndroidiOSReact前端后端产品设计 等领域,想要查看更多优质译文请持续关注 掘金翻译计划

相关文章
相关标签/搜索