Dubbo的工作原理
服务容器启动的时候,加载,运行服务提供者,根据服务提供者的配置信息,通过main函数的完成spring的初始化,
并根据配置的协议规则等信息,完成服务的初始化
服务提供者启动时,连接注册中心地址将自己注册服务注册到注册中心
服务消费者启动时,也会连接注册中心,向注册中心订阅自己需要的服务
注册中心根据订阅关系,返回给消费者需要的服务提供者列表。如果注册中心变更,回基于长连接推送最新列表
服务消费者在远程调用时,从本地缓存的地址列表,随机一台,发起调用。根据请求协议规则,跨进程调用提供者。
这时如果发生故障,发生故障转移
服务提供者和消费者的,调用次数,调用时间,有监控中心记录
Dubbo的实现原理
利用微内核+插件。利用spi机制实现各个层的扩展。Dubbo天生就具有极强的灵活的拓展性。采用url这个参数的信息,根据参数自适用目标类
除了service和config层部署基于spi,其他都是。
分为10各层
服务层:最上面接口层,业务实现
配置层:发布服务,引用服务
代理层(调用,扩展点),注册层,监控层,信息交换层(Exchange):同步转异步
远程调用层(Protocol)、扩展接口为 Protocol、Invoker 和 Exporter。Protocol 是服务域
网络传输层(Transport):抽象mina和netty,以 Message 为中心,扩展接口为 Channel、Transporter、Client、Server 和 Codec。
数据序列化层(Serialize):可复用的一些工具,扩展接口为 Serialization、 ObjectInput、ObjectOutput和ThreadPool。
Dubbo扩展机制spi
可扩展的体现:框架的功能增加时,不需要修改原来的代码,只需要增加代码。符合开闭原则
框架的使用者,在添加某些功能时,不需要修改框架的代码,只需要改自己的代码就行
主要是:Dubbo的微内核+插件的机制
基于:factory模式
ioc容器
osgi容器
不依赖其他容器。参考了java的spi机制。dubbo利用jdk的内置spi实现的扩展
java的spi jdk内置的扩展机制
定义接口,在classpath路径下定义与接口名一样的文件。文件里面配置实现类,JDK通过java.util.ServiceLoader这个类加载扩展的接口
java的spi的不足
不提供依赖注入
不提供spring能力的功能(ioc apo),难以扩展bean
适合简单场景
dubbo对原生SPI机制进行了一些扩展
名词术语:
扩展点(Extension Point): 是一个Java的接口。
扩展(Extension):扩展点的实现类。
扩展实例(Extension Instance)
扩展点实现类的实例:实现类的一代理
扩展自适应实例(Extension Adaptive Instance):可以称为扩展点实现类的代理类。当接口有多个实现的时候,可以运行时,根据参数,可以自 应的调用相应的实现了类。
dubbo的配置:(系统配置)一种是启动dubbo后就不会改变的:比如:超时时间
(运行时加载): 针对某一次的RPC调用,可以设置它的超时时间是30秒钟,以覆盖系统级别的配置。对于Dubbo而言,每一次的RPC调用的参数都是未知的。只有在运行时,根据这些参数才能做出正确的决定的执行。
dubbo使用rpc调用时,调用参数未知,运行时才知道,所以,扩展点有多个实例,在运行时获取参数时才知道要调用的哪个实例, 这时候就需要一个代理模式了,它实现了扩展点接口,方法内部可以根据运行时参数,动态的选择合适的扩展实现。而这个代理就是自适应实例
学习dubbo的LoadBalance扩展点 @SPI(RandomLoadBalance.NAME)
注解: @SPI 用于声明接口是个扩展点,使用ExtentionLoade加载 @Adaptive声明接口方法是自适应,根据参数调用子类实现
扩展别名 :给接口扩展点起的别名 一些路径:扩展的配置文件
@SPI(RandomLoadBalance.NAME)
public interface LoadBalance {
@Adaptive("loadbalance")
}
表示接口是扩展点,扩展别名是里面的值
@Adaptive("loadbalance") 该接口方法是自适应调用实现。根据接口中的入参参数loadBalance字段值作为自适用条件。根据url参数里面的这个字段
我们如何定义扩展点
定义一个类实现扩展点接口,实现扩展方法,
扩展点配置文件添加实现类
dubbo的集群容错
说的是利用dubbo进行rpc调用的服务出问题了,怎么办的
failover 故障转移,失败了,重试其他机器
failfase 失败,立刻响应失败。通常用于非幂等性的写操作
failSafe 失败安全,失败了忽略 用于日志记录
Failback 失败自动恢复,失败了继续重试,用于消息通知
dubbo的通讯协议
通过bean可以知道他调用:GrizzlyTransporter,MinaTransporter,NettyTransporter。
就是创建了netty的server嘛
Protocol接口查找通讯协议入口点,从写入参数的 URL中获取通讯服务的信息,进行server的创建。通讯默认是Netty
dubbo的远程通讯
利用miny或者netty
服务调用者调用服务提供者:
服务提供者:有一个监控线程,监控线程通过selector组件发送监控网络事件,selectSocketChannnel监控端口号,监控着连接服务提供的请求。
当前发现有请求过来,网络事件会新建socketChannel建立连接,相应的selector的组件对应的处理线程会处理解析请求。之后通过代理模式进行请求业务处理。返回结果
相应:提供者将结果通过socketChannel封装,返回到调用者这里。调用者也有自己的监控线程监控谁连接自己。建立连接 ,通过监控线程处理相应结果。同提供者的
netty的实现
基于Nio非阻塞io实现通讯的。NIO的实现,基于socket建立服务器连接。客户端建立连接到服务端利用io多路复用,io多路复用是通过Reactor(反应器)模式实现的。
io多路复用:
利用一个监听线程监听客户端连接的状态,达到就绪状态,通过select和poll函数,将多个socket传入,运行socket,并将socket交由事件发分器进行分发给不同的事件处理器handle,去处理请求。
Reactor模式:
服务端有一个循环监听的主线程,主线程主要监听连接socket。监听到客户端有效端口请求,调用socketChannel.accept方法返回socket。之后,通过selector组件,事件分发器分发请求到handle,handle回建立相应的线程处理请求。
以上需要的额外扩展
I/o
处理数据主要分为2部分:
将数据加载到内核缓存里面
数据从内核缓存到用户缓存
分类:阻塞io,非阻塞io,异步阻塞io,异步非阻塞io
Reactor模式过程
client发送请求给server,服务端通过一个线程监听连接serverSocket。accpet()返回一个连接,事件分发器会建立一个对应的线程。处理这个连接的信息,线程处理请求连接的过程是阻塞的。但是多个客户端的请求过来是可以并发的。利用事件分发器创建多个线程进行执行
流程:
① 服务器端的Server是一个线程,线程中执行一个死循环来阻塞的监听客户端的连接请求和通信。
② 当客户端向服务器端发送一个连接请求后,服务器端的Server会接受客户端的请求,ServerSocket.accept()从阻塞中返回,得到一个与客户端连接相对于的Socket。
③ 构建一个handler,将Socket传入该handler。创建一个线程并启动该线程,在线程中执行handler,这样与客户端的所有的通信以及数据处理都在该线程中执行。当该客户端和服务器端完成通信关闭连接后,线程就会被销毁。
④ 然后Server继续执行accept()操作等待新的连接请求。
io多路复用
用一个线程进行检查多个描述符(socket)的状态。调用select和poll函数传入多个socket过来,如果有一个完成状态就返回。都没有完成就阻塞,一直到超时。
就绪状态的socket真正执行的时候,会运行一个执行线程进行执行。
一般多路复用,需要事件分发器,作用是:将哪些读写的事件,分发给不同的事件处理器处理
事件分发器设计模式reactor的模式,Proactor基于异步io的
Reactor模式是基于同步I/O的。一种实现多个客户端请求服务端并发处理的一种模式 。当请求抵达时,会利用io多路复用进行分法处理请求