1、完全随机算法缺点:所有服务器的访问概率都是相同的 。
package com.example.demo.core.random; import JAVA.util.Arrays;import java.util.List;import java.util.Random; /** * 负载均衡算法 * 完全随机算法 */public class RandomServer {public static List<String> list = Arrays.asList("10.180.11.126:8888","10.180.11.128:8888","10.180.11.130:8888");static Random random = new Random();public static String getServer() {int number = random.nextInt(list.size());return list.get(number);}public static void main(String[] args) {for(int i = 0; i < 15; i++) {System.out.println(getServer());}}}2、加权随机算法场景:有的服务器性能高,可以让随机到此服务器的可能性增大
缺点:权重低的服务器可能很长一段时间都访问不到3
package com.example.demo.core.random; import java.util.*; /** * 负载均衡算法 * * 如果某一台服务器性能比较高,设置访问的权重高一点 * * 加权随机算法 */public class WeightRandomServer {public static Map<String,Integer> map = new HashMap<>();static {map.put("10.180.11.126:8888",2);map.put("10.180.11.128:8888",7);map.put("10.180.11.130:8888",1);}static Random random = new Random();/*** 当权重设置过大时,list容易被撑爆* @return*/public static String getServer() {List<String> list = new ArrayList<>();for(Map.Entry<String,Integer> entry: map.entrySet()) {//根据权重,决定向list中添加几次for(int i = 0; i < entry.getValue(); i++) {list.add(entry.getKey());}}//list的大小int weight = map.values().stream().mapToInt(p -> p).sum();int number = random.nextInt(weight);return list.get(number);}/*** 优化后* @return*/public static String getServer1() {//计算总权值int weight = map.values().stream().mapToInt(p -> p).sum();//随机一个随机数int index = random.nextInt(weight);//遍历服务mapfor(Map.Entry<String,Integer> entry : map.entrySet()) {//如果权重大于索引if(entry.getValue() >= index) {// 返回这个服务return entry.getKey();}//否则,索引 = 当前索引 - 当前服务的权重index = index - entry.getValue();}return "";}public static void main(String[] args) {for(int i = 0; i < 15; i++) {//System.out.println(getServer());System.out.println(getServer1());}}}3、完全轮询算法缺点:从头到尾轮询一遍,不能根据服务器性能设置权重
package com.example.demo.core.poll; import java.util.Arrays;import java.util.List; /** * 完全轮询算法 */public class PollServer {public static List<String> list = Arrays.asList("10.180.11.126:8888","10.180.11.128:8888","10.180.11.130:8888");static int index;public static String getServer() {if(index == list.size()) {index = 0;}return list.get(index++);}public static void main(String[] args) {for(int i = 0; i < 15; i++) {System.out.println(getServer());}}}4、加权轮询算法有点:可以根据服务器性能设置访问权重
缺点:可能某个服务器权重大,长时间执行,遇到耗时大的请求,压力会很大
package com.example.demo.core.poll; import java.util.HashMap;import java.util.Map; /** * 加权轮询算法 * 实际中可能遇到某个服务器压力较大,长时间执行 。*/public class WeightPollServer {public static Map<String,Integer> map = new HashMap<>();static {map.put("10.180.11.126:8888",2);map.put("10.180.11.128:8888",7);map.put("10.180.11.130:8888",5);}static int index;public static String getServer() {int weight = map.values().stream().mapToInt( p -> p).sum();int number = (index++) % weight;for(Map.Entry<String,Integer> entry : map.entrySet()) {if(entry.getValue() >= number) {return entry.getKey();}number = number - entry.getValue();}return "";}public static void main(String[] args) {for(int i = 0; i < 15; i++) {System.out.println(getServer());}}}5、平滑加权轮询算法优点:根据权重分配服务,同时又保证权重低的服务可以被访问到
缺点:集群环境下,同一个用户访问无法分流到固定一台机器
package com.example.demo.core.smooth; /** * 平滑加权 */public class SmoothWeight {private int weight;private int currentWeight;private String address;public int getWeight() {return weight;}public void setWeight(int weight) {this.weight = weight;}public int getCurrentWeight() {return currentWeight;}public void setCurrentWeight(int currentWeight) {this.currentWeight = currentWeight;}public String getAddress() {return address;}public void setAddress(String address) {this.address = address;}public SmoothWeight(int weight, int currentWeight, String address) {this.weight = weight;this.currentWeight = currentWeight;this.address = address;}}package com.example.demo.core.smooth; import java.util.HashMap;import java.util.Map; /** * 平滑加权轮询算法 */public class SmoothWeightPollServer {public static Map<String,SmoothWeight> map = new HashMap<>();static {map.put("10.180.11.126:8888",new SmoothWeight(5,5,"10.180.11.126:8888"));map.put("10.180.11.128:8888",new SmoothWeight(2,2,"10.180.11.128:8888"));map.put("10.180.11.130:8888",new SmoothWeight(4,4,"10.180.11.130:8888"));}public static String getServer() {SmoothWeight maxSmoothWeight = null;int weight = map.values().stream().mapToInt(SmoothWeight :: getWeight).sum();for(Map.Entry<String,SmoothWeight> entry : map.entrySet()) {SmoothWeight currentSmoothWeight = entry.getValue();if(maxSmoothWeight == null || currentSmoothWeight.getCurrentWeight() > maxSmoothWeight.getCurrentWeight()) {maxSmoothWeight = currentSmoothWeight;}}assert maxSmoothWeight != null;maxSmoothWeight.setCurrentWeight(maxSmoothWeight.getCurrentWeight() - weight);for(Map.Entry<String,SmoothWeight> entry : map.entrySet()) {SmoothWeight currentSmoothWeight = entry.getValue();currentSmoothWeight.setCurrentWeight(currentSmoothWeight.getCurrentWeight() + currentSmoothWeight.getWeight());}return maxSmoothWeight.getAddress();}public static void main(String[] args) {for(int i = 0; i < 15; i++) {System.out.println(getServer());}}}
推荐阅读
- 如何实现一个简单的RPC
- 安卓|vivo秀商务旗舰X Note主摄:V1芯片下 实现实时黑光夜视
- 四个最佳实践,引导你写出高质量JavaScript模块
- Java 字符串格式化 Formatter
- redis各类型数据结构和底层实现源码分析
- Java集合详解
- TimingWheel 时间轮算法是如何实现的?
- 如何在Java中创建不可变类?
- 探究Java中的final关键字
- 利用openresty+lua+redis 实现封杀频繁恶意访问IP地址
