本文编写于 270 天前,最后修改于 270 天前,其中某些信息可能已经过时。

目前微服务是一个十分火热的关键词,各大互联网公司都普遍采用了微服务技术作为大型系统架构的解决方案,那么,对于微服务,你们是否也想我一样,有以下疑问呢:
微服务是什么?
微服务解决了什么问题?
微服务有什么特点?
下面,我们带着这三个问题,慢慢来剖析微服务。

一、单体架构的不足

首先我们从传统工程的单体架构来说起,什么是单体架构呢?
一个归档包包含了应用所有功能的应用程序,我们通常称之为单体应用。那么构建单体应用的架构风格,我们就称之为单体架构,这是一种比较传统的架构风格。
下面这幅图就是一个单体架构的样例:


上图是一个电影销售系统的图,我们把整个系统分为了“电影模块”、“订单模块”和“用户模块”,所有模块共享UI,所有模块连接同一个数据库。该系统使用Java开发,则会打包成一个war包,部署到tomcat中,这就是同一个单体架构。
相信很多项目初期的架构,都是上面的单体架构。但是对着业务的发展,整个项目越来越复杂、模块越来越多,此时我们将会面临以下问题:

●复杂性逐渐变高
当系统的功能越来越庞大,代码量也会十分庞大,难以优化和维护。同时模块变多之后,模块与模块之间的边界也越来越模糊。

●技术债务逐步上升
一般在软件开发团队,开发人员的流动性比较强,每个开发人员都有可能会埋坑,且每个开发人员的技术水平不一,随着开发人员在项目的进进出出,单体架系统的技术债务就会明显逐渐上升,因为埋得坑没有人去解决。

●部署速度逐渐变慢
随着业务的发现,模块越来越多,整个项目的代码也越来越多,项目的体积越来越大,所以部署速度起来也会很慢。

●阻碍技术创新
因为技术是不断在发展的,而项目一开始的设计肯定是基于之前的技术架构,而若干年后,如果想对这个技术架构进行更新或者替换,此时就要替换依赖、更改配置、更改标签等。风险很大,不利于项目的拓展。

●无法按需伸缩
在上面的图片中,电影模块是CPU密集性的服务,而订单模块是一个IO密集性的服务,如果有一天订单模块发生了瓶颈,此时我们就需要采购更好的内存和硬盘,但因为所有模块是打包在一起部署的,我们同时又要考虑它的CPU也不能太差,此时我们可能就要做一些妥协。

我们该如何解决单体架构的这些缺点呢?在IT发展的历史中,架构的技术也随着对系统要求的提高,也进行了演进:
●单体架构
●SOA
●微服务

我们下面着重来介绍一下微服务。

二、什么是微服务

关于微服务,业界并没有一个非常明确的定义,这里引用Martin Fowler(ThoughtWorks公司的首席科学家)对微服务的定义:
简而言之,微服务架构风格这种开发方法,是以开发一组小型服务的方式来开发一个独立的应用系统的。其中每个小型服务都运行在自己的进程中,并经常采用HTTP资源API这样轻量的机制来相互通信。这些服务围绕业务功能进行构建,并能通过全自动的部署机制来进行独立部署。这些微服务可以使用不同的语言来编写,并且可以使用不同的数据存储技术。对这些微服务我们仅做最低限度的集中管理。

总结一下上面的话,可以看出,微服务有以下特性:

1.每一个微服务可独立运行在自己的进程里

2.一系列独立运行的微服务共同构建起了整个系统

3.每个服务为独立的业务开发,一个微服务一般完成某个特定的功能,如“订单管理”、“用户管理”等。

4.微服务之间通过一些轻量级的通信机制进行通信,例如通过REST API或者RPC的方式进行调用。

三、微服务与单体服务的对比

下图左侧是一个单体服务,右侧是一个微服务群:

左侧的单体架构,所有的模块放在一起,共享UI以及数据库等资源。
右侧的微服务,每个模块单独运行,并且每个模块有自己的数据库。例如订单模块是IO密集的,它的数据可能使用Redis进行存储;而电影模块的数据适合使用关系型数据库,那么它的数据可能使用Mysql进行存储。它们相互之间通过一系列轻量级的通信机制进行通信。

所以这里可以得出,微服务的优点为:

●易于开发和维护
针对单个的某一个微服务模块,因为它只关注某一块业务(例如订单),所以业务难度和代码量都会小很多。

●启动较快
因为系统按照业务被分成了一个个单独的模块,每个模块都只专注于自己的业务,所以这些模块都是中小型工程,启动起来相对于启动整个单体应用来说,绝对快很多。

●局部修改容易部署
对某些业务的改动,只需要重新部署该业务相关的微服务模块即可,无需将整个项目重新部署。

●技术栈不受限
系统按照业务被分成了一个个单独的模块,每个模块都可以使用完全不同的技术栈,因为各个模块之间是通过轻量级的通信机制进行通信的,开发语言的关联性为零。

●按需伸缩
每个模块可以根据自己的业务需求,给不同的模块进行不同角度的软硬件的升级即可。

●DevOps
有很多自动化的工具来辅助我们开发和运维(Docker容器等)

除了上面的优点,同时微服务也给我们带来了一些挑战:

●运维要求更高
在单体架构中,我们只需要维护一个系统即可,而微服务需要维护每一个微服务模块。

●分布式的复杂性
要考虑分布式的一致性、可用性、容错性,以及分布式情况下数据存储的事务控制等等一些列复杂问题。

●接口调整成本高
例如用户服务会被电影微服务调用,如果用户的模型或者业务发生了变化,此时电影微服务也要发生改变。

●重复劳动
在单体架构下,我们往往会沉淀一些公共组件(例如StringUtils等),各个模块都可以直接使用。而在不同的微服务中可能就需要自己去构建它,造成一定的重复劳动。

如果使用的都是Java语言的前提下,可以使用Maven构建一个公共jar包,打包到私服中去,所有模块都去引用,这样是可以的。但是微服务是不绑定技术栈的,如果一个微服务用Java,一个用PHP,此时两个微服务还是要各自编写各自的公共工具类的。

四、微服务的设计原则

了解了微服务的细节后,我们来了解一下微服务的设计原则,以方便指导没有写过的童鞋如何以正确的姿势开发微服务。
微服务的设计原则如下:

●单一职责原则
指的是每一个微服务模块,只关心自己的业务规则。例如订单模块只关心订单的相关业务,不牵扯其它业务的逻辑。

●服务自治原则
每一个微服务模块的开发,需要有自己的开发、测试、运维、部署这一条独立的栈,并且有自己的数据库等一切,完全把其当成一个单独的项目来做,不牵扯到其它无关业务。

●轻量级通信原则
微服务的通信协议需要跨平台、跨语言的通信协议,因为微服务是不绑定技术栈的,不论使用Java、PHP还是.net去开发Web系统,它们之间的通信一定是去语言特色的。

●接口明确原则
前面提到了微服务的“接口调整成本高”,那么怎么去避免它呢?我们一开始就应该规划好微服务的模块是一种什么样的模型,尽量去避免A接口的改动会导致B接口的改动这种情况。

五、微服务的开发框架

每一种技术都会有相关的框架作为支撑,下面就是实现微服务的常见框架:
1.Spring Cloud(https://projects.spring.io/spring-cloud)
springcloud基于springboot构建,是微服务架构的集大成者,将一系列优秀的组件进行了整合。

2.Dubbo(http://dubbo.io)
Dubbo关注的是服务治理

3.Dropwizard(http://www.dropwizard.io)
Dropwizard关注的是单个微服务的开发

4.Consul、etcd & etc.
consul是google开源的一个使用go语言开发的服务发现、配置管理中心服务。
etcd是用于共享配置和服务发现的分布式,一致性的KV存储系统

下一篇我们正式来进行Spring Cloud的逐步学习。