微服务架构模式简介

1Monolith架构模式

首先请回想一下我们所开发的服务是什么样子的。通常情况下,这个服务所对应的代码由多个项目所组成,各个项目会根据自身所提供功能的不同具有一个明确的边界。在编译时,这些项目将被打包成为一个个JAR包,并最终合并在一起形成一个WAR包。接下来,我们需要将该WAR包上传到Web容器中,解压该WAR包,并重新启动服务器。在执行完这一系列操作之后,我们对服务的编译及部署就已经完成了

      这种将所有的代码及功能都包含在一个WAR包中的项目组织方式被称为整体架构(Monolith。在项目较小的情况下,这种代码组织方式还是可以接受的但随着项目的逐渐变大,整个开发流程的时间也会变得很长:即使在仅仅更改了一行代码的情况下,软件开发人员需要花费几十分钟甚至超过一个小时的时间对所有代码进行编译,并接下来花费大量的时间重新部署刚刚生成的产品,以验证自己的更改是否正确。

      如果应用的部署非常麻烦,那么为了对自己的更改进行测试,软件开发人员还需要在部署前进行大量的环境设置,进而使得软件开发人员的工作变得繁杂而无趣:

      从上面的示意图中可以看到,在应用变大之后,软件开发人员花在编译及部署的时间明显增多,甚至超过了他对代码进行更改并测试的时间,效率已经变得十分低下。

      在变得越来越大的同时,我们的应用所使用的技术也会变得越来越多。这些技术有些是不兼容的,就比如在一个项目中大范围地混合使用C++Java几乎是不可能的事情。在这种情况下,我们就需要抛弃对某些不兼容技术的使用,而选择一种不是那么适合的技术来实现特定的功能。

      除此之外,由于按照Monolith组织的代码将只产生一个包含了所有功能的WAR包,因此在对服务的容量进行扩展的时候,我们只能选择重复地部署这些WAR包来扩展服务能力,而不是仅仅扩展出现系统瓶颈的组成:

      但是这种扩展方式极大地浪费了资源。就以上图所展示的情况为例:在一个服务中,某个组成的负载已经达到了90%,也就是到了不得不对服务能力进行扩容的时候了。而同一服务的其它三个组成的负载还没有到其处理能力的20%。由于Monolith服务中的各个组成是打包在同一个WAR包中的,因此通过添加一个额外的服务实例虽然可以将需要扩容的组成的负载降低到了45%,但是也使得其它各组成的利用率更为低下。

      可以说,所有的不便都是由于Monolith服务中一个WAR包包含了该服务的所有功能所导致的。而解决该问题的方法就是Microservice架构模式。

2Microservice架构模式

      简单地说,Microservice架构模式就是将整个Web应用组织为一系列小的Web服务。这些小的Web服务可以独立地编译及部署,并通过各自暴露的API接口相互通讯。它们彼此相互协作,作为一个整体为用户提供功能,却可以独立地进行扩容。

就以下图所示的WikiPedia服务架构为例:

      从上图中可以看到,WikiPedia包含了一系列服务,如数据访问服务Databases,搜索服务Search等。这些服务都包含了数量不等的服务实例,以确保能在不同负载的情况下为用户提供优质的服务。在用户的请求到达时,它们将协同工作,一起完成对用户请求的响应。

      在使用Microservice架构模式的情况下,软件开发人员可以通过编译并重新部署单个子服务的方式来验证自己的更改,而不再需要重新编译整个应用,从而节省了大量的时间。同时由于每个子服务是独立的,因此各个服务内部可以自行决定最为合适的实现技术,使得这些子服务的开发变得更为容易。最后如果当前系统的容量不够了,那么我们只需要找到成为系统瓶颈的子服务,并扩展该子服务的容量即可:

微服务架构是一种特定的软件应用程序设计方式——将大型软件拆分为多个独立可部署服务组合而成的套件方案,其中各项服务都拥有自己的进程并利用轻量化机制(通常为HTTP源API)实现通信。

微服务架构的本质,是用一些功能比较明确、业务比较精练的服务去解决更大、更实际的问题。

 

      第一个就不说了,第二个垂直架构,典型的比如SSH框架,帮大家考虑了模块化、MVC等,但并没有考虑服务化。第三个是分布式架构,以SOA为代表的这类技术已经热了很多年,现在也是企业架构的主体支撑部分。而第四个以微服务架构为支撑的技术只在一些先进企业或互联网公司已经运用。

3Microservice实现

      相信大家的第一个问题就是,Microservice架构模式中各个子服务应该如何相互协作以向用户提供服务的呢?按照上面我们的讲解,Microservice架构模式中各个子服务应该是独立的,否则它们之间将产生耦合,进而带来一系列问题:这些子服务彼此不独立,需要使用分布式事务保持其数据一致性,子服务不易被重用等。但是如果这些子服务绝对独立,甚至不包含一点点逻辑上的耦合,那么它们之间也将无法进行协作。因此在论坛讨论中常常出现的问题就是,这些子服务之间哪里可以出现耦合?可以出现什么程度的耦合?

      这个问题实际上非常简单,那就是UI。我们知道,在一个BS服务中,服务端和客户端之间存在着一定程度的耦合。两者通过服务所暴露的API进行沟通。而基于Microservice架构模式的服务也不例外:

      既然运行在用户浏览器中的UI需要与其它各个子服务进行交互,那么它完全可以作为一个中介者来完成各个子服务之间的交互。例如在显示产品页面的时候,该页面逻辑会向产品服务及库存服务同时发送请求,以并行地得到产品的详细信息以及该产品的当前库存。

      因此在一个基于Microservice架构模式的服务中,常常会出现一个前端服务。该服务所提供的页面会与各个服务沟通。但是它实际上与各个子服务之间却不需要通讯:

      或许您会说,在这种情况下,我们的各个子服务就没有UI了。而UI服务不仅仅需要处理所有的前端业务逻辑,而且随着时间的推移,其可能会变成另外一个庞然大物。除此之外,如果希望整个平台能够允许第三方服务接入,那么这种打包在一起的UI服务将变成整个平台扩展性的阻碍。

      是的。如果需要解决这个问题,那么您就需要在应用中尝试借鉴服务定位器(Service Locator模式。此时我们需要的则是一个UI框架,其允许用户通过特定方式在应用中插入各个子服务所提供的UI,并允许您通过一些机制来发现已经在平台中注册的具有特定功能的API,并允许您对该API进行调用。我相信,随着Microservice架构模式的不断发展,会有越来越多的支持这种扩展方式的UI类库出现。

      另外一种模式则是Message Broker。简单地说,Message Broker就是一个消息的中转平台。该平台允许其它组成向其中注册消息,也允许其它组成侦听消息。当一个组成将一个消息发送到了Message Broker之上后,其它侦听该消息的各个组成则会根据消息中所包含的信息更新自己的状态。

      反过来,如果您的服务需要支持移动设备,如手机,iPad等,我们就不能让这些移动设备一个一个地访问子服务了。这是因为这些移动设备的带宽一般来说都非常小,而且用户常常处于信号不是很好的地方,因此在向这些子服务一个个地发送请求将快速消耗掉它们所拥有的有限的带宽。为了解决这个问题,我们常常需要在这些子服务前搭建一个代理服务。该代理服务会将用户请求根据业务逻辑拆分为对各个子服务的请求,并将各个子服务所返回的结果归纳为一个响应返回给用户:

4Microservice的优点与劣势

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

      独立部署:由于微服务具备独立的运行进程,所以每个微服务也可以独立部署。当某个微服务发生变更时无需编译、部署整个应用。由微服务组成的应用相当于具备一系列可并行的发布流程,使得发布更加高效,同时降低对生产环境所造成的风险,最终缩短应用交付周期。

      技术选型灵活:微服务架构下,技术选型是去中心化的。每个团队可以根据自身服务的需求和行业发展的现状,自由选择最适合的技术栈。由于每个微服务相对简单,当需要对技术栈进行升级时所面临的风险较低,甚至完全重构一个微服务也是可行的。   由于Microservice架构模式中的各个子服务无论是在代码量方面还是最终生成的WAR包方面都较Monolith架构所搭建的服务小,因此在IDE支持,启动速度方面都具有相当的优势。

      容错:当某一组建发生故障时,在单一进程的传统架构下,故障很有可能在进程内扩散,形成应用全局性的不可用。在微服务架构下,故障会被隔离在单个服务中。若设计良好,其他服务可通过重试、平稳退化等机制实现应用层面的容错。

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

同时,这种小粒度的服务已经可以由一个几个人所组成的小组来完成,而不再需要通过来自世界各地的不同小组协同开发,进而大大降低了沟通成本,提高了开发的效率。

总而言之就是小,独立进程,自动化。

 

      但是反过来,Microservice架构模式中各个子服务的独立性也会导致一系列问题:

数据一致性的问题:最明显的就是需要多个子服务相互配合的情况。由于这些子服务是不同的进程,因此在这些进程之间保持数据的一致性,或添加一个新的跨子服务的用户用例实际上都是一件非常麻烦的事情。

测试复杂度:测试一个基于微服务架构的应用也是很复杂的任务。比如,采用流行的Spring Boot架构,对一个单体式web应用,测试它的REST API,是很容易的事情。反过来,同样的服务测试需要启动和它有关的所有服务(至少需要这些服务的stubs)。不能低估了采用微服务架构带来的复杂性。

部署相对复杂:部署一个微服务应用也很复杂,一个分布式应用只需要简单在复杂均衡器后面部署各自的服务器就好了。每个应用实例是需要配置诸如数据库和消息中间件等基础服务。相对比,一个微服务应用一般由大批服务构成。每个服务都有多个实例。这就造成许多需要配置、部署、扩展和监控的部分,除此之外,你还需要完成一个服务发现机制(后续文章中发表),以用来发现与它通讯服务的地址(包括服务器地址和端口)。传统的解决问题办法不能用于解决这么复杂的问题。接续而来,成功部署一个微服务应用需要开发者有足够的控制部署方法,并高度自动化。

      此外,微服务架构模式应用的改变将会波及多个服务。比如,假设你在完成一个案例,需要修改服务ABC,而A依赖BB依赖C。在单体式应用中,你只需要改变相关模块,整合变化,部署就好了。对比之下,微服务架构模式就需要考虑相关改变对不同服务的影响。比如,你需要更新服务C,然后是B,最后才是A

最后的最后

为初学者提供学习指南,为从业者提供参考价值。我坚信码农也具有产生洞见的能力。扫描下图二维码关注,学习和交流!

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码农洞见

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值