Nginx基于权重的轮询算法的实现,它不但实现了基于权重的轮询算法,而且还实现了平滑的算法。
所谓平滑,就是在一段时间内,不仅服务器被选择的次数的分布和它们的权重一致,而且调度算法还比较均匀的选择服务器,而不会集中一段时间之内只选择某一个权重比较高的服务器。
如果使用随机算法选择或者普通的基于权重的轮询算法,就比较容易造成某个服务集中被调用压力过大。举个例子,比如权重为{a:5, b:1, c:1)
的一组服务器,Nginx的平滑的轮询算法选择的序列为{ a, a, b, a, c, a, a }
,
这显然要比{ c, b, a, a, a, a, a }
序列更平滑,更合理,不会造成对a
服务器的集中访问。
c#版本代码如下:
///
2 /// 权重对象
3 ///
4 public class WeightObject
5 {
6 ///
7 /// 当前权重
8 ///
9 public int CurrentWeight { set; get; }
10
11 ///
12 /// 有效
13 ///
14 public int EffectiveWeight { set; get; }
15
16
17 ///
18 /// 权重
19 ///
20 public int Weight { set; get; }
21
22
23 }
24
25 public class BalancingAssignHelper
26 {
27
28 ///
29 /// 算法:
30 /// on each peer selection we increase current_weight of each eligible peer by its weight,
31 ///select peer with greatest current_weight and reduce its current_weight by total number of weight points distribute damong peers.
32 public static T Next(List servers) where T : WeightObject
33 {
34 if (servers == null || servers.Count == 0)
35 {
36 return null;
37 }
38 if (servers.Count == 1)
39 {
40 return servers[0];
41 }
42
43 T best = null;
44
45 //计算权重总和
46 int total = 0;
47 for (int i = 0; i )
48 {
49
50 T w = servers[i];
51
52 if (w == null)
53 {
54 continue;
55 }
56
57 w.CurrentWeight += w.EffectiveWeight;
58 total += w.EffectiveWeight;
59
60 if (w.EffectiveWeight w.Weight)
61 {
62 w.EffectiveWeight++;
63 }
64
65 if (best == null || w.CurrentWeight > best.CurrentWeight)
66 {
67 best = w;
68 }
69
70 }
71
72 if (best == null)
73 {
74 return null;
75 }
76
77 best.CurrentWeight -= total;
78 return best;
79 }
80 }
81
82 //1.声明一个继承RandomObject的实体类,如:*
83 public class ServerWeightObject : WeightObject
84 {
85 ///
86 /// 名称
87 ///
88 public string Name { set; get; }
89 ///
90 /// 描述
91 ///
92 public string Description { set; get; }
93 //...其它相关的字段/属性
94
95 public ServerWeightObject()
96 {
97 EffectiveWeight = Weight;
98 }
99 }
100
101
102 ///
103 /// DEMO
104 ///
105 public class BalancingAssignDemo
106 {
107
108 public void Main()
109 {
110
111 //1.初始化调用数据,如:
112 List list = new List();
113 list.Add(new ServerWeightObject { Name = "A", Weight = 2 });
114 list.Add(new ServerWeightObject { Name = "B", Weight = 3 });
115 list.Add(new ServerWeightObject { Name = "C", Weight = 5});
116 //list.Add(new ServerWeightObject { Name = "D", Weight = 3 });
117 //list.Add(new ServerWeightObject { Name = "E", Weight = 4 });
118 //list.Add(new ServerWeightObject { Name = "F", Weight = 5 });
119 //list.Add(new ServerWeightObject { Name = "G", Weight = 60 });
120 for (int i = 0; i 20; i++)
121 {
122 System.Diagnostics.Debug.Write(BalancingAssignHelper.Next(list).Name);
123 }
124 }
125 }