当前位置: 首页 > 科技观察

实现微服务架构的关键技术

时间:2023-03-16 19:49:23 科技观察

大家都在说微服务架构。微服务架构到底是什么?它的特点和设计模式是什么?我们在构建微服务架构的过程中,如何将这些设计模式应用到实战中呢?如何保证数据的一致性?今天就以上问题分享一下我的看法。微服务架构特点什么是微服务架构?看下图英文部分,是MartinFowler在2014年提出的,微服务架构是一种架构模型。既然是建筑模型,就一定要满足一些特点。他提到微服务架构是一系列小微服务的组合。那么,什么是“小微服务”呢?可能每个人的理解都不一样。每个人都应该知道SOA架构。SOA架构的粒度比较粗。我们应该以什么粒度拆分微服务?在我看来,微服务架构本质上是一种业务架构,所以你对业务理解得越深,你的微服务拆分就会越合理。比如我们做一个二手交易平台(转转),包括用户系统、产品系统、交易系统和搜索推荐系统。因为各个系统相对独立,我们可以按照各个业务模块来拆分微服务。当然这还不够,因为你的产品有很多功能,但是大意是要根据具体产品的内部逻辑进一步拆分。其次,围绕特定业务建模。脱离业务场景谈微服务架构是耍流氓。有两种方法:一是把某个领域的模型看成一个独立的业务单元:比如二手交易中的商品、订单、用户等;其次,将业务行为视为一个独立的业务单元:比如发送邮件、单点登录验证、推送Serve。第三,整个微服务可以独立部署,因为每个维度的服务进程都是独立的,所以很容易理解每??个模块的独立部署。四是分散管理。创建去中心化管理意味着微服务的各个模块与开发语言和运行平台无关。开发语言可以是C++,也可以是go,也可以是世界上最著名的语言。运行平台Linux、Unix、Windows等都可以。最后一点是轻量级通信,简单易懂。通信与模块语言和平台无关。尽量选择轻量级的通信来做这件事,这样很容易实现跨平台、跨语言。说完这些特点,我们可以看看一个标准的DEMO级微服务架构由哪些元素组成?如下图所示,主要包括网关、微服务、数据存储、注册中心、配置中心。既然是DEMO级别的,肯定和实际情况不一样。那么,在实际的情况下,我们应该怎么做呢?这个例子也是我最近在做的二手交易平台——转转。这个和DEMO有一些区别。前面***层还是网关,下面是微服务的聚合层,用来处理各种业务逻辑;聚合层下面是我们的数据原子层,主要作为数据访问代理,但是根据不同的业务垂直分离。可以看到有网关、数据层、注册中心、配置中心,但是在业务处理部分分为两层:一层是原子层,是整个数据访问的代理层,提供用户界面;另一个是原子层。Layer是上层的业务聚合层。架构设计模式和实际案例上面我大致讲了微服务的一些特点,DEMO级别的微服务包括哪些部分,以及我们在实际案例中的架构设计模式。那么,我们为什么要用这个模型来做呢?除了这种架构模式,还有哪些架构模式呢?这里,模式还是很多的,我重点说一下这几点:链式设计模式、聚合器设计模式和异步共享模式。首先说一下下行设计模式。这种模式下,APP前端请求先经过网关层,然后连续调用两个微服务。调整完微服务1,还要调整微服务2。为什么叫链条?因为调用先来到微服务1后,再同步调用微服务2,微服务2会做一些处理,微服务2处理完后反馈给微服务1,微服务1再反馈给Gateway,****反馈到应用程序。在实际业务场景中,这种模式用于涉及交易和订单的业务场景。接下来是聚合器设计模式。来自APP前端的调用请求通过Gateway到达汇聚层。它需要调用三个微服务。聚合层对三个微服务的返回结果进行一些聚合处理,比如排序或者去重,然后聚合后反馈给网关和APP前端。这是一个典型的聚合器设计模式。第三种模式是数据共享模式。这种模式比较简单。比如APP通过微服务网关,然后调用微服务1和微服务2。理想情况下,微服务1和微服务2有自己独立的DB,但在某些情况下,由于微服务1和微服务2的请求量和存储量都较小,从资源利用的角度来看,这两个微服务的DB是共享的,所以这就是数据共享模式。最后一个是异步消息设计模式,无论是链式设计、聚合器模式还是共享数据模式,架构模式都是同步模式。也就是说,我发出一个请求,要等到每个链接都处理完了,才发给客户端。如果请求不需要关注处理结果,此时可以异步执行。APP更新请求通过微服务网关,持久化到MQ,写入MQ成功后立即响应APP客户端。之后,微服务从MQ订阅更新消息,进行异步处理。我们还将使用这种方法来提高吞吐量。模型。从百度到转转,这几年经历了很多业务场景。我用的无非是聚合器的数据模式,异步和数据共享。尤其是前两个用得很多。让我们看下面的一些例子。接下来,让我们看一个例子。这是我们2015年打造的一个二手交易平台(转转)。这个二手交易平台包括商品、分类搜索、关键词搜索、商品推荐等功能。来自用户的请求首先通过网关。网关下面是我们的汇聚层。然后聚合层调用产品、交易、推荐和搜索相关信息。最后,聚合层聚合微服务原子层的结果,并将响应发送给客户。结尾。具体如下图所示:异步消息方式的案例比较早。当时我们做了一个feed流,类似于现在的微信朋友圈。这是我在百度上做的。当时我们采用的架构模式是异步架构模式。前面是我们的APP,经过网关,到达异步提交层,可以看成是具有持久化功能的MQ。用户请求通过网关后返回到消息异步提交层,业务处理部分从MQ中读取数据并进行异步处理。这时候吞吐量会增加,但是会带来一些混乱。比如我这时候发一个feed,用户直接去数据库里查。异步提交消息队列可能会有延迟。如果找不到提要,用户会感到困惑。如何解决这个问题呢?我们想能不能在前端为我们做点什么?比如提交MQ,返回Response200后,配合前面的section插入这个feed。当用户再次刷新时,我相信会在几秒钟后。即使有延迟,此消息也已由您的企业处理。当然,我们这里有具体的场景,社区有时候可以做,但是涉及到金融相关的场景肯定不行。数据一致性实践微服务模块比较分散,数据也比较分散。整个系统的复杂度非常高。如何进行数据一致性实践?LocalTransaction可以在单个模块中完成,但在微服务系统中就不行了。虽然很难解决,但必须解决。如果不解决,微服务架构将难以落地。我们知道在微服务中实现强一致性是非常困难的。今天分享的更多的是解决最终一致性问题。因为是基于微服务下的不同数据库,LocalTransaction是不可用的。你一定听说过分布式事务中的两阶段提交和三阶段提交。其实这种场景在微服务架构下是行不通的,因为它本质上是同步模式,在同步模式下处理数据。一致性吞吐量下降很多。我们的业务场景无非两种:第一种是异步调用,也就是有请求进来就直接写入消息队列,这种模式比较简单。今天我们主要讲讲在同步调用的场景下,如何打造数据的最终一致性。既然是同步调用场景,业务系统的吞吐量不能降低,怎么办?建立异步分布式事务,业务调用失败后以异步的方式对业务进行补偿。我们的想法是能否在整个业务逻辑层实现分布式事务语义策略?有两种方法可以实现它。一是在正常请求调整时记录业务调用链(正常接口调用的完整参数),二是异常时沿调用链逆向补偿。基于这个思路,我们的架构设计有三个重点,第一是基于补偿机制,第二是记录调用链,第三是提供幂等的补偿接口。在架构层面,见下图,右边是聚合器架构设计模式,左边是异步补偿服务。首先需要在汇聚层引入Proxy。首先在方法的基础上,在方法名上添加注解,标记补偿方法的名称,例如:-@Compensable(cancelMethod="cancelRecord")另外,聚合层通过代理记录当前调用请求参数在调用原子层之前。如果业务正常,调用结束后,会归档或删除当前方法的调用记录。如果业务异常,则回滚查询调用链。我们在原子层面做了什么?主要有两个方面,第一是提供普通的原子接口,第二是提供补偿幂等接口。分布式事务的关键是两张表(如上图),***是事务组表,假设A->B->C的三个请求是一个事务,先为ABC生成一个事务ID写入在这张表中,会记录这笔交易的状态,默认是正常的,执行失败后我们将状态从1(正常)变为2(异常);第二张表是事务调用组表,主要记录事务组中事务的每次调用和相关参数,所以调用原子层前需要记录请求参数。如果失败了,我们需要把这个交易的状态从1变成2;第三,一旦状态从1变为2,就执行补偿服务。这就是我们的补偿逻辑,就是不断地扫描事务所在的表,比如每秒扫描一次事务组表,看有没有表中状态为2的服务需要补偿。这个想法对业务的侵入相对较小。让我们来看看我们的实际例子。比如二手交易平台创建订单交易群的正常流程,从锁定库存到减红包再到创建订单。创建事务组后,调用业务。首先,Proxy记录锁库存调用的参数。然后开始调用锁库存服务,成功之后再开始减红包和创建订单的流程,全部成功直接返回。我们再来看看异常过程。前几步是一样的,只是在红包服务转移时,Proxy创建红包失败,会抛出异常,业务正常返回。聚合层Proxy需要将事务组的状态从1改为2,此时左边的补偿服务异步补偿调用。作者简介:孙轩,58集团技术委员会主席,本文来自作者在CCTC2017的演讲。