杨明翰的微服务教学系列之概述篇V0.1(持续更新)


前言

随着Docker容器化技术的普及,
这几年微服务几乎成为了分布式架构的首选。

在很久很久以前(甚至是2020年的今天),
仍然有很多中小公司采用单节点架构(又称单块&单体架构),
来架构JavaWeb、Java服务端应用。

刚开始我们的项目还很小,代码量、访问量都很少,
但随着时间的推移以及业务逻辑与代码量的不断增长,
也许1-2年后,我们编写的"小婴儿"会变成"大胖子"。

原来我们所有的代码都被放在一个项目内,
运行在一个进程中,维护和继续开发这坨代码,
会有一种很酸爽的感觉。

那我们该怎么办?很简单,我们需要拆、拆、拆,
把大而复杂的问题分解成一堆小而简单的问题,
这就是分而治之,架构演变的本质就是各种拆。

我们可以把大规模系统进行拆分&分解,
再在每个拆分后的单元中进行开发、测试、维护即可,
这样就避免了牵一发而动全身的窘境。


架构演变

微服务是一种分布式架构,
用来提高服务器对并发对处理能力,
那什么又是分布式架构呢?

不如让我们来回顾一下JavaWeb项目的架构演变历史,
架构演变好像是从猿进化成人的过程,
当然,这种演变是需要有业务环境支撑的,
当你的应用日均PV不到100时,就不需要考虑分布式的问题。

(名词解释-节点:
我理解成提供服务的软件服务器,可以部署在多台物理机,
也可以部署在一台物理机的多台虚拟机中。)

单体架构

单体又称[单节点/单块/Monolith]架构,
一般只有用户、服务器、数据库,
适用于简单、用户访问量较少的项目。

把所有的代码都堆在1个应用且运行在1个Tomcat中,
Tomcat与MySQL运行在单节点的服务器中。

这种All in One的方式是有好处的,
创业初期,不用什么架构,走敏捷开发,
最快速的实现需求,把业务落地才是王道,
至少能快速在外网上让用户访问与使用。

之前去云栖大会听讲座,
淘宝的第一个版本用的就是一台普通的电脑当作为服务器,
所有的功能耦合在一个项目里,
每次往生产环境上发版本,要上传一个600MB的包。

杨明翰的微服务教学系列之概述篇V0.1(持续更新)

单体架构特点:

  • 单节点,没有容灾,服务器宕机只能重启;
  • 负载能力差,但访问量较少,所以也还OK;
  • 节省部署和运维成本;

前后端分离架构

随着访问量与代码量的不断增长,Tomcat的压力会越来越大,
从而性能越来越慢,我们需要进行对架构进行升级。

把原来耦合在一起的前后端拆一下(前后端分离),
把动态资源与静态资源也拆一下(动静分离)。

Tomcat作为应用服务器,性能很有限,尤其是1台Tomcat,
因此我们需要引入Nginx或Tengine这样的Web服务器,
通过Nginx来提供[静态/前端]资源的访问并使用CDN加速,
通过Tomcat来提供[动态/后端]资源的访问,大家各司其职。

细节可参考:
https://yangminghan.blog.****.net/article/details/65446892

杨明翰的微服务教学系列之概述篇V0.1(持续更新)

前后端分离架构特点:

  • Nginx的性能较高,提供静态资源访问(HTML、JS、CSS、图片等等),有效地减少了Tomcat的压力;

  • Nginx支持热部署,静态资源随便改,不用重启服务就直接有效果,Nginx部署配置简单,支持gzip压缩,加快网络传输速度,自带IP黑名单功能等等;

  • Nginx接收HTTPS请求,在通过Nginx把HTTPS请求转化成HTTP请求分给后端的应用服务器(内网Tomcat)集群,有效的提升了安全性,后端的应用服务器是外网访问不到的,所以不用再用HTTPS;

  • 加快项目的打包速度,大量的前端代码与资源被转移到了Nginx上,Tomcat这边只需要打包Java代码即可;

  • 应用分离,分为Web服务器(Nginx)与应用服务器(Tomcat),通过Ajax请求+Restful API来[获取数据/提交数据],使用JSON进行交互,进一步减少了服务器与用户之间的流量,从而使得服务器能够负载更多的用户;

负载均衡

Nginx可以做负载均衡,
我们可以多部署几个Tomcat通过Nginx的反向代理,
把压力均匀的分配各个Tomcat上,增加了后端的吞吐。

负载均衡也可以用阿里云SLB或域名解析做一级负载,
Nginx做二级负载,以后配合Docker玩弹性扩容,
产生巨大威力,由于部署了多个Tomcat,
Session持久化问题需要考虑。

垂直拆分

在All in One的前提下,当服务器系统资源不够时,
虽然我们可以通过水平扩展,增加[节点/计算资源],
通过暴力加机器的方式来解决性能问题。

但这种性能加速度其实会变得越来越小,
因为我们的项目还是耦合在一起的,
项目中包含着所有的后端代码,大家都部署在一起。

这时,我们需要进一步地拆分项目,
将一个很大的应用拆分成许多个小应用,
根据项目业务的不同,把项目模块化,
拆成一些互不相干的若干[子项目/模块/应用],
再把这些[子项目/模块/应用]独立部署,甚至部署多份,
这样就形成一个个小的负载均衡和集群,
再次避免牵一发而动全身,这样也可以提升吞吐,
这被称为垂直应用架构,为微服务架构打基础。

此外,我们可以将不同类型的服务部署在不同的服务器上,
减少单点宕机带来的灾难性后果,鸡蛋不要放在一个篮子里。

例如:
应用服务器、数据库服务器、文件服务器、消息队列服务器,
并把这些服务器分别独立部署,通过使用更多的服务器,
来提升我们的整体吞吐量。

分布式服务架构

但随着访问量的持续上升,
前后端分离已经不能再满足我们的需求,
我们的应用需要使用更多的神兵利器,
像什么分布式缓存、消息队列、注册中心、搜索引擎、NOSQL等等。

这时,你的缓存、数据库、消息队列等服务,
都应该是分布式的。

分布式服务架构能够进一步拆分,
使得整个架构更加明细,
同时使用了消息中间件等等中间件,
使得应用的吞吐量得到了极大的提升。

杨明翰的微服务教学系列之概述篇V0.1(持续更新)

服务化

经过前面的进化,
项目拆成了越来越多的独立部署的垂直[子项目/模块/应用],

随着业务的发展,模块与模块交互的地方越来越多,
可以复用的逻辑也越来越多,
这时我们需要把一些公用的核心的业务抽出来,
封装起来,发展成独立的服务,
之后再逐渐发展成稳定的服务中心,
用来提升业务复用与整合,
使得Web应用能更快速地响应多变的市场需求。

就像阿里的大牛说过,
没有淘宝的积累,天猫能那么快的出来吗?
淘宝和天猫的很多东西是复用的,
就是底层调用的是相同的服务中心,
例如:用户中心、订单中心等等。

在保证功能不变的前提下,
我们将后端应用再拆分成2部分:
Web应用与服务,分别独立部署,可以再负载均衡与集群。

服务独立部署后将把自己的位置注册给注册中心,
Web应用通过注册中心去查找路由信息,
再通过调用服务来满足自己的业务需求。

服务既可以暴露给Web应用走内部调用,
也可以直接暴露给网关让客户端外部调用。

注册中心

主要负责服务注册与服务发现,下文有详细介绍,不再赘述。

消息队列

拆分同步消息,使用消息中间件,
可以将大量的异步操作发送到消息中间件中,
后台服务均匀的消费这些消息,
避免了访问时的峰值对于整个数据库的压力影响,
同时拆分了异步的操作,能够提升了服务的吞吐量,
避免大量耗时的操作影响用户。

分布式缓存

分布式缓存缓存指的是,
像Redis、Memcached这样的高速缓存,
一般支持KV形式的查询,对于传统数据库来说,
缓存的性能要好的多。

分布式缓存可以有效避免通过数据库来查询影响性能。

虽然缓存架构有数据一致性与缓存失效的问题,
但是能极大的提升企业应用的负载能力。

高速缓存的使用分为两种情况:

  1. 基于请求的缓存:当http请求到达服务器,应用先去请求缓存,是否存在结果,如果没有结果,应用再去数据库查询,反馈给用户,并写到缓存之中;
  2. 利用缓存做session持久:解决前后端分离的session持久化痛点,把session持久化在缓存中。

数据一致性

大量使用缓存,数据库与缓存之间如果没有同步机制,
数据库有更新,而没有及时更新到缓存中,
那用户查询到的结果还是之前的结果,数据就不一致了。

未完待续

缓存失效

缓存无法像数据库一样永久持久化数据,
一般在写入缓存时,都会设置超时时间,
当某个特定时刻大量并发来临时,
当过了超时时间之后,数据会失效,
所有的查询压力陡增到数据库,导致数据库宕机。

未完待续

分布式数据库

由于海量数据与高并发访问,需要使用分库分表+多主多从,
数据库读写分离,配置多个读库来和主库同步。

将所有的查询都映射到读库上,
避免了数据库写入时对读取数据造成影响,
设置读库还能在主库挂掉的情况下进行读写切换,
瞬间将读库切换成主库,使得正常的业务不受影响。

分布式运维

运维难度大幅度增加,
服务器的增多、第三方中间件的部署、
数据库主从等等比之前增加了许多需要监控的机器,
对于服务器的部署必须要能自动化的运行,
而且必须要对应用进行实时监控,
在应用发生异常之后,能够及时的通知,
这些都极大的增加了运维的难度。

弹性计算架构

分布式服务架构的瓶颈在于,如果出现高并发,
对于某些应用以及部署这些应用的节点的压力会非常大,
有可能导致整个物理服务器都受到影响,
为了更好的负载压力和均匀的分配服务器的资源,
于是就产生了弹性计算架构。

当服务越来越多时,会存在一些容量评估和资源浪费等问题,
我们需要一个调度中心,
基于访问压力实时动态地管理集群容量,
用于资源调度和治理中心,从而提高机器利用率。

未完待续

Docker

在监控到某个服务或应用的压力负载增加到70%以上的时候,
使用脚本可以新增一系列的Docker容器做容器化,
并将服务启动起来,
这些操作能在秒级瞬间增加许多服务器资源来抗住洪峰,
当负载下降的时候就将这些资源回收,
能够节省服务器的资源来给其他服务使用。

不需要去部署与分配多台虚拟机,
而是采用Docker技术将应用部署在Docker容器之中,
可以使得服务器资源得到实时分配。

并行计算充分利用企业资源来提供最大化的服务。
资源最大化利用。

基于Docker容器,可以快速复制节点,
在某部分物理机房出现问题时,
能够快速在其他机房复制大量应用,
高效解决了异地容灾的问题。

未完待续

Hadoop

基于Hadoop的日志收集平台,在服务产生应用日志后,
将日志写入Hadoop集群,
不用担心日志在docker容器停止之后造成丢失,
同时能够更方便的对集群日志做查询。

同样Hadoop在处理离线资源的时候,一般是在凌晨,
这个时候负载都很低,可以空出很多服务器资源,
在处理Hadoop任务之前,
可以使用Docker新增很多节点再来进行计算,
高效的利用了服务器的资源,
使用Hadoop计算大数据,速度非常快。

分库分表后,使用数据库中间件来做路由,
同时数据库中间件还能配置数据库中的数据,
同步到Hadoop集群中,再配置一些离线任务,
使用Hadoop来计算,计算的结果保存在Hadoop之中,
再用数据库中间件来读取Hadoop的计算结果,
最后写入数据库。

使用数据库中间件来对数据进行处理,
生成更高效的数据来节省数据库资源。

未完待续


传统架构的痛点

杨明翰的微服务教学系列之概述篇V0.1(持续更新)

后端代码包含Module A、B、C共3个模块,
其中模块A、B各占10%的系统资源,模块C占80%,
我们把所有的代码(包括前端代码+后端代码),
都揉进一个WAR包里,
然后这个WAR包发布到生产环境上的Web容器(Tomcat),
然后启动Web容器,你的服务就可以被外网的用户访问啦。

后端代码会连接到数据库(MySQL)进行数据的增删改查。

这跟大家在学习JavaWeb时做的"xxx管理系统",
有异曲同工之妙。

后来慢慢的进化成前后端分离架构,
WAR包里关于前端的部分被摘出去了,
但WAR包里的各种Java代码还是紧紧的拥抱在一起,
都在一个JavaWeb项目中。

后来访问量逐渐增大,模块C逐渐成为了系统的性能瓶颈,
一台应用服务器似乎扛不住了,那我们就需要扩容!

扩容的话需要需要使用负载均衡(软硬皆可),
然后再多买几个节点,
在上面安装Web容器,
再把这个WAR包发布到这些web容器上,再启动。

要知道所有的请求都会消耗服务端的计算资源,
并且计算资源是有限的,例如CPU,内存,带宽等。

哎哟,不错哦,我们貌似用上了高大上的集群&负载均衡,
这些Web容器组成了一个集群,整体对外提供服务,
服务端的负载能力也大大提升。

这样貌似没有什么问题,各种业务有条不紊的在运行,
团队内部一片祥和。

但是,问题来了,同志们。
随着时间的推移以及业务逻辑与代码量的增长,也许1-2年后,我们编写的"小婴儿"成长为了一个"大胖子"。

所有的代码被放在一个项目内,运行在一个进程中,
维护和继续开发这坨代码,会很痛。
所以,痛在哪里?

浪费资源

我们的性能瓶颈在C模块,
在需要扩容时只扩容C模块就可以有效缓解系统压力,
但因为模块A、B、C是耦在一起的,
因此每次扩容的时候都会把模块A、B也带上。

不能根据不同的业务做扩容,
80%的负载来自20%的业务(例如:登录),
其实我真的只想扩容那20%的业务,
但不可能,每次扩容都额外浪费设备成本。

部署效率低

即使改一个小地方,必须要重新构建&部署整个系统,
更何况是部署在整个集群环境,有n个tomcat需要部署,
部署速度慢,因为WAR包很大,
测试工程师的冒烟与回归测试需要花时间,
并且系统需要7x24小时在线。

一个小改动的上线也许都需要等到凌晨发布,
生产效率特低,时间就是金钱,我的朋友。

技术选型单一

WAR包里放的都是.class文件,
无法使用其他编程语言来开发某个模块,
也许其他语言&技术更适合开发某一个模块呢。

牵一发而动全身

一个功能出bug造成内存溢出,或者系统hung掉,
整个应用系统全部玩完,因为大家都是在一个进程中,
我们需要隔离性。

代码结构臃肿

随着时间的推移,项目中的代码会越来越多,
代码结构越来越复杂,面对吨级的代码,
维护成本和新人学习成本都非常高。
代码隔离性差,
不想让新人看到所有的代码而又想让他做一些边角料的功能。

WebUI与这些Module封装在一个war包中,
需要将此war包部署到Tomcat上才能运行。
ModuleC要占用80%的系统资源,成为了整个系统的瓶颈,
从而降低了系统的性能。

性能吃紧,那么我们需要扩容。
我们把WAR包复制一份到另一台Tomcat上,
再在2个Tomcat上面加一个负载均衡即可,
这样我们实现了水平扩展。

我们甚至可以一直这么水平扩展下去,扩展成n个tomcat,只要负载均衡能抗住就可以。
这样可以有效的提升整个系统的负载能力。

但是,这样却造成了巨大的资源浪费,因为我们对资源占用率不高的ModuleA与ModuleB也进行了扩展,但其实我们只想
对ModuleC进行扩展而已。

(资源浪费的例子:比如ModuleA与ModuleB占用了200mb的硬盘,而ModuleC只占用了1mb,
那我每次水平扩展的时候有200mb相当于浪费掉了,造成了硬盘的浪费。
再或者ModuleA与ModuleB里有1万个类,而ModuleC只有100个类,
那JVM启动后,需要使用classloader来加载类到内存中,造成了内存的浪费。等等)


微服务架构

马丁老爷子(Martin Fowler),
于2014年提出了"Mirco Service"的概念,
之后互联网上就开始对这一概念进行了激烈讨论并落地。

在Docker容器化技术逐渐普及后,
一个崭新的轻量级SOA架构伴随着Docker向我们走来了。

微服务是一种架构,微服务是一种分布式系统架构,
微服务架构将原有业务拆成更细粒度的服务,
每个服务的的责任单一且可独立部署,服务内部高内聚,
隐含内部细节,服务之间低耦合,彼此相互隔离。

微服务的思想不只停留在开发阶段,
它贯穿于设计、开发、测试、部署、
运维等软件生命周期阶段,所以:无自动化,不微服务。。

简而言之,微服务架构就是按照业务,
将服务拆分到不同的程序(进程),单独部署,发布。

杨明翰的微服务教学系列之概述篇V0.1(持续更新)

其中每个Service可以理解成针对不同的业务做的拆分(用户服务、积分服务、商品服务等),
每个Service单独部署,运行为独立的程序。

每个Service可以有自己的DB,
也可以多个Service共享一个DB,
对于高负载的Service,还可以启动多个增加负载。

当Service启动时,
会自动将自己的访问信息&地址(IP+端口号+服务名称)注册到Service Registry(注册中心)
(这就是大名鼎鼎的服务注册,重要概念)。

服务消费者(consumer, 图中的Web UI)发出请求后,
请求被送到Service Gateway(服务网关)中,
网关去服务中心获取本次请求服务的所在IP+端口号(这就是大名鼎鼎的服务发现,重要概念),
然后服务网关去调用对应的服务。


注意:
原始的单体架构中,因为所有的组件都耦在一起,
导致用户访问的IP+端口号就是服务器上Service的IP+端口号。

但在分布式架构中,组件进行了打散,
Service被部署在了不同的IP+端口号上,
那我们怎么知道某个服务被运行在哪个地方呢?
这就延伸出来了服务发现,我要发现服务,才能调用服务,
那通过什么发现呢?通过服务中心来发现服务。
服务中心是怎么知道每个服务都在哪里呢?
因为服务启动的时候会进行服务注册。

当某些服务,访问日渐变多(例如商城最近生意越来越好),我们可以直接增加机器,多部署一些商城服务,
就可以直接提高系统的处理能力。

微服务需要:
容器化、自动化运维部署、服务监控与服务治理等等。

交付流程

我们对每一个微服务进行设计、开发、测试、部署,
因为服务之间是没有彼此依赖的。

交付流程:
Service1:设计->开发->测试->部署
Service2:设计->开发->测试->部署
Service3:设计->开发->测试->部署

在设计阶段,我们将产品功能拆成若干个服务,
为每个服务设计API接口,需要给出API文档。

在开发阶段,
我们去实现API接口,
也包括完成API的单元测试工作。
前端工程师去开发WEB UI,
可根据API文档早出一些假数据(mock数据),
前端工程师不必等待后端API全部开发完毕,
才能开始自己的工作。

在测试阶段,
前后端工程师分别将自己的代码部署到测试环境上,
测试工程师将针对测试用例进行手动或自动化测试,
随后产品经理将从产品功能上进行验收。

在部署阶段,运维工程师将代码部署到预发环境中,
测试工程师再进行一些冒烟测试,
当不再发现任何问题时,
经技术经理确认,运维工程师将代码部署到生产环境中,
这一系列的部署过程都需要做到自动化,才能提高工作效率。

在小团队中,一名工程师可兼任多种角色。

Git分支规范

最稳定的代码放在master分支上,
我们不要直接在master分支上提交代码,
只能在该分支上进行代码合并操作,
例如将其他分支的代码合并到master分支上。

我们日常开发中的代码,
需要从master分支上拉一条dev分支出来,
该分支所有人都能访问,但一般情况下,
我们也不会直接在该分支上提交代码,
代码同样是从其他分支合并到dev分支上去的。

当我们需要开发某个功能时,
需要从dev分支上拉出一条功能开发分支,
例如dev-1与dev-2,
在这些分支上并行的开发具体功能。

当功能开发完毕后,我们决定发布版本了,
此时需要从dev分支上拉出一条release分支
(Alex:因为线上bug的修复也会同步到dev分支上,
所以要再拉出来一个),例如release-1.0.0,
并将需要发布的功能从相关dev-1、
dev-2分支一同合并到release分支上,
随后针对release分支部署测试环境,
测试工程师在该分支上做功能测试,
开发工程师在该分支上修改bug。

待测试工程师无法找到任何bug时,
我们可以将该release分支部署到预上线环境中,
再次验证后,如果没有任何bug,
可将release分支部署到生产环境中,
待上线完成后,
将release分支上的代码同时合并到dev与master。
并在master分支上打一个tag,例如v1.0.0。

当在生产环境中发现bug时,
我们需要从对应的tag上(例如v1.0.0),
拉出一条hotfix分支(例如hotfix-1.0.1),
并在该分支上进行bug修复。

待bug全部修复后,
需将hotfix分支上的代码同时合并到dev与master上。

版本号的格式为x.y.z。
x用于有重大重构时才会升级x,
y用于有新的特性发布时才会升级,
z用于修改了某个bug后才会升级。

开发与部署

使用Spring Boot框架来进行代码开发,
支持你快速的开发出Restful风格的微服务架构,
Spring Boot并不是一个全新的技术,
而是把老的技术(SpringMVC、Spring等)进行有机结合,
使用约定大于配置的理念来进行整合,提供了默认的配置,
大量减少配置,简化开发,加快开发速度,
并提供可插拔的设计。

Spring Boot具有嵌入式Tomcat,支持热部署,
将代码打成jar包并发布服务,还提供一些开箱即用的插件,
使我们的开发效率提升。

通过Maven插件,
可以把Spring Boot的应用打成可执行jar包以及热部署,
打包后通过Jenkins+Docker,
发布到生产环境的Docker容器。
Spring Boot+Docker负责封装服务。

Jenkins负责自动化发布、部署微服务,
Docker容器化封装微服务。

通过Jenkins搭建自动化部署系统,
将jar包发布到生产环境的Docker镜像,
Docker镜像生成Docker容器并启动服务。

微服务组件

服务网关

目前可以用作服务网关的技术有:
Spring Cloud Gateway、Zuul、Node.js等

如果是Node.js搭建微服务网关,
通过node.js将请求转发到Tomcat上,
实现反向代理,调用服务。
node.js的效率较高(单线程模型&非阻塞异步式I/O),为了实现高可用,node.js一般需要实现集群。

路由、过滤

限流、熔断、降级

鉴权

负载均衡

注册中心

目前可以用作注册中心的技术有:
Zookeeper、Redis、Nacos等。

在服务被部署到生产环境的Docker容器中后,
服务需要启动,启动时会进行服务注册,
将地址信息(IP+端口号+服务名称)注册到服务中心里。

zookeeper中有一个名为znode的内存树状模型,
树上的节点用于存放各种服务的地址信息(ip+端口号+服务名称),使用node.js连接zookeeper发现服务,
通过服务名称去找对应的ip+端口号。spring boot与node.js分别为zookeeper的客户端,分别进行服务注册与服务发现。
为了实现高可用,zookeeper一般需要实现集群。

服务注册

服务发现

服务调用

微服务特性

  • 按业务垂直拆出服务,模块化,根据业务模块划分服务种类;

  • 每个服务可独立部署且相互隔离,服务之间是没有干扰的、互不影响的,可将每个服务放入独立的进程中部署运行,因为进程之间是完全隔离且安全的,某个服务出问题并后不会影响到其他服务,不再牵一发而动全身,每个服务可以提供多个API,每个API都具有责任单一性;

  • 当某个微服务发生变更或升级时无需编译、部署整个应用(不用做大面积详细的冒烟测试,不怕变更影响到其他功能),由微服务组成的应用相当于具备一系列可并行的发布流程,使得发布更加高效且更容易,同时降低对生产环境所造成的风险,最终缩短应用交付周期,让测试更容易识别与隔离问题,提升生产效率;

  • 通过HTTP或RPC的轻量级API方式来调用服务,需要跨进程间的远程调用,进程间的调用比线程间的调用更耗资源;

  • 运维工程师需要使用自动化技术来部署微服务,并且要对整个系统进行监控预警,保障系统有高可用性,需要高效地管理这些服务,运维成本会上升;

  • 复杂性上升,因为是分布式架构,每个服务可以部署在任意一个节点上,进程间通讯机制、网络延迟、系统容错、局部失效、分布式事务等问题会频发;

  • 部署依赖较强,对于复杂的业务情况,可能存在多个服务来共同完成一件事情,服务之间虽然没有相互调用,但需要有调用顺序性要求,业务依赖性导致了部署的依赖性,从而在某一时间点,同一微服务可能具备多个版本;

  • 系统被拆成多个服务后,方便我们对每一个服务进行监控,收集每个服务的性能指标数据,当某个服务出现性能瓶颈时会有报警,我们可以及时水平扩展该服务,以获得更大的吞吐量,不至于扩展整个应用;

  • 复杂度可控,在将应用分解的同时,规避了原本复杂度无止境的积累。每一个微服务专注于单一功能,并通过定义良好的接口清晰表述服务边界。由于体积小、复杂度低,每个微服务可由一个小规模开发团队完全掌控(2-5人),易于保持高可维护性和开发效率,并且微服务对新人比较友好;

  • 技术选型灵活,微服务架构下,技术选型是去中心化的。每个团队可以根据自身服务的需求和行业发展的现状,自由选择最适合的技术栈。由于每个微服务相对简单,当需要对技术栈进行升级时所面临的风险较低,甚至完全重构一个微服务也是可行的;

  • 单块架构应用也可以实现横向扩展,就是将整个应用完整的复制到不同的节点。当应用的不同组件在扩展需求上存在差异时,微服务架构便体现出其灵活性,因为每个服务可以根据实际需求独立进行扩展;

  • 一个微服务一般完成某个特定的功能,比如消息管理、客户管理等等。一些微服务还会发布API给其它微服务和应用客户端使用;


总结

不要为了微服务而微服务,
使用微服务架构后,可能在每一分钟都在交付新服务,
这样你就会拥有一个敏捷的且即时响应的应用程序平台,
当然这一平台一直在不断改进中,微服务架构也在前进着。

在复杂度&业务量较小时采用单体应用的生产率更高,
复杂度&业务量到了一定规模,
单体应用的生产率开始急剧下降,我们需要对架构进行升级。