高级程序员知识学习(Dubbo相关知识)

Dubbo 是一款高性能、轻量级的开源 RPC 框架,提供服务自动注册、自动发现等高效服务治理方案,。

RPC的原理及组成

https://img-blog.csdnimg.cn/20200128141852699.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly90aGlua3dvbi5ibG9nLmNzZG4ubmV0,size_16,color_FFFFFF,t_70

Provider:暴露服务的服务提供方

Consumer:调用远程服务消费方

Registry:服务注册与发现注册中心

Monitor:监控中心和访问调用统计

Container:服务运行容器

Dubbo 和 Spring Cloud 有什么哪些区别?

Dubbo 底层是使用 Netty 这样的 NIO 框架,是基于 TCP 协议传输的,配合以 Hession 序列化完成 RPC 通信。

Spring Cloud 是基于 Http 协议 Rest 接口调用远程过程的通信,相对来说 Http 请求会有更大的报文,占的带宽也会更多。但是 REST 相比 RPC 更为灵活,服务提供方和调用方的依赖只依靠一纸契约,不存在代码级别的强依赖,这在强调快速演化的微服务环境下,显得更为合适,至于注重通信速度还是方便灵活性,具体情况具体考虑。

Dubbo 有哪些注册中心?

    Multicast 注册中心:Multicast 注册中心不需要任何中心节点,只要广播地址,就能进行服务注册和发现,基于网络中组播传输实现。

    Zookeeper 注册中心:基于分布式协调系统 Zookeeper 实现,采用 Zookeeper 的 watch 机制实现数据变更。

    Redis 注册中心:基于 Redis 实现,采用 key/map 存储,key 存储服务名和类型,map 中 key 存储服务 url,value 服务过期时间。基于 Redis 的发布/订阅模式通知数据变更。

Simple 注册中心。

推荐使用 Zookeeper 作为注册中心

Dubbo 的注册中心集群挂掉,发布者和订阅者之间还能通信么?

可以通讯。启动 Dubbo 时,消费者会从 Zookeeper 拉取注册的生产者的地址接口等数据,缓存在本地。每次调用时,按照本地存储的地址进行调用。

Dubbo的服务和路由策略

Dubbo是一个分布式服务框架,能避免单点故障和支持服务的横向扩容。一个服务通常会部署多个实例。如何从多个服务 Provider 组成的集群中挑选出一个进行调用,就涉及到一个负载均衡的策略

有一个Dubbo的用户服务,在北京部署了10个,在上海部署了20个。一个杭州的服务消费方发起了一次调用,然后发生了以下的事情:

    根据配置的路由规则,如果杭州发起的调用,会路由到比较近的上海的20个 Provider。

    根据配置的随机负载均衡策略,在20个 Provider 中随机选择了一个来调用,假设随机到了第7个 Provider。

    结果调用第7个 Provider 失败了。

    根据配置的Failover集群容错模式,重试其他服务器。

    重试了第13个 Provider,调用成功。

上面的第1,2,4步骤就分别对应了路由,负载均衡和集群容错。 Dubbo中,先通过路由,从多个 Provider 中按照路由规则,选出一个子集。再根据负载均衡从子集中选出一个 Provider 进行本次调用。如果调用失败了,根据集群容错策略,进行重试或定时重发或快速失败等。 可以看到Dubbo中的路由,负载均衡和集群容错发生在一次RPC调用的不同阶段。最先是路由,然后是负载均衡,最后是集群容错。 本文档只讨论负载均衡,路由和集群容错在其他的文档中进行说明。

Dubbo内置了4种负载均衡策略:

RandomLoadBalance:随机负载均衡。随机的选择一个。是Dubbo的默认负载均衡策略。

RoundRobinLoadBalance:轮询负载均衡。轮询选择一个。

LeastActiveLoadBalance:最少活跃调用数,相同活跃数的随机。活跃数指调用前后计数差。使慢的 Provider 收到更少请求,因为越慢的 Provider 的调用前后计数差会越大。

ConsistentHashLoadBalance:一致性哈希负载均衡。相同参数的请求总落在同一台机器上使用一致性 Hash 算法,让相同参数的请求总是发到同一 Provider。当某一台 Provider 崩溃时,原本发往该 Provider 的请求,基于虚拟节点,平摊到其它 Provider,不会引起剧烈变动。Dubbo的4种负载均衡的实现,大多数情况下能满足要求。有时候,因为业务的需要,我们可能需要实现自己的负载均衡策略。

注意RPC的负载均衡实在client端实现的,而不是在zk实现的。

Dubbo SPI 和 Java SPI 区别?

JDK SPI:

JDK 标准的 SPI 会一次性加载所有的扩展实现,如果有的扩展很耗时,但也没用上,很浪费资源。所以只希望加载某个的实现,就不现实了

DUBBO SPI:

1、对 Dubbo 进行扩展,不需要改动 Dubbo 的源码

2、延迟加载,可以一次只加载自己想要加载的扩展实现。

3、增加了对扩展点 IOC 和 AOP 的支持,一个扩展点可以直接 setter 注入其

它扩展点。

4、Dubbo 的扩展机制能很好的支持第三方 IoC 容器,默认支持 Spring Bean

Dubbo的设计模式

Dubbo 用到哪些设计模式?

Dubbo 框架在初始化和通信过程中使用了多种设计模式,可灵活控制类加载、权限控制等功能。

工厂模式

Provider 在 export 服务时,会调用 ServiceConfig 的 export 方法。ServiceConfig中有个字段:

private static final Protocol protocol =

ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtensi

on();

Dubbo 里有很多这种代码。这也是一种工厂模式,只是实现类的获取采用了 JDKSPI 的机制。这么实现的优点是可扩展性强,想要扩展实现,只需要在 classpath下增加个文件就可以了,代码零侵入。另外,像上面的 Adaptive 实现,可以做到调用时动态决定调用哪个实现,但是由于这种实现采用了动态代理,会造成代码调试比较麻烦,需要分析出实际调用的实现类。

装饰器模式

Dubbo 在启动和调用阶段都大量使用了装饰器模式。以 Provider 提供的调用链为例,具体的调用链代码是在 ProtocolFilterWrapper 的 buildInvokerChain 完成的,具体是将注解中含有 group=provider 的 Filter 实现,按照 order 排序,最后的调用顺序是:

EchoFilter -> ClassLoaderFilter -> GenericFilter -> ContextFilter ->

ExecuteLimitFilter -> TraceFilter -> TimeoutFilter -> MonitorFilter ->

ExceptionFilter

更确切地说,这里是装饰器和责任链模式的混合使用。例如,EchoFilter 的作用是判断是否是回声测试请求,是的话直接返回内容,这是一种责任链的体现。而像ClassLoaderFilter 则只是在主功能上添加了功能,更改当前线程的 ClassLoader,这是典型的装饰器模式。

RPC的关键技术

1、动态代理

生成Client Stub(客户端存根)和Server Stub(服务端存根)的时候需要用到Java动态代理技术,可以使用JDK提供的原生的动态代理机制,也可以使用开源的:CGLib代理,Javassist字节码生成技术。

2、序列化和反序列化

在网络中,所有的数据都将会被转化为字节进行传送,所以为了能够使参数对象在网络中进行传输,需要对这些参数进行序列化和反序列化操作。

    序列化:把对象转换为字节序列的过程称为对象的序列化,也就是编码的过程。

    反序列化:把字节序列恢复为对象的过程称为对象的反序列化,也就是解码的过程。

目前比较高效的开源序列化框架:如Kryo、FastJson和Protobuf等。

3、NIO通信

出于并发性能的考虑,传统的阻塞式 IO 显然不太合适,因此我们需要异步的 IO,即 NIO。Java 提供了 NIO 的解决方案,Java 7 也提供了更优秀的 NIO.2 支持。可以选择Netty或者MINA来解决NIO数据传输的问题。

4、服务注册中心

可选:Redis、Zookeeper、Consul 、Etcd。一般使用ZooKeeper提供服务注册与发现功能,解决单点故障以及分布式部署的问题(注册中心)。

Dubbo 使用的是什么通信框架?

默认使用 Netty 作为通讯框架。

Dubbo 支持哪些协议,它们的优缺点有哪些?

    Dubbo: 单一长连接和 NIO 异步通讯,适合大并发小数据量的服务调用,以及消费者远大于提供者。传输协议 TCP,异步 Hessian 序列化。Dubbo推荐使用dubbo协议。

    RMI: 采用 JDK 标准的 RMI 协议实现,传输参数和返回参数对象需要实现 Serializable 接口,使用 Java 标准序列化机制,使用阻塞式短连接,传输数据包大小混合,消费者和提供者个数差不多,可传文件,传输协议 TCP。 多个短连接 TCP 协议传输,同步传输,适用常规的远程服务调用和 RMI 互操作。在依赖低版本的 Common-Collections 包,Java 序列化存在安全漏洞。

    WebService:基于 WebService 的远程调用协议,集成 CXF 实现,提供和原生 WebService 的互操作。多个短连接,基于 HTTP 传输,同步传输,适用系统集成和跨语言调用。

    HTTP: 基于 Http 表单提交的远程调用协议,使用 Spring 的 HttpInvoke 实现。多个短连接,传输协议 HTTP,传入参数大小混合,提供者个数多于消费者,需要给应用程序和浏览器 JS 调用。

    Hessian:集成 Hessian 服务,基于 HTTP 通讯,采用 Servlet 暴露服务,Dubbo 内嵌 Jetty 作为服务器时默认实现,提供与 Hession 服务互操作。多个短连接,同步 HTTP 传输,Hessian 序列化,传入参数较大,提供者大于消费者,提供者压力较大,可传文件。

    Memcache:基于 Memcache实现的 RPC 协议。

    Redis:基于 Redis 实现的RPC协议。

Dubbo 支持分布式事务吗?

目前暂时不支持,可与通过 tcc-transaction 框架实现

介绍:tcc-transaction 是开源的 TCC 补偿性分布式事务框架

TCC-Transaction 通过 Dubbo 隐式传参的功能,避免自己对业务代码的入侵。

Dubbo 可以对结果进行缓存吗?

为了提高数据访问的速度。Dubbo 提供了声明式缓存,以减少用户加缓存的工作量<dubbo:reference cache=“true” />

其实比普通的配置文件就多了一个标签 cache=“true”

Dubbo 必须依赖的包有哪些?

Dubbo 必须依赖 JDK,其他为可选。

Dubbo 支持哪些序列化方式?

默认使用 Hessian 序列化,还有 Duddo、FastJson、Java 自带序列化。

Dubbo 在安全方面有哪些措施?

    Dubbo 通过 Token 令牌防止用户绕过注册中心直连,然后在注册中心上管理授权。

    Dubbo 还提供服务黑白名单,来控制服务所允许的调用方。

服务调用是阻塞的吗?

默认是阻塞的,可以异步调用,没有返回值的可以这么做。Dubbo 是基于 NIO 的非阻塞实现并行调用,客户端不需要启动多线程即可完成并行调用多个远程服务,相对多线程开销较小,异步调用会返回一个 Future 对象。

服务提供者能实现失效踢出是什么原理?

服务失效踢出基于 zookeeper 的临时节点原理。

同一个服务多个注册的情况下可以直连某一个服务吗?

可以点对点直连,修改配置即可,也可以通过 telnet 直接某个服务。

Dubbo 服务降级,失败重试怎么做?

可以通过 dubbo:reference 中设置 mock=“return null”。mock 的值也可以修改为 true,然后再跟接口同一个路径下实现一个 Mock 类,命名规则是 “接口名称+Mock” 后缀。然后在 Mock 类里实现自己的降级逻辑

Dubbo 使用过程中都遇到了些什么问题?

在注册中心找不到对应的服务,检查 service 实现类是否添加了@service 注解无法连接到注册中心,检查配置文件中的对应的测试 ip 是否正确。

猜你喜欢

转载自blog.csdn.net/weixin_41605937/article/details/106002879