dubbo的底层原理

一、Duboo基本概念解释

Dubbo是一种分布式服务框架。 Webservice也是一种服务框架,但是webservice并不是分布式的服务框架,他需要结合F5实现负载均衡。因此,dubbo除了可以提供服务之外,还可以实现软负载均衡。它还提供了两个功能Monitor 监控中心和调用中心。这两个是可选的,需要单独配置。

Dubbo的计数架构图如下:

这里写图片描述

我们解释以下这个架构图:

Consumer服务消费者,Provider服务提供者。Container服务容器。消费当然是invoke提供者了,invoke这条实线按照图上的说明当然同步的意思了,多说一句,在实际调用过程中,Provider的位置对于Consumer来说是透明的,上一次调用服务的位置(IP地址)和下一次调用服务的位置,是不确定的。这个地方就是实现了软负载。

服务提供者先启动start,然后注册register服务。

消费订阅subscribe服务,如果没有订阅到自己想获得的服务,它会不断的尝试订阅。新的服务注册到注册中心以后,注册中心会将这些服务通过notify到消费者。

Monitor这是一个监控,图中虚线表明Consumer 和Provider通过异步的方式发送消息至Monitor,Consumer和Provider会将信息存放在本地磁盘,平均1min会发送一次信息。Monitor在整个架构中是可选的(图中的虚线并不是可选的意思),Monitor功能需要单独配置,不配置或者配置以后,Monitor挂掉并不会影响服务的调用。

二、dubbo原理

本篇博客的内容总体上比较抽象,如果一个想马上使用dubbo的同学来说,读这篇博客效果不太好,本篇博客没有写怎么使用、配置dubbo,接下来,我再令写一篇dubbo入门包含demo的博客。

I、初始化过程细节:
上图中的第一步start,就是将服务装载容器中,然后准备注册服务。和Spring中启动过程类似,spring启动时,将bean装载进容器中的时候,首先要解析bean。所以dubbo也是先读配置文件解析服务。
解析服务:
1)、基于dubbo.jar内的Meta-inf/spring.handlers配置,spring在遇到dubbo名称空间时,会回调DubboNamespaceHandler类。
2)、所有的dubbo标签,都统一用DubboBeanDefinitionParser进行解析,基于一对一属性映射,将XML标签解析为Bean对象。
源码截图:
在ServiceConfig.export 或者ReferenceConfig.get 初始化时,将Bean对象转会为url格式,将所以Bean属性转成url的参数。
然后将URL传给Protocol扩展点,基于扩展点的Adaptive机制,根据URL的协议头,进行不同协议的服务暴露和引用。
暴露服务:

a、 只暴露服务端口

在没有使用注册中心的情况,这种情况一般适用在开发环境下,服务的调用这和提供在同一个IP上,只需要打开服务的端口即可。
即,当配置 or
ServiceConfig解析出的URL的格式为:
Dubbo://service-host/com.xxx.TxxService?version=1.0.0
基于扩展点的Adaptiver机制,通过URL的“dubbo://”协议头识别,直接调用DubboProtocol的export()方法,打开服务端口。

b、向注册中心暴露服务:

和上一种的区别:需要将服务的IP和端口一同暴露给注册中心。
ServiceConfig解析出的url格式为:
registry://registry-host/com.alibaba.dubbo.registry.RegistryService?export=URL.encode(“dubbo://service-host/com.xxx.TxxService?version=1.0.0”)

基于扩展点的Adaptive机制,通过URL的“registry://”协议头识别,调用RegistryProtocol的export方法,将export参数中的提供者URL先注册到注册中心,再重新传给Protocol扩展点进行暴露:
Dubbo://service-host/com.xxx.TxxService?version=1.0.0

引用服务:

a、直接引用服务:

在没有注册中心的,直连提供者情况下,
ReferenceConfig解析出的URL格式为:
Dubbo://service-host/com.xxx.TxxService?version=1.0.0

基于扩展点的Adaptive机制,通过url的“dubbo://”协议头识别,直接调用DubboProtocol的refer方法,返回提供者引用。

b、从注册中心发现引用服务:

此时,ReferenceConfig解析出的URL的格式为:
registry://registry-host/com.alibaba.dubbo.registry.RegistryService?refer=URL.encode(“consumer://consumer-host/com.foo.FooService?version=1.0.0”)

基于扩展点的Apaptive机制,通过URL的“registry://”协议头识别,就会调用RegistryProtocol的refer方法,基于refer参数总的条件,查询提供者URL,如:
Dubbo://service-host/com.xxx.TxxService?version=1.0.0

基于扩展点的Adaptive机制,通过提供者URL的“dubbo://”协议头识别,就会调用DubboProtocol的refer()方法,得到提供者引用。
然后RegistryProtocol将多个提供者引用,通过Cluster扩展点,伪装成单个提供这引用返回。

三、远程调用细节:

服务提供者暴露一个服务的详细过程:

这里写图片描述

上图是服务提供者暴露服务的主过程:
首先ServiceConfig类拿到对外提供服务的实际类ref,然后将ProxyFactory类的getInvoker方法使用ref生成一个AbstractProxyInvoker实例,到这一步就完成具体服务到invoker的转化。接下来就是Invoker转换到Exporter的过程。
Dubbo处理服务暴露的关键就在Invoker转换到Exporter的过程,下面我们以Dubbo和rmi这两种典型协议的实现来进行说明:
Dubbo的实现:
Dubbo协议的Invoker转为Exporter发生在DubboProtocol类的export方法,它主要是打开socket侦听服务,并接收客户端发来的各种请求,通讯细节由dubbo自己实现。
Rmi的实现:
RMI协议的Invoker转为Exporter发生在RmiProtocol类的export方法,他通过Spring或Dubbo或JDK来实现服务,通讯细节由JDK底层来实现。

服务消费者消费一个服务的详细过程

这里写图片描述

上图是服务消费的主过程:
首先ReferenceConfig类的init方法调用Protocol的refer方法生成Invoker实例。接下来把Invoker转为客户端需要的接口即可。



### Dubbo底层通信协议实现原理 Dubbo 是一个高性能的 Java 分布式服务框架,其核心功能之一是通过自定义的 RPC 协议实现远程过程调用。以下是关于 Dubbo 底层通信协议的具体实现原理: #### 1. 自定义 Dubbo RPC 协议 Dubbo 使用了一种基于 TCP/IP 的自定义二进制协议来完成服务间的通信[^1]。这种协议的设计目标是为了提高传输效率并减少网络开销。具体而言,Dubbo 协议的消息结构通常由以下几个部分组成: - **魔数 (Magic Number)**:用于标识这是一个 Dubbo 协议的数据包。 - **序列化方式**:指定消息体使用的序列化算法(如 Hessian、Kryo 或 Protobuf)。 - **标志位**:表示该消息是否为请求/响应以及是否有异常发生等状态信息。 - **数据长度**:指示后续实际负载数据的字节大小。 - **正文内容**:包含具体的业务参数或返回值。 这些字段共同构成了 Dubbo 数据帧的标准格式,从而使得两端能够高效解析彼此间交换的信息。 #### 2. 基于 Socket 的消息传递机制 在 Dubbo 中,所有的请求与应答均依赖底层的 Socket 进行传输[^3]。当消费者发起一次远端方法调用时,它会先构建好对应的 Request 对象并通过网络将其打包成上述提到的那种标准化形式发送出去;与此同时,在另一侧提供者监听到来自外部连接之后,则负责解码传入流中的原始比特串还原成为可操作的对象实例供本地逻辑进一步处理完毕后再按照相同流程反向构造 Response 并且回馈回去形成闭环交互模式。 值得注意的是,尽管整个 I/O 操作看似同步执行但实际上由于采用了 Netty/Mina 等 NIO 技术库作为支撑所以本质上还是属于非阻塞型设计——这意味着即使是在等待对方回复期间也不会占用过多计算资源而是交还控制权给事件循环继续处理其他任务直到真正获取到最终结果为止才会重新激活关联上下文恢复原有链条上的下一步动作。 #### 3. 异步回调模型 正如前面所描述那样,一旦某个线程完成了初始阶段的任务即将携带必要元数据封装好的指令提交至输出缓冲区后即可立即释放不再关心后续进展如何因为真正的反馈将会被专门分配出来的工作者池接管下来单独运行直至结束才把成果交付回原来位置处以便应用程序层面可以正常接收利用。这样的架构极大提升了系统的吞吐能力和并发性能尤其适用于大规模集群环境下频繁发生的跨节点通讯场景之中表现尤为突出显著优于传统单一线性顺序作业的方式。 ```java // 示例代码展示了一个简单的 Dubbo 客户端和服务端之间的交互过程 public class SimpleDubboExample { public static void main(String[] args) throws Exception { // 创建 Dubbo 配置对象... ReferenceConfig<GreetingService> reference = new ReferenceConfig<>(); reference.setInterface(GreetingService.class); GreetingService greetingService = reference.get(); String message = greetingService.sayHello("World"); System.out.println(message); // 输出服务器返回的内容 // ...省略更多配置细节 } } ``` 以上就是有关 Dubbo 如何在其内部达成高效的远程调用背后隐藏的技术秘密概述说明版本啦! ---
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

maple 枫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值