SpringCloud和分布式

202 阅读5分钟

SpringCloud和分布式

www.1024sou.com/article/247…

blog.csdn.net/qq_41889508…

组件

注册发现:Eureka

负载均衡:Ribbon

断路器: Hystrix

服务网管:Zuul

分布式配置:Config

业务背景

假设开发一个电商网站,要实现支付订单的功能,流程如下:

  • 创建一个订单后,如果用户立刻支付了这个订单,我们需要将订单状态更新为“已支付”
  • 扣减相应的商品库存
  • 通知仓储中心,进行发货
  • 给用户的这次购物增加相应的积分

Eureka

注册中心,记录了一个注册表,哪个服务在哪台服务器上的哪个端口

解决微服务过多而不方便管理的问题

微服务通过Eureka Client获取被调用服务的信息,Client通过请求Eureka Server获取服务信息,发送请求。

  • Eureka Client: 负责将这个服务的信息注册到Eureka Server中
  • Eureka Server: 注册中心,里面有一个注册表,保存了各个服务所在的机器和端口号

自我保护机制

如果在15分钟内超过85%的节点都没有正常的心跳,那么Eureka就认为客户端与注册中心出现了网络故障,此时会出现以下几种情况:

1.Eureka不再从注册列表中移除因为长时间没收到心跳而应该过期的服务 2.Eureka仍然能够接受新服务的注册和查询请求,但是不会被同步到其它节点上(即保证当前节点依然可用) 保证可用性,牺牲一致性 3.当网络稳定时,当前实例新的注册信息会被同步到其它节点中 因此, Eureka可以很好的应对因网络故障导致部分节点失去联系的情况,而不会像zookeeper那样使整个注册服务瘫痪。

Zookeeper

ZK保证CP,即保证一致性

Eureka保证AP,优先可用性

Feign

声明式客户端

解决微服务间调用的问题,帮助我们简化服务间的调用,例如建立连接、构造请求、解析响应

原理:使用动态代理,对于添加@FeignClient注解的接口,创建动态代理

Feign会根据@RequestMapping等注解,动态构造出要请求的服务地址。

Ribbon

负载均衡工具。

解决多个微服务实例的场景下,请求如何分发的问题。

Ribbon从Eureka Client获取服务的注册列表,默认使用Round Robin算法,选择目标服务器

常见的复杂均衡策略:随机 (Random),轮询 (RoundRobin),一致性哈希 (ConsistentHash)

Nginx

Nginx- 服务端负载均衡: nginx是客户端所有请求统一交给nginx,他来实现负载均衡属于服务器端的负载均衡

Ribbon - 客户端负载均衡:Ribbon获取服务的注册信息后,在本地轮询来实现负载均衡,适用于服务间调用的场景

Hystrix

熔断降级

解决服务雪崩的问题

服务雪崩:一个微服务故障引发多个微服务失效的连锁反应

服务熔断:熔断机制是应对雪崩效应的一种微服务链路保护机制,当请求失败达到一定次数或者比例,直接返回某个错误码

熔断机制的注解是@HystrixCommand.

服务降级:微服务分级,在资源不够的场景,关闭部分微服务,保证核心业务正常运行

Zuul

网络路由,类似于门面模式,对外提供统一的网管入口,由Zuul网管抓饭请求到具体服务

外部应用,如浏览器,移动端不需要了解具体服务,只需要想统一网管发送请求

解决问题:提供统一的降级、限流、认证授权、安全

Gateway

限流

处理方式:拒绝服务,排队,降级

算法:

1.滑动窗口

2.漏桶算法

3.令牌桶算法

Config

配置管理

解决问题:每个微服务由自己的配置信息,难以管理

可以做到配置,代码分离,单独管理,配置难以维护的问题

原理

1.配置文件存储在远端git(比如github,gitee等仓库),config-server从远端git拉取配置文件,并保存到本地git。 2.本地git和config-server的交互是双向的,因为当远端git无法访问时,会从本地git获取配置文件 3.config-client(即各个微服务),从config-server拉取配置文件

CAP

一致性,可用性,分区容错性

CA:mysql

CP: ZK

AP:

BASE

基本可用性:时间上的损失,功能上损失(保证核心功能,时延可能变大)

软状态:不同节点间数据同步存在时延

最终一致性:多个节点间的不同副本在一定时间后达到一致

2PC

事务分为2个阶段,表决阶段-执行阶段

分布式锁

实现方案

数据库

操作简单,性能开销大,在某个表中添加或删除记录

Redis

利用Redis的SETNX的原子特性,配合Redis过期策略,以及异常处理,实现过期自动释放锁

Zookeeper

在某个路径下,创建临时顺序节点,谁的id小,认为获得锁成功,其他节点增加一个watcher监听,实时获取到变化,性能不如redis

分布式ID

要求

全局唯一,高性能,能递增

1.uuid

生成简单,全局唯一,但是结果比较长,不能自增,没有含义,在数据库主键等场景不好使用

2.数据库自增ID

生成简单,单调递增,容易被猜测,并发访问压力大,DB单点故障

优化

多数据库,为了防止生成重复id,可以修改自增的步长

优化二

号段模式,每次返回一个号段,例如1-1000

3.Redis

利用redis的incr命令实现Id的原子自增

考虑redis持久化

4.雪花算法

Snowflake生成的是Long类型的ID,一个Long类型占8个字节,每个字节占8比特,也就是说一个Long类型占64个比特。

Snowflake ID组成结构:正数位(占1比特)+ 时间戳(占41比特)+ 机器ID(占5比特)+ 数据中心(占5比特)+ 自增值(占12比特),总共64比特组成的一个Long类型。