最近最火的词是什么?那大概就是 微服务 ( Microservice
)了。最近也火的一踏糊涂的Docker、AppOps也都是围绕着微服务领域的。在微服务领域还有很多相关名词。这些名词有一个共同的特点那就是晦涩难懂。他们就像中国古代的道、气、八卦等词一样, 一解释就懂,一问就不知,一讨论就打架。
本文主要来介绍几个和微服务相关的概念。这些概念的都是博主在浏览了大量资料之后总结出的个人见解,如有偏颇,请指正,共勉之。
首先来谈两个前端和移动端比较常见的词: 组件化
和 模块化
(后面我会说到为什么要先介绍 组件化
和 模块化
)。
首先,可以肯定的是,组件化和模块化的中心思想都是 分而治之
。目的都是将一个庞大的系统拆分成多个组件或者说是模块。
首先来看维基百科中关于组件化( Component-based software engineering )的介绍:
Component-based software engineering (CBSE), also known as component-based development (CBD), is a branch of software engineering that emphasizes the separation of concerns in respect of the wide-ranging functionality available throughout a given software system. It is a reuse-based approach to defining, implementing and composing loosely coupled independent components into systems. This practice aims to bring about an equally wide-ranging degree of benefits in both the short-term and the long-term for the software itself and for organizations that sponsor such software.
大概意思就是:组件化就是基于可重用的目的,将一个大的软件系统按照分离关注点的形式,拆分成多个独立的组件,主要目的就是 减少耦合 。
维基百科中对模块化 Modular Programming 的定义如下:
Modular programming is a software design technique that emphasizes separating the functionality of a program into independent, interchangeable modules, such that each contains everything necessary to execute only one aspect of the desired functionality.
With modular programming, concerns are separated such that modules perform logically discrete functions, interacting through well-defined interfaces.
模块化的目的在于将一个程序按照其功能做拆分,分成相互独立的模块,以便于每个模块只包含与其功能相关的内容,模块之间通过接口调用。将一个大的系统模块化之后,每个模块都可以被高度复用。
从上面的定义中可以看出,组件化和模块化的意思差不多,主要思想都是分而治之。只是一个把拆分之后的每个片段叫做组件、另一个把拆分之后的片段叫做模块。那么这两种拆分在拆分方式上是不是有什么不同的?
关于组件化和模块化的区别,我在网上看了好多资料,也没有人能给出准确的回答。其实没有准确回答的原因也比较明显,那就是大多数时候我们真的不需要严格的区分这两个名字。我们要学习的是其中的解耦和分治的思想和目的。
从另外一个角度来讲,如果真的要区分一下组件化和模块化的话,那么可以认为这两种分而治之的目的稍有区别:
模块化的目的是为了 重用
,模块化后可以方便重复使用和插拨到不同的平台,不同的业务逻辑过程中。
组件化的目的是为了 解耦
,把系统拆分成多个组件,分离组件边界和责任,便于独立升级和维护。
要谈微服务,那么必须建立在分布式的基础上,对于一个集中式系统也无需谈微服务。在我的另外一篇文章初识分布式系统中介绍过集中式系统和分布式系统的区别,这里再简单回顾一下:
集中式系统用一句话概括就是:一个主机带多个终端。终端没有数据处理能力,仅负责数据的录入和输出。而运算、存储等全部在主机上进行。
集中式系统的最大的特点就是部署结构非常简单,底层一般采用从IBM、HP等厂商购买到的昂贵的大型主机。因此无需考虑如何对服务进行多节点的部署,也就不用考虑各节点之间的分布式协作问题。但是,由于采用单机部署。很可能带来系统大而复杂、难于维护、发生单点故障(单个点发生故障的时候会波及到整个系统或者网络,从而导致整个系统或者网络的瘫痪)、扩展性差等问题。
分布式就是一群独立计算机集合共同对外提供服务,但是对于系统的用户来说,就像是一台计算机在提供服务一样。分布式意味着可以采用更多的普通计算机(相对于昂贵的大型机)组成分布式集群对外提供服务。计算机越多,CPU、内存、存储资源等也就越多,能够处理的并发访问量也就越大。
拿电商网站来说,我们一般把一个电商网站横向拆分成商品模块、订单模块、购物车模块、消息模块、支付模块等。然后我们把不同的模块部署到不同的机器上,各个模块之间通过 远程服务调用 ( RPC
)等方式进行通信。以一个分布式的系统对外提供服务。
提到分布式,一个不得不提的词就是服务化,服务化架构使搭建分布式系统成为了可能。
传统的软件开发面临着很多的问题,比如: 代码重复率高、代码庞大难以维护、无法快速迭代、测试成本高、可伸缩性差、可靠性差、模块间高度依赖。为了解决上面这些问题,我们一般采用拆分、解耦、分层、独立等方式来解决。有了服务化架构,我们就可以在很大程度上解决这些问题。
服务化是一种粗粒度、松耦合的以服务为中心的架构,服务之间通过定义明确的协议和接口进行通信。
这里说到的“服务”,本质上来说,就是指“RPC”。单纯的RPC功能实现,其实很简单,无非就是client发起调用,中间某个组件(甚至就是client本身)拦截调用信息,序列化后将信息传输到server端,server端收到调用请求后反序列化,根据请求详细发起实际调用后返回响应传输回给client端。这样的RPC很常见,比如常见的存储过程调用就是一例。但是在一个复杂的业务环境,如何管理和协同这些大量的RPC才是最麻烦的事情。所以,一般提到的“服务化”更多指的是对RPC的管理。服务化一般关注服务注册,服务协调,服务可用性,服务通讯协议和内容交换等。
面向服务架构(Service-Oriented Architecture, SOA
)又称“面向服务的体系结构”,是Gartner于2O世纪9O年代中期提出的面向服务架构的概念。
面向服务架构,从语义上说,它与面向过程、面向对象、面向组件一样,是一种软件组建及开发的方式。与以往的软件开发、架构模式一样,SOA只是一种体系、一种思想,而不是某种具体的软件产品。
这里,我们通过一个例子来解释一下到底什么是SOA?如何做到SOA?
SOA也可以说是一种是设计原则(模式),那么它包含哪些内容呢?事实上,这方面并没有最标准的答案,多数是遵从著名SOA专家Thomas Erl的归纳:
标准化的服务契约 Standardized service contract
服务的松耦合 Service loose coupling
服务的抽象 Service abstraction
服务的可重用性 Service reusability
服务的自治性 Service autonomy
服务的无状态性 Service statelessness
服务的可发现性 Service discoverability
服务的可组合性 Service composability
这些原则总的来说要达到的目的是:提高软件的重用性,减少开发和维护的成本,最终增加一个公司业务的敏捷度。
既然是面向服务的架构,那么我们就先来定义一个服务,
public interface Echo { String echo(String text); } public class EchoImpl implements Echo { public String echo(String text) { return text; } }
上面这段代码相信有过JavaWeb开发经验的人都不会陌生。就是定义了一个服务的接口和实现。
那么,定义了服务,我们就做到了SOA了么?
我们用Thomas Erl定义的原则来对比一下,用松耦合和可重用这几个原则来尝试分析一下上面Echo示例:
Echo的服务契约是用Java接口定义,而不是一种与平台和语言无关的标准化协议,如 WSDL
, CORBA IDL
。当然可以抬杠,Java也是行业标准,甚至全国牙防组一致认定的东西也是行业标准。
Java接口大大加重了与Service客户端的耦合度,即要求客户端必须也是Java,或者JVM上的动态语言(如 Groovy
、 Jython
)等等……
同时,Echo是一个Java的本地接口,就要求调用者最好在同一个JVM进程之内……
Echo的业务逻辑虽然简单独立,但以上技术方面的局限就导致它无法以后在其他场合被轻易重用,比如分布式环境,异构平台等等 ESB
是SCA思想实现的基础设施。 ESB
主要作用是集中注册发布服务,为服务与传输协议之间解耦。并不是所有的 SOA
架构都需要 ESB
, ESB
是 SCA
特有的。当然任何符合ESB特征的解决方式都可以称之为 ESB
,也不仅仅是 SCA
内部的。
因此,我们可以认为Echo并不太符合 SOA
的基本设计原则。
修改一下上面的Echo,添加Java EE的 @WebServices
注解
@WebServices public class EchoImpl implements Echo { public String echo(String text) { return text; } }
现在将Echo发布为Java WebServices,并由底层框架自动生成WSDL来作为标准化的服务契约,这样就能与远程的各种语言和平台互操作了,较好的解决了上面提到的松耦合和可重用的问题。按照一般的理解,Echo似乎就成为比较理想的SOA service了。
使用 WebServices
只是一种相对简单的方案,SOA的最常见的解决方案是 SCA
,其次还有 JBI
, BPEL
等。 ESB
是SCA思想实现的基础设施。 ESB
主要作用是集中注册发布服务,为服务与传输协议之间解耦。关于SCA和ESB并不是本文的重点,感兴趣的朋友可以从网络上获取更多资料。(可以从上图中看到ESB在整个SOA架构中所扮演的角色)
面向对象( OO
)和 面向服务 ( SO
)在基础理念上有大量共通之处,比如都尽可能追求抽象、封装和低耦合。
但SO相对于OO,又有非常不同的典型应用场景,比如:
多数OO接口(interface)都只被有限的人使用(比如团队和部门内),而SO接口(或者叫契约)一般来说都不应该对使用者的范围作出太多的限定和假设(可以是不同部门,不同企业,不同国家)。还记得贝佐斯原则吗?“团队必须做好规划与设计,以便未来把接口开放给全世界的程序员,没有任何例外”。
多数OO接口都只在进程内被访问,而SO接口通常都是被远程调用。
简单讲,就是SO接口使用范围比一般OO接口可能广泛得多。我们用网站打个比方:一个大型网站的web界面就是它整个系统入口点和边界,可能要面对全世界的访问者(所以经常会做国际化之类的工作),而系统内部传统的OO接口和程序则被隐藏在web界面之后,只被内部较小范围使用。而理想的SO接口和web界面一样,也是变成系统入口和边界,可能要对全世界开发者开放,因此SO在设计开发之中与OO相比其实会有很多不同。( 微观SOA:服务设计原则及其实践方式(上篇) )
微服务架构( MicroService
)是一种服务化架构风格,通过将功能分散到各个离散的服务中以实现对解决方案的解耦。微服务架构强调的第一个重点就是业务系统需要彻底的组件化和服务化(这也是我们为什么要先介绍组件化和服务化的原因)。微服务的诞生并非偶然。它是互联网高速发展,敏捷、精益、持续交付方法论的深入人心,虚拟化技术与DevOps文化的快速发展以及传统单块架构无法适应快速变化等多重因素的推动下所诞生的产物。
微服务的流行,Martin功不可没,先看看他是如何定义微服务的:
The microservice architectural style 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.
总结起来大概以下四点:
Martin自己也说了,每个人对微服务都可以有自己的理解,不过大概的标准还是有一些的。
看了SOA和微服务,很多人会认为这不就是一回事儿么。其实SOA和微服务就是差不多的。
如果一句话来谈SOA和微服务的区别,即微服务不再强调传统SOA架构里面比较重的ESB企业服务总线。微服务把所有的“思考”逻辑包括路由、消息解析等放在服务内部,去掉一个大一统的ESB,服务间轻通信,是比SOA更彻底的拆分。( 微服务(Microservice)那点事 )
关于微服务这里只是做一个简单的介绍,要想真正的了解微服务还有很多路要走,比如 康威定律 (我后面会专门写一篇文章介绍康威定律)、 服务间通信 、 服务的注册与发现 、 服务治理 与 服务编排 等。。。
本文主要介绍了 组件化 、 模块化 、 集中式 、 分布式 、 服务化 、 面向服务的架构 、 微服务架构 等概念。但是,正所谓实践出真知。还是要在日常工作中实际运用才能真正的掌握。
(全文完)