微服务、分布式

目录

电商业务场景介绍

Nacos

Eureka

Nacos与Eureka比较

Feign

Feign和OpenFeign的区别

Ribbon

Hystrix 

Zull

Gateway

CAP理论

BASE理论

分布式ID

分布式锁

分布式事务

RPC

Spring Cloud、Dubbo的区别


电商业务场景介绍

先来给大家说一个业务场景,假设咱们现在开发一个电商网站,要实现支付订单的功能,流程如下:

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

针对上述流程,我们需要有订单服务、库存服务、仓储服务、积分服务。整个流程的大体思路如下:

  • 用户针对一个订单完成支付之后,就会去找订单服务,更新订单状态
  • 订单服务调用库存服务,完成相应功能
  • 订单服务调用仓储服务,完成相应功能
  • 订单服务调用积分服务,完成相应功能

至此,整个支付订单的业务流程结束

下图这张图,清晰表明了各服务间的调用过程:

 整体架构原理:

Nacos

1、服务注册:

 服务注册的策略的是每5秒向nacos server发送一次心跳,心跳带上了服务名,服务ip,服务端口等信息。同时 nacos server也会向client 主动发起健康检查,支持tcp/http检查。如果15秒内无心跳且健康检查失败则认为实例不健康,如果30秒内健康检查失败则剔除实例。

2、配置中心

3、如何理解Nacos中的命名空间?

命名空间,也就是namespace。在Nacos中,不管是配置还是服务,都是属于某一个命名空间中的,默认情况下都是属于pulibc这个命名空间中的。我们可以在Nacos中新增命名空间,也就相当于开辟了另外一套存放服务和配置的地方,命名空间之间是独立的,完全不冲突的,所以我们可以利用Nacos中的命名空间来实现不同环境、不同租户之间的服务注册和配置。

4、Nacos的注册中心应该是CP还是AP

Nacos既能保证CP,也能保证AP;如果注册的节点是临时节点,那么就是AP,如果是非临时节点,那么就是CP,默认是临时节点。

Eureka

Netflix Eureka 是由 Netflix 开源的一款基于 REST 的服务发现组件,包括 Eureka Server 及 Eureka Client。

  • Eureka Client:负责将这个服务的信息注册到Eureka Server中
  • Eureka Server:注册中心,里面有一个注册表,保存了各个服务所在的机器和端口号
  • Register(服务注册):当Eureka Client 向Eureka Server 注册时, Eureka Client 提供自身的元数据,比如IP 地址、端口、运行状况H1 标的Uri 、主页地址等信息。
  • Renew(服务续约):Eureka Client 在默认的情况下会每隔30 秒发送一次心跳来进行服务续约。通过服务续约来告知Eureka Server该Eureka Client 仍然可用,没有出现故障。
    正常情况下,如果Eureka Server在90 秒内没有收到Eureka Client 的心跳, Eureka Server 会将Eureka Client 实例从注册列表中删除。
  • Fetch Registries(获取服务注册列表信息):Eureka Client 从Eureka Server 获取服务注册表信息,井将其缓存在本地。Eureka Client 会使用服务注册列表信息查找其他服务的信息,从而进行远程调用。该注册列表信息定时(每30 秒) 更新一次
  • Cancel(服务下线,主动下线):Eureka Client 在程序关闭时可以向Eureka Server 发送下线请求。发送请求后,该客户端的实例信息将从Eureka Server 的服务注册列表中删除。
    该下线请求不会自动完成,需要在程序关闭时调用以下代码:DiscoveryManager.getinstance().shutdownComponent();
  • Eviction(被动下线,主动剔除):在默认情况下,当Eureka Client 连续90 秒没有向Eureka Server 发送服务续约(心跳)时, Eureka Server 会将该服务实例从服务注册列表删除,即服务剔除。

配置信息:

eureka: # eureka 的配置分为3类:server 、client 、实例

  server: # server配置
    eviction-interval-timer-in-ms: 10000 # 服务端间隔多少毫秒做定期的删除操作
    renewal-percent-threshold: 0.85 # 续约百分比 超过85%的应用没有和你续约,那么eureka会保护服务,不会剔除任何一个服务

  client:
    service-url:                                              # 注册到eureka-server的地址,如果是多个地址(集群)则用逗号分割
    defaultZone: http://peer1:8761/eureka,http://peer2:8762/eureka,http://peer3:8763/eureka
    register-with-eureka: true                                # 设置是否要将服务注册到 eureka-server中
    fetch-registry: true                                      # 应用是否去拉取服务列表到本地
    registry-fetch-interval-seconds: 10                       #为了解决服务列表的脏读问题,配置到服务注册中心拉取列表的间隔 ,时间越短脏读越少,时间越长性能消耗越大

  instance:
    instance-id: ${eureka.instance.hostname}:${spring.application.name}:${server.port}  # 主机名称:应用名称:端口号
    hostname: localhost  # 主机名称 或 服务的ip
    prefer-ip-address: true # 以ip的形式显示具体的服务信息
    lease-renewal-interval-in-seconds: 5 # 服务实例的续约时间间隔 秒

CAP原则:(C:一致性、A:可用性、P:分区容错性)

Eureka是AP模式;Zookeeper是CP模式;Nacos即使AP模式也是CP模式

Nacos与Eureka比较

1、Nacos具备服务优雅上下线和流量管理,具有丰富的API和美化的后台管理页面,而Eureka的后台页面仅供展示,需要使用api操作上下线且不具备流量管理功能。

2、Nacos整合了注册中心、配置中心功能,把原来两套集群整合成一套,简化了部署维护。

3、Eureka是Netflix 公司的产品现在已经停止更新了,而Nacos是阿里巴巴提供的产品

4、Nacos是支持AP和CP的,默认是AP(临时节点);而Eureka只支持AP

Feign

Feign是是一个声明式的Web Service客户端。

Feign的一个关键机制就是使用了动态代理

  • 首先,如果你对某个接口定义了@FeignClient注解,Feign就会针对这个接口创建一个动态代理
  • 接着你要是调用那个接口,本质就是会调用 Feign创建的动态代理,这是核心中的核心
  • Feign的动态代理会根据你在接口上的@RequestMapping等注解,来动态构造出你要请求的服务的地址
  • 最后针对这个地址,发起请求、解析响应

1、采用Get方式进行调用:

所有的参数必须加@RequestParam注解,并在@RequestMapping注解中指明是Get方法

2、采用Post方式进行调用:

在所有参数前加上@RequestParam注解,并指明feign消费服务的方式为POST。

有且只有一个参数前为@RequestBody或什么也没有(如果有多个参数,那么其余参数前必须有@RequestParam)。

Feign和OpenFeign的区别

 1、Feign是Netflix公司生产的产品,是一个轻量级的服务调用工具。

2、Feign中已经集成了Ribbon,通过负载均衡算法可以从注册中心中寻找服务。

3、OpenFeign是在Feign上增强的一个 产品,除了集成Ribbon外,还支持SpringMVC的注解和Hystrix的功能。

Ribbon

Ribbon Netflix 公司开源的一个负载均衡的组件。

负载均衡算法:轮询(默认)、随机、哈希、权重

怎么自己实现:自定义策略类,继承AbstractLoadBalancerRule并重写choose 方法

Hystrix 

Hystrix是Netstflix 公司开源的一个项目,它提供了熔断器功能,能够阻止分布式系统中出现联动故障。

Zull

Zuul 是由 Netflix 孵化的一个致力于“网关 “解决方案的开源组件。

 

Gateway

CAP理论

分布式系统不可能同时满足一致性、可用性和分区容忍性,最多只能同时满足其中两项。是分布式系统设计的理论

  • 一致性(C:Consistency):在分布式系统中的所有数据备份,对系统的一个数据更新成功之后,如果所有用户都能够读取到最新的值,该系统就被认为具有强一致性。

  • 可用性(A:Availability):分布式系统在面对各种异常时可以提供正常服务的能力,对于用户的每一个操作请求总是能够在有限的时间内返回结果。

  • 分区容错性(P:Partition Tolerance):分布式系统在遇到任何网络分区故障的时候,仍然需要能对外提供一致性和可用性的服务,除非是整个网络环境都发生了故障。

Zookeeper:CP; Eureka :AP; Nacos:既保证了AP原则,有保证了CP原则。

BASE理论

Basically Available(基本可用)Soft-state(软状态)Eventually Consistent(最终一致性) 三个短语的缩写。 是 CAP 理论中 AP 方案的延伸。

即使无法做到强一致性,但每个应用都可以根据自身业务特点,采用适当的方式来使系统达到最终一致性。也就是牺牲数据的一致性来满足系统的高可用性,系统中一部分数据不可用或者不一致时,仍需要保持系统整体的基本可用

基本可用:

  • 响应时间上的损失:正常情况下,处理用户请求需要0.5s返回结果,但是由于系统出现故障,处理用户请求的时间变成3s。
  • 系统功能上的损失:正常情况下,用户可以使用系统的全部功能,但是由于系统访问量突然剧增,系统的非核心功能无法使用。

软状态:

  • 数据可以存在中间的状态,允许数据在不同副本之间的同步存在一定的延时

最终一致性:

  • 指的是系统中所有的数据副本,在经过一段时间的同步后,最终能够达到一个一致的状态。而不需要实时保证系统数据的强一致性。

分布式ID

分布式 ID 需要满足全局唯一性高可用高性能使用简单的特点,除了上述的基本特点外,一个好的分布式ID还应该具备安全(不包含敏感信息)有序递增(提高数据库的读写性能)的特点。

1、UUID:

  • 优点:生成足够简单,本地生成无网络消耗,具有唯一性
  • 缺点:生成的内容是字符串,不能满足有序递增,且长度较长占用储存空间

2、单机数据库自增:

  • 优点:生成的ID有序递增,占用储存空间较少
  • 缺点:可能存在数据库宕机的风险,不满足高可用的特点

3、数据库集群:

  • 优点:解决了数据库宕机的风险
  • 缺点:不利于后续扩容,而且实际上单个数据库自身压力还是大,依旧无法满足高并发场景。

4、数据库号段模式:从数据库批量的获取自增ID,每次从数据库取出一个号段范围

idmax_idstepbiz_typeversion
当前最大id号段的布长业务类型版本号

5、Redis:基于String类型的incr命令实现ID的原子性自增。

  • 优点:生成的ID有序递增,占用储存空间较少,效率高
  • 缺点:需要考虑redis持久化的问题
    • RDB:会定时打一个快照进行持久化,假如连续自增但redis没及时持久化,而这会Redis挂掉了,重启Redis后会出现ID重复的情况。
    • AOF:会对每条写命令进行持久化,即使Redis挂掉了也不会出现ID重复的情况,但由于incr命令的特殊性,会导致Redis重启恢复的数据时间过长。

6、雪花算法:生成的是Long类型的ID,一共占8个字节,实现方:百度(uid-generator)、美团(Leaf)、滴滴(Tinyid)

  • 优点:生成的ID是递增有序的,效率较高
  • 缺点:依赖于服务器的时间(服务器的时钟回拨可能会出现ID重复)

分布式锁

分布式锁是为了解决分布式系统中控制共享资源访问的问题。分布式锁应该具备以下特点:

  • 互斥 :任意一个时刻,锁只能被一个线程持有;
  • 高可用 :锁服务是高可用的。并且,即使客户端的释放锁的代码逻辑出现问题,锁最终一定还是会被释放,不会影响其他线程对共享资源的访问。
  • 可重入:一个节点获取了锁之后,还可以再次获取锁。

1、MySQL:

  • 悲观锁方式:可以使用select ... for update 来实现分布式锁。通过表的主键索引或唯一索引实现。
  • 乐观锁方式:基于CAS的思想实现;搞个version字段,每次更新修改,都会自增加一,然后去更新余额时,把查出来的那个版本号,带上条件去更新,如果是上次那个版本号,就更新,如果不是,表示别人并发修改过了,就继续重试。这种方式适合并发不高的场景,一般需要设置一下重试的次数
  • 优点:实现方式简单
  • 缺点:没有锁失效的机制,操作数据库需要一定的开销,性能问题需要考虑。

2、zookeeper:

  • 基于zookeeper临时有序节点可以实现的分布式锁,在客户端对某个方法进行加锁的时候,在zookeeper的指定节点目录下生成一个唯一临时有序的节点。
  • 判断是否获取锁的方式:只需要判断有序节点中序号最小的一个。
  • 释放锁的方式:只需将这个临时有序的节点删除即可
  • 优点:解决了死锁的情况,具备高可用的特点
  • 缺点:需要频繁的创建节点和删除节点,性能不如Redis

3、Redis:

  • 使用setnx命令进行加锁,value最好使用UUID保证唯一性,并且设置过期时间。(Redis中命令是setnx,Java中的命令是setIfAbsent)
  • 使用del的方式进行释放锁,在释放锁的时候要判断锁是否是自己的。
  • 当key不存在时设置值并返回true,当key存在时不进行任何操作并返回false。
  • 使用看门狗来进行锁自动续期的操作  或者  测试业务执行所需要的平均时间,过期时间比平均时间大3s。

分布式事务

2PC(俩阶段提交协议):

  • 准备阶段:事务管理器向参与者发出消息,参与者在本地执行事务,并将事务执行前后的顺序分别写到undolog和redolog文件中,此时事务还并未提交。
  • 提交阶段:如果事务管理器收到参与者执行失败的消息,则直接给所有的参与者发送回滚的操作,否则发送提交的操作。最后释放所有的资源并删除所有的日志文件记录。

解决方式:使用seata的AT模式,AT模式与2PC协议的步骤基本类似。

seata的使用方法:在pom文件中加入seata的依赖,在事务的发起者添加@GlobalTransition注解,开启全局事务。

RPC

RPC(Remote Procedure Call) 即远程过程调用

为什么要 RPC ?

 两个不同的服务器上的服务提供的方法不在一个内存空间,所以,需要通过网络编程才能传递方法调用所需要的参数。方法调用的结果也需要通过网络编程来接收。如果我们自己手动网络编程来实现这个调用过程的话工作量是非常大的,因为我们需要考虑底层传输方式、序列化方式等。

RPC 能帮助我们做什么呢?

就是为了让你调用远程方法像调用本地方法一样简单。举个例子:两个不同的服务 A、B 部署在两台不同的机器上,服务 A 如果想要调用服务 B 中的某个方法的话就可以通过 RPC 来做。

RPC的核心功能组件

  • 客户端(服务消费端) :调用远程方法的一端。
  • 客户端 Stub(桩) : 这其实就是一代理类。代理类主要做的事情很简单,就是把你调用方法、类、方法参数等信息传递到服务端。
  • 网络传输 : 网络传输就是你要把你调用的方法的信息比如说参数啊这些东西传输到服务端,然后服务端执行完之后再把返回结果通过网络传输给你传输回来。
  • 服务端 Stub(桩) :这个桩就不是代理类了。我觉得理解为桩实际不太好,大家注意一下就好。这里的服务端 Stub 实际指的就是接收到客户端执行方法的请求后,去指定对应的方法然后返回结果给客户端的类。
  • 服务端(服务提供端) :提供远程方法的一端。

RPC 的工作流程:

 

  1. 服务消费方(client)调用以本地调用方式调用服务;
  2. client stub 接收到调用后负责将方法、参数等组装成能够进行网络传输的消息体;这就是所谓的marshalling。
  3. client stub 找到服务地址,并将消息发送到服务端;这个过程可能是面向连接或无连接的。
  4. server stub 收到消息后进行解码;也叫 unmarshalling。
  5. server stub 根据解码结果调用本地的服务;
  6. 本地服务执行并将结果返回给 server stub ;
  7. server stub 将返回结果打包成消息并发送至消费方;
  8. client stub 接收到消息,并进行解码;
  9. 服务消费方得到最终结果。并且返回值被设置在本地进程的堆栈中。

RPC 与 REST 的区别

1、RPC 与 REST 最大的区别就在于 RPC 提供了更好的抽象,REST 至少需要提供 URL 以及请求参数,而 RPC 隐藏了与网络传输的相关实现细节。

2、RPC 可以基于任何网络通信协议,调用者并不会关心具体的协议;而 REST 通常基于 HTTP协议。

RPC的优缺点

1、可以在分布式环境以及本地环境中使用

2、对用户隐藏内部消息传递机制。

3、不适合传输大量的数据

Spring Cloud、Dubbo的区别

  • 初始定位不同:SpringCloud定位为微服务架构下的一站式解决方案;Dubbo 是 SOA时代的产物,它的关注点主要在于服务的调用和治理
  • 生态环境不同:SpringCloud依托于Spring平台,具备更加完善的生态体系;而Dubbo一开始只是做RPC远程调用,生态相对匮乏,现在逐渐丰富起来。
  • 调用方式:SpringCloud是采用Http协议做远程调用,接口一般是Rest风格,比较灵活;Dubbo是采用Dubbo协议,接口一般是Java的Service接口,格式固定。但调用时采用Netty的NIO方式,性能较好。
  • 组件差异比较多:例如SpringCloud注册中心一般用Eureka,而Dubbo用的是Zookeeper

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值