1、dubbo 的工作原理?
Dubbo是一款分布式服务框架,它的工作原理大致如下:
(1)服务提供方:服务提供方暴露服务,并向注册中心注册服务信息。
(2)注册中心:注册中心负责管理服务提供方的服务信息,并提供服务消费方查询服务的接口。
(3)服务消费方:服务消费方向注册中心询问服务的信息,并进行服务的调用。
(4)负载均衡:当有多个服务提供方时,Dubbo会自动进行负载均衡,使消费方请求分散到不同的服务提供方上。
(5)集群容错:Dubbo支持多种集群容错机制,例如failover、failfast等,以保证服务的高可用性。
Dubbo的工作原理是通过服务的提供方和消费方进行通信,并通过注册中心进行统一管理,从而实现分布式服务的调用。
2、注册中心挂了可以继续通信 吗?
如果注册中心挂了,Dubbo 默认是不能继续通信的,因为服务消费者和服务提供者都需要从注册中心获取对方的地址信息才能进行通信。但是,Dubbo 支持配置多个注册中心,所以当一个注册中心挂了,可以通过其他注册中心继续提供服务。 另外,Dubbo 还支持本地存储,可以将服务的地址信息存储在本地磁盘,在注册中心挂了的情况下也可以从本地磁盘中获取服务的地址信息,继续提供服务。 因此,如果需要保证 Dubbo 系统的高可用,建议设置多个注册中心,并配置本地存储。
3、一次 RPC 请求的流程包括以下几个步骤:
(1)客户端请求:客户端向服务端发送一次 RPC 请求。
(2)服务的查找与绑定:RPC 框架在本地维护一个注册中心,客户端根据请求的服务名称从注册中心获取相应的服务信息,并将该服务绑定到客户端本地。
(3)参数序列化:客户端将请求参数序列化,准备传输给服务端。
(4)网络传输:客户端通过网络将请求数据包发送到服务端。
(5)参数的反序列化:服务端接收请求,将请求数据包反序列化,获得请求参数。
(6)调用服务:服务端根据请求参数调用相应的服务方法,计算并生成响应数据。
(7)参数序列化:服务端将响应数据序列化,准备传输给客户端。
(8)网络传输:服务端通过网络将响应数据包发送到客户端。
(9)参数的反序列化:客户端接收响应数据,将响应数据包反序列化,获得响应结果。
(10)返回结果:客户端将响应结果返回给调用方
4、Dubbo 支持多种通信协议,包括:
(1)Dubbo 自定义协议:是 Dubbo 框架的默认协议,支持高效率的二进制序列化。
(2)RMI协议:是 Java 远程方法调用(Remote Method Invocation)的默认协议,基于 Java 序列化,它是一种比较通用的协议。
(3)Hessian 协议:是一种基于 HTTP 协议的二进制序列化协议,可以穿越防火墙,比较适合在不同语言间通信。
(4)HTTP 协议:是一种通用的网络传输协议,可以在不同语言间通信,但由于需要序列化和反序列化,所以效率较低。
(5)Thrift 协议:是一种由 Facebook 开发的高效的、支持多种语言的远程调用协议。
(6)Memcached 协议:是一种高效的缓存协议,适合在服务消费者和服务提供者之间进行短暂的数据交换。
Dubbo 可以通过配置的方式,选择合适的通信协议,来满足不同的需求。
5、Dubbo支持以下序列化协议:
(1)Hessian2
(2)Java
(3)JSON
(4)FastJSON
(5)Native Java
(6)FST
(7)Kryo
Hessian是一种二进制序列化协议,它支持多种数据类型的编码,包括基本类型、字符串、字节数组、日期、集合、对象等。 Hessian 对数据结构进行了优化,使得序列化后的数据尽可能地紧凑,并且易于进行反序列化。它的序列化格式简单易懂,使用的数据结构也较为简单。 Hessian 对于简单的数据类型,例如字符串、整数等,会进行缩短的编码,从而节省了序列化所需的字节数。 对于复杂的数据结构,如对象、列表等,Hessian 则使用更加复杂的编码方式。 Hessian 的编码方式灵活多样,可以根据需要自行选择最适合的编码方式,并且在支持绝大多数编程语言的前提下,使用 Hessian 实现数据的序列化和反序列化非常方便。
6、PB 知道吗?为什么 PB 的效率是最高 的?
PB (Protocol Buffers) 是一种 Google 开发的高效的、轻量级的、二进制序列化协议。PB 的效率之高的原因有以下几点:
(1)序列化和反序列化的效率比其他序列化协议高,因为它是预先生成代码,然后再编译运行,而不是在运行时进行反射,因此效率更高。
(2)PB 使用二进制格式序列化数据,相对于文本格式序列化的方式效率更高,序列化和反序列化的时间更短。
(3)PB 使用预先定义的消息模式,因此不需要额外的字节来存储字段名称,而只需要存储字段数据。
(4)PB 使用预定义的消息格式,因此在反序列化时不需要解析字段名称,只需要根据字段编号解析数据。 因此,PB 的序列化效率显然是最高的。
7、dubbo 负载均衡策略和集群容错策略都有哪些?动态代理 策略呢?
Dubbo 支持的负载均衡策略有以下几种:
(1)RandomLoadBalance:随机策略,随机选择一个服务提供者进行调用。
(2)RoundRobinLoadBalance:轮询策略,顺序选择服务提供者进行调用。
(3)LeastActiveLoadBalance:最少活跃调用策略,选择并发调用最少的服务提供者进行调用。
(4)ConsistentHashLoadBalance:一致性哈希策略,按照哈希算法选择服务提供者进行调用。
Dubbo 支持的集群容错策略有以下几种:
(1)FailoverCluster:失败自动切换,当服务提供者故障时,会自动切换到另一台服务提供者。
(2)FailfastCluster:快速失败,立即抛出异常。
(3)FailsafeCluster:失败安全,忽略错误的调用结果,继续向下执行。
(4)BroadcastCluster:广播调用,将请求广播到所有服务提供者,不管服务调用结果。
Dubbo 支持的动态代理策略有以下几种:
(1)JdkDynamicProxy:使用 JDK 动态代理实现。
(2)JavassistProxy:使用 Javassist 动态代理实现。
(3)JdkLambdaProxy:使用 JDK 8 Lambda 表达式动态代理实现。
8、dubbo spi 思想的具体体现
Dubbo的SPI(Service Provider Interface)思想是在Java技术框架中比较常见的一种设计模式,它主要用于提供扩展性和可插拔性。Dubbo通过SPI机制为各种服务提供者提供可插拔的扩展接口,用户可以根据需要扩展和替换各种服务提供者。
Dubbo的SPI体现在其内部的插件机制上。比如,Dubbo的协议实现、序列化实现、线程池实现等都是通过SPI机制实现的。在Dubbo的配置文件中,用户可以指定插件的具体实现类,如果没有指定,Dubbo会根据SPI机制选择一个默认实现类。
Dubbo的SPI机制实际上是通过Java的ServiceLoader实现的,当Dubbo启动时,它会扫描系统中所有的服务提供者,然后通过ServiceLoader加载所有的服务提供者实现类,并把它们注册到Dubbo的插件系统中。因此,如果用户想要实现自己的扩展点,可以通过实现SPI接口并使用ServiceLoader机制进行注册,然后在Dubbo的配置文件中指定该扩展点的实现类即可。
9、Java spi 思想的体现
Java SPIs (Service Provider Interfaces) 是 Java 框架中常见的一种扩展机制。它允许第三方开发者在系统内部实现扩展,并且不影响系统的核心代码。它的核心思想就是通过接口的形式来管理系统内部的扩展,可以根据系统的需要动态加载提供扩展实现的第三方插件。 Java SPIs通常在系统的META-INF/services 目录中预先定义好的接口下创建文件,该文件定义了系统内部扩展的实现类。当系统启动时,它会读取这些文件并加载对应的扩展实现。
这样的好处是,系统的核心代码可以与扩展实现进行隔离,因此扩展可以根据需要随时修改和扩展,而不影响系统的核心代码。比如jdbc接口,由各自的数据库厂商实现
10、如何基于 dubbo 进行服务治理、服务降级、失败重试以及超时重试?
Dubbo 提供了一系列服务治理功能,包括服务降级、失败重试以及超时重试等。以下是实现这些功能的具体步骤:
(1)服务降级:服务降级是指在某些情况下,阻止客户端访问服务的能力,以避免服务出现故障对系统整体造成影响。Dubbo支持配置方法级别的服务降级,可以通过使用Sentinel 或其他限流框架来实现。
(2)失败重试:失败重试是指当服务调用失败时,Dubbo 会自动重试服务调用,以提高服务的可用性。失败重试可以通过在 Dubbo 的配置文件中指定重试次数和重试间隔来实现。
(3)超时重试:超时重试是指当服务调用的时间超过预定的超时时间时,Dubbo 会自动重试服务调用。超时重试可以通过在 Dubbo 的配置文件中指定超时时间来实现。
11、分布式服务接口的幂等性如何设计(比如不能重复扣款)?
幂等性是指同一个请求多次执行的结果与一次执行的结果相同。在分布式服务中,幂等性往往是一个比较重要的问题,因为分布式环境下网络不稳定或请求重试等因素可能导致请求多次发送。
幂等性设计有以下几种方法:
(1)使用接口版本号:每次请求时附带接口版本号,服务端根据版本号进行匹配,避免请求重复处理。
(2)使用唯一请求编号:每次请求时生成一个唯一请求编号,服务端检查编号是否已经被处理过,避免请求重复处理。
(3)使用接口锁:服务端在接收到请求时,判断该接口是否已经被锁定,避免请求重复处理。
(4)使用数据库事务:通过事务的原子性,保证请求只被处理一次。
这些方法不是互斥的,实际应用中可以根据具体业务需求选择合适的方案。
需要注意的是,幂等性设计有一定的复杂度,因此需要结合业务需求和系统性能,合理地平衡误差和复杂度。
12、分布式服务接口请求的顺序性如何保证?
分布式服务接口请求的顺序性保证方案主要有以下几种:
(1)串行化处理请求:在接口服务端通过单线程或锁机制来确保请求的串行处理,从而保证请求的顺序性。
(2)序列化请求:在请求发起端把请求按照顺序加入队列中,然后在服务端依次处理队列中的请求,保证请求的顺序性。
(3)可靠消息:通过可靠消息中间件,如RabbitMQ或ApacheKafka,在发送请求前先将请求序列化,再将请求发送到消息队列中,服务端通过消息队列来接收请求并处理,保证请求的顺序性。
13、如何自己设计一个类似 Dubbo 的 RPC 框架?
举个栗子,我给大家说个最简单的回答思路: - 上来你的服务就得去注册中心注册吧,你是不是得有个注册中心,保留各个服务的信息,可以用 zookeeper 来做 - 然后你的消费者需要去注册中心拿对应的服务信息吧,而且每个服务可能会存在于多台机器上。 - 接着你就该发起一次请求了,咋发起?当然是基于动态代理了,你面向接口获取到一个动态代理,这个动态代理就是接口在本地的一个代理,然后这个代理会找到服务对应的机器地址。 - 然后找哪个机器发送请求?那肯定得有个负载均衡算法了,比如最简单的可以随机轮询 - 接着找到一台机器,就可以跟它发送请求了, 第一个问题咋发送?你可以说用 netty 了,nio 方式; 第二个问题发送啥格式数据?你可以说用 hessian 序列化协议了,或者是别的,对吧。然后请求过去了。 - 服务器那边一样的,需要针对你自己的服务生成一个动态代理,监听某个网络端口了,然后代理你本地的服务代码。接收到请求的时候,就调用对应的服务代码。
14、zk 分布式锁
zk 分布式锁,其实可以做的比较简单,就是某个节点尝试创建临时znode,此时创建成功了就获取了这个锁;这个时候别的客户端来创建锁会失败,只能注册个***监听这个锁。释放锁就是删除这个 znode,一旦释放掉就会通知客户端,然后有一个等待着的客户端就可以再次重新加锁。
15、如何做技术选型?Sentinel 还是 Hystrix?
选择 Sentinel 还是 Hystrix 主要取决于您的系统需求和特定场景。
(1)Sentinel 是阿里巴巴开源的系统流量控制和保护框架,旨在通过对流量进行细粒度的控制来保护您的微服务系统。它提供了很多实用的功能,例如流量限制、熔断、系统自我保护、热点参数限流、等等。
(2)Hystrix 是 Netflix 开源的微服务容错框架,提供了熔断、隔离、降级、资源隔离、缓存等功能,并且可以方便的监控微服务的状态。
如果您需要一个更加丰富的功能集合和细粒度的流量控制,那么您可以考虑选择 Sentinel; 如果您需要一个容错框架,并且对监控需求较强,那么 Hystrix 可能是更好的选择。最终选择哪种技术,还需要考虑您的系统需求和具体场景。