dubbo分层,rpc和http区别,dubbo的服务暴露
RPC 就是 Remote Procedure Call,远程过程调用
1、和http的区别
HTTP 只是应用层的传输协议,协议只是规范了一定的交流格式。http相当于国际通用方案,因为通用所以信息臃肿。
- 大量的HTTP头等信息。
- 其次是效率低,还是因为第七层的缘故,必须按照HTTP协议进行层层封装。
RPC是一个完整的远程调用方案,它包括了:接口规范+序列化反序列化规范+通信协议。RPC相当于定制协议,
2、dubbo的分层和各层的作用
大的三层分别为 Business(业务层)、RPC 层、Remoting(远程调用层),并且还分为 API 层和 SPI 层。
分为大三层其实就是和我们知道的网络分层一样的意思,只有层次分明,职责边界清晰才能更好的扩展。
而分 API 层和 SPI 层这是 Dubbo 成功的一点,采用微内核设计+SPI扩展,使得有特殊需求的接入方可以自定义扩展,做定制的二次开发。
接下来咱们再来看看每一层都是干嘛的。
-
Service,业务层,就是咱们开发的业务逻辑层。
-
Config,配置层,主要围绕 ServiceConfig 和 ReferenceConfig,初始化配置信息。
-
Proxy,代理层,服务提供者还是消费者都会生成一个代理类(javassist动态代理),使得服务接口透明化,代理层做远程调用和返回结果。
-
Register,注册层,封装了服务注册和发现。
-
Cluster,路由和集群容错层,负责选取具体调用的节点,处理特殊的调用要求和负责远程调用失败的容错措施。
-
Monitor,监控层,负责监控统计调用时间和次数。
-
Portocol,远程调用层,主要是封装 RPC 调用,主要负责管理 Invoker,Invoker代表一个抽象封装了的执行体,之后再做详解。
-
Exchange,信息交换层,用来封装请求响应模型,同步转异步(通过futuer.get()),每个request都要一个id,response就是通过id去找对应的结果
-
Transport,网络传输层,抽象了网络传输的统一接口,这样用户想用 Netty 就用 Netty,想用 Mina 就用 Mina。
-
Serialize,序列化层,将数据序列化成二进制流,当然也做反序列化。
3、dubbo的服务暴露
a、首先dubbo是采用 URL 的方式来作为约定的参数类型,被称为公共契约
protocol://username:password@host:port/path?key=value&key=value
URL 具体的参数如下:
- protocol:指的是 dubbo 中的各种协议,如:dubbo thrift http
- username/password:用户名/密码
- host/port:主机/端口
- path:接口的名称
- parameters:参数键值对
b、利用Spring扫描配置文件了生成 Spring 的 BeanDefinition,然后利用 Spring 最终创建对应的对象。
c、时机:服务的暴露起始于 Spring IOC 容器刷新完毕之后,会根据配置参数组装成 URL, 然后根据 URL 的参数来进行本地或者远程调用
d、再利用 Dubbo SPI 机制根据 URL 的参数选择对应的实现类,实现扩展
e、通过 javassist 动态封装 ref (你写的服务实现类),统一暴露出 Invoker 使得调用方便,屏蔽底层实现细节,然后封装成 exporter 存储起来,等待消费者的调用,并且会将 URL 注册到注册中心,使得消费者可以获取服务提供者的信息。
参考:https://mp.weixin.qq.com/s/ISiN06QynyE2pPtX3cGQ9w
https://mp.weixin.qq.com/s/ISiN06QynyE2pPtX3cGQ9w
4、服务的引入
和服务暴露,在 Spring 容器刷新完成之后开始暴露,而服务的引入时机有两种,第一种是饿汉式,第二种是懒汉式
饿汉式是通过实现 Spring 的InitializingBean
接口中的 afterPropertiesSet
方法,容器通过调用 ReferenceBean
的 afterPropertiesSet
方法时引入服务。
懒汉式是只有当这个服务被注入到其他类中时启动引入流程,也就是说用到了才会开始服务引入。
默认情况下,Dubbo 使用懒汉式引入服务,如果需要使用饿汉式,可通过配置 dubbo:reference 的 init 属性开启。
a、服务引入的3中模式---本地引入,直接远程引入,注册中心引入
直连远程引入服务,这个其实就是平日测试的情况下用用,不需要启动注册中心,由 Consumer 直接配置写死 Provider 的地址,然后直连即可。
注册中心引入远程服务,这个就是重点了,Consumer 通过注册中心得知 Provider 的相关信息,然后进行服务的引入,这里还包括多注册中心,同一个服务多个提供者的情况,如何抉择如何封装,如何进行负载均衡、容错并且让使用者无感知,这就是个技术活。
流程:
1、简述一下就是先检查配置,通过配置构建一个 map ,然后利用 map 来构建 URL ,再通过 URL 上的协议利用自适应扩展机制调用对应的 protocol.refer 得到相应的 invoker 。
2、判断到底是本地调用、远程调用、还是注册中心调用。如果是注册中心,订阅注册中心相关信息,得到远程 provider
的 ip 等信息,再通过netty
客户端进行连接。
2、然后再构建代理,封装 invoker 返回服务引用,之后 Comsumer 调用的就是这个代理类。
4、服务的调用过程
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)