dubbo 说白了,就是一种 http 调用。
只不过,很多东西不用你自己做,已经帮你封装好了。所以使用起来很方便。
提供服务方,会对编写的接口进行封装,并缓存起来,后续使用。
调用方,会对需要调用的接口类封装,缓存起来,后续使用。
所以,那个接口类还是你认识的接口类吗???
作为调用方,接口类已经不是你引入的那个接口类了。因为dubbo做了封装,产生了一个实现类的东东,当然不是服务方的实现类逻辑。而是封装的和你调用的实现类差不多,里面有这个接口类的所有方法对应的实现方法。
那这些实现方法里面的实现逻辑都是什么呢?
http 调用!封装好的http 调用。这就是调用方的invoker
服务方的接口实现类呢,
放心,还是你认识的那个实现类。只不过dubbo克隆了个架子。
为什么要克隆个架子呢?
服务方不是发了个http过来调用吗,这边需要接得住啊,不能派错了对吧。所以要克隆下架子,然后在架子里面处理下是谁家的孩子,老几啊。
到这里,要分清下。
写出来的接口类和实现类是代码层面的,但是运行起来后,dubbo 帮我们在虚拟机中生成了这些类的wrapper包装类以及invoker。别纠结它们是怎么存在的。 一个是你写的实实的代码,另一个就当作是二元空间存在的吧。
就像你写信,接下来就是等着收回信,但是你不需要知道这中间这封信是通过箱子还是桶被送信员取走的。根据地址门牌号派给收信方。
下面讲个粒子吧
画的有点抽象,先看着吧,哈哈哈
讲解:
天亮了,超市进行库存和位置统计,统计剩余的数量,位置。相当于应用启动时,dubbo 对暴露的服务类封装,缓存起来,后面对着取。
你需要买饼干、瓜子、草莓味雪糕,告诉接线员,接线员拿个小本本记下来了,你等着结果就行了。然后接线员就打电话给超市接线员,相当于通信。
接线员告诉超市的接线员,我需要这些,接线员也拿着小本本记下来。这里就相当于通信内容解码。
然后超市接线员就根据天亮统计的库存和位置找到对应商品在什么位置,相当于取出invoker 对象,然后判断要找谁。然后就去对应的位置取商品,这里就相当于调用你写的实现类的方法,干实活了。
为什么这么做不直接用http?
最近电话费太贵了,换成微信、QQ、视频通信吧。是不是像通信协议???
超市肯定不止一家对吧。
接线员今天心情不错,每个超市都光顾下,很平均。轮询
今天心情不佳,点到谁就是谁。随机
谁跟我聊天比较多,我就点谁。活跃数
你指定某一个家超市,每次都是。一致性hash
这些是不是负载均衡策略??
新开了一家超市,倒闭了一家超市,都会告诉接线员。动态注册和发现。
还要说为啥不直接用http吗。不用直接配地址,nginx 能做负载,但是负载策略呢?协议呢?能动态发现吗?
关于dubbo 的轮询策略机制
分别有 随机、轮询、活跃数、一致性hash。这里只讲下轮询的。
dubbo 最新的 RoundRobinLoadBalance 策略机制相比之前更新了很多。最初的比较易懂,就是来一个请求依次减减,将所有服务器权重值减为0再重新开始,问题就是,请求处理很集中。比如三台,权重为 [8,2,1] ,一次减的话,第一台处理了前8个,后面两个估计都快睡着了。
调整后就稍微复杂点了,但是也不是很难理解。我们来看下官方说明:
每个服务器对应两个权重,分别为 weight 和 currentWeight。其中 weight 是固定的,currentWeight 会动态调整,初始值为0。当有新的请求进来时,遍历服务器列表,让它的 currentWeight 加上自身权重。遍历完成后,找到最大的 currentWeight,并将其减去权重总和,然后返回相应的服务器即可。
A、B、C 分别是 [ 5,1,1]
请求 | 自身权重 | 上一次权重 | 本次currentWeight(上一次+自身) | 结果(减去权重总和) | 选择 |
1 | [5,1,1] | [0,0,0] | [0+5=3,0+1=1,0+1=1] -> [5,1,1] | [5-7= -2 , 1,1]->[-2,1,1] | A |
2 | [5,1,1] | [-2,1,1] | [-2+5=3,1+1=2,1+1=2] -> [3,2,2] | [3 - 7 = -4 ,2,2] -> [-4,2,2] | A |
3 | [5,1,1] | [-4,2,2] | [-4+ 5=1,2 + 1=3,2+1=3]->[1,3,3] | [1,3-7=-4,3]->[1,-4,3] | B |
4 | [5,1,1] | [1,-4,3] | [1+5=6,-4+1=-3,3+1=4] ->[6,-3,4] | [6-7=-1,-3,4]->[-1,-3,4] | A |
每次请求,自身权重+上一次的权重,然后选择这些权重中最大值的一台,减去权重总和,就是下一次权重的初始了。