-
Notifications
You must be signed in to change notification settings - Fork 3
/
scheduling_group.go
163 lines (139 loc) · 3.76 KB
/
scheduling_group.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package serverconfigs
import (
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/schedulingconfigs"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
"github.com/iwind/TeaGo/maps"
)
// SchedulingGroup 负载均衡分组
type SchedulingGroup struct {
Scheduling *SchedulingConfig `yaml:"scheduling" json:"scheduling"`
PrimaryOrigins []*OriginConfig
BackupOrigins []*OriginConfig
hasPrimaryOrigins bool
hasBackupOrigins bool
schedulingIsBackup bool
schedulingObject schedulingconfigs.SchedulingInterface
}
// Init 初始化
func (this *SchedulingGroup) Init() error {
this.hasPrimaryOrigins = len(this.PrimaryOrigins) > 0
this.hasBackupOrigins = len(this.BackupOrigins) > 0
if this.Scheduling == nil {
this.Scheduling = &SchedulingConfig{
Code: "random",
Options: maps.Map{},
}
}
return nil
}
// NextOrigin 取得下一个可用源站
func (this *SchedulingGroup) NextOrigin(call *shared.RequestCall) *OriginConfig {
if this.schedulingObject == nil {
return nil
}
if this.Scheduling != nil && call != nil && call.Options != nil {
for k, v := range this.Scheduling.Options {
call.Options[k] = v
}
}
var candidate = this.schedulingObject.Next(call)
// 末了重置状态
defer func() {
if candidate == nil {
this.schedulingIsBackup = false
}
}()
if candidate == nil {
// 启用备用服务器
if !this.schedulingIsBackup {
this.SetupScheduling(true, true)
candidate = this.schedulingObject.Next(call)
if candidate == nil {
// 不检查主要源站
this.SetupScheduling(false, false)
candidate = this.schedulingObject.Next(call)
if candidate == nil {
// 不检查备用源站
this.SetupScheduling(true, false)
candidate = this.schedulingObject.Next(call)
if candidate == nil {
return nil
}
}
}
}
if candidate == nil {
return nil
}
}
return candidate.(*OriginConfig)
}
// AnyOrigin 取下一个任意源站
func (this *SchedulingGroup) AnyOrigin(excludingOriginIds []int64) *OriginConfig {
for _, origin := range this.PrimaryOrigins {
if !origin.IsOn {
continue
}
if !this.containsInt64(excludingOriginIds, origin.Id) {
return origin
}
}
for _, origin := range this.BackupOrigins {
if !origin.IsOn {
continue
}
if !this.containsInt64(excludingOriginIds, origin.Id) {
return origin
}
}
return nil
}
// SetupScheduling 设置调度算法
func (this *SchedulingGroup) SetupScheduling(isBackup bool, checkOk bool) {
// 如果只有一个源站,则快速返回,避免因为状态的改变而不停地转换
if checkOk {
if len(this.PrimaryOrigins) == 1 && len(this.BackupOrigins) == 0 && this.schedulingObject != nil {
return
}
}
this.schedulingIsBackup = isBackup
if this.Scheduling == nil {
this.schedulingObject = &schedulingconfigs.RandomScheduling{}
} else {
typeCode := this.Scheduling.Code
s := schedulingconfigs.FindSchedulingType(typeCode)
if s == nil {
this.Scheduling = nil
this.schedulingObject = &schedulingconfigs.RandomScheduling{}
} else {
this.schedulingObject = s["instance"].(schedulingconfigs.SchedulingInterface)
}
}
if !isBackup {
for _, origin := range this.PrimaryOrigins {
if origin.IsOn && (origin.IsOk || !checkOk) {
this.schedulingObject.Add(origin)
}
}
} else {
for _, origin := range this.BackupOrigins {
if origin.IsOn && (origin.IsOk || !checkOk) {
this.schedulingObject.Add(origin)
}
}
}
if !this.schedulingObject.HasCandidates() {
return
}
this.schedulingObject.Start()
}
// 判断是否包含int64
func (this *SchedulingGroup) containsInt64(originIds []int64, originId int64) bool {
for _, id := range originIds {
if id == originId {
return true
}
}
return false
}