一、从康威定律说起

关于微服务的理论思想,我们可以从一个著名的定律说起---康威定律,康威定律是一个叫梅尔文·康威的程序员,他在1968年发布了一篇文章,文中论述了设计系统的组织与系统本身的关系,并列举了各个不同行业的真实案例,最后得出了结论:“oganizationrs which design systems (in the broad sense used here) are constrained to produce designs which are copies of the communication structures of these organizations”。

一个成功的程序员自然要懂微服务(学微服务看这篇)(1)

大致的意思就是:系统设计(产品结构)等同组织形式,每个设计系统的组织,其产生的设计等同于组织之间的沟通结构,简单一点理解就是:系统设计受限于设计系统的组织架构形式,用大白话来说就是:有什么样的组织架构就会设计出什么样的系统架构。

当然,这个结论在当时并没有上升到定律的高度,直到《人月神话》、《架构之美》这两本书畅销书都引用了其观点并“大肆吹捧”,康威定律才慢慢传播开,最终成为了与摩尔定律齐名的软件工程定律。

虽然时间过去了50多年,但这些结论依然历久弥新。当一个组织增长到一定的规模,组织之间的沟通、协调就会出现低效与冗余,为应对内外部环境,组织就要进行适当的变革。在互联网公司这种变革的成果,就是诞生了一个个独立作战的小团队,无论是腾讯的“大公司小团队理念”,还是亚马逊贝佐斯提出的“二个披萨饼原则”,(一个团队的规模最多只能用两个披萨饼喂饱)都印证了这点。

同样,随着组织的变革也影响着系统架构的设计,因为系统架构一个十分重要的职责就是:“解决团队分工协助问题,系统架构体现了组织的沟通与协助方式。这正是康威定律所说的“系统设计(产品结构)等同组织形式”。

二、单体架构与微服务

有了康威定律的理论基础,从组织的维度我们可以认为微服务的本质是:

“将一个个业务功能拆分出来,并由一个微型团队来开发、构建、运维,团队与团队之间通过定义清晰的边界进行沟通”。

下面将通过两张图,更细致的理解微服务的概念:

一个成功的程序员自然要懂微服务(学微服务看这篇)(2)

单体架构

先看第一张图,这是典型的单体架构风格,由人数众多的大团队在一个单体里面进行协助开发,在业务复杂程度低,团队规模不大时,这种方式团队能聚焦核心业务,快速响应。但随着业务的不断发展,团队人数的不断扩张,系统的规模与复杂性会成指数级增长,整个研发过程就会面临着3个问题:

人数众多,团队之间沟通协调困难,信息不一致(可以参考项目管理中的沟通途径计算)

项目工程庞杂,各类库与组件的依赖关系错综复杂,大量重复性代码,项目推进举步维艰;

代码管理、版本管理变得困难,构建编译时间变长,运维部署困难,系统启动时间变长;

这些问题,直接影响着团队的交付效率,影响着系统的可用性、可扩展、可伸缩等。

而面对这些问题的解决之道就是微服务,我们再看第二张图微服务的架构风格。

一个成功的程序员自然要懂微服务(学微服务看这篇)(3)

微服务架构

我觉得有必要先给微服务下一个定义,这里我引用软件领域泰斗级人物“马丁·福勒”他对微服务的定义。对于马丁·福勒,你可能没听说过他,但是作为一个程序员你不可能不知道他的作品《重构》,就在今年5月份《重构》出了第二版,更不可能不知道由他与其他15为软件泰斗共同创造的“敏捷软件宣言”。

微服务定义:

“微服务架构风格是以一组小服务来开发单个应用程序的方法,每一个服务运行在自己独立的进程中并使用轻量的方法通信,通常是一个HTTP API接口。这些服务围绕相关业务范围构建并且由全自动化部署机器独立部署。这些服务只需要最低限度的管理,可以用不同的编程语言去编写并且使用不同的数据存储技术”

基于微服务的定义我们可以总结出微服务的一些特征:

一个成功的程序员自然要懂微服务(学微服务看这篇)(4)

微服务特征

1)服务小而美:微服务是以一组小的服务组成,一个重要的特点就是小,至于具体多小,有一些不同的声音,这个不能一概而论,要看具体情况。我们需要使用领域建模的方法来定义服务的粒度,领域建模的知识我会在后面的文章中详细的介绍。

2)服务独立自治:独立自制是微服务一个显著的特征,主要体系在几个方面,第一,微服务由独立的团队来开发;第二、微服务可以使用不同的平台与语音;第三,独立于具体项目已产品的形式存在; 第四,微服务运行在独立的进程中,可独立部署;

3)服务松散耦合:微服务将业务划分清晰的边界,再封装到一个独立的服务中,符合软件设计的单一职责与最少依赖原则,微服务将系统的抽象程度提到了更高的层次,将系统对代码或组件的依赖转换为对接口,对服务的依赖;

4)服务互联互通:微服务强调小,轻量,服务通过相互连通组成复杂的业务功能,服务通信方式可根据具体场景,选择基于HTTP Restfull的轻量级协议,或是效率高的RPC协议,甚至可以选择基于消息队列的异步调用方式等;

5)非中心化治理:去中心化是微服务的又一个重要特征,去中心包括数据非中心化,管理去非中心化,微服务采用非集中化的数据存储,各个服务使用自己独立的数据存储,微服务也没有一个集中的服务管理器。

6)演进式设计:演进式架构已增量的、非破坏的变更作为第一原则,演进式设计也是微服务所提倡的。例如,要对一个巨型单体应用进行微服务转型,肯定不是把这个大的单体应用直接干掉不要,建一个新的微服务平台出来,而是要以增量的、非破坏的方式把某项业务一步步抽离形成新的服务。

三、 微服务带来的问题与挑战

架构设计是一门权衡、取舍的艺术,没有银弹,更没有十全十美的架构,微服务架构为我们带来了如:“可扩展性”、“容错性”、“灵活性”等诸多优点。我们收获这些好处的同时,也一定会带来某些弊端与挑战,这些挑战可以从四个方面来说:

1)分布式带来的通信复杂性与不确定性

对于单体应用,要完一个业务操作,我们通过本地方法调用,这些调用都在同一个进程内完成。进程内地的方法调用或类库调用,由平台语言本身来提供,比如JVM通过线程栈,能提供可靠、确定的调用机制,并且时间延长几乎可以忽略不计。而在分布式环境中,要完成一个业务操作,服务之间需要跨进程,跨网络进行相互调用,我们称之为远程方法调用,这两种调用方式有着这本质的区别,进程内调用习以为常的事情,在远程调用时就成了必须要面对的问题,这些问题包括:

服务的调用方(消费者)怎样找到被调用(提供者)方?

如果某个依赖服务挂了(进程死了、网络异常,服务器宕机)怎么办?

服务接口需要暴露在网络上,接口的安全怎么保证?

业务代码分散在各个进程中,那统一处理的代码怎么办(比如异常、日志)?单体中我们有AOP编程

如果服务调用链层级太深,时间延迟怎么办?

对于一个业务bug、或线上问题涉及多个服务调用,怎么快速定位、排查问题?

2)非中心化带来的数据不一致性

微服务的一个重要特征是数据的非中心化存储,各个服务使用自己独立的数据库。这就带来了一个严峻的挑战,就是数据库的一致性问题。在单体系统中,使用单一数据库,程序员只需要关心最的核心业务问题,我们用数据库的ACID特性,就能轻易的保证数据的一致性,在代码框架的支持下只需要一个标记就能搞定一个事务处理。但是在分布式数据库中要做到这些,就是个非常棘手的问题,需要我们做很多额外的工作,同样对于像报表查询,统计业务从前一个sql语句能搞定的事情,数据非中心存储后就会非常麻烦。

3)众多服务带来构建、配置、测试、部署的困难性

软件系统最终是要经过编译、测试、部署到多个环境进行最终验证,最后再依次部署到生产环境,同时还要考虑生产环境的回滚策略,这些流程在单体应用中只是规模,体积比较大,但毕竟数量是少数的。我们需要可能只是一些细心与耐心。但系统被拆分成诸多微服务之后,假设有20个,同样的事情,重复的劳动我们需要做20次并且保存每次都不能出错,量变引起质变,当服务超过一定数量,我们要面对的不仅仅是重复劳动的问题。

4)业务解耦带来的微服务拆分困难性

对于单体应用,如果我们的业务设计做的不好,模块化划分不到位,后果可能还没有那么严重,毕竟所有的数据都在一个数据库中,所有的代码也都可以进程内调用,大不了我就加一层来解决,实在不行就加两层(玩笑话),但是,我们想象一下,如果微服务在业务设计时没有规划好,把不该放一起的放到一起,该放一起的强行拆开,整个微服务就成了一团乱麻,远程调用的开销,服务的治理会是一场灾难。

微服务强调的是基于业务功能构建,业务功能之间要松散耦合,有明确边界。然后,对于一个复杂业务系统,在设计早期要做的这点并非易事。

根据墨菲定律--“凡是可能出错的那它一定会出错”,选择微服务就一定会遇到上述我说的这些问题。

四、微服务的适应性

看到微服务这么多困难与挑战,是不是感到迷茫与沮丧,确实,“没有银弹”,“没有神丹妙药”,微服务不一定适合所有公司、所有项目。那么我们应该怎样权衡微服务与单体架构呢?这里就涉及到一个经济学中边际成本与收益的问题。我又得请出我们的大神“马丁.福勒”了,大神在一篇“微服务的适用性”文章中用一张图清晰的说明了微服务的适用场景。我们先来看看这张图:

一个成功的程序员自然要懂微服务(学微服务看这篇)(5)

​微服务 系统复杂性与生产力关系

图上的X轴表示系统复杂性,Y轴表示生产力,两条曲线表示微服务与单体应用,在两个维度上的表现。当系统复杂性比较小的时候(X轴靠近左边),单体应用的生产力要高于微服务,其实这很好理解,因为微服务要考虑,自动化部署、服务监控、故障处理、数据一致性等诸多问题,而这些对于业务系统本身来说都是额外的工作。当软件复杂性不高,团队规模不大时,这些工作会占据整个研发工作的很大比重。

当系统复杂性变大时,微服务额外部分的工作占整个研发工作的比重变小,而微服务带来的收益越来越大,这时整个研发的生产力并没有像单体架构那样直线下降,所以微服务能够在系统复杂性增加时,还能持续的保持良好的生产力。

在尝试微服务转型之前,我们需要结合公司的实际情况,考虑微服务带来的挑战与收益,再判断我们是否真的需要微服务。“马丁.福勒”的建议是:“ 除非系统过于复杂而无法作为一个整体进行管理,否则甚至不要考虑使用微服务,大多数的应用系统应该使用单体架构,只是要注意在单体内做好模块化,而不是直接使用微服务”

微服务架构充满刺激与挑战,但好消息是,对于大多数项目与团队,并不需要从零开始,我们只需“站在巨人的肩膀上”,领会他们的设计精髓、用好他们的成果即可。下面的文章我们将重点介绍微服务架构的具体技术方案与通用实践。

作者:攀岩飞鱼

来源:https://xie.infoq.cn/article/83386f6d764984f3b64b760fb

,