一、SOA 和微服务对比
开门见山,直接给出部分维度下SOA 和微服务的对比情况:
接下来,详细从不同的对比维度说下SOA和微服务的特点:
1、服务粒度
整体上来说,SOA 的服务粒度要粗一些,而微服务的服务粒度要细一些。例如,对一个大型企业来说,“员工管理系统”就是一个 SOA 架构中的服务;而如果采用微服务架构,则“员工管理系统”会被拆分为更多的服务,比如“员工信息管理”“员工考勤管理”“员工假期管理”和“员工福利管理”等更多服务。
2、服务通信
SOA 采用了 ESB 作为服务间通信的关键组件,负责服务定义、服务路由、消息转换、消息传递,总体上是重量级的实现。微服务推荐使用统一的协议和格式,例如,RESTful 协议、RPC 协议,无须 ESB 这样的重量级实现。Martin Fowler 将微服务架构的服务通讯理念称为“Smart endpoints and dumb pipes”,简单翻译为“聪明的终端,愚蠢的管道”。之所以用“愚蠢”二字,其实就是与 ESB 对比的,因为 ESB 太强大了,既知道每个服务的协议类型(例如,是 RMI 还是 HTTP),又知道每个服务的数据类型(例如,是 XML 还是 JSON),还知道每个数据的格式(例如,是 2017-01-01 还是 01/01/2017),而微服务的“dumb pipes”仅仅做消息传递,对消息格式和内容一无所知。
3、服务交付
SOA 对服务的交付并没有特殊要求,因为 SOA 更多考虑的是兼容已有的系统;微服务的架构理念要求“快速交付”,相应地要求采取自动化测试、持续集成、自动化部署等敏捷开发相关的最佳实践。如果没有这些基础能力支撑,微服务规模一旦变大(例如,超过 20 个微服务),整体就难以达到快速交付的要求,这也是很多企业在实行微服务时踩过的一个明显的坑,就是系统拆分为微服务后,部署的成本呈指数上升。
4、应用场景
SOA 更加适合于庞大、复杂、异构的企业级系统,这也是 SOA 诞生的背景。这类系统的典型特征就是很多系统已经发展多年,采用不同的企业级技术,有的是内部开发的,有的是外部购买的,无法完全推倒重来或者进行大规模的优化和重构。因为成本和影响太大,只能采用兼容的方式进行处理,而承担兼容任务的就是 ESB。
微服务更加适合于快速、轻量级、基于 Web 的互联网系统,这类系统业务变化快,需要快速尝试、快速交付;同时基本都是基于 Web,虽然开发技术可能差异很大(例如,Java、C++、.NET 等),但对外接口基本都是提供 HTTP RESTful 风格的接口,无须考虑在接口层进行类似 SOA 的 ESB 那样的处理。
通过前面的详细分析和比较,似乎微服务本质上就是一种比 SOA 要优秀很多的架构模式,那是否意味着我们都应该把架构重构为微服务呢?其实不然,SOA 和微服务是两种不同理念的架构模式,并不存在孰优孰劣,只是应用场景不同而已。我们介绍 SOA 时候提到其产生历史背景是因为企业的 IT 服务系统庞大而又复杂,改造成本很高,但业务上又要求其互通,因此才会提出 SOA 这种解决方案。如果我们将微服务的架构模式生搬硬套到企业级 IT 服务系统中,这些 IT 服务系统的改造成本可能远远超出实施 SOA 的成本。
二、微服务的陷阱
在选择技术实现时,不能盲目的选择微服务,需要考虑团队的规模、业务的发展以及基础技术的支撑等情况来看,不要以为实施了微服务后就什么问题都解决了,而一旦真正实施后才发现掉到微服务的坑里面去了。那微服务具体有哪些坑呢?
1、服务划分过细,服务间关系复杂
服务划分过细,单个服务的复杂度确实下降了,但整个系统的复杂度却上升了,因为微服务将系统内的复杂度转移为系统间的复杂度了。
从理论的角度来计算,n 个服务的复杂度是 n×(n-1)/2,整体系统的复杂度是随着微服务数量的增加呈指数级增加的。下图形象了说明了整体复杂度:
2、服务数量太多,团队效率急剧下降
微服务的“微”字,本身就是一个陷阱,很多团队看到“微”字后,就想到必须将服务拆分得很细,有的团队人员规模是 5 ~ 6 个人,然而却拆分出 30 多个微服务,平均每个人要维护 5 个以上的微服务。
这样做给工作效率带来了明显的影响,一个简单的需求开发就需要涉及多个微服务,光是微服务之间的接口就有 6 ~ 7 个,无论是设计、开发、测试、部署,都需要工程师不停地在不同的服务间切换。
开发工程师要设计多个接口,打开多个工程,调试时要部署多个程序,提测时打多个包。测试工程师要部署多个环境,准备多个微服务的数据,测试多个接口。运维工程师每次上线都要操作多个微服务,并且微服务之间可能还有依赖关系。
3、调用链太长,性能下降
由于微服务之间都是通过 HTTP 或者 RPC 调用的,每次调用必须经过网络。一般线上的业务接口之间的调用,平均响应时间大约为 50 毫秒,如果用户的一起请求需要经过 6 次微服务调用,则性能消耗就是 300 毫秒,这在很多高性能业务场景下是难以满足需求的。为了支撑业务请求,可能需要大幅增加硬件,这就导致了硬件成本的大幅上升。
4、调用链太长,问题定位困难
系统拆分为微服务后,一次用户请求需要多个微服务协同处理,任意微服务的故障都将导致整个业务失败。然而由于微服务数量较多,且故障存在扩散现象,快速定位到底是哪个微服务故障是一件复杂的事情。下面是一个典型样例。
如果多个微服务同时发生不同类型的故障,则定位故障更加复杂,如下图所示。
5、没有自动化支撑,无法快速交付
如果没有相应的自动化系统进行支撑,都是靠人工去操作,那么微服务不但达不到快速交付的目的,甚至还不如一个大而全的系统效率高。例如:
- 没有自动化测试支撑,每次测试时需要测试大量接口。
- 没有自动化部署支撑,每次部署 6 ~ 7 个服务,几十台机器,运维人员敲 shell 命令逐台部署,手都要敲麻。
- 没有自动化监控,每次故障定位都需要人工查几十台机器几百个微服务的各种状态和各种日志文件。
6、没有服务治理,微服务数量多了后管理混乱
信奉微服务理念的设计人员总是强调微服务的 lightweight 特性,并举出 ESB 的反例来证明微服务的优越之处。但具体实践后就会发现,随着微服务种类和数量越来越多,如果没有服务治理系统进行支撑,微服务提倡的 lightweight 就会变成问题。主要问题有:
- 服务路由:假设某个微服务有 60 个节点,部署在 20 台机器上,那么其他依赖的微服务如何知道这个部署情况呢?
- 服务故障隔离:假设上述例子中的 60 个节点有 5 个节点发生故障了,依赖的微服务如何处理这种情况呢?
- 服务注册和发现:同样是上述的例子,现在我们决定从 60 个节点扩容到 80 个节点,或者将 60 个节点缩减为 40 个节点,新增或者减少的节点如何让依赖的服务知道呢?
如果以上场景都依赖人工去管理,整个系统将陷入一片混乱,最终的解决方案必须依赖自动化的服务管理系统,这时就会发现,微服务所推崇的“lightweight”,最终也发展成和 ESB 几乎一样的复杂程度。
参考:
康伟定律:https://segmentfault.com/a/1190000011118897https://segmentfault.com/a/1190000011118897