对于微服务的理解
- 单体架构
- 首先从单体架构来说,虽然他开发简单,但他所有的模块都写在一起,耦合性太高了, 而且扩展性很差,如果项目大一点部署起来也挺恶心。只有一些适合单体架构的小项目才用。
- 分布式架构(SOA)
- 而分布式项目就是把一个大项目拆分成若干个小项目,实现了流量的分担,而且可以根据 不同的模块进行优化。
- 微服务
- SpringCloud是什么?
- SpringCloud是一系列框架的集合,集成SpringBoot,提供很多优秀服务:服务发现和注册,统一配置中心, 负载均衡,网关, 熔断器等的一个微服务治理框架。
- 微服务的几个组件是什么?
- Eureka: 注册中心, 服务注册和发现
- Ribbon: 负载均衡, 实现服务调用的负载均衡
- Hystrix: 熔断器
- Feign: 远程调用
- Zuul: 网关
- Spring Cloud Config: 配置中心
CAP理论是什么?
- 一致性(Consistency) (所有节点在同一时间具有相同的数据)
- 可用性(Availability) (保证每个请求不管成功或者失败都有响应)
- 分隔容忍(Partition tolerance) (系统中任意节点挂掉货数据丢失不会影响整个系统的运行)
Eureka注册中心
Eureka是什么?
- Eureka注册中心,提供服务注册和发现,有客户端和服务端两大组件,Eureka服务端作为服务的注册中心, 用来提供服务注册, 支持集群部署,每一个Eureka节点地位都一样,采用异步的方式进行数据同步。Eureka客户端分为提供者和消费者。
- Eureka工作流程?
- Eureka是基于ap定理的,保证每个请求不管成功或者失败都有响应,系统中任意节点挂掉或数据丢失不会影响整个系统的运行。提供者启动后以键值对的方式向Eureka注册自己信息,一个键可以对应多个服务,通过定时线程定期以http方式进行心跳检测,心跳周期默认30秒一次,超过90秒没发现心跳认为宕机,Eureka每隔60秒会剔除标记为宕机的服务,但他有自我保护机制,当心跳失败比例超过阈值(默认85%),开启保护机制,不再剔除服务。当Eureka注册完提供者的信息,会立刻缓存到readWrite中,再通过定时线程定期写入readOnly中,消费者作为服务调用方,每隔30秒去readOnly拉取服务列表,然后使用负载均衡算法选出一个服务进行调用。
- EureKa的高可用体现在哪里?
- 多台Eureka互相注册在对方上。
EureKa的AP体现在哪里?
基于raft的协议的注册中心
- 基于raft的协议的注册中心采用的是cp定理,所有节点在同一时间具有相同的数据且系统中任意节点挂掉或数据丢失不会影响整个系统的运行。当服务启动后,提供者注册自己的信息到nacos中,就会设置一个监听线程对每一个服务进行监听,当有一个节点宕机,监听线程会立刻把那个节点的信息从 nacos的服务列表中剔除,然后通知消费者重新再来拉取最新的服务列表,保证服务的一致性。
- 而nacos的集群是由一个leader和多个follower组成,采用2PC方案进行数据同步,当他们发起数据同步前,leader会询问每一个follower,当超过半数以上的follower都响应 leader表示没问题,进行数据同步保持一致性。如果集群中某个节点宕机了,是follower还好,如果是leader,整个集群会发起leader选举,在leader选举出来之前,整个注册中心都无法对外提供服务。
- 基于Distro的协议的注册中心内核原理
- nacos集群中,当服务实例把数据提交给nacos时,会进行转发请求交给一个nacos去写入本地,它会调用sync去异步的同步数据到其他nacos中去,保证数据的基本一致。如果某个服务器需要在nacos中去拿数据,nacos会有一个监听线程,nacos如果没有得到数据,就不会给服务器,等nacos的数据同步过来后再通知服务器,让服务器来拉取注册列表信息。他虽然是保证的ap,但是nacos集群中的c也可以处于基本一致,只是相对弱一点。当新增一个nacos就会轮询拿到每个nacos中的数据进行比较,最终把数据写到新增的这个nacos中。如果nacos集群中的每个nacos来互相心跳请求,心跳请求会进行数据校验,主要交换的数据是md5的校验值,如果发现某个nacos的数据相差过大就会全量拉取补齐数据,如果某个nacos宕机重连了,落后太多也会进行一次全量拉取。
- nacos健康检测机制
- nacos的心跳探测分为2种,临时实例,和持久化实例.
- 临时实例,选择AP架构,使用Distro协议,分布式协议的一种,服务是放在内存中。
- 每隔5秒生产者服务器上报心跳,nacos如果3次没有接收到心跳就标为不健康实例,超过30秒没收到心跳就剔除这个服务实例。
- 持久实例,选择CP架构,使用Raft协议来实现服务是放在磁盘中!
- nacos会每隔20秒主动向生产者服务器发送探测心跳,就算探测失败,也只会把它标记为不健康实例,不会剔除。
- 临时实例,选择AP架构,使用Distro协议,分布式协议的一种,服务是放在内存中。
- nacos的心跳探测分为2种,临时实例,和持久化实例.
nacos关于雪崩的cap问题
Feign是一种非常轻量级的RPC框架,他只是把service层请求伪装成http请求,进行微服务与微服务之间的调用,他的组件集成了Ribbon负载均衡策略和Hystrix熔断器,负载均衡策略默认是开启的,而且采用轮询机制,熔断器默认关闭的, 需要通过配置文件进行设置开启。
RPC:就是为了解决远程调用服务的一种技术,使得调用者像进程内调用一样,通过注入接口,直接方法调用。
Feign的源码逻辑
● Feign在源码中使用到克隆设计模式它会复制出和原来这个类一模一样的(这个类会重写Object类中 clone(),它会调用clone方法,把自己克隆出来)
● 克隆模式:
○ 深克隆: 就是复制出来的对象完全一致,引用不同,完全分离。
○ 浅克隆: clone出来的对象是指向同一个引用的地址。Feign的丢数据问题
就是因为clone一个新对象,里面没有具体数据,带有token的请求先访问了A, A这边clone了一个新对象,再去访问B,新对象里就没了数据。
解决方案:我们定义一个拦截器,拦截那个对象,去获取里面的数据,clone出新的对象后,把数据放回新的对象,这样就保证了数据的完整性(必须是同一个requst请求)。
熔断器hstrix
分布式系统存在的问题
- 服务雪崩:就是由于某一个服务调用过程中出现了卡顿,导致所有的服务都不能正常使用
- 解决方案:
- 超时方案
- 发起服务调用时,设置一个超时时间,如果超过时间都还没响应,则当前线程自动销毁,释放资源。
- 超时方案
- 隔离模式
- 线程池隔离
- 对系统发来的请求按类型进行划分,对不同类型的请求使用线程池来资源隔离,每种类型的请求互不影响,如果一种类型的请求线程资源耗尽,则对后续的该类型请求直接返回,不再调用后续资源。
- 信号量隔离
- 使用一个信号池,每个请求过来拿一个信号量,释放资源后信号量+1,拿到信号量才能允许访问,如果信号量为0时则不允许新的请求。
- 线程池隔离
- 熔断降级
- 服务熔断
- 断路器有多个状态,Hystix会对请求情况计数,当一定时间内失败请求百分比达到阈值,则触发熔断,断路器会完全打开。所有请求都会被降级,打开后会进入休眠时间(默认是5S)。随后断路器会自动进入半开状态。此时会释放1次请求通过,若这个请求是健康的,则会关闭断路器,否则继续保持打开,再次进行5秒休眠计时。
- 服务降级
- 降级指的请求故障时, 不会阻塞, 会返回一个友好提示,不会影响其他服务的运行。
- 限流:限制业务访问的QPS,避免服务因流量的突增而故障
- 服务熔断
Ribbon