分布式系统Dubbo

发布时间 2023-12-31 23:38:34作者: yanggdgg

一、简介

1.Dubbo介绍

Dubbo 是一个高性能的分布式服务框架,由阿里巴巴开发并开源,于2018年捐献给了Apache基金会。它提供了服务治理、负载均衡、容错机制、分布式调用等功能,旨在简化分布式应用开发,提高应用的可扩展性和可维护性。

Dubbo 主要包括以下核心功能:

  1. 远程调用: 提供高性能的远程调用协议和序列化机制。

  2. 服务治理: 包括服务自动注册、发现、路由、降级和集群容错等。

  3. 负载均衡: 支持多种负载均衡策略,例如随机、轮询、一致性哈希等。

  4. 容错机制: 提供服务降级、超时处理、失败重试等容错机制。

  5. 分布式部署: 支持分布式部署,方便构建微服务架构。

Dubbo 的架构包括服务提供者、服务消费者和注册中心。服务提供者将服务注册到注册中心,服务消费者从注册中心获取服务提供者的信息,并进行远程调用。

2. 分布式架构介绍

当集群架构的项目业务达到一定程度时,增加节点对集群性能提升的效果不明显了,此时分布式架构就体现出优势了。

分布式架构就是将一个完整的系统,按照业务功能,拆分成一个个独立的子系统。

在分布式结构中,每个子系统就被称为“服务”。这些子系统能够独立运行在web容器中,它们之间通过RPC方式通信。

分布式的优势:

  • 系统之间的耦合度大大降低,可以独立开发、独立部署、独立测试,系统与系统之间的边界非常明确,排错也变得相当容易,开发效率大大提升。
  • 系统之间的耦合度低使得系统更易于扩展。我们可以针对性地扩展某些服务。
  • 服务的复用性更高。比如,当我们将用户系统作为单独的服务后,该公司所有的产品都可以使用该系统作为用户系统,无需重复开发。

 

3. RPC 远程调用

RPC(Remote Procedure Call,远程过程调用)是一种通过网络从远程计算机上请求服务,而不需要了解底层网络细节的通信协议。

它允许像调用本地服务一样调用远程服务,使得分布式系统中的不同部分能够相互通信和协作。

在传统的本地过程调用(Local Procedure Call)中,调用过程与被调用过程在同一地址空间,它们直接共享相同的内存空间。

而在 RPC 中,调用过程和被调用过程可能运行在不同的机器上,通过网络进行通信。

RPC 的目标是让远程调用看起来像本地调用一样简单,对开发者屏蔽底层的网络通信细节。

RPC两个作用:

  • 屏蔽远程调用跟本地调用的区别,让我们感觉就是调用项目内的方法

  • 隐藏底层网络通信的复杂性,让我们更加专注业务逻辑。

常见 RPC 技术和框架:

  • 阿里的 Dubbo/Dubbox。

  • Google gRPC。

  • Spring Cloud OpenFeign。

4. Dubbo支持的协议

协议是两个网络实体进行通信的基础,数据在网络上从一个实体传输到另一个实体,以字节流的形式传递到对端。

在这个字节流的世界里,如果没有协议,就无法将这个一维的字节流重塑成为二维或者多维的数据结构以及领域对象。

Dubbo支持的协议

  • Dubbo协议

  • Hessian协议

  • HTTP协议

  • RMI协议

  • WebService协议

  • Memcached协议

  • Redis协议

推荐: 使用Dubbo协议

5. Dubbo核心组件

5.1 Registry 注册中心

在Dubbo微服务体系中,注册中心是其核心组件之一。Dubbo通过注册中心实现了分布式环境中各服务之间的注册与发现,是各个分布式节点之间的纽带。

其主要作用如下:

 

  • 动态加入:一个服务提供者通过注册中心可以动态地把自己暴露给其他消费者,无须消费者逐个去更新配置文件。
  • 动态发现:一个消费者可以动态地感知新的配置、路由规则和新的服务提供者,无须重启服务使之生效。
  • 动态调整:注册中心支持参数的动态调整,新参数自动更新到所有相关服务节点。
  • 统一配置:避免了本地配置导致每个服务的配置不一致问题。

 

常见注册发现服务

  • zookeeper

  • eureka

  • nacos

  • consul

5.2 服务提供者Provider

服务的提供方

5.3 服务消费者 Consumer

调用远程服务的服务消费方

5.4 监控中心 Monitor

主要负责监控统计调用次数和调用时间等。

5.5 工作流程

  1. 服务提供者启动过程:

    • 服务提供者启动时,会向注册中心注册自己提供的服务,包括服务接口、版本、分组等信息。

    • 注册中心收到服务提供者的注册信息后,将其存储在本地,并定期将更新的服务信息同步到其他节点。

    • 服务提供者还会定期从注册中心获取服务消费者的地址列表,以便后续的远程调用。

  2. 服务消费者启动过程:

    • 服务消费者启动时,会向注册中心订阅自己感兴趣的服务,包括服务接口、版本、分组等信息。

    • 注册中心收到服务消费者的订阅请求后,将匹配的服务提供者地址列表发送给服务消费者。

    • 服务消费者根据获取的地址列表,建立与服务提供者的连接。

  3. 远程调用过程:

    • 服务消费者根据负载均衡策略,选择一个合适的服务提供者进行远程调用。

    • 通过 RPC 协议,服务消费者将请求消息发送给服务提供者。

    • 服务提供者接收到请求消息后,解析出请求参数,然后调用本地对应的服务实现进行处理,并将结果通过 RPC 协议返回给服务消费者。

  4. 服务调用监控和管理:

    • Dubbo 支持对服务调用的性能、成功率、错误率等指标进行监控,方便管理员及时发现和解决问题。

    • Dubbo 还提供了丰富的服务治理能力,如动态配置、路由规则、限流熔断等,帮助开发者更好地管理和维护分布式系统。

  5. 服务下线和更新:

    • 当服务提供者需要下线或更新服务时,可以向注册中心发送注销或更新通知。

    • 注册中心收到通知后,会将其广播到其他节点,以便及时更新服务信息。

二、Docker高级特性

1. 序列化协议安全

由于网络传输的数据必须是二进制数据,但调用方请求的出入参数都是对象,所以需要对需要传输的数据进行序列化

2. 地址缓存

dubbo服务消费者在 第一次调用时 ,会将服务提供方地址缓存到本地 ,以后在调用则不会访问注册中心。

服务提供者地址发生变化时,注册中心会通服务消费者。

3. 超时机制

 

服务消费者在调用服务提供者的时候发生了阻塞、等待的情形,这个时候,服务消费者会一直等待下去。

 

 

在某个峰值时刻,大呈的请求都在同时请求服务消费者,会造成线程的大呈堆积,势必会造成雪崩。

 

dubbo利用超时机制来解决这个问题,设置一个超时时间,在这个时间段内,无法完成服务访问,则自动断开连接。

3.1 超时机制配置

超时时间默认1000,单位毫秒。

服务提供者配置

@Service(timeout = 3000)//3S超时 
public class UserServiceImpl implements UserService

注意这个@Service注解不是spring提供的,而是dubbo提供的,标识当前类为服务提供者,并进行暴露。

服务消费者配置

@Reference(timeout = 2000)//2s超时
private UserService userService;

@Reference注解表示远程调用,会为表标识的接口生成代理对象,然后拦截实现类的方法进行远程调用。

3.3 超时覆盖

当双方都配置了超时时间,只要一方的超时时间更短就会覆盖另一方的配置。

超时是针对消费者而言的,但是提供者、消费者都可以配置超时时间

这其实是一种策略,其实服务端的超时配置是消费端的缺省配置,即如果服务端设置了超时,任务消费端可以不设置超时时间,简化了配置。

另外针对控制的粒度,Dubbo支持了接口级别也支持方法级别,可以根据不同的实际情况精确控制每个方法的超时时间。

Dubbo的超时配置可以配置在生产者和消费者两端,但一般建议将超时时间配置在生产者端。

因为生产者端更贴近业务实现,对超时时间的把握更准确,而消费者端更多的是调用服务,超时时间可以相对宽松一些。

同时,在配置超时时间时,需要考虑方法的实际执行时间、网络延迟等因素,避免超时时间设置过短导致调用失败。

因此,一般建议将超时时间配置在生产者端,并根据实际业务情况进行调整

4. 重试机制

Dubbo在调用服务时失败默认会重试 2 次,避免因网络抖动导致请求失败。

配置:

@Service(timeout = 3000,retries = 2)

5. 多版本

5.1 灰度发布(金丝雀发布)

当出现新功能时,会让一部分用户先使用新功能,用户反馈没问题时,再将所有用户迁移到新功能。

版本迁移步骤

  1. 在低压力时间段,先升级一半提供者为新版本

  2. 再将所有消费者升级为新版本

  3. 然后将剩下的一半提供者升级为新版本

6. 负载均衡

Dubbo是一个分布式服务框架,能避免单点故障和支持服务的横向扩容。一个服务通常会部署多个实例。

6.1 Dubbo内置负载均衡策略

Dubbo内置负载均衡策略

  1. RandomLoadBalance:随机负载均衡,随机的选择一个,默认该策略。

  2. RoundRobinLoadBalance:轮询负载均衡。

  3. LeastActiveLoadBalance:最少活跃调用数,相同活跃数的随机。

  4. ConsistentHashLoadBalance:一致性哈希负载均衡,相同参数的请求总是落在同一台机器上。

6.2 负载均衡策略配置

服务提供者

@Service(version = "2.0.0",loadbalance = "roundrobin")
public class UserServiceImpl implements UserService 

服务消费者

@Reference(version = "*",loadbalance = "random")
private UserService userService;

参数:

  • random:随机负载均衡
  • leastactive:最少活跃调用数,相同活跃数的随机
  • roundrobin:轮询负载均衡
  • consistenthash:一致性哈希负载均衡

7. 集群容错

集群容错是分布式系统中的一种机制,旨在提高系统的可用性和稳定性。

在一个分布式系统中,服务通常被部署在多个节点上,当一个节点或服务出现故障时,集群容错机制能够保证系统仍能够继续工作,而不至于因为单点故障而导致整个系统的崩溃。

7.1 容错模式

容错模式

  1. Failover Cluster:失败重试。默认值。当出现失败,重试其它服务器,默认重试2次,使用retries配置。一般用于读操作

  2. Failfast Cluster : 快速失败,只发起一次调用,失败立即报错。通常用于写操作。

  3. Failsafe Cluster : 失败安全,出现异常时,直接忽略。返回一个空结果。日志不重要操作。

  4. Failback Cluster : 失败自动恢复,后台记录失败请求,定时重发。非常重要的操作。

  5. Forking Cluster:并行调用多个服务器,只要有一个成功即返回。

  6. Broadcast Cluster:广播调用所有提供者,逐个调用,任意一台报错则报错。 同步要求高的可以使用这个模式。

7.2 配置

@Service(version = "2.0.0",cluster = "failover")
public class UserServiceImpl implements UserService 

8. 服务降级

8.1 介绍

服务降级,当服务器压力剧增的情况下,根据当前业务情况及流量对一些服务和页面有策略的降级,以此释放服务器资源以保证核心任务的正常运行。

两种场景:

  • 当下游的服务因为某种原因响应过慢,下游服务主动停掉一些不太重要的业务,释放出服务器资源,增加响应速度!
  • 当下游的服务因为某种原因不可用,上游主动调用本地的一些降级逻辑,避免卡顿,迅速返回给用户

8.2 配置

消费方对该服务的方法调用都直接返回null值,不发起远程调用。用来屏蔽不重要服务不可用时对调用方的影响。

@Reference(mock = "force:return null")

消费方对该服务的方法调用在失败后,再返回null值,不抛异常。用来容忍不重要服务不稳定时对调用方的影响。

@Reference(mock = "fail:return null")

9. 服务限流

9.1 限流算法

① 漏桶算法

漏桶算法思路很简单,水(请求)先进入到漏桶里,漏桶以一定的速度出水,当水流入速度过大会直接溢出,可以看出漏桶算法能强行限制数据的传输速率。

② 令牌桶算法

令牌桶算法的原理是系统会以一个恒定的速度往桶里放入令牌,而如果请求需要被处理,则需要先从桶里获取一个令牌,当桶里没有令牌可取时,则拒绝服务。

 

9.2 漏桶 vs 令牌桶的区别

漏桶的天然特性决定了它不会发生突发流量,就算每秒1000个请求到来,那么它对后台服务输出的访问速率永远恒定。而令牌桶则不同,其特性可以“预存”一定量的令牌,因此在应对突发流量的时候可以在短时间消耗所有令牌,其突发流量处理效率会比漏桶高,但是导向后台系统的压力也会相应增多。

9.3 配置限流

① 并发控制

例:服务端并发执行(或占用线程池线程数)不能超过10个

@Service(executes = 10)

② 连接控制

占用连接的请求的数不能超过10个。

@Service(actives= 10)

Dubbo的限流算法采用了滑动窗口算法。滑动窗口算法需要存储多份计数器,每个格子存一份,因此相比计数器算法,滑动窗口算法在实现上需要更多的存储空间。如果滑动窗口的精度越高,需要的存储空间就越大。

此外,Dubbo也支持使用令牌桶算法或漏桶算法实现自定义限流Filter,并且也可以考虑分布式限流。