微服务的优缺点

本文来源于我在InfoQ中文站翻译的文章,原文地址是:http://www.infoq.com/cn/news/2014/06/microservices


近期一段时间以来,社区中环绕着微服务产生了许多争论,也充斥着大量的宣传。过去的10年间,我们已经实现了许多笨重的SOA解决方式,微服务是业界期待已久的解决方式么?或者说微服务要比总体解决方式更加简单?

在讨论这些话题之前,我们最好先对微服务下个定义。在题为微服务的文章中,作者James LewisMartin Fowler是这样定义微服务架构风格的:

开发单个应用作为一系列小型服务的套件,当中每一个服务都执行在自己的进程中,而且通过轻量级的机制实现彼此间的通信,这一般是HTTP资源API。这些服务是环绕着业务功能构建的,而且能够通过全然自己主动化的部署机制进行独立部署。这些服务的集中式管理做到了最小化,每一种服务都能够通过不同的编程语言进行编写,而且能够使用不同的数据存储技术。

微服务的一些优势是显而易见的:

  • 每一个服务都很easy,仅仅关注于一个业务功能。
  • 每一个微服务能够由不同的团队独立开发。
  • 微服务是松散耦合的。
  • 微服务能够通过不同的编程语言与工具进行开发。

这些优势使得微服务看起来是很完美的解决方式,只是微服务难道就没有缺点么?

Contino的CTO Benjamin Wootton正在基于微服务对一个系统进行架构设计,他遇到了不少困难,而且将遇到的这些问题发表在了题为Microservices - Not A Free Lunch!的文章中。以下是文章的一些摘要。

运维成本过高

故障恢复后,20个服务可能要占领40——60个进程,同一时候弹性问题也浮现出来了。在加入了负载均衡与消息中间件后,进程的数量还会持续添加。运维与编排全部这些服务是个“令人望而却步的任务”,Wootton说到:

实现全部这些需求须要高质量的监控与运维基础设施。保持一台应用server的持续执行就须要专人来负责,但如今我们还得确保几十、甚至是几百个进程都处于执行状态、不能将磁盘空间耗尽、不能出现死锁,还要保证性能。这真是一个很棘手的任务。

运维的过程须要自己主动化,只是由于“并没有多少框架和开源工具能够对此提供支持”,结果就是“使用微服务的团队要在他们编写具有业务价值的第一行代码前须要大量使用自己定义脚本或是进行开发以管理这些进程”。

DevOps是必须的

Wootton觉得实现微服务的组织须要DevOps,这是由于:

你不能简单地将通过这样的风格构建的应用抛给运维团队。开发团队须要很关注运维与产品,由于基于微服务的应用与其环境上下文是很紧密地集成到了一起的。

由于许多服务可能都须要自己的数据存储,因此开发人员还须要“搞清楚怎样部署、执行、优化以及支持各种NoSQL产品”。

接口不匹配

服务依赖于彼此间的接口进行通信。改变一个服务的接口会对其它服务造成影响,Wootton谈到:

改动了契约一方的语法或是语义,那么全部其它服务都须要理解这个改变。在微服务环境下,这意味着简单的交叉改变会导致许多不同的组件发生变化,这些组件须要以一种协调一致的方式进行公布。

当然了,我们能够通过向后兼容的方式避免这些变化的发生,只是实际情况却是业务驱动的需求让我们没法实现分阶段的公布。

假设彼此协同的服务向前推进而且不再同步了,比方说使用canary公布方式,那么改动消息格式的效果就难以可视化了。

代码反复

为了避免将“同步耦合引入到系统中”,Wootton觉得有时须要向不同服务加入一些代码,这就会导致代码反复,而代码反复“是很不好的,由于每一个代码实例都须要进行測试和维护”。一种解决方式是在服务间使用共享库,只是“在多语言环境下这即可不通了,而且引入了耦合就意味着服务须要并行公布来维护彼此间的隐式接口”。

分布式系统的复杂性

作为一种分布式系统,微服务引入了复杂性和其它若干问题,比方说“网络延迟、容错性、消息序列化、不可靠的网络、异步、版本号化、应用层中的负载变化等等”。

异步

Wootton觉得微服务经常会使用异步编程、消息与并行,假设要求某个操作必须是同步且具有事务的,那么这就很复杂了,这要求我们得“管理好相关联的ID以及分布式事务,将各种动作绑定在一起”。

測试

使用微服务架构时,測试是还有一个须要考虑的问题,由于“不管是手工測试还是自己主动化測试,我们都很难以一致的方式重现环境”,Wootton说到:

当加入了异步与动态消息负载后,要測试以这样的风格构建的系统就难上加难了,同一时候也无法对将要公布到生产的各种服务抱有信心。

我们能够測试每一个服务,只是在这样的动态环境下,很微妙的行为都会从服务间的交互中产生出来,这是难以做到可视化的,也不易想清楚,更不必说全面的測试了。

Brady评论了Wootton的文章,谈到了他尝试从总体应用向微服务转变的经历:

正在从事的一个项目就在从一个总体应用向微服务迁移,我们遇到了你在文章中提到的大量问题。最后有大量反复代码(由于这些服务是使用不同语言和框架构建的),遇到了许多“隐式契约”问题。比方说,将一个服务的User数据映射到还有一个服务上(当中一个服务不一定像还有一个服务一样须要全部的数据)。尽管这样的方式有一些显而易见的优点,只是在使用之前一定要有很精心的规划才行。最后,我们所採取的方式是对总体应用进行模块化(这样就能够在模块间共享代码仓库、部署和代码了,同一时候依旧保持良好的松散耦合的组件)并将一些模块放到自己独立的微服务中来实现独立的部署与管理,当然了,我们仅仅在必要的情况下才这么做。

还有一位读者Dennis Ehle也分享了他在微服务方面的经验,他给出的结论是微服务是有代价的:

我们眼下为一个客户实现了一个CD管道自己主动化框架,有450个开发人员,50个服务(或者叫微服务)。对于我来说,这样的架构最迷人的地方在于这450个开发人员都不须要编写一行代码来支持顾客的用户界面。UX方面的工作是由一个不同的小组完毕的。
尽管很灵活、风险小,而且节省了成本,这个客户也很喜欢这一点,直接的结果就是从总体架构全然迁移过来了,只是毋庸置疑的是,由于文中提到的众多因素,使用微服务还是须要付出额外的成本的。

此外,读者Steve Willcox提到了微服务所引入的一些挑战:

作为从总体Java应用转换为SOA实现过程中的一名技术领导,我遇到了文中提到的全部问题,只是相对于将其看作是问题,我将他们看作构建更好的软件的机会。

文中提到“须要大量的DevOps技术”,我觉得这很好啊。这样,开发人员就有机会了解自己编写的代码是怎样执行的了。採用SOA实现会迫使你成为一名DevOps,服务团队开发人员自己做DevOps,而不像曾经那样“将东西丢给集中化的运维团队”。这对于让开发团队负责自己代码的运维来说是积极的。

没错,相对于总体应用来说,採用微服务会有许多其它的服务要构建、測试和部署,只是时至今日,这些事情应该都是自己主动化的了。仅仅要遵循同样的自己主动化模式,2个和20个的工作量事实上区别不大。

关于代码反复,读者Willcox觉得结果事实上没那么差:

对于这一点,我过去是很纯粹的,觉得全部的代码反复都是不好的,只是接下来我认识到这样的纯粹性有时会导致更高的代价,更复杂的系统。我如今就变得很实际了,简单性也是很重要的一个方面。我很认可Richard Gabriel在The Rise of Worse is Better一文中对此的论述。

总而言之,微服务架构有许多吸引人的地方,只是在拥抱微服务之前,你须要认清它所带来的挑战。

查看英文原文:The Strengths and Weaknesses of Microservices

原文地址:https://www.cnblogs.com/mengfanrong/p/3813676.html