1. 分布式架构基本背景
随着互联网的发展,网站应用的规模不断扩大,单一机器性能无法应对,需要实现分布式服务结构来保证业务的正常运作
分布式架构:在分布式数据系统中,用户感觉不数据是分布的,即用户不须知道关系是否分割,有无副本,数据存在于那个站点以及事物在哪个站点上执行。对用户来说,分布式架构和单体架构他们是感受不到的
假设原来我们有一个单体系统,原本代码之间都是直接基于Spring框架走JVM内存调用,现在拆分为分布式架构,将系统拆分为n个小系统部署在不同的机器上,然后基于分布式服务框架(比如dubbo)搞进行rpc调用,接口与接口之间通过网络通信进行请求和响应。
分布式系统之间最重要的特点就是服务间要跨网络进行调用
2. Dubbo的基础知识
2.1. 基础介绍
Dubbo是阿里巴巴公司开源的一个高性能优秀的服务框架,使得应用可通过高性能的RPC实现服务的输出和输入功能,可以和Spring框架进行集成。
Dubbo是一款高性能、轻量级的开源Java RPC框架,它提供了三大核心能力:
- 面向接口的远程方法调用:网络通信框架,提供对多种NIO框架抽象封装,包括“同步转异步”和“请求-响应”模式的信息交换方式
- 智能容错和负载均衡:提供基于接口方法的透明远程过程调用,包括多协议支持,以及软负载均衡,失败容错,地址路由,动态配置等集群支持
- 以及服务自动注册和发现:服务注册,基于注册中心目录服务,使服务消费方能动态的查找服务提供方,使地址透明,使服务提供方可以平滑增加或减少机器。
2.2. 各个成分作用
1)注册中心
生产者在这注册并发布内容 消费者订阅并接收发布的内容
2)消费者
消费者来自客户端,他从注册中心获取到方法,可以调用生产者中的方法。
3)生产者(provider)
来自服务端,生产内容,在SpringBoot中,如果容器还没有初始化成功,便无法提供服务,因此生产前需要先启动容器。
4)容器(container)
生产者在启动执行的时候,必须依赖容器才能正常启动(默认依赖的是spring容器)
5)监控(Monitor)
统计服务的调用次数与时间等,这里可以通过调用次数频率设置一些限流操作等
2.3. 流程
调用流程:
- 服务容器负责启动,加载,运行服务提供者。
- 服务提供者在启动时,向注册中心注册自己提供的服务。
- 服务消费者在启动时,向注册中心订阅自己所需的服务。
- 注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。
这里使用长连接感知服务提供者的存在,服务提供者宕机,注册中心将立即推送事件通知消费者。服务提供者本身是无状态的,任意一台宕掉后,不影响使用。如果全部宕机了,那么消费者就无限重连等待提供者恢复。实际上消费者本身也有缓存机制,会缓存调用过的提供者列表
- 服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。
- 服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。
3. Dubbo架构设计(进阶深入)
3.1. 架构流程
整体架构图如下
图中从下至上分为十层,各层均为单向依赖,右边的黑色箭头代表层之间的依赖关系,每一层都可以剥离上层被复用
Dubbo的整体架构分为十层,具体十层的作用可以看下面这篇文章
总结下来可以大致分为以下步骤
- 服务提供者启动,开启Netty服务,创建Zookeeper客户端,向注册中心注册服务。
- 服务消费者启动,通过Zookeeper向注册中心获取服务提供者列表,与服务提供者通过Netty建立长连接。
- 服务消费者通过接口开始远程调用服务,ProxyFactory通过初始化Proxy对象,Proxy通过创建动态代理对象。
- 动态代理对象通过invoke方法,层层包装生成一个Invoker对象,该对象包含了代理对象。
- Invoker通过路由,负载均衡选择了一个最合适的服务提供者,在通过加入各种过滤器,协议层包装生成一个新的DubboInvoker对象。
- 再通过交换成将DubboInvoker对象包装成一个Reuqest对象,该对象通过序列化通过NettyClient传输到服务提供者的NettyServer端。
- 到了服务提供者这边,再通过反序列化、协议解密等操作生成一个DubboExporter对象,再层层传递处理,会生成一个服务提供端的Invoker对象.
- 这个Invoker对象会调用本地服务,获得结果再通过层层回调返回到服务消费者,服务消费者拿到结果后,再解析获得最终结果
说到底就是一个提供者暴露和消费者消费的过程
3.2. 提供者暴露
- 服务通过ref生成一个AbstractProxyInvoker实例,这一步是Dubbo的核心
主要有以下好处:
AbstractProxyInvoker作为Invoker的实现,可以适配不同的协议和传输方式,使得服务实现可以以一种统一的方式暴露给不同的客户端- 通过将服务实现封装为
Invoker,Dubbo框架可以在不同的协议和传输方式之间切换,而不需要修改服务实现本身 - 在
AbstractProxyInvoker中,可以集成各种服务治理和扩展功能,如负载均衡、限流、熔断等。这些功能可以在Invoker的调用过程中被触发和执行,从而实现对服务调用的精细控制。
3.3. 消费者消费
通过上面的学习,我发现最重要的就是这个Invoker封装,Dubbo的核心就是这个Invoker,消费者要调用服务者就要去传入相关配置信息完善一个Invoker对象,通过Invoker对象来调用提供者
3.4. 心得总结
个人认为,这些中间件本质上都是辅助我们完成任务的工具。使用这些工具并非难事,然而,对于优秀程序员来说,深入了解工具背后的运作原理,才是提升问题解决能力和工作效率的关键。以SQL调优为例,如果我们缺乏索引相关的知识,不了解索引在什么情况下可能失效,或者不清楚左连接、右连接、内连接等具体操作背后的逻辑,又怎么进行SQL调优。这些原理性的知识是我们在面对性能问题或错误时,能够迅速定位并解决问题的基石。
因此,当我们在使用各种中间件或工具时,不妨多花一些时间去学习它们背后的原理。这样,在未来的某一天,当某个bug突然出现时,我们就能够凭借对原理的深刻理解,一眼看出问题的所在,并迅速解决它
4. 本次学习参考相关文章
将近2万字的Dubbo原理解析,彻底搞懂dubbo-阿里云开发者社区