谈谈你对微服务的理解

微服务的定义:微服务是一种分布式系统解决方案,推动细粒度服务的使用,每个服务都可以独立运行且这些服务可以协同工作。

微服务定义中的任何一个系统都应该可以独立部署、独立运行,并能独立完成一个业务的闭环。

微服务是去中心化的,他认为任何单独的服务都可以独立自治,不受其他系统的制约和调配。

服务要保持独立自治性,就应该完全使用自己的数据库,而不是和别的系统共用。

微服务架构的核心目标是把复杂问题简单化,通过服务划分,把一个完整的系统拆分成多个高内聚、低耦合的小的子系统。使每个子系统可以独立的运行、升级和测试。然后再通过一些集成手段将这些子系统组合在一起,对外提供完整功能的过程。所以我们对微服务设计的过程就是对系统如何做拆分和集成的过程。

微服拆分带来的问题

微服务给我们带来的好处显而易见,我们通过一定的设计原则也一定能够设计出最适合自己业务的服务来,但是这样做会给我们系统的运行、监控、测试、部署带来什么副作用吗? 答案是肯定的,由于微服务天生是基于分布式系统架构的,所以分布式系统固有的问题它都有,比如数据的一致性、服务的可用性等。另外,由于微服务对系统划分的粒度非常细,本来很多单体的系统被部署到了多个进程中,这给测试、部署、监控等环节所带来的复杂性也是超乎想象的。那因此我们就放弃微服务了吗?当然不会,任何系统架构的设计过程,其实都是在解决系统复杂度的过程。微服务架构的复杂度虽然大,但是并不是不能解决的,下面针对几个常见的问题来分析一下在微服务架构中应该如何应对。

数据的一致性 我们在一个只拥有一个数据库的系统中处理事务是很简单的事情,很多关系型数据对ACID的实现都是非常严格的,但是到了微服务架构的环境中,保持事务的完整性似乎变的不可能,由于网络传输的不可靠性(虽然这种情况出现的概率很小),被分散在多个进程中的系统在共同完成一个写操作时就会可能出现维护自己的数据状态时不能保持一致性的问题,比如不能够同时提交本地事务,或者不能够同时回滚。对于这个问题.我们应该怎么做呢? 首先要有重试机制,及当对一个子服务的写操作请求失败后,可以重试几次,直到系统的响应成功为止,这就要求每个有写操作的子服务需要支持幂等,因为有可能上一次已经写成功了,只是由于网络问题,没有正常返回结果。 由于许多时候网络问题不是瞬间的,可能会持续一段时间,那么我们就一直重试下去吗?肯定也不会,我们会采用补偿机制来修复事务的一致性,比如库存系统在扣减成功后,需要在订单系统上修改客户订单状态,但是尝试多次后,订单系统一直响应失败,那怎么办呢,可以给库存系统发一个增加库存的请求,算是补偿。这样整个系统在一定时间段内还是保证了数据是一致的状态。 最后可以使用柔性事务(TCC),柔性事务这个词最早是由支付宝的团队提出的,它的核心思想是要求在涉及写操作的业务中支持一个软状态,怎么理解这个“软状态”呢,就是不是一个确定的状态,比如正在处理中的订单。举个例子,系统在从A状态到达B状态时必须要先经过C(软状态),而C不是一个实际的业务状态,这样做不但可以起到资源检查并预占的作用,同时还可以做为回退到A还是前进到B的中间状态节点。

服务的容错性 在微服务架构中,肯定会有一个系统依赖其它系统来完成一次操作的情况,那么当依赖的下游系统宕机或者由于网络问题导致服务长时间不能响应的时候怎么办,上游系统不可能一直重试吧。这时我们需要采用熔断保护措施才能保证上游系统不被下游系统拖死.具体我们应该怎么做呢? 超时,首先我们对任何服务的调用都应该有超时机制,当长时间没有应答时就要认为调用失败并终止等待了。 隔离,即便有超时机制,系统也可能会因为超时时间过长,而处于“漫长”的等待中,更可怕的是当某个下游服务的整个集群全挂了的时候,上游服务不应该被这一个服务拖死。我们应该对资源进行合理分配,把调用下游接口的资源进行隔离,其实有很多时候只是一个不影响主业务流程的下游服务挂了,这不应该成为我们整个服务不能访问的原因,我们可以采用为每个对下游资源的调用分配最大个数的线程池或者连接池来解决这个问题。 断路保护,在互联网的场景中,高并发、高吞吐的请求是非常普遍的要求,这种情况下,即便我们做了超时机制和资源隔离,也会由于大量的请求使我们的系统处于不必要的繁忙状态,我们应该对那些一直出错误的响应进行处理,把已经尝试过多次的失败请求进行累计,当达到一定值的时候,忽略对它的调用。我们之后定时去监控,看看它恢复了没有就可以了。 服务降级,当系统出现断路的时候除了不再访问下游资源,还需要做些什么呢?总不能给用户返回一个下游服务有异常的错误,通常情况下我们会通过缓存或者静态资源来给用户返回一些非实时的数据,让用户无感知,这就是服务降级。 当然系统的容错处理方式远不止这些,很多时候是根据实际的业务场景来处理的,只要我们一直不要忘记网络是不可靠的这个事实,对一切可能出现的异常情况进行捕获和规避,就能做到系统稳定可靠的运行

系统的性能 在微服务环境中,当用户对系统发起一个请求后,最上游的服务要经过多次网络传输、多次请求╱应答数据解析才能完成一个整体的请求交互,所以必将带来更多的资源开销和更大的访问延时,我们应该如何应对呢? 首先,可以考虑使用RPC进行远程通讯,虽然目前基于restful的http请求很热,它所带来的简单性和规范性是一般RPC框架不具备的,但是不得不承认,基于二进制传输协议的RPC通讯框架在性能上的优势是http协议很难达到的。所以在一些对性能要求比较苛刻的系统中,优先考虑RPC。 其次,增加缓存使用,缓存虽然不是分布式系统架构中的银弹,但是它无处不在,它的好处在这里我们就不深入讨论了。微服务系统性能瓶颈归根到底还是多次网络请求,解决它最好的办法就是减少调用,我们尽量把每次对下游系统的请求进行缓存。虽然有时这确实是一厢情愿,但在设计微服务系统时,请你首先考虑使用它。 最后,我们说说扩展,前面聊了几点其实也只是尽量在缩小和单体系统之间的差距而已,并没有从根本上解决性能瓶颈。而对于系统扩展性,是微服务系统与生俱来就有的,通过扩展我们可以减少单个服务的复杂性,使某个服务的请求所要处理的业务逻辑简单很多,最常见的情况是数据库的结构简单了,之前需要各种关联的查询没有了,因为我们每个服务只负责自己的那几张表。这有什么好处呢,首先是垂直扩展简单了,系统的关联性减弱后,我们可以很容易的对系统进行拆分,使之前许多复杂的多表查询变成了简单的单表查询,从而使sql优化这些让我们经常头疼的东西减少了,更重要的是单表查询为我们带来的一个更大的好处就是使数据库的水平扩展也变得十分容易。所以在微服务架构的环境中,我们要始终考虑如何用多个简单的业务逻辑来代替一个复杂的业务逻辑,因为这样更容易实现数据库在水平和垂直方向上的扩展。

实施复杂 当系统被拆分成多个单独的服务时,无论在部署、测试还是监控环节,都会产生大大超出单个系统的工作量,这在做集成测试的时候会尤为突出。小而多的应用服务必然需要更多的部署节点,应对这样的问题,需要我们必须接受自动化文化,自动化部署和自动化测试方案必须要在微服务实施开始前就规划好。关于自动化部署和测试的方案有很多,而且大多数都已经很成熟。

1、什么是微服务? 微服务是分布式架构的一种,分布式架构其实就是要把服务做一个拆分,而springcloud只是解决了拆分过程中的服务治理问题。

在单体架构中,我们把所有的服务都写在一起,随着业务的复杂代码的耦合度就会越来越高,不便于将来的升级维护。

所以往往需要拆分这些服务,微服务在拆分的时候,会根据业务功能模块把一个单体的应用拆分成许多个独立的项目,每个项目完成一部分的业务功能,然后独立开发和部署。这些独立的项目就成为一个微服务。进而构成一个服务集群。

举例: 一个商城系统就得提供相当多的服务, 比如订单服务,用户功能,商品服务,支付服务等等,这些模块如果使用单体架构来实现,那么耦合度会相当高,开发难度也会很大。如果使用微服务开发,把每一个服务都当成一个单体应用来开发,那么订单服务,用户服务,商品服务,支付服务等模块,每一个就成为一个微服务。

由这些微服务构成整个的商城系统。这样明显是更加合理的。每个服务也可以根据业务的需要去进行集群部署。一方面降低了服务的耦合,一方面有利于服务的维护升级。

2、微服务的相关技术栈: 2.1 注册中心: 一个业务往往就需要多个服务来共同完成,比如一个请求发送过来,先是调用了服务a,然后服务a调用服务b,服务b调用服务c;

然而,当业务越来越复杂的时候,这些服务之间的调用关系就错综复杂,所以这个时候需要一个注册中心,用来记录每一个服务的ip,端口,以及它能完成的功能,然后这些服务之间要互相调用的时候,不用去记录服务的ip,只要到注册中心找就可以了。

2.2 配置中心: 每个服务都有自己的配置文件,而一个上线的项目可能会有成百上千的服务,这些配置文件,我们不可能一个一个去修改,这个时候需要一个配置中心,它主要用来统一管理整个服务集群成千上百的配置,我们要变更某些配置,只要找到配置中心就可以了,它就会去找到对应的配置,实现配置的热更新。

2.3 网关: 所有的请求进来,并不能直接就去访问对应的服务,而是要通过一个网关服务,由它来路由到对应的服务。

2.4 分布式缓存: 数据库层,由于数据库即使是集群部署,也很难抗住高并发,往往还需要一个缓存集群,把数据库的数据搬到内存中以提高访问效率。请求先查询缓存,缓存未命中的时候再去查询数据库。

2.5 分布式搜索: 对于一些复杂的数据的搜索、统计、分析,我们还需要使用搜索集群。

2.6 消息队列: 在分布式架构中,还需要消息队列,因为一个业务往往会调用多个服务,但我们不能等到所有的服务都执行完成再返回响应数据,因为这样操作就类似串行执行,响应速度有所下降。这个时候可以使用消息队列,让服务发送消息通知其他服务去执行指定的任务,而自己则可以结束运行,提高响应速度。

2.7 分布式日志服务: 分布式日志服务:主要用来统计成百上千的服务的运行日志,方便系统出问题时的定位。

2.8 系统监控链路追踪: 系统监控链路追踪:可以实时监控整个服务集群的所有节点的运行状态。 3、单体架构和微服务的区别: 3.1 单体架构: 将业务的所有功能集中在一个项目中开发,打成一个包部署。

架构简单,部署成本低,但是代 码的耦合度搞,所有的模块都耦合在一起。

3.2 分布式架构: 根据业务功能对系统进行拆分,每个业务模块都作为独立的项目来开发,成为一个服务。

降低服务之间的耦合度,有利于服务升级拓展;

4、微服务的特征: 4.1 单一职责: 微服务拆分粒度更小,每一个服务都对应唯一的业务能力,做到单一职责,避免重复业务开发;

4.2 面向服务: 微服务对外暴露业务接口;

4.3 自治: 团队独立,技术独立,数据独立,部署独立;

4.4 隔离性强: 服务调用做好隔离、容错、降级、避免出现级联问题。

5、服务拆分及远程调用: 5.1 服务拆分的原则: 不同微服务,不要重复开发相同的业务;

微服务数据独立,不要访问其他微服务的数据库;

微服务可以将自己的业务暴露为接口,供其他微服务调用。

5.2 服务的远程调用: 1、服务的远程调用:类比浏览器发送http请求给服务,可以获取到对应的json,那么在java代码中,我们也可以发送一个http请求给另一个服务以获取对应的json数据。 2、在java中,我们要发送http请求,可以使用restTemplate;

点赞

当前页面评论已关闭。

隐藏
变装