- 哈希 -
负载均衡算法中的哈希算法,就是根据某个值生成一个哈希值,然后对应到某台服务器上去。当然可以根据用户,也可以根据请求参数,或者根据其他,想怎么来就怎么来。如果根据用户,就比较巧妙的解决了负载均衡下Session共享的问题,用户小明走的永远是A服务器,用户小笨永远走的是B服务器。
那么如何用代码实现呢?这里又需要引出一个新的概念:哈希环。
什么?我只听过奥运五环,这个哈希环又是什么鬼?容我慢慢道来。
哈希环,就是一个环!这……好像……有点难解释呀,我们还是画图来说明吧。
一个圆是由无数个点组成的,这是最简单的数学知识,相信大家都可以理解吧,哈希环也一样,哈希环也是有无数个“哈希点”构成的,当然并没有“哈希点”这样的说法,只是为了便于大家理解。
我们先计算出服务器的哈希值,比如根据IP,然后把这个哈希值放到环里,如上图所示。
来了一个请求,我们再根据某个值进行哈希,如果计算出来的哈希值落到了A和B的中间,那么按照顺时针算法,这个请求给B服务器。
理想很丰满,现实很孤单,可能三台服务器掌管的“区域”大小相差很大很大,或者干脆其中一台服务器坏了,会出现如下的情况:
可以看出,A掌管的“区域”实在是太大,B可以说是“很悠闲”,像这种情况,就叫“哈希倾斜”。
那么,怎么避免这种情况呢?——虚拟节点。
什么是虚拟节点呢,说白了,就是虚拟的节点……好像跟没解释一样啊……还是上一张丑到爆炸的图吧:
如图所示,正方形的是真实的节点,或者说真实的服务器,五边形的是虚拟节点,或者说是虚拟的服务器。当一个请求过来,落到了A1和B1之间,那么按照顺时针的规则,应该由B1服务器进行处理,但是B1服务器是虚拟的,它是从B服务器映射出来的,所以再交给B服务器进行处理。
要实现此种负载均衡算法,需要用到一个平时不怎么常用的Map:TreeMap,对TreeMap不了解的朋友可以先去了解下TreeMap,下面放出代码:
private static String go(String client) { int nodeCount = 20; TreeMap<Integer, String> treeMap = new TreeMap(); for (String s : new Servers().list) { for (int i = 0; i < nodeCount; i++) treeMap.put((s + "--服务器---" + i).hashCode(), s); } int clientHash = client.hashCode(); SortedMap<Integer, String> subMap = treeMap.tailMap(clientHash); Integer firstHash; if (subMap.size() > 0) { firstHash = subMap.firstKey(); } else { firstHash = treeMap.firstKey(); } String s = treeMap.get(firstHash); return s; } public static void main(String[] args) { System.out.println(go("今天天气不错啊")); System.out.println(go("192.168.5.258")); System.out.println(go("0")); System.out.println(go("-110000")); System.out.println(go("风雨交加")); }
运行结果:
哈希负载均衡算法到这里就结束了。
- 最小压力 -
最小压力负载均衡算法是指:选择一台当前最“悠闲”的服务器,如果A服务器有100个请求,B服务器有5个请求,而C服务器只有3个请求,那么毫无疑问会选择C服务器,这种负载均衡算法是比较科学的。但是遗憾的是,在当前的场景下无法模拟出“原汁原味”的最小压力负载均衡算法的。
当然在实际的负载均衡下,可能会将多个负载均衡算法合在一起实现,比如先根据最小压力算法,当有几台服务器的压力一样小的时候,再根据权重取出一台服务器,如果权重也一样,再随机取一台等等。
今天的内容到这里就结束了,谢谢大家。