10

微服务基本概念和核心组件(200709)

 4 years ago
source link: http://blog.sina.com.cn/s/blog_493a84550102z8n8.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

我们先看下当前互联网上对微服务的主流定义。

微服务 可以在“自己的程序”中运行,并通过“轻量级设备与HTTP型API进行沟通 ”。关键在于该服务可以在自己的程序中运行。通过这一点我们就可以将服务公开与微服务架构(在现有系统中分布一个API)区分开来。在服务公开中,许多服务都可以被内部独立进程所限制。如果其中任何一个服务需要增加某种功能,那么就必须缩小进程范围。在微服务架构中,只需要在特定的某种服务中增加所需功能,而不影响整体进程。

微服务不需要像普通服务那样成为一种独立的功能或者独立的资源。定义中称,微服务是需要与业务能力相匹配,这种说法完全正确。不幸的是,仍然意味着,如果能力模型粒度的设计是错误的,那么,我们就必须付出很多代价。

看完上面的图后,估计还是很难真正抓住微服务的关键点。在我很早就谈到过,在理解和认识一个概念的时候,你一定要用和你已有的知识概念做对比,进行差异分析,你就很容易抓住要点在哪里。

而要了解微服务一样,你了解了和传统单体应用的差别,基本微服务核心就了解了。简单来说微服务本身就是将传统的单体应用大拆小,然后通过一种轻量高效的标准接口进行协同的架构模式。

从一个例子来讲起

为了更好的解释微服务,包括后面对微服务很多关键组件的解释,我们需要准备一个业务系统功能常见来进行举例说明,具体的背景如下。当前我们准备构建一个SRM供应商关系管理业务系统,这个系统经过前期业务和需求分析,包括了供应商管理,物料管理,招投标,供应商绩效评估四个功能模块。当然在构建整个系统的时候还有类似底层的系统管理,流程引擎等技术模块组件。

我们要构建的SRM系统就是典型的单体应用,那么我们来看这个单体应用构建模式转变到微服务构建模式后究竟带来了哪些变化。如下图,我们从开发态和运行态去分析。

feUFBj3.jpg!web

从这个图我们基本就把微服务核心的关键点看清楚了。即:

一个单体变多个微服务模块,而且从数据库到逻辑层到前端完全独立

微服务模块间通过Http Rest接口高效集成协同

各个微服务完全独立部署,扩展的时候数据库,集群都单独扩展

以上实际上就是我们经常谈到的微服务区别于单体架构最关键的几个点。在掌握了这个核心概念后你才清楚哪些不是微服务基本特征。比如微服务必须容器化部署,没有这个说法,微服务也可以传统方式部署。还有就是微服务开发必须前后端分离,实际上也没有这个说法,前后端不分离只要微服务间完全纵向解耦就是微服务架构。

基于SOA和中台思想对上面拆分进行重构

如果按照上面的模块拆分进行独立的设计,开发和部署,完全是符合微服务架构的思想的。但是是否符合SOA和中台能力共享思想呢?

我再强调下SOA和中台里面的一个关键思想,即:你要去找到你的核心业务能力提供,而不是马上去关心你的能力或最终数据是如何形成的。能力最终提供属于中台能力,能力如何形成的可以属于前台应用能力。

比如上面谈到的供应商,物料两个微服务,我们发现核心就是提供可共享的供应商和物料数据能力。但是这两个数据如何形成的? 一方面是可以直接在后台录入,一个方面还是可以是供应商自己进行供应商认证申请,我们审核通过后进入到供应商库。

那么供应商数据本身属于中台能力,供应商信息的申请流程可属于前台应用功能。

是否严格的逻辑层和数据库1对1对应?

这个是我今天想拿出来讨论的第二个问题,即很多人在进行微服务架构设计的时候往往走两个极端。或者是数据库不拆分就一个大库,或者就是数据库完全按微服务1对1拆分。那么我们上层规划的20个微服务,是否就一定有20个对应的数据库实例ID?

在数据库拆分细一定带来我们在设计实现时候两个问题

其一是我们常说的分布式事务处理问题,有用库拆分无法再用数据库层事务

其二是原来一个关联sql搞定的事情,全部变成了逻辑层多次服务调用后进行服务组装

以上两个问题不仅仅是带来的开发工作量,而且更重要的是影响到数据一致性。正是由于这个原因,我们提出一个微服务集的概念。微服务集的意思可以理解为逻辑层仍然按照标准的微服务要求去构建,每个逻辑层都可以编译可独立部署的Jar包。但是对应微服务集里面的多个微服务可共用一个数据库。

而基于上面场景,供应商和物料本身关联业务场景相当多,放在一个数据库显然是更加适合。经过重新思考后,我们整体的逻辑架构变化为:

R7RVvqj.jpg!web

基于实际业务场景驱动,对微服务初步设计重构后体现为两点

其一是供应商和物料合并为一个数据库而不进行拆分

其二是逻辑层的微服务基于复用分层思路拆分为三个微服务模块

拆分后的三个微服务如何交互?

在完成基本的拆分后,我们来看拆分完成后的三个微服务模块如何交互。

如果我们仍然把SRM看成一个大的应用,并且SRM系统的能力接口不需要对外暴露,不需要互联网APP应用协同的时候。在这种情况下,走微服务架构体系里面的服务注册中心来完成接口交互。简单来说就是微服务间的接口消费调用是一种去中心化的架构模式。

我们以供应商申请微服务,需要在申请审核通过后,调用供应商管理提供的信息导入API接口将数据导入到供应商管理模块中来举例说明。

mMj6NvR.jpg!web

从图里面可以看到整个过程简单的三个关键步骤。

第一,供应商管理将实现的API接口注册到注册中心

第二,申请模块从注册中心获取接口的地址信息

第三,根据拿到的地址信息直接发起对接口的点对点调用

为何叫去中心化?

从上图整个过程可以看到,整个服务调用只有获取地址会和数据中心发生关系,实际获取到地址后即是接口的点对点调用,这个时候接口的数据流完全不经过注册中心。

那么获取地址的时候注册中心宕机了怎么办?

所以可以看到一般来说,获取的地址信息都会在本地微服务模块缓存,后续在调用的时候如果注册中心有故障,那么就访问本地缓存的地址信息。对于这点本身又需要稍微展开下分两个实现方式来进一步解释下。

其一,负载均衡的能力在注册中心

在这种情况下,我们每次消费接口,都必须调用注册中心服务来获取最终轮询出来的目标地址信息。只有在注册中心不可用情况下,我们才访问本地缓存。

其二,负载均衡的能力在本地微服务

在这种情况下,只需要获取注册中心的地址信息清单,同时在地址状态变更的时候被动获取注册中心的变更消息推送。那么后续所有接口访问都和注册中心无关。

微服务间交互是否一定是Http Rest接口?

多个微服务如果不对外提供能力,仅仅是内部接口交互,那么Http Rest接口并不是必须的。比如我们常说的Dubbo框架,可以采用更加高效的RPC接口进行交互,而且底层还可以走TCP协议。但是一涉及到对外能力提供,涉及到主动网络防火墙问题时,一般只能走Http接口交互。

当然你可以理解为,同样一个接口实现,我们可以在内部交互的时候走高效的RPC接口模式,而仅仅需要对外暴露服务能力的时候将其发布为Http Rest接口。

从服务注册中心到API网关

对于一个应用里面的多个微服务需要统一对外暴露接口能力的时候,这个时候就涉及到OpenAPI能力开放平台或API网关,那么首先来解释下API网关。

uMnEFbr.jpg!web

如何给API网关一个定义?

简单来说API网关就是将所有的微服务提供的API接口服务能力全部汇聚进来,统一接入进行管理,也正是通过统一拦截,就可以通过网关实现对API接口的安全,日志,限流熔断等共性需求。如果再简单说下,通过网关实现了几个关键能力。

内部的微服务对外部访问来说位置透明,外部应用只需和网关交互

统一拦截接口服务,实现安全,日志,限流熔断等需求

从这里,我们就可以看到API网关和传统架构里面的ESB总线是类似的,这些关键能力本身也是ESB服务总线的能力,但是ESB服务总线由于要考虑遗留系统的接入,因此增加了类似遗留系统适配,协议转换,复杂数据映射等能力。

微服务架构不再需要ESB,并且一定是去中心化的?

这是必须要搞清楚的一个问题。首先看下微服务架构里面确实不需要传统ESB,但是需要一个ESB的轻量实现,即我们说的API网关。因为微服务架构里面都是标准的Http Rest接口,不再存在复杂的遗留接口适配,复杂协议转换等问题。但是我们常说的接口服务代理,统一的安全,日志,流控功能仍然需要。

同时微服务架构内部各个微服务模块间本身是去中心化的,但是当微服务架构里面各个微服务需要对外提供接口服务能力给外部应用使用时候,外部应用和微服务间由于增加了API网关又变成了一个中心化的架构。所以不要一提到微服务就去中心化,这个理解本身也是不对的。

对于API网关来说,核心就是实现两类能力,一个是对API全生命周期管理能力,包括了API接口的注册,接入,发布,测试,变更和版本管理,下线等。另外一个关键能力就是我们常说的安全,日志,流控方面的能力。

而这些能力最常见的实现方式就是通过插件进行拦截处理,如下:

ERzQZ3u.jpg!web

如上图,API网关里面的关键对象注意包括了接入系统(微服务),消费系统,注册接入的API接口,发布的Proxy API接口,在代理和原始服务间有一个路由对象。只要有这些最基本的对象就可以实现最简单场景下的服务接入。

而其它所有的扩展可以看到都应该基于插件式方式的扩展,这些插件包括了安全认证类插件,流量控制类插件,日志监控类插件,转换类插件。

任何一个API接口和插件之间是一种多对多的关系。即一个API接口可以被作用多个插件,同时一个插件本身又可以应用在多个API接口上。插件本身就类似于AOP横切,对服务请求消息的输入和输出进行拦截,在拦截到信息后进行相关的安全或其他管控处理。

当然插件本身一定会损耗性能,在实现的时候需要考虑对服务运行数据,运行统计数据的缓存,特别是对于流控的实时计算过程。

业务场景需求引入网关

还是基于上面的案例,供应商申请流程我们希望开发一个APP应用给用户自己申请。这个APP供应商在公网就可以正常访问和登录使用。

前面谈到,API网关使用重要场景就是需要对外提供服务能力。这个对外可能是和外部其它系统集成,也可以是我们的应用本身会开发外部互联网使用的APP。

在这个时候API网关引入就变成了必须。

RVbAFvQ.jpg!web

API网关本身也实现了外部应用和我们内部微服务间的安全隔离,比如我们把API网关还可以部署到整个基础设施架构的DMZ区等。

是否可以不用API网关?

当然,你也可以不用类似Kong等API网关产品,那么这个时候我们常说的一些共性的安全,日志,限流熔断能力无法实现。但是最基本的代理路由转发能力是必须的,因此你在前期可以使用类似Ngnix来实现请求转发并替代API网关的使用。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK