[转]阿里巴巴前架构师 360 度无死角剖析微服务

原文地址: https://my.oschina.net/osccreate/blog/785004

微服务是当前软件架构领域非常热门的词汇,在社区中也有很多热烈的讨论。因此,在 OSC 第 130 期高手问答中,我们策划的主题是“究竟什么才是微服务”,并邀请了黄勇作为高手嘉宾。

黄勇,现任特赞公司 CTO,曾任阿里巴巴公司系统架构师。对微服务架构与大数据技术有深入研究,具有丰富的网站架构设计经验与项目管理经验,擅长敏捷开发模式。国内开源软件推动者之一,活跃于“开源中国”社区网站,Smart 开源框架创始人,图书《架构探险:从零开始写Java Web框架》作者。热爱技术交流,乐于分享自己的工作经验与生活感悟。

微服务是近年来备受关注的话题,它的出现让我们想起了十年前的 SOA(Service-Oriented Architecture,面向服务架构),但它比传统的 SOA 更容易理解,也更容易实践,它将“面向服务”的思想做得更加彻底。

尤其是当国外的一些知名技术公司成功实践了微服务以后,这股热潮就吹遍了国内的大街小巷,我们也看到很多的项目使用了微服务,但实际上依然有不少朋友对于微服务有着不少疑惑。

因此本篇文章,会介绍与微服务架构相关的一些基础概念、适用场景以及如何解决在实践中遇到的问题等内容。

一、与微服务相关的一些基本概念

我以前做过微服务,基本框架是 Spring MVC,微服务之间和微服务与平台之间的访问是通过在 Zookeeper 上的 Dubbo 通讯的,请问这算是微服务吗?

其实微服务架构的范围是相当广的,这些我认为只是微服务架构的一部分。稍后我也出一篇文章,将上周去 QCon 分享的微服务架构,给大家再次做一个介绍。

如何更好理解【微服务】这个“微”字。从设计之初,开发,部署,运维,监控,等有什么地方(基于你的过往历程)需要关注的?

我认为「微」并非它的体积足够小,而是它的责任足够单一,很多人误解了「微」的真实含义,认为服务拆分得足够小就是微服务了,其实并非这样。此外,「微」还有“微不足道”的意思,也就是说,某个服务出现故障,它不会影响整个系统。

听说微服务是个很大的概念,Dubbo 只是实现了其中一小部分,请问完善的微服务架构是什么样的?Spring Cloud 是否算是完善的微服务?

微服务架构的范围比较大,Dubbo 和 Spring Cloud 都只是解决了微服务的一部分问题,并未完全覆盖。稍后我也出一篇文章,将上周去 QCon 分享的微服务架构,给大家再次做一个介绍。

如果分布式服务本来拆分的颗粒度就比较细,每一个模块都是独立的服务,可不可就理解为相当于微服务?

微服务并非细粒度服务的组合,也就是说,粒度要细到什么程度,这取决于对业务功能的把控能力。此外,微服务是一种架构思想,包括看得见的微服务,还包括看不见的基础设施和自动化技术作为支撑。

请问微服务的核心系统是什么?是微服务的发现和组织吗?每个微服务很好做,如何把他们组合起来,有没有现成的系统可以参考?

我认为微服务的核心是:服务注册中心(Service Registry)与服务网关(Service Gateway),它们配合完成服务注册与服务发现。
将服务组合起来也成为“服务编排”,有多重做法,可以在服务网关中进行编排,也可以通过中间服务进行编排,我更倾向于后者,这样确保服务网关不包含任何业务,更加轻量级。
微服务比普通架构需要多做那些工作?OpenStack 的架构设计属于什么类型?微服务是不是需要更多的运行资源?

微服务架构比传统架构更加依赖于对自动化运维的支持。
OpenStack 是一款云计算平台,为云计算的 IaaS 层提供了解决方案。
在微服务架构中,需要相关的基础设施与很多独立运行的服务,我认为相比较传统架构而言,所消耗的硬件资源较高一些。但从现在来看,硬件资源的成本已经非常低了。
SOA、WebService、RESTful 这些概念有什么本质的区别。开发者平常使用的那些 AJAX、HTTP 接口(含 session 状态的)算得上 RESTful 接口吗?

RESTful 是一种架构风格,SOA 是一种架构思想,可以认为 RESTful 有助于 SOA 的落地化。
RESTful 一般应用在 HTTP 协议上,在前后端分离架构中,前端通过 AJAX 技术发送 RESTful HTTP 请求到后端,获取后端 JSON 数据,并进行界面渲染。同样,RESTful 也用于微服务架构中,每个服务对外暴露 REST API 作为通信接口。
从什么角度能区分出或者划分微服务和 RPC 分布式之间的区别或者关系?

微服务是一种应用架构模式,而 RPC 是一种远程调用方式,它们是不一样的概念;而在微服务中会出现服务之间的调用,为了确保性能,我们一般采用 RPC 来调用。

是否有接触过“领域驱动的分析与设计方法(DDD)”,你是如何理解“DDD”与“微服务”之间关系的?

DDD 是基于领域对象的设计思想,微服务是基于服务的业务架构,DDD 与微服务可相辅相成。

公司现在用的是 Dubbo 框架,这是微服务框架还是 SOA?记得有些博客说微服务去中心化,那这个中心是不是就是 Dubbo 里的注册中心?

Dubbo 从本质上来讲属于微服务框架,它有服务注册与发现,也有服务之间不同协议的通信,以及服务调用的监控。而传统的 SOA 更倾向于使用 ESB 这类总线的方式来实现服务的注册与通信,可以把 ESB 看成是一个中心,因此相对微服务而言,传统 SOA 更加重量级一些。我认为微服务是 SOA 的一种轻量级实现,它的本质还是 SOA。
所谓去中心化,实际上是确保不因为中心而导致单点故障,如果能解决这个问题,有中心又如何呢?因此,我认为不要一味地去中心化,要合理地去中心化才是正道。

二、什么场景下选择微服务?

微服务架构我觉得比较适合新项目,如果用于已有项目那相当于要重构,或者逐步拆分做微服务架构?是不是这样?还是有什么更好的方法?

对于业务流程较为复杂,且业务会变得逐渐复杂的项目,可以考虑使用微服务架构。
对于已有项目而言,可考虑逐步进行微服务化,也可考虑在新业务中使用微服务架构。
我想利用微服务实现系统的模块化,便于公共模块复用和水平扩展,但目前的系统规模其实都很小,这种情况是不是不适合使用微服务?

我认为微服务架构用于业务较复杂或目前业务简单但将来有可能变得复杂的架构,建议视具体情况来确定合理的架构,不要为了微服务而去微服务。

高并发低延迟的系统能使用微服务吗?

我认为高并发场景不太适合使用微服务,因为微服务会带来一些调用链的开销,高并发场景需要做到尽可能地的延迟以及更高效的通讯。

微服务与 SOA 到底有什么区别,各自的应用场景是什么?到底在什么样的情况才适合使用微服务架构?

我认为微服务是 SOA 的轻量级解决方案,微服务的本质还是 SOA,只是更加容易落地而已。

我认为在以下几种情况下,可考虑使用微服务架构:

应用变得越来越大时
项目存在多种开发语言时
感觉到经典架构模式太重时
修改了一个 bug 需要平滑升级时
想对系统进行细粒度监控时
当然还有其他使用场景,但微服务不是万灵丹,不能适用于所有场景。而且微服务对运维是有一定的要求的,尤其是自动化运维。即便业务目前比较简单,但将来会变得复杂,也建议使用微服务架构。

三、如何考量微服务的技术选型?

微服务的开源技术选型能介绍几种吗?Spring Cloud 如何解决跨语言的问题呢?

比较知名的微服务开源技术选型莫过于 Spring Cloud,它对 Netflix 提供的相关组件做了一定的封装,让开发者更容易上手。当然,我更加希望本书所先介绍的开源技术选型会被更多人接受与应用。

这次你的这本关于轻量级微服务,我有几个问题,你的这本书里关于微服务的技术选型是怎么考量的?书中提到了 Spring Boot,你对于 Spring 的这个技术怎么看?现在微信小程序比较流行,微服务会成为小程序的技术首选吗?

这本书中关于微服务的技术选型问题,我做了大量的思考并实践,所选择的方案均为开源,且非常轻量级,目的是帮助大家能够快速搭建这款轻量级微服务架构。
虽然这本书讲到的微服务开发框架是 Spring Boot,用过的人都知道它有明显的优势,当然也有明显的劣势,毕竟底层还是基于 Spring,而 Spring 从当初的轻量级似乎变得越来越重,我希望有更好的轻量级框架可以出现,所以当初写了一款 Smart 框架以及《架构探险》第一本书,目的只是抛砖引玉,希望有更多的朋友都能投身到国内开源行业中,创造更优秀的开源项目。
我非常看好微信小程序的未来,但微服务是否成为小程序的技术首选,我不太敢下次评论,咱们一起静观其变吧。
微服务框架是在 SOA 的基础上提出的吗?在技术选型要注意哪些点,用 Spring Cloud 还是 Spring Boot?怎样做到轻量级,有哪些参考?

我认为微服务是传统 SOA 的轻量级解决方案,它让 SOA 更加容易落地。
在微服务技术选型方面,我建议竟可能地轻量级,做到“进可攻退可守”,至于 Spring Cloud 还是其他框架,完全取决于我们对技术本身的理解以及对业务的把控能力,技术也业务需要相互结合才能产生价值。
希望这本书中所设计的轻量级开源方案,会帮助您更快地搭建微服务架构。

四、实施微服务的开发成本有多高?

该在多大规模的项目中使用微服务比较合适?微服务会增加架构复杂度吗?带来的收益是否可以抵消?

我认为对于业务比较清晰的项目均可使用微服务架构,并非需要具备多大规模。
微服务架构会带来系统的复杂度(成本),但必然会带来一些收益,至于成本和收益是否低效,这取决于我们对微服务与业务的理解与把控能力。
实施微服务后,对于开发成本是不是更高了?

我认为实施微服务并未提高开发成本,而是提高运维成本,一个好的微服务架构离不开运维方面的支持。本书下册将针对运维方面将以描述,敬请期待。

微服务一般都要用到 Docker,这样对研发人员和运维人员技术就要求更高了,如何快速有效实施微服务架构?

实施微服务必然会提高运维方面的成本,但我认为这是有价值的,尤其是自动化运维技术,也需要培养开发人员的运维思想。

微服务挺多人说玩不起,是不是相对来说实施成本挺高的?

玩不起包括两层含义:一是认为成本较高;二是担心有风险(怕玩挂了)。

五、微服务中的事务

如何简单有效的实现事务?

可使用消息队列的方式,实现服务之间的事务控制。服务调用完毕,写入消息队列,通过消息驱动的方式调用其他服务。

服务间是不是应该避免相互间调用, 由 API Gateway 来组织各个服务?

没错,应该避免服务间的调用,而使用服务网关作为调用入口,但我不建议在服务网关处组织服务调用,而是通过一个中间服务来编排,或使用消息驱动方式来完成。

服务与服务之间的事务怎么做?

在微服务架构中,建议尽量避免服务之间的调用,因此服务粒度的切分是至关重要的;服务间的调用会产生分布式事务问题,建议采用“最终一致性”方法来确保分布式事务,业界有两种常用做法:CQRS 和 Event Sourcing。

目前,微服务的事务是大家最关心的,微服务的分布式事务问题如何解决?请问,现在业界有没有开源的解决微服务事务的项目。

微服务的事务控制比较复杂,我们需要做到尽可能避免服务之间的调用,这取决于我们对微服务切分的粒度控制。

微服务分布式事务一般借助消息驱动与日志追踪的方式来解决,以达成事务的“最终一致性”,业界有 CQRS 与 Event Sourcing 来解决微服务的事务问题,希望对您有帮助。

如何使用事务补偿模式解决分布式事务问题?

事务补偿机制说简单点就是,在应用程序中通过代码的方式做到数据的还原。一般情况下,我们需借助消息队列与日志追踪等方式来实现。

微服务在事务控制方面,容错方面有什么较好的实践方式?

微服务的事务控制本质上是分布式事务控制,建议使用“最终一致性”来确保。
在容错方面,需要有基础设施平台的支撑,比如服务网关的熔断机制。

六、微服务的业务该如何拆分?

微服务业务拆分有没有什么原则要点?

微服务业务拆分可按整体业务组件来拆分,也可按单一业务功能来切分。建议切分步骤从粗到细,逐步细化,否则开始就过细,导致依赖性太高,增加复杂度。

一个大服务怎么拆最好,依据是什么,微服务拆分如何控制合适的粒度?另外现在的微服务的教程好像都是针对 Java 的,比如 Spring Boot,其他语言有没有成熟的体系?

建议从整个业务流程来分析,首先抽象出公共服务,然后采用大粒度的方式来切分,最后逐步细化切分粒度,微服务切分粒度取决于我们对业务的理解与把控能力。其他开发语言也有类似于 Spring Boot 的微服务开发框架,比如 .NET 的 Nancy。

怎样来控制微服务的粒度?就是有没有什么样的原则和最佳实践来判断一个功能(接口)是应该属于 A 服务还是应该属于 B 服务。

微服务的粒度控制取决于我们对业务的理解与把控能力,一切所谓的原则都是不靠谱的。

微服务目前对于各个功能拆分是不是有些太细?

我认为微服务的切分粒度没有必要太细,适合业务发展并能提高开发效率的架构才是好架构。

微服务拆分如果粒度太细,会不会导致维护成本增加?响应时间增加?事务控制如何实现?

微服务粒度问题取决于我们对业务的理解与把控能力,无需太细。
可借用消息队列和日志追踪进行事务控制,也可使用 CQRS 或 Event Sourcing 解决方案。
如何控制粒度在方法级别的接口的调用权限?

此处所描述的“接口”是否理解为服务的 API 接口呢?API 调用的权限控制可在微服务架构中的服务网关(Service Gateway)处加以控制。

单体架构拆分成微服务后,每个服务能独立布署,也便于横向扩展,但也面临如下的问题:

  1. 微服务拆分粒度的原则是?2. 微服务的服务治理?

服务是根据业务功能来拆分的,拆分服务时需降低彼此之间的耦合性,尽可能一个服务只做一件事情,即“单一职责原则”。
服务治理问题所涉及的问题较多,将在这本书下册中加以描述,敬请期待,也欢迎进一步探讨。
服务拆分之后就会出现,微服务调用微服务的情况,导致效率很慢,接口的 QPS 很低,怎么解决?

我的建议是,尽可能避免服务之间的调用,不妨使用消息队列的方式来降低服务之间的耦合,当然必要的直接调用可使用 RPC 技术,它具备优秀的性能,可确保较高的 QPS。

七、使用微服务遇到的问题

我在公司实现分布式的过程中遇到了 3 个问题,如您有时间请您给些思路:

分布式事务:当前采用消息队列,队列的消费者使用 Redis 做分布式锁来实现幂等消费,不知道这种方式存在什么隐患?或者有没有更好的方式?
日志聚合:目前想要做一个日志聚合功能,暂时考虑还是使用消息队列处理,不知道有什么业界成熟的方式?
方法调用次数统计,暂时我们想使用 AOP + 消息队列 + strom 的方式来实现方法调用与耗时统计,不知道业界成熟的方式是什么?
消息队列可用于分布式事务控制,这项技术已经在业界被证实是可用的。此外,还有 CQRS 与 Event Sourcing 技术也可以尝试一下。
日志聚合可使用业界流行的 ELK,即 Elasticsearch + Logstash + Kibana 来实现,L 用于收集日志,E 用于存储日志,K 用于展现日志。
方法调用次数统计,不建议放在服务内部通过 AOP 来控制,建议在微服务架构的服务网关(Service Gateway)加以控制。
我觉得接口调用次数统计,也可以结合 flume + Mq + strom 做实时统计,这样可以根据日志信息获取调用次数额外的东西,如调用者所在的地区等。

看具体要求是怎样的,如果只是简单记录 API 调用次数,可在服务网关处增加此功能,将结果记录到 MQ 中。

权限分访问权限与资源权限。想请教下资源权限在微服务中怎么做?比如我有个商品服务跟优惠服务,想要控制某个用户只能查询商品和创建优惠券,是每个微服务都有独自的权限功能,还是有个权限服务统一下发和调配各个微服务的权限?或者贵公司在微服务中是怎么做权限这块的?

访问权限建议在服务网关处加以控制。
资源权限建议抽象出一个单独的中间件加以控制。
微服务下有不同的存储介质,对于跨数据库的分页查询有什么好的办法吗?

使用微服务架构可以做到:

一个服务使用一个数据库(单库)
一个服务使用多个数据库(多库)
对于“多库”而言,可在服务内部聚合数据,也可使用数据库中间件来解决此问题。

SOA 与 MSA(微服务架构)区别在于系统一体化与服务组件分散化(“微化”)的区别。服务组件微化可以让关注点进一步缩小范围,服务之间的规范或者实现的关联性进一步降低(https://my.oschina.net/waylau/blog/617857)。但同时引入的一些问题:

服务治理;
服务的版本更新;
服务之间的权限是如何来做控制的;
服务如何来划分颗粒度。
请教下,贵公司在实践过程中,有无遇到过上述问题,是如何解决的?

您说的非常好,这些问题可能都是每一位微服务实践者所要面对的问题,考验我们的是,如何选择合理的技术来解决此类问题。比如,服务治理可通过 Kubernetes、Mesos、Docker Swarm 等技术来实现,服务版本可通过 ZooKeeper、Etcd、Consul 等技术来控制,服务权限可自行实现权限中间件来解决,服务颗粒度划分考验我们的是对业务的深度理解(这才是最为关键的)。总之,有具体技术能解决的可能都不是问题,可能是问题的往往是我们对自身业务的理解与把控能力。

  1. 微服务对网络、数据库连接、缓存服务器等资源的影响;2. 微服务是否需要多版本服务共存?

微服务对网络、数据库、缓存方面较传统架构而言,没有过高的要求,但对运维方面要求较高。
微服务需要考虑服务多版本问题,尤其是服务升级时,需要做到平滑,对整体系统没有任何影响。
针对微服务的全局 ID 生成策略。不知道黄老师有没有什么好的建议?

看了很多的分布式 ID 生成策略。提到很多 ID 趋势递增的策略,这个有什么用?
为什么要让 ID 具体有顺序功能?如何保证顺序?
不知道黄老师在实际项目中用了什么策略,希望能分享一下。

实际上 ID 生成策略并非是微服务架构所涵盖的范畴。我认为比较好的 ID 生成策略需要结合您所面临的实际需求,一般应用场景下,可通过 Redis 来生成并管理 ID,它具备较高的并发能力,且能确保分布式一致性。

有一个关于测试的问题想请教。是不是微服务更偏重敏捷模式呢?对于测试而言更容易开展工作?自动化测试覆盖率更高?

我认为微服务与敏捷没有必然的关系,微服务讲究的是将“化整为零”,敏捷倡导的是“小步快跑”,但两者可以有效地结合起来加以应用。
较传统架构而言,微服务的测试复杂度和覆盖面将更为广泛,不仅需要对每个服务进行测试,而且需要对整体应用加以验证。因此,我们需要使用自动化测试技术来提高测试效率。
微服务是否就一定是进程级别的?在同一个进程内实现微服务可行吗?如果一个服务就一个进程,这样是不是会耗费大量系统资源?

微服务讲究的是服务可以独立开发与部署,如果在进程内进行微服务,将带来很高的复杂度,就像当年的 OSGi 那样,理念非常好,但实践起来却困难重重。
一个服务一个进程,这样让服务的隔离性更加彻底,配合 Docker 容器技术,可以更加高效低利用服务器硬件与网络资源。
微服务目前有什么成熟的一整套开源方案吗?包括测试、版本控制,发布流程,代码错误回滚?

业界也有其他优秀的微服务开源方案,例如 Java 领域的 Netflix 与 Spring Cloud。当然,我更希望本书所提到的开源方案,可以被更多人接受并应用。

微服务怎么解决调用链过长导致的调试或异常追踪过难的问题呢?

调用链追踪是微服务落地的一个挑战,我们一般通过追踪平台来解决,推荐使用开源的 Zipkin。

微服务一般是 JSON 格式调用,与其他调用方式有什么区别么?

我认为 JSON 格式只是 REST API 返回值的一种,微服务并非局限于 REST API 通信。

楼主推荐使用 Spring Cloud 构建微服务吗?

Spring Cloud 对微服务架构提供了很好的技术封装,建议对其充分了解的情况下使用。

微服务都是通过 HTTP 方式对外提供?

微服务对外的接口不一定局限于 HTTP 或 HTTPS,也可以是 TCP,需要根据具体情况而定。

使用 REST 通信其实挺麻烦的,还需要封装一层调用方法,不知道有没有类似的问题?

REST API 是一个种轻量级通信方式,也有助于跨平台调用,我们的做法往往是提供一个客户端 SDK,目前已有大量的技术来快速实现 REST SDK,比如 Spring RestTemplate,或 Retrofit。

八、微服务与容器的结合会碰撞出怎样的问题?

目前很火的容器技术和微服务如何结合?

由于微服务架构是可以做到服务的异构性的,也就是说,我们可根据实际情况,选择最适合的开发语言来实现服务。容器技术具备隔离性,可将异构开发语言的服务进行统一封装,并有助于自动化部署,以及持续交付。

Docker 容器技术的出现,为微服务提供了更便利的条件,比如更小的部署单元,每个服务可以通过类似 Node.js 或 Spring Boot 的技术跑在自己的进程中。可能在几十台计算机中运行成千上万个 Docker 容器,这么多 Docker 容器怎么来有效管理?出错了如何排查呢?

实际上您提到的是服务治理问题,目前有大量的技术可以做到,比如:Google Kubernetes、Apache Mesos、Docker Swarm 等。

听说使用 Docker 运行 Java 一点优势都没有,微服务架构大量启动 Docker 集群,内存利用率很低,虽然 Java 运行效率很高。您怎么看?

Java 应用经 Docker 化后,最明显的问题是 Docker 镜像体积较大,启动 Docker 容器所占用的系统资源较高。建议根据实际业务场景,选择最为合适的开发语言实现对应的微服务,而并非局限于 Java 应用之上。

如果不使用 Docker,会给微服务带来哪些不便?

如果没有 Docker 这类容器技术,可能会降低微服务的部署与交付能力。

Spring Boot 与 Docker 整合, 在大数据使用方面多不多?

Spring Boot 与 Docker 整合,在许多领域都有应用,当然不排除大数据方面。