dubbo调用模块核心功能是发起一个远程方法的调用并顺利拿到返回结果,其体系组成如下:
参见源码:
com.alibaba.dubbo.config.ReferenceConfig#createProxy
com.alibaba.dubbo.common.bytecode.ClassGenerator
com.alibaba.dubbo.rpc.proxy.javassist.JavassistProxyFactory
Dubbo 目前官方支持以下负载均衡策略:
设置方式支持如下四种方式设置,优先级由低至高
TODO 一至性hash 演示
配置loadbalance
配置需要hash 的参数与虚拟节点数
发起远程调用
Dubbo 官方目前支持以下容错策略:
设置方式支持如下两种方式设置,优先级由低至高
注:容错机制 在基于 API设置时无效 如 referenceConfig.setCluster(“failback”); 经测试不启作用
异步调用是指发起远程调用之后获取结果的方式。
异步调用配置:
注:在进行异步调用时 容错机制不能为 cluster=“forking” 或 cluster=“broadcast”
异步获取结果演示:
编写异步调用代码
编写同步调用代码
分别演示同步调用与异步调用耗时
异步调用结果获取Demo
demoService.sayHello1("han");
Future
类似于 WEB 中的Filter ,Dubbo本身提供了Filter 功能用于拦截远程方法的调用。其支持自定义过滤器与官方的过滤器使用
以上配置 就是 为 服务提供者 添加 日志记录过滤器, 所有访问日志将会集中打印至 accesslog 当中
泛化提供
是指不通过接口的方式直接将服务暴露出去。通常用于Mock框架或服务降级框架实现。
TODO 示例演示
public static void doExportGenericService() {
ApplicationConfig applicationConfig = new ApplicationConfig();
applicationConfig.setName("demo-provider");
// 注册中心
RegistryConfig registryConfig = new RegistryConfig();
registryConfig.setProtocol("zookeeper");
registryConfig.setAddress("192.168.0.147:2181");
ProtocolConfig protocol=new ProtocolConfig();
protocol.setPort(-1);
protocol.setName("dubbo");
GenericService demoService = new MyGenericService();
ServiceConfig service = new ServiceConfig();
// 弱类型接口名
service.setInterface("com.tuling.teach.service.DemoService");
// 指向一个通用服务实现
service.setRef(demoService);
service.setApplication(applicationConfig);
service.setRegistry(registryConfig);
service.setProtocol(protocol);
// 暴露及注册服务
service.export();
}
泛化引用
是指不通过常规接口的方式去引用服务,通常用于测试框架。
ApplicationConfig applicationConfig = new ApplicationConfig();
applicationConfig.setName("demo-provider");
// 注册中心
RegistryConfig registryConfig = new RegistryConfig();
registryConfig.setProtocol("zookeeper");
registryConfig.setAddress("192.168.0.147:2181");
// 引用远程服务
ReferenceConfig reference = new ReferenceConfig();
// 弱类型接口名
reference.setInterface("com.tuling.teach.service.DemoService");
// 声明为泛化接口
reference.setGeneric(true);
reference.setApplication(applicationConfig);
reference.setRegistry(registryConfig);
// 用com.alibaba.dubbo.rpc.service.GenericService可以替代所有接口引用
GenericService genericService = reference.get();
Object result = genericService.$invoke("sayHello", new String[]{"java.lang.String"}, new Object[]{"world"});
是指通过非常方法参数传递参数,类似于http 调用当中添加cookie值。通常用于分布式追踪框架的实现。使用方式如下 :
//客户端隐示设置值
RpcContext.getContext().setAttachment("index", "1"); // 隐式传参,后面的远程调用都会隐
//服务端隐示获取值
String index = RpcContext.getContext().getAttachment("index");
通过令牌验证在注册中心控制权限,以决定要不要下发令牌给消费者,可以防止消费者绕过注册中心访问提供者,另外通过注册中心可灵活改变授权方式,而不需修改或升级提供者
使用:
**初始连接:**
引用服务增加提供者==>获取连接===》是否获取共享连接==>创建连接客户端==》开启心跳检测状态检查定时任务===》开启连接状态检测
源码见:com.alibaba.dubbo.rpc.protocol.dubbo.DubboProtocol#getClients
心跳发送:
在创建一个连接客户端同时也会创建一个心跳客户端,客户端默认基于60秒发送一次心跳来保持连接的存活,可通过 heartbeat 设置。
源码见:com.alibaba.dubbo.remoting.exchange.support.header.HeaderExchangeClient#startHeatbeatTimer
断线重连:
每创建一个客户端连接都会启动一个定时任务每两秒中检测一次当前连接状态,如果断线则自动重连。
源码见:com.alibaba.dubbo.remoting.transport.AbstractClient#initConnectStatusCheckCommand
连接销毁:
基于注册中心通知,服务端断开后销毁
源码见:com.alibaba.dubbo.remoting.transport.AbstractClient#close()
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qpmnBUDV-1596786886903)(https://cdn.nlark.com/yuque/0/2020/png/99448/1596786742278-21a1ab2e-dcf1-485d-99ba-82525ee2ac28.png)]
客户端线程协作流程:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UpagZQrB-1596786886907)(https://cdn.nlark.com/yuque/0/2020/png/99448/1596786742375-3f0de740-2d6d-4b6e-95a0-ac8bbf0ea507.png)]
调用调试:
客户端的执行线程:
1、业务线程
1) DubboInvoker#doInvoke(隐示传公共参数、获取客户端、异步、单向、同步(等待返回结果))
2)AbstractPeer#send// netty Client客户端发送消息 写入管道
3)DubboCodec#encodeRequestData // Request 协议编码
2、IO线程
DubboCodec#decodeBody //Response解码
AllChannelHandler#received 派发消息处理线程
3、调度线程
DefaultFuture#doReceived // 设置返回结果
服务端线程协作:
线程池