轮询算法

在多台机器实现负载均衡的时候,经常用到轮询调度算法(Round-Robin Scheduling)。

轮询调度算法就是以循环的方式依次将请求调度不同的服务器,即每次调度执行i = (i + 1) mod n,并选出第i台服务器。

算法的优点是其简洁性,它无需记录当前所有连接的状态,所以它是一种无状态调度。

1、算法流程:
假设有一组服务器 S = {S0, S1, …, Sn-1} ,有相应的权重,变量i表示上次选择的服务器,权值cw初始化为0,i初始化为-1 ,当第一次的时候取权值取最大的那个服务器,通过权重的不断递减,寻找适合的服务器返回,直到轮询结束,权值返回为0

 1 import java.math.BigInteger;
  2 import java.util.ArrayList;
  3 import java.util.HashMap;
  4 import java.util.List;
  5 import java.util.Map;
  6 import java.util.Map.Entry;
  7
  8 /**
  9  * 权重轮询调度算法(WeightedRound-RobinScheduling)-Java实现
 10  * @author huligong
 11  * */
 12 public class WeightedRoundRobinScheduling {
 13
 14     private int currentIndex = -1;// 上一次选择的服务器
 15     private int currentWeight = 0;// 当前调度的权值
 16     private int maxWeight = 0; // 最大权重
 17     private int gcdWeight = 0; //所有服务器权重的最大公约数
 18     private int serverCount = 0; //服务器数量
 19     private List<Server> serverList; //服务器集合
 20
 21     /**
 22      * 返回最大公约数
 23      * @param a
 24      * @param b
 25      * @return
 26      */
 27     private static int gcd(int a, int b) {
 28         BigInteger b1 = new BigInteger(String.valueOf(a));
 29         BigInteger b2 = new BigInteger(String.valueOf(b));
 30         BigInteger gcd = b1.gcd(b2);
 31         return gcd.intValue();
 32     }
 33
 34
 35     /**
 36      * 返回所有服务器权重的最大公约数
 37      * @param serverList
 38      * @return
 39      */
 40     private static int getGCDForServers(List<Server> serverList ) {
 41         int w = 0;
 42         for (int i = 0, len = serverList.size(); i < len - 1; i++) {
 43             if (w == 0) {
 44                 w = gcd(serverList.get(i).weight, serverList.get(i + 1).weight);
 45             } else {
 46                 w = gcd(w, serverList.get(i + 1).weight);
 47             }
 48         }
 49         return w;
 50     }
 51
 52
 53     /**
 54      * 返回所有服务器中的最大权重
 55      * @param serverList
 56      * @return
 57      */
 58     public static int getMaxWeightForServers(List<Server> serverList) {
 59         int w = 0;
 60         for (int i = 0, len = serverList.size(); i < len - 1; i++) {
 61             if (w == 0) {
 62                 w = Math.max(serverList.get(i).weight, serverList.get(i + 1).weight);
 63             } else {
 64                 w = Math.max(w, serverList.get(i + 1).weight);
 65             }
 66         }
 67         return w;
 68     }
 69
 70     /**
 71      *  算法流程:
 72      *  假设有一组服务器 S = {S0, S1, …, Sn-1}
 73      *  有相应的权重,变量currentIndex表示上次选择的服务器
 74      *  权值currentWeight初始化为0,currentIndex初始化为-1 ,当第一次的时候返回 权值取最大的那个服务器,
 75      *  通过权重的不断递减 寻找 适合的服务器返回,直到轮询结束,权值返回为0
 76      */
 77     public Server GetServer() {
 78         while (true) {
 79             currentIndex = (currentIndex + 1) % serverCount;
 80             if (currentIndex == 0) {
 81                 currentWeight = currentWeight - gcdWeight;
 82                 if (currentWeight <= 0) {
 83                     currentWeight = maxWeight;
 84                     if (currentWeight == 0)
 85                         return null;
 86                 }
 87             }
 88             if (serverList.get(currentIndex).weight >= currentWeight) {
 89                 return serverList.get(currentIndex);
 90             }
 91         }
 92     }
 93
 94
 95     class Server {
 96         public String ip;
 97         public int weight;
 98         public Server(String ip, int weight) {
 99             super();
100             this.ip = ip;
101             this.weight = weight;
102         }
103         public String getIp() {
104             return ip;
105         }
106         public void setIp(String ip) {
107             this.ip = ip;
108         }
109         public int getWeight() {
110             return weight;
111         }
112         public void setWeight(int weight) {
113             this.weight = weight;
114         }
115     }
116
117
118     public void init() {
119         Server s1 = new Server("192.168.0.100", 3);//3
120         Server s2 = new Server("192.168.0.101", 2);//2
121         Server s3 = new Server("192.168.0.102", 6);//6
122         Server s4 = new Server("192.168.0.103", 4);//4
123         Server s5 = new Server("192.168.0.104", 1);//1
124         serverList = new ArrayList<Server>();
125         serverList.add(s1);
126         serverList.add(s2);
127         serverList.add(s3);
128         serverList.add(s4);
129         serverList.add(s5);
130
131         currentIndex = -1;
132         currentWeight = 0;
133         serverCount = serverList.size();
134         maxWeight = getMaxWeightForServers(serverList);
135         gcdWeight = getGCDForServers(serverList);
136     }
137
138
139     public static void main(String[] args) {
140         WeightedRoundRobinScheduling obj = new WeightedRoundRobinScheduling();
141         obj.init();
142
143         Map<String,Integer> countResult = new HashMap<String,Integer>();
144
145         for (int i = 0; i < 100; i++) {
146             Server s = obj.GetServer();
147             String log = "ip:"+s.ip+";weight:"+s.weight;
148             if(countResult.containsKey(log)){
149                 countResult.put(log,countResult.get(log)+1);
150             }else{
151                 countResult.put(log,1);
152             }
153             System.out.println(log);
154         }
155
156         for(Entry<String, Integer> map : countResult.entrySet()){
157             System.out.println("服务器 "+map.getKey()+" 请求次数: "+map.getValue());
158         }
159     }
160
161 }

  

时间: 2024-08-04 16:00:51

轮询算法的相关文章

轮询算法设计及其代码框架

在实际的软件开发项目中,经常会遇到某模块需要向其它模块发消息的情况.为了减轻消息接收者的负担,我们会采用一种叫做轮询的机制来发送消息.本文介绍轮询算法的流程及其代码框架. 1.算法流程 假设消息发送模块为模块A,消息接收模块为模块B.模块A安装了一个,模块B安装了N个.所有模块都同时启动. 算法流程如图1所示: 图1 轮询算法流程 2.代码框架 static int g_iSendIdx = 0; for (iLoopFlag = 0; iLoopFlag < N; iLoopFlag ++)

实现一个简单的轮询算法

前言 负载均衡,大家应该听的也不少了,也实践过N次了. 当然也会知道,负载均衡是有不少算法的:随机,轮询,加权轮询,最少连接.... 本文重点说的是轮询. 先举个例子看看轮询算法是如何运作的. 假设我们的API站点有3台负载(10.0.10.1,10.0.10.2和10.0.10.3),客户端第一次请求API的时候,会访问.1拿到结果,第二次会访问.2拿到结果,第三次则会访问.3拿到结果,后面就是依次类推. 在致就是这个样子的访问顺序. .1->.2->.3>.1>.2......

十四.nginx,web,反向代理,调用加权轮询算法,nfs服务

一.部署nginx反向代理web服务,调度算法使用加权轮询: 1.首先配置一个nginx服务端,三个web客户端.用vmware 新建虚拟机完成,并用xshell连接 2.在服务端和3个web客户端都下载epel_release 和nginx软件包; yum install epel_release -y ;  yum install nginx -y 3.关闭服务端和web客户端的防火墙,在服务端和web客户端都开启nginx软件包并且查看是否开启; 如未开启重新启动nginx: system

LVS负载均衡地址转换使用轮询算法实验(结尾代码随记)

地址转换模式:调度服务器有双网卡,做NAT映射,请求经过调度服务器, 也是各个节点服务器回应客户机的出口,可作用于私网,较安全. 实验思路及环境 一.调度服务器配置双网卡,做网关,请求的流量以及转发的流量走调度服务器走 二.资源服务器两台都提供网页服务,为了测试,两台的内容不相同ip:192.168.10.10/24 httpd服务ip:192.168.10.20/24 httpd服务 三.远程存储设备使用NFS做远程存储,给资源服务器提供内存支持 图解如下 1.安装ipvsadm包 yum i

平滑加权轮询算法下的降权

func (this *LoadBalance) RoundRobinByWeight3() *HttpServer { //平滑加权轮询 for _, s := range this.Servers { s.CWeight = s.CWeight + s.Weight } sort.Sort(this.Servers) max := this.Servers[0] max.CWeight = max.CWeight - SumWeight return max } 来自为知笔记(Wiz) 原文

平滑加权轮询算法

static void Test1() { var sv = new ServerConfig[] { new ServerConfig{Name="A", Weight = 4}, new ServerConfig{Name="B", Weight = 2}, new ServerConfig{Name="C", Weight = 1} }; int index = 0; int sum = sv.Sum(m => m.Weight);

加权轮询算法

func (this *LoadBalance) RoundRobinByWeight() *HttpServer { server := this.Servers[ServerIndices[this.CurIndex]] this.CurIndex = (this.CurIndex + 1) % len(ServerIndices) //ServersIndices存放的是按照权重排放的索引,如3,1,2 则ServerIndices=[0,0,0,1,2,2] 然后遍历ServerIndi

负载均衡算法(二)加权轮询负载均衡算法

/// <summary> /// 加权轮询算法 /// </summary> public static class WeightRoundRobin { private static object obj = new object(); private static int pos = 0; static Dictionary<string, int> dic = new Dictionary<string, int> { { "192.168

# IT明星不是梦 #分布式负载均衡算法之亲和性轮询

无论是在早期的负载均衡器中,还是当前微服务基于客户端的负载均衡中,都有一个最基础的轮询算法,即将请求平均分布给多台机器,今天聊聊在此基础上, kube proxy是如何实现亲和性轮询的核心数据结构. 了解亲和性策略实现,失败重试等机制 1. 基础筑基 1.1 Service与Endpoints Service和Endpoint是kubernetes中的概念,其中Service代表一个服务,后面通常会对应一堆pod,因为pod的ip并不是固定的,用Servicel来提供后端一组pod的统一访问入口