分布式

CAP

C:consistency 一致性 分布式系统能够同时访问同一份数据副本

A:availability 可用性 非故障节点能够在合理时间内获得合理的结果

P:Partition Tolerance 分区容错性 分布式系统当发生网络分区时,服务仍然可用

而是在P为条件下,只能实现A或者C。也就是说,在发生网络分区后,我们只能保证一致性或者可用性。

当没有发生网络分区时,也就是没有P为条件,那么自然可以同时满足A和C。

zookeeper:保证CP,zookeeper有leader节点,写操作只能由leader来做,Follower只能处理读操作,这样就保证数据的一致性。

Eureka:保证AP,Eureka各个服务器节点都是平等的,只要有至少一个节点,就能够保证可用。

Nacos:保证AP和CP,默认支持AP,通过命令进行切换为CP。

BASE理论

  • 基本可用(Basically Available)

    当系统发生不可预知的故障时,允许损失部分可用性。

    • 响应时间的损失:原先0.5s就能返回的结果,允许2s内返回
    • 系统功能的损失:可以损失非核心功能,而保证核心功能的可用
  • 软状态(Soft State)

    允许存在中间状态,允许在多个节点的数据副本存在时延

  • 最终一致性(Eventually Consistent)

    在一个时间期限后,要保证数据的最终一致性

分布式ID

对于单个数据库我们使用id自增就能保证,id不重复。

对于两个数据库,我们分别设置起始值和步长就能避免id重复,但是这时在添加一个数据库,则要重新修改初始值和步长。

号段模式:我们可以先从数据库中取出一段数据,比如id为100到200,当需要使用时,在本地直接提取使用,使用完这100个id后,再从数据库中取200到300的id。

redis:通过redis,在redis中使用incr自增,也能够保证id的不重复。

雪花算法:对分布式id的bit进行分配,比如64bit的一个id,从左到右,第一位符号位,接下来41bit为时间戳,接下来10bit为工作机器id,接下来12bit为序列号。这样就能够保证id的不重复。

限流算法

固定窗口计数机算法

规定一分钟之内只能有100个请求,如果多了则丢弃该请求。该方法无法防止突增的请求,比如前30秒只有1个请求,后30秒突然进来99个请求,无法保证限流的速率。

滑动窗口计数机算法

将一分钟划分成60个格子,大小为30的窗口不断移动,每秒的请求放到格子中,如果窗口中的请求超过阈值,就不再处理其他请求。

漏桶算法

输出的水流是一定的,这样就能保证输出速率稳定。把请求比作水,当请求来时,则将水输入到水桶上方,即使上方的水是突然激增的,那输出也仍然是稳定的。如果木桶大小固定,上方水满了,则水将溢出,也就是说请求丢弃。

缺点是,我们总是以固定的速率流出,我们希望当请求少时,固定速率流出自然没问题,但是当请求到峰值,我们希望流出速率大一些。

令牌桶算法

仍然是一个固定大小的桶,我们以固定速率生产令牌,当请求来时,对于大的请求,消耗多点的令牌,小请求就少点令牌。如果桶内令牌没有了,则丢弃请求。这个算法就能解决动态去做“流出速率”,峰值时流出速度快,平时呢流出速率平稳。

RPC

做为远程调用框架,目的是希望调用远程方法就像本地方法一样简单。

客户端:通过简单注解或者使用类调用远程方法

客户端代理类:通过动态代理,让客户端执行的方法最终让代理类来执行。代理类拿到服务名/方法名,参数等信息封装到request中,然后通过网络调用发送给服务端

网络调用:最简单的可以用socket,当然netty更流行,编写Netty的客户端与服务端

服务端:Netty中拿到request,知道了方法名,可以通过反射创建实现了该方法的类,然后调用之,得到结果后,再通过Netty服务端传送给客户端

注册中心:我们可以用zk,创建节点,节点为服务名,节点下数据为机器ip地址。服务端启动时,首先将自己能够提供的服务注册到zk上。客户端根据服务名从zk中找到具体的ip地址,然后根据ip地址发送访问。

网关

微服务下多个服务,对于权限管理,流量控制,日志,监控等和业务无关的东西提取出来,统一管理,因此就有网关。

网关可以做:鉴权,限流,请求路由,日志,监控。

微服务

服务注册与发现:Eureka,nacos

微服务有很多消费者,提供者,我们不希望将他们之间的调用写死,因为针对某个服务,可能有多个机器去运行他,那么我们希望有一个人能够统一管理,那么注册中心可以解决我们的问题。服务提供者将自己的服务注册到注册中心,消费者只需根据服务名从注册中心拿到提供者地址。并且对于网关,负载均衡,熔断降级,消息队列等等组件,他们都希望自己能够获得注册在注册中心的某些信息,从而进行操作。

比如监控功能,就需要拿到注册中心的所有提供者消费者信息,来判断他们的健康情况。

总之,注册中心统一对服务的管理,当我们需要使用或者查看这些服务状态时,只需访问注册中心即可。

负载均衡:Ribbon

nacos自己集成了Ribbon,要使用负载均衡,首先我们要讲restTemplate通过@Bean注解注册到spring中,然后或者使用注解,或者通过代码指定负载均衡策略即可,然后调用restTemplate.getForObject或者restTemplate.postForObject即可调用另一个服务的方法。

Openfeign:有人觉得直接写restTemplate.postForObject,这样不美观,我就是想调用另一个服务就跟调用本地方法一样,那么这个Openfeign就可以帮助我们。我们写一个接口,接口中方法指明另一个服务的接口,然后我们在controller调用的时候,加个注解,直接调用接口的方法,看起来多像在本地调用方法啊!

熔断和降级:Hystrix,sentinel

当服务调用链路A->B->C,其中服务C发生故障,导致B有大量请求堆积,最终耗尽B的所有资源,B挂掉,然后A也堆积大量请求,A也挂掉,这就是服务雪崩。

为了防止服务雪崩,我们需要熔断器,当某个服务故障时,切断调用链路,告知上一个服务,当前服务已经故障了。

服务降级,比如某服务访问量过大,我们一次处理不了那么多请求,我们可以做服务降级。比如突然有1000订单,我们一下子处理不了,那么我们可以让一部分请求走降级,返回稍后重试的提示信息。

sentinel不仅仅有熔断降级等功能,他还提供了多种其他功能,如限流,负载保护,实时监控,调用链路等。

网关:gateway,zuul

网关可以做路由映射,过滤器。

链路跟踪:zipkin

每个服务是一个圆点,服务调用之间有连线,做出来的效果,真好看。。。😄

06-03 05:01