微服务架构概述
微服务架构是当前软件开发领域得技术热点。什么是微服务?它解决了哪些问题?它又具有哪些特点?
单体应用架构存在得问题
一个归档包(例如war格式)包含所有功能得应用程序,通常称为单体应用。而架构单体应用得方法论,就是单体应用架构。
以一个电影售票系统为例。
该应用尽管已经进行了模块化,但由于UI和若干业务模块最终都被打包在一个war包中,该war包包含了整个系统所有的业务功能,这样的应用系统称为单体应用。相信很多项目都是从单体应用开始的。单体应用比较容易部署、测试,在项目的初期,单体应用可以很好地运行。然而,随着需求的不断增加,越来越多的人加入开发团队,代码库也在飞速地膨胀。慢慢地,单体应用变得越来越臃肿,可维护性、灵活性逐渐降低,维护成本越来越高。
- 复杂性高:以一个百万行级别地单体应用为例,整个项目包含地模块非常多、模块地边界模糊、依赖关系不清晰、代码质量参差不齐、混乱地堆砌在一起…整个项目非常复杂。每次修改代码都心惊胆战,甚至添加一个简单地功能,或者修改一个Bug都会带来隐含地缺陷。
- 技术债务:随着时间推移、需求变更和人员更迭,会逐渐形成应用程序地技术债务,并且越积越多。“不坏不修(Not broken,don`t fix)”,这在软件开发中非常常见,在单体应用中这种思想更甚。已使用地系统设计或代码难以修改,因为应用程序中地其他模块可能会以意料之外地方式使用它。
- 部署效率低:随着代码的增多,构建和部署的时间也会增加。而在单体应用中,每次功能的变更或缺陷的修复都会导致需要重新部署整个应用。全量部署的方式耗时长、影响范围大、风险高,这使得单体应用项目上线部署的频率较低。而部署频率低又导致两次发布之间会有大量的功能变更和缺陷修复,出错概率比较高。
- 可靠性差:某个应用Bug,例如死循环、OOM等,可能会导致整个应用的崩溃。
- 扩展能力受限:单体应用只能作为一个整体进行扩展,无法根据业务模块的需要进行伸缩。例如,应用中有的模块是计算密集型的,它需要强劲的CPU;有的模块则是IO密集型的,需要更大的内存。由于这些模块部署在一起,不得不在硬件的选择上做出妥协。
- 阻碍技术创新:单体应用往往使用统一的技术平台或方案解决所有的问题,团队中的每个成员都必须使用相同的开发语言和框架,要想引入新框架或新技术平台会非常困难。例如,一个使用Struts2构建的、有100万行代码的单体应用,如果想要换用Spring MVC,毫无疑问切换的成本是非常高的。
如何解决单体应用架构存在的问题
微服务就是用来解决这种问题的架构模式。
什么是为微服务
就目前来看,微服务本身没有一个严格的定义,每个人对微服务的理解都不同。
Martin Fowler在他的博客中是这样描述微服务的。
In short, the microservice architectural style [1] is an approach to developing a single application as a suite of small services, each running in its own process and communicating with lightweight mechanisms, often an HTTP resource API. These services are built around business capabilities and independently deployable by fully automated deployment machinery. There is a bare minimum of centralized management of these services, which may be written in different programming languages and use different data storage technologies.
总之,微服务这种架构风格就是把一组小服务演化成为一个单一的应用的一种方法。每个应用都运行在自己的进程中,并通过轻量级的机制保持通信,就像HTTP这样的API。这些服务要基于业务场景,并使用自动化布署工具进行独立的发布。可以有一个非常轻量级的集中式管理来协调这些服务,可以使用不同的语言来编写服务,也可以使用不同的数据存储。
原文http://martinfowler.com/articles/microservices.html
可以看到,微服务框架应具备以下特性
- 每个微服务可独立运行在自己的进程中
- 一系列独立运行的微服务共同构建起整个系统
- 每个服务为独立的业务开发,一个微服务只关注某个特定的功能,例如订单管理、用户管理等。
- 微服务之间通过轻量的通信机制进行通信,例如通过RESTful API进行调用。
- 可以使用不同的语言与数据存储技术
- 全自动的部署机制
整个应用分为多个微服务,各个微服务独立运行在自己的进程中,并分别有自己的数据库,微服务之间使用REST或者其他协议通信。
微服务架构的优点与挑战
相对单体应用架构来说,微服务架构有着显著的优点。但是,微服务并非是完美的,使用微服务也为我们的工作带来了一定的挑战。
微服务架构的优点
- 易于开发和维护:一个微服务只会一个特定的业务功能,所以它业务清晰、代码量较少。开发和维护单个微服务相对简单。而整个应用是若干个微服务构建而成的,所以整个应用也会被维护在一个可控状态。
- 单个微服务启动较快:单个微服务代码量较少,所以启动会比较快。
- 局部修改容易部署:单体应用只要有修改,就得重新部署整个应用,微服务解决了这样的问题。一般来说,对某个微服务进行修改,只需要重新部署这个服务即可。
- 技术栈不受限:在微服务架构中,可以结合项目业务及团队的特点,合理地选择技术栈。例如某些服务可使用关系型数据库MySQL;某些微服务有图形计算的需求,可以使用Neo4j;甚至可根据需要,部分微服务使用Java开发,部分微服务使用Node.js开发。
- 按需伸缩:可根据需求,实现细粒度的扩展。例如,系统中的某个微服务遇到了瓶颈,可以结合这个微服务的业务特点,增加内存、升级CPU或者是增加节点。
综上所述,单体应用架构的缺点,恰恰是微服务的优点,而这些优点使得微服务看起来简直非常完美。但是微服务仍然面临许多挑战。
微服务架构面临的挑战
- 运维要求较高:更多的服务意味着更多的运维投入。在单体架构中,只需要保证一个应用的正常运行。而在微服务中,需要保证几十甚至几百个服务正常运行与协作,这给运维带来了很大的挑战。
- 分布式固有的复杂度:使用微服务构架的是分布式系统。对于一个分布式系统,系统容错、网络延迟、分布式事务等都会带来巨大的挑战。
- 接口调整成本高:微服务之间通过接口进行通信。如果修改某一个微服务的API,可能所有使用了该接口的微服务都需要做调整。
- 重复劳动:很多服务可能都会使用相同的功能,而这个功能并没有达到分解为一个微服务的程度,这个时候,可能各个服务都会开发这一功能,从而导致代码重复。
尽管可以使用共享库来解决这个问题(例如可以将这个功能封装成公共组件,需要该功能的微服务引用该组件),但共享库在多语言环境下就不一定行的通了。
微服务设计原则
和数据库设计的N范式一样,微服务也有一定的设计原则,这些原则指导我们更加合理地架构微服务。
- 单一职责原则:单一职责原则指的是一个单元(类、方法或者服务等)只应关注整个系统功能中单独、有界限地一部分。单一职责原则可以帮助我们更优雅地开发、更敏捷地交付。单一职责原则是SOLID原则之一。
- 服务自治原则:服务自治是指每个微服务应具备独立地业务能力、依赖与运行环境。在微服务架构中,服务是独立地业务单元,应该与其他服务高度解耦。每个微服务从开发、测试、构建、部署,都应当可以独立运行,而不应该依赖其他的服务。
- 轻量级通信机制:微服务之间应该通过轻量级的通信机制进行交互。笔者认为,轻量级的通信机制应具备两点:首先,它的体量较轻;其次,它应该是跨语言、跨平台的。例如我们所熟悉的REST协议,就是一个典型的轻量级通信机制;而例如Java的RMI协议则不大符合轻量级通信机制的要求,因为它绑定了Java语言。微服务架构中常用的协议有REST、AMQP、STOMP、MQTT等。
- 微服务粒度:微服务的粒度是难点,也常常是争论的焦点。应对使用合理的粒度划分微服务,而不是一味地把服务做小。代码量地多少不能作为微服务划分地依据,因为不同地微服务本身地业务复杂性不同,代码量也不同。在微服务地设计阶段,就应确定其边界。微服务之间应相对独立并保持松耦合。领域驱动设计(Domain Driven Design, DDD)中的“限界上下文(Bounded Context)”可作为划分微服务边界、确定微服务粒度的重要依据。
微服务架构的演进是一个循序渐进的过程。在演进过程中,常常会根据业务的变化,对微服务进行重构,甚至是重新划分,从而让架构更加合理。最终,当微服务的开发、部署、测试以及运维的效率很高,并且成本很低时,一个好的微服务架构就形成了。
如何实现微服务架构
技术选型
相对于单体应用的交付,微服务应用的交付要复杂很多,不仅需要开发架构的支持,还需要一些自动化部署工具,以及IaaS、PaaS或CaaS的支持。
- 开发框架的选择:可使用Spring Cloud作为微服务开发框架。首先,Spring Cloud具备开箱即用的生产特性,可大大提升开发效率;再者,Spring Cloud的文档丰富、社区活跃,遇到问题比较容易获得支持;更为可贵的是,Spring Cloud为微服务架构提供了完整的解决方案。当然,也可以使用其他的开发框架或者解决方案来实现微服务,例如Dubbo、Dropwizard、Armada等。
- 运行平台:微服务并不绑定运行平台,将微服务部署在PC Server,或者阿里云、AWS等云计算平台都是可以的。出于轻量、灵活、应用支持等方面考虑,可以选择在Docker上部署微服务。