对Netflix Ribbon的Loadbalancer类源码设计合理性的一点质疑
首先,这只是我个人的一点质疑,可能是因为我自己菜没有领悟到作者的意思,也正因此,想发出来跟大家一起探讨.
在昨晚,我因为在编写自己的开源项目的负载均衡模块(这是我开源项目的介绍:https://www.cnblogs.com/yangfeiORfeiyang/p/9621909.html),所以去看了下Netflix的RibbonLoadbalancer的源码,然后它是这样做的
首先定义一个ILoadBalancer接口,这个接口是干嘛的呢?大家可以想象为一个自动饮料机,我们想要饮料的时候,按一个按键(chooseServer(Object key)),投一个硬币(当然它的几个源码实现类里,这个key其实没有多少意义),就能获得我们想要的饮料,由此来看,大家可以将它抽象为一个对我们隐藏了内部细节的容器

下面再来看一个接口,这个接口是干什么的呢?将注释里的英文翻译下,就是这个接口是定义负载均衡的规则的,最典型的负载均衡规则就是轮询啊,根据响应时间进行自动权重啊(根据响应时间这个,它的源码里是有实现类的ResponseTimeWeightedRule不过被标记为了过时类,也就是不推荐我们使用)

好了,接下来就是我认为它不合理的地方了,请看下面这个实现了IRule的抽象类,请注意它的成员变量,它封装了ILoadbalancer类

请大家想象一个场景,现在你想去一个超市买水果,你有可能走路去,有可能骑车去,也有可能做公交车,不管怎样,去超市买水果这是一个没有细节的概念,为什么没有细节呢?因为我们不知道你会以什么样的方式去,此时你会以什么样的方式去就是一个可能会发生变化的变量.
那么对比到我们的代码里,ILoadBalancer就是你要去超市买水果,这是一个没有变化的,封闭了细节的概念,试问你在自动饮料机买饮料的时候知道饮料机内部经历了什么样的变化吗?而IRule就是我们是以什么样的方式去超市了,此时它是可能会发生变化的,因为我们有可能用轮询算法,有可能用权重算法,但不管用什么,它们最终都会取出一个Server.,这个结果是不会改变的,也就代表
我们的ILoadBalancer是不会改变的,那么你将ILoadBalancer封装到IRule里是什么意思呢?我"个人"认为,正确的做法应该是这样的:

好吧,我继续看了一会又发现一个问题,这个问题也在验证了我的想法是对的

很明显,作者自己也知道,IRule应该是ILoadbalancer的细节

what???敢情您饶了一大圈最后又绕回去了呀.我们再看看rule.choose(key)里的具体内容

额额额,你调来调去最后又调回来了...
不过,有一行代码让我感觉到了作者的高并发编程水平真的不错...

首先这个nextServerCyclicCounter是个AtomticInteger类.
我们先说说为什么作者不直接nextServerCyclicCounter.getAndIncrement(),然后取模呢?因为如果要getAndIncrement的话,那么会导致一个问题,那么就是我就要写出这样的代码
if(nextServerCyclicCounter.get()==服务数量){
nextServerCyclicCounter.set(0)
}
但是这样就有一个问题,那就是虽然AtomticInteger类的每个操作都是原子性的,但是加起来就不是了,也就是说,假设有两个线程,一个A,一个B.
第一步:线程A刚刚进入了判断,还没来得及设置为0,CPU时间片就被抢了
第二步:线程B也进来了,那么他们拿到的将是同样的数据.连续两次设置为0.当然可能会有N个线程进来N次设置为0
而用这个方法呢?就不会有这个问题了,它等于是拿到当前值,然后再拿预期值,之后,看看当前值是否发生了改变,改变的话就重新获取,是的话就将预期值换成当前值并返回预期值(比较换值这个过程借助了unsafe类保证了是原子性的),没错,这里最妙的就是这个死循环包含的代码,它等于是每次重新拿最新的值去试(因为AtomticInteger类里的value字段上了volatile关键字),完美的避开了我们上述的问题.
正当我感叹这个作者实在是高的时候...我看了下译文

额,好吧,我也算是受到了您的启发,学到了一手,哈哈哈
完毕~欢迎大家说出我不对的地方...
对Netflix Ribbon的Loadbalancer类源码设计合理性的一点质疑的更多相关文章
- Netflix Ribbon源码设计错误的证据(附正确示例)
我在之前一篇博客里https://www.cnblogs.com/yangfeiORfeiyang/p/9644254.html 里对Netflix Ribbon的Loadbalancer类源码设计的 ...
- Java集合---Array类源码解析
Java集合---Array类源码解析 ---转自:牛奶.不加糖 一.Arrays.sort()数组排序 Java Arrays中提供了对所有类型的排序.其中主要分为Prim ...
- Cocos2d-X3.0 刨根问底(六)----- 调度器Scheduler类源码分析
上一章,我们分析Node类的源码,在Node类里面耦合了一个 Scheduler 类的对象,这章我们就来剖析Cocos2d-x的调度器 Scheduler 类的源码,从源码中去了解它的实现与应用方法. ...
- List 接口以及实现类和相关类源码分析
List 接口以及实现类和相关类源码分析 List接口分析 接口描述 用户可以对列表进行随机的读取(get),插入(add),删除(remove),修改(set),也可批量增加(addAll),删除( ...
- Thread类源码剖析
目录 1.引子 2.JVM线程状态 3.Thread常用方法 4.拓展点 一.引子 说来也有些汗颜,搞了几年java,忽然发现竟然没拜读过java.lang.Thread类源码,这次特地拿出来晒一晒. ...
- Java并发编程笔记之Unsafe类和LockSupport类源码分析
一.Unsafe类的源码分析 JDK的rt.jar包中的Unsafe类提供了硬件级别的原子操作,Unsafe里面的方法都是native方法,通过使用JNI的方式来访问本地C++实现库. rt.jar ...
- python附录-builtins.py模块str类源码(含str官方文档链接)
python附录-builtins.py模块str类源码 str官方文档链接:https://docs.python.org/3/library/stdtypes.html#text-sequence ...
- Long类源码浅析
1.Long类和Integer相类似,都是基本类型的包装类,类中的方法大部分都是类似的: 关于Integer类的浅析可以参看:Integer类源码浅析 2.这里主要介绍一下LongCache类,该缓存 ...
- java.lang.Void类源码解析_java - JAVA
文章来源:嗨学网 敏而好学论坛www.piaodoo.com 欢迎大家相互学习 在一次源码查看ThreadGroup的时候,看到一段代码,为以下: /* * @throws NullPointerEx ...
随机推荐
- php随机生成国内ip地址
获得一个国家所有ip段,随机生成国内ip地址的缩水实现.注意: $ip_long数组中后5个值在64位系统中可能是错误的(下面代码中 $ip_long 数组的后五个值在32位系统中为负数,64位系 ...
- 按Home键切换到后台后会触发libGPUSupportMercury.dylib: gpus_ReturnNotPermittedKillClient导致crash
转自:http://www.eoeandroid.com/thread-251598-1-1.html 好像有很多朋友都碰到过这个问题,即在真机调试时,按hone键返回桌面,再回到app时,app会c ...
- openstack No valid host was found. There are not enough hosts available.
root@dell-PowerEdge-T30:~# gedit /var/log/nova/nova-conductor.logroot@dell-PowerEdge-T30:~# gedit /v ...
- SQLite连接
SQLite -连接 SQLite的联接子句用于从数据库中的两个或多个表合并的记录.JOIN是用于通过使用共同的每个值从两个表结合域的装置. SQL定义了三个主要类型的连接: CROSS JOIN I ...
- c++ 中的函数调用中的参数传递
概述 初学 \(c++\),一直搞不懂其参数传递方式.故找到一篇不错的文章:刘志华的深入探讨C++语言中参数传递问题.亲自实践一遍,并作此记录,以加深印象. 主要内容 本文主要分为五个小部分, ...
- SSH整合JAR包详解
如果要使用连接池,添加JAR : c3p0-0.9.1.2.jar
- 带图形桌面的CentOS7----中安装VMWareTools以及支持中文输入
主机是WIN10操作系统 安装VMWareTools的方法:https://jingyan.baidu.com/article/e8cdb32b136ad637052bad26.html 在图形化Ce ...
- String中indexof函数的用法
int indexOf(int ch) 返回指定字符在此字符串中第一次出现处的索引. int indexOf(int ch, int fromIndex) 从指定的索引开始搜索,返回在此字符串中第一次 ...
- js解析器
1>js的预解析 找var function 参数等 所有的变量,在正式运行代码前,都提前赋了一个值:未定义 所有的函数,在正式运行代码前,都是整个函数块. 遇到重名的:只留一个 如果变量与函数 ...
- 不同深度的图片转换cvConvertScale
不同深度图像的转换:要注意范围比如IPL_DEPTH_8U 转到 IPL_DEPTH_32U要用cvConvertScale(pImg8, pImg32, 1.0/255, 0); 要除255反过来I ...