springCloud各组件详解

1、服务的发现与注册Eureka
Spirng Cloud Eureka使用Netflix Eureka来实现服务注册与发现,它既包含了服务端组件,也包含了客户端组件,并且服务端与客户端均采用java编写,所以Eureka主要适用于通过java实现的分布式系统,或是JVM兼容语言构建的系统。

Eureka的服务端提供了较为完善的REST API,所以Eureka也支持将非java语言实现的服务纳入到Eureka服务治理体系中来,只需要其他语言平台自己实现Eureka的客户端程序。目前.Net平台的Steeltoe、Node.js的eureka-js-client等都已经实现了各自平台的Ereka客户端组件。

Eureka服务端,即服务注册中心。它同其他服务注册中心一样,支持高可用配置。依托于强一致性提供良好的服务实例可用性,可以应对多种不同的故障场景。

Eureka服务端支持集群模式部署,当集群中有分片发生故障的时候,Eureka会自动转入自我保护模式。它允许在分片发生故障的时候继续提供服务的发现和注册,当故障分配恢复时,集群中的其他分片会把他们的状态再次同步回来。集群中的的不同服务注册中心通过异步模式互相复制各自的状态,这也意味着在给定的时间点每个实例关于所有服务的状态可能存在不一致的现象。

服务的注册中心是什么?

所谓的服务注册中心就是用每个服务单元向注册中心登记自己提供的服务,包括服务的主机与端口号,服务版本号、通讯协议等一些附加信息。注册中心按照服务名分类组织服务清单,同时还需要以心跳检测的方式去监测清单中的服务是否可用,若不可用需要从服务清单中剔除,以达到排除故障服务的效果。

服务的注册中心使用注解@EnableEurekaServer
t服务提供客户端方:@EnableDiscoveryClient 此注解支持多种服务中心,如eureka,zk,等等,所以一般使用这个。
@EnableEurekaClient 只支持eureka所以用上一种

我们配置yml时spring.application.name属性为什么要配置成“-”符号的链接形式而不是下划线呢?

配置下划线会造成客户端找不到服务端的具体实例名称。

关于Eureka 的自我保护机制与剔除服务机制

剔除服务机制:当服务提供方(客户端)注册到Eureka后,每30S将会向Eureka发起一次请求表示自己有心跳
服务器正常,当90S都没有发请求时候Eureka会认为服务器宕机了,则会在60S后统一清除所有宕机的服务器。

自我保护机制:当服务没有按每30S按时发请求时,Eureka将会统计15分钟内心跳的请求成功概率,如果低于85%则可能服务提供方有延迟问题或者网络故障,这样会将服务提供方保护起来不会剔除。Eureka就认为客户端与注册中心出现了网络故障,此时会出现以下几种情况:

  1. Eureka不再从注册列表中移除因为长时间没收到心跳而应该过期的服务

  2. Eureka仍然能够接受新服务的注册和查询请求,但是不会被同步到其它节点上(即保证当前节点依然可用)

  3. 当网络稳定时,当前实例新的注册信息会被同步到其它节点中

因此, Eureka可以很好的应对因网络故障导致部分节点失去联系的情况,而不会像zookeeper那样使整个注册服务瘫痪。
yml文件中的配置

eureka:
  server:
     enable-self-preservation: false # 关闭自我保护模式(缺省为打开)
     eviction-interval-timer-in-ms: 1000 # 扫描失效服务的间隔时间(缺省为60*1000ms)

为什么采用Eureka作为注册中心?
了解这个之前我们先了解下CAP 原则
什么是CAP原则:
C(Consistency):数据一致性。分布式系统中,数据会有副本,无论是否从副本中取数据,从哪个副本取数据,结果都是一样的。保证所有地方数据一样就是保证了数据一致性。由于网络或者机器故障等因素,可能有些副本数据写入正确,有些却写入错误或者失败,这样就导致了数据的不一致了。而满足数据一致性规则,就是保证所有数据都要同步

A(Availability):可用性。即 只要收到用户的请求,服务器就必须给出回应。我们需要获取数据时,都能够正常的获取到想要的数据(允许可接受范围内的网络延迟),也就是说,要保证任何时候请求数据都能够正常响应

P(Partition Tolerance):分区容错性。当网络通信发生故障时,集群仍然可用,不会因为某个节点挂了或者存在问题,而影响整个系统的正常运作。大多数分布式系统都分布在多个子网络。每个子网络就叫做一个区(partition),区间通信可能失败。比如,一台服务器放在中国,另一台服务器放在美国,这就是两个区,它们之间可能无法通信,系统设计的时候,必须考虑到这种情况

一般来说,分区容错无法避免,因此可以认为 CAP 的 P 总是成立。CAP 定理告诉我们,剩下的 C 和 A 无法同时做到,所以需要取舍是做到 A 还是 C 。

Zookeeper 保证 CP

Zookeeper 是保证数据的一致性的,但是并不是强一致的。

比如客户端 A 提交一个写操作,Zookeeper 在过半数节点操作成功之后就可以返回,但此时,客户端 B 的读操作请求的是 A 写操作尚未同步到的节点,那么读取的就不是 A 最新提交的数据了。
我们可以在读取数据的时候先执行一下 sync 操作,即与 leader 节点先同步一下数据,再去取,这样才能保证数据的强一致性。

关于可用性,Zookeeper 的 master 节点因为网络故障与其他节点失去联系时,剩余节点会重新进行 leader 选举,选举 leader 的时间太长,需要 30 ~ 120 s, 且选举期间整个 Zookeeper 集群都是不可用的,这就导致在选举期间注册服务瘫痪。同时,在云部署的环境下,因网络问题使得 Zookeeper 集群失去 master 节点是较大概率会发生的事,整个服务停下这么长的时间是非常严重的,比如双十一。

Eureka 保证 AP

就是针对 Zookeeper 出现的这一问题,Eureka选择了优先保证可用性。

大规模网络部署时,失败是在所难免的。Eureka各个节点都是平等的,几个节点挂掉不会影响正常节点的工作,剩余的节点依然可以提供注册和查询服务。当向注册中心查询服务列表时,我们可以容忍注册中心返回的是几分钟以前的注册信息,但不能接受服务直接 down 掉不可用。而集群部署的 Eureka 即使挂掉一定的数量,也可以保证有信息可以返回,依然可以提供注册和查询服务,只不过查到的信息可能不是最新的。

ribbon 提供了负载均衡和重试机制。

作为服务注册中心,最重要的是要保证可用性,可以接受短时间内数据不一致的情况,所以 Eureka 会更适合。

2、Feign 远程调用
需要调用的其他服务接口时,通过 @FeignClient 注解动态代理生成对应的实现类,最终减少了调用代码的编写。

问题来了,Feign是如何做到的呢?其实Feign的一个机制就是使用了动态代理,
(1) 首先,如果你对某个接口定义了@FeignCl
ient注解,Feign就会针对这个接口创建一个动态代理
(2)接着你要是调用那个接口,本质就是会调用 Feign创建的动态代理,这是核心中的核心
(3)Feign的动态代理会根据你在接口上的@RequestMapping等注解,来动态构造出你要请求的服务的地址
(4)最后针对这个地址,发起请求、解析响应

3、Ribbon负载均衡

说完了,那么问题来了,如果库存服务上面部署了台机器,

192.168.169:9000
192.168.170:9000
192.168.171:9000
192.168.172:9000
192.168.173:9000

那Feign怎么知道请求那台服务器呢,这是SpringCloud就派上用场了,Ribbon 务就是解决这个问题的,他的作用是负载均衡,会帮你在每一次请求的时候选择一台机器,均匀的把请求发送到各个机器上 ,Ribbon的负载均衡默认的使用RoundRobin轮询算法,什么是轮询算法?如果订单服务对库存发起十次请求,那就先让你请求第一台机器,然后是第二台机器,第三台机器,…接着循环到第十台机器

此外,Ribbon是和Feign以及Eureka紧密协作,完成工作的,具体如下:

首先Ribbon会从 Eureka Client里面获取到对应的服务注册表,也就知道了所有的服务都部署在了那台机器上,在监听哪些端口,

然后Ribbon就可以使用默认的Round Robin算法,从中选择一台机器,

4、Hystrix熔断、服务降级

在微服务架构里,一个系统会有多个服务, 以本文的业务场景为例:订单服务在一个业务流程里需要调用三个服务,现在假设订单服务自己最多只有100个线程可以处理请求然后呢,积分服务不幸的挂了,每次订单服务调用积分服务的时候,都会卡住几秒钟,然后抛出—个超时异常。

分析下这样会导致什么问题:如果系统在高并发的情况下,大量请求涌过来的时候,订单服务的100个线程会卡在积分服务这块,导致订单服务没有一个线程可以处理请求,然后会导致别的请求订单服务的时候,发现订单服务挂掉,不响应任何请求了,这种问题就是微服务架构中恐怖的服务器雪崩问题:如下图,这么多的服务互相调用要是不做任何保护的话,某一个服务挂掉会引起连锁反应,导致别的服务挂掉,比如积分服务挂了会导致订单服务的线程全部卡在请求积分服务这里没有一个线程可以工作,瞬间导致订单服务也挂了别人请求订单服务全部会卡住,无法响应。
Hystrix是隔离、熔断以及降级的一个框架。啥意思说白了就是Hystrix会搞很多小线程池,每个小线程池里的线程仅用去请求的服务,

5、zull网关路由
Zuul:微服务网关,这个组件是负责网络路由的!

什么是网络路由?

假设你后台部署了几百个服务,现在有个前端兄弟,人家请求是直接从浏览器那儿发过来的。打个比方:人家要请求一下库存服务,你难道还让人家记着这服务的名字叫做inventory-service?部署在5台机器上?就算人家肯记住这一个,你后台可有几百个服务的名称和地址呢?难不成人家请求一个,就得记住一个?你要这样玩儿,那就是中美合拍,文体开花了!

上面这种情况,压根儿是不现实的。所以一般微服务架构中都必然会设计一个网关在里面,像android、ios、pc前端、微信小程序、H5等等,不用去关心后端有几百个服务,就知道有一个网关,所有请求都往网关走,网关会根据请求中的一些特征,将请求转发给后端的各个服务。

而且有一个网关之后,还有很多好处,比如可以做统一的降级、限流、认证授权、安全,等等。

总结一下SpringCloud结果核心组件:

Eureka:个服务启动时,Eureka会将服务注册到EurekaService,并且EurakeClient还可以返回过来从EurekaService拉去注册表,从而知道服务在哪里

Ribbon:服务间发起请求的时候,基于Ribbon服务做到负载均衡,从一个服务的对台机器中选择一台

Feign:基于fegin的动态代理机制,根据注解和选择机器,拼接Url地址,发起请求

Hystrix:发起的请求是通过Hystrix的线程池来走,不同的服走不同的线程池,实现了不同的服务调度隔离,避免服务雪崩的问题

Zuul:如果前端后端移动端调用后台系统,统一走zull网关进入,有zull网关转发请求给对应的服务

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值