dubbo
服务框架, 远程通讯,集群容错,自动发现
spi:
接口全限定名找到指定目录下对应的文件,获取具体的实现类然后加载
增加缓存存储实例,对ioc api对支持
流程:
之前的博客实战总结: https://so.csdn.net/so/search?q=dubbo&t=blog&u=ma15732625261
Dubbo原理和机制详解(非常全面)-CSDN博客
注册中心:
zk。redis。simple
支持的协议
dubbo:nio 复用单一长连接 线程池并发
rmi:jdk自带 基于tcp 短连接
hessian:rpc框架基于http,大数据压缩,需要hessian.jar支持,需要序列化
webService:xml 远程调用,文本序列化 soap
thrif:跨语言 rpc 二进制 效率更高
RPC:远程方法调用方式
rpcServer导出export远程接口,客户端RpcClient引入import远程接口
提供接口代理实现实际委托rpcProxy封装调用信息转rpcInvoker执行
客户端rpcInvoker通过rpcConnector维持服务端通道rpcChannel 使用rpcProtocol执行协议编码
服务端rpcAcceptor接收客户端调用请求,使用rpcProtocol执行协议解码,rpcProcessor
通信
TCP:面向连接 可靠 基于字节流的传输层通信协议
序列号按顺序发送数据 首部序列号+数据长度 =》下一步接受序号 应答返回
三次握手建立连接
浅谈TCP,一文带你搞懂TCP - 知乎 这篇其实就够了
四次挥手端口连接
TCP协议详解_tcp请求-CSDN博客
RMI:java中实现的rpc,j2ee
远程对象实现rmi.Remote接口,实现UniCastRemoteObject类,能被访问到,将自身拷贝socket形式传输给客户端
netty
IO网络通信-CSDN博客 自己的博客 请笑纳
服务引入:代码流程
饿汉式
调用referenceBean的afterPropertiesSet方法引入服务
referenceBean实现factoryBean接口,任意服务interface进行自动注入或getBean获取,getObject函数服务引用过程
本地引入走injvm协议,服务器缓存中取exporter
直连远程引入服务,测试情况下 不需要启动注册中心,consumer配置写死地址 直连
注册中心引入远程服务,consumer通过注册中心得知provider信息,服务引入
懒汉式:默认
服务被注入到其他类启动引入流程,用到了再引入
获取注册中心实例,向注册中心注册自己,订阅providers configurators routers ,触发dubboInvoker生成,cluster封装多个服务调用者,返回一个invoker
配置构建一个map,利用map构建url,通过url协议利用自适应扩展机制调用相应的protocol.refer得到invoker,构建代理,封装invoker返回服务引用,consumer调用这个(提供者的)代理类
服务暴露:代码流程
url:
protocol://username:password@host:port/path?key=value&key=value
protocol:各种协议 dubbo thrift http
path:接口名称。parameters:参数键值对
扩展:serviceBean实现了applicationListener,监听contextRefreshedEvent时间,ioc容器刷新完调用onApplicationEvent方法,暴露启动点,据配置url 利用dubbo spi 据url参数选择对应实现类
通过javassist动态封装服务实现类,同一暴露出invoker,封装exporter存储起来,等待消费者调用,url注册到注册中心,消费者获取服务提供者信息
一个服务多个协议都需要暴露,多中协议分别向多注册中心暴露注册
调用过程
系统交互
rpc完成服务调用,多协议doubbo http rest
消费者调用服务时将 调用的服务接口信息 + 当前方法信息 + 执行方法入参信息 = invocation
不同协议将不同数据组织方式 / 传输方法 将对象传输给服务提供者
提供者接收对象,找到对应服务实现 反射执行方法 网络响应结果给消费者
过程中服务容错 / 负载均衡 /filter机制 /动态路由
负载均衡AbstractLoadBalance|doSelect
平衡加权轮询RoundRobinLoadBalance
private ConcurrentMap<String, ConcurrentMap<String, WeightedRoundRobin>> methodWeightMap = new ConcurrentHashMap<String, ConcurrentMap<String, WeightedRoundRobin>>();
加权随机RandomLoadBalance
for (int i = 1; i < length; i++) {
int weight = getWeight(invokers.get(i), invocation);
weights[i] = weight;//注意i下标
// 计算出所有权重和,以便在进行随机时设定范围
totalWeight += weight;
if (sameWeight && weight != firstWeight) {
sameWeight = false;
}
}
//针对各提供供者权重不一的情况,则找到第一个大于随机数的提供者即可
if (totalWeight > 0 && !sameWeight) {
// If (not every invoker has the same weight & at least one invoker's weight>0), select randomly based on totalWeight.
int offset = ThreadLocalRandom.current().nextInt(totalWeight);
// Return a invoker based on the random value.
for (int i = 0; i < length; i++) {
offset -= weights[i];
if (offset < 0) {
return invokers.get(i);
}
}
}
一致性哈希ConsistentHashLoadBalance
private final ConcurrentMap<String, ConsistentHashSelector<?>> selectors = new ConcurrentHashMap<String, ConsistentHashSelector<?>>();
取第多少个参数,参与一致性hash算法 定位invoker
this.virtualInvokers = new TreeMap<Long, Invoker<T>>();
treeMap虚拟节点,hashCode->invoker形式存储
最小活跃数LeastActiveLoadBalance
if (!sameWeight && totalWeight > 0) {
// If (not every invoker has the same weight & at least one invoker's weight>0), select randomly based on
// totalWeight.
// 如果权重不相同且权重大于0则按总权重数随机
// 并确定随机值落在哪个片断上(第一个相减为负的值)
int offsetWeight = ThreadLocalRandom.current().nextInt(totalWeight);
// Return a invoker based on the random value.
for (int i = 0; i < leastCount; i++) {
int leastIndex = leastIndexes[i];
offsetWeight -= weights[leastIndex];
if (offsetWeight < 0) {
return invokers.get(leastIndex);
}
}
}
自定义
实现loadBalance接口
添加文件src/main/resource/META-INF/dubbo/com.alibaba.dubbo.rpc.cluster.LoadBalance;
设置负载均衡策略
路由 --- 负载均衡 -- 集群容错
Dubbo中先通过路由,从多个 Provider中按照路由规则,选出一个子集
再据负载均衡从子集中选出一个 Provider 进行本次调用
如调用失败,根集群容错策略,进行重试或定时重发或快速失败等
分层设计
https://cn.dubbo.apache.org/zh-cn/docsv2.7/dev/source/service-invoking-process/