什么是rpc?
rpc远程过程调用。通过网络通信来实现远程的调用。
原理图
步骤:
1.服务提供者定义接口和服务实现并提交到注册中心
2.客户端从注册中心订阅服务
3.客户端通过代理对象调用服务。代理类主要是对客户端网络进行增强。
4.客户端代理把需要调用的对象、方法、参数序列化成数据
5.客户端与服务端通过socket通讯传输数据
6.服务端从网络中拿到调用信息反序列化成对象、方法、参数
7.服务端代理对象通过网络信息反射调用服务实现类,将返回结果通过网络传回客户端
涉及到技术:
socket通信、jdk动态代理、反射、序列化
存在问题
socket通讯效率,io方式和瓶颈,序列化速度,服务管理
什么是dubbo?
dubbo是一个分布式、高性能、透明化的rpc框架。
作为一个分布式高性能透明化的rpc框架dubbo需要考虑的问题是如何解决rpc调用存在的通讯效率,io方式,序列化速度和服务的管理等问题。
透明化
针对于透明化调用问题,dubbo完美集成了spring容器,基于Spring的标签和注解实现了,代码上无侵入性,仅仅通过一些dubbo相关的配置或者注解就可以完成rpc调用。
服务端:配置文件中所有的service标签都会被解析成ServiceBean实例,实现了Spring的initializingBean接口,在afterPropertiesSet方法中完成服务的暴露操作。
服务暴露的过程:将dubbo.xml文件中的信息解析出来,将所有的策略和服务实现端口ip等信息组装到url中,并针对服务配置的每个协议类型进行一次服务的注册,注册到指定的注册中心上。protocol.expert方法中完成
消费端:配置文件中所有的reference标签都会解析成ReferenceBean实例,实现Spring的initializingBean接口,在afterPropertiesSet方法中完成服务的引入。
服务引入的过程:通过服务全路径名(key)从注册中心中拿到指定服务接口下所有的URL,然后针对每个URL创建一个消费端的一个代理对象,用于和服务端进行rpc调用。protocol.refer方法中完成
高性能
dubbo的高性能主要是体现在dubbo的协议和序列化上。
dubbo的默认协议是dubbo协议,默认序列化方式是hessian,dubbo协议是单一长连接,NIO模式,有很好的并发性能。但是传输数据有限制不超过(100kb)
其他协议和序列化方式:
rmi,使用的是Java序列化方式。适用的场景是,服务提供者和消费者数量差不多,文件传输场景
hessian,使用的是hessian序列化方式,适用的场景是,服务提供者多于消费者,文件传输场景
http-json
web service-soap文本序列化方式
Dubbo的spi
spi-策略模式。根据配置选择实际调用的接口实现类。
jdk的spi
1.在MATA-INF.service路径下创建一个名称和接口全路径名称相同的文件,在文件中配置实现类的全路径名称
2.通过jdk的ServiceLoader获取接口的配置所有实现类,然后迭代的方式调用目标方法。
dubbo的spi
dubbo的扩展机制做的非常的优秀
使用步骤:
1.dubbo的spi只能针对dubbo框架中带有@SPI注解的接口进行扩展,而且只能对这些接口中带有的@adaptive注解的方法进行扩展
2.自定义一个扩展实现类实现需要扩展的目标接口,重写要求重写的方法。在重写方法中完成自定义的扩展逻辑;
3.在MATA-INF.dubbo路径下创建一个名称为目标接口全路径名的文件,在文件中以key-value方式配置扩展实现类。key自定义,value为自定义实现类全路径名
4.在需要使用的地方通过key来指定选定的策略。
原理
dubbo的spi机制是通过核心类ExtensionLoader来实现的,针对每个@spi的接口都可以创建一个对应的ExtensionLoader来创建目标接口的代理类对象。这个代理类对象是代码的方式创建出只@spi接口中@adaptive方法的源码,再通过其对对应的ExtensionLoader加载器进行编译加载。通过debug的方式拿到对应的代理类代码分析可以看出,是创建出来的代理类中拿到包含服务所有信息的URL,然后从url中解析出该接口对应的实际使用的策略的key,读取配置文件,拿到其具体的实现类对象,然后通过实现类对象调用扩展的方法。
在dubbo中所有的扩展机制都是通过此方式完成的