mirror of
https://github.com/TeaOSLab/EdgeCommon.git
synced 2026-04-30 19:45:19 +08:00
反向代理源站实现使用域名分组
This commit is contained in:
@@ -28,6 +28,8 @@ type OriginConfig struct {
|
||||
MaxConns int `yaml:"maxConns" json:"maxConns"` // 最大并发连接数
|
||||
MaxIdleConns int `yaml:"idleConns" json:"idleConns"` // 最大空闲连接数
|
||||
|
||||
Domains []string `yaml:"domains" json:"domains"` // 所属域名
|
||||
|
||||
StripPrefix string `yaml:"stripPrefix" json:"stripPrefix"` // 去除URL前缀
|
||||
RequestURI string `yaml:"requestURI" json:"requestURI"` // 转发后的请求URI TODO
|
||||
RequestHost string `yaml:"requestHost" json:"requestHost"` // 自定义主机名 TODO
|
||||
|
||||
@@ -2,7 +2,6 @@ package serverconfigs
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/configutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/schedulingconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
|
||||
"github.com/iwind/TeaGo/lists"
|
||||
"sync"
|
||||
@@ -45,11 +44,8 @@ type ReverseProxyConfig struct {
|
||||
requestHostHasVariables bool
|
||||
requestURIHasVariables bool
|
||||
|
||||
hasPrimaryOrigins bool
|
||||
hasBackupOrigins bool
|
||||
schedulingIsBackup bool
|
||||
schedulingObject schedulingconfigs.SchedulingInterface
|
||||
schedulingLocker sync.Mutex
|
||||
schedulingGroupMap map[string]*SchedulingGroup // domain => *SchedulingGroup
|
||||
schedulingLocker sync.RWMutex
|
||||
|
||||
addXRealIPHeader bool
|
||||
addXForwardedForHeader bool
|
||||
@@ -64,9 +60,68 @@ func (this *ReverseProxyConfig) Init() error {
|
||||
this.requestHostHasVariables = configutils.HasVariables(this.RequestHost)
|
||||
this.requestURIHasVariables = configutils.HasVariables(this.RequestURI)
|
||||
|
||||
this.hasPrimaryOrigins = len(this.PrimaryOrigins) > 0
|
||||
this.hasBackupOrigins = len(this.BackupOrigins) > 0
|
||||
// 将源站分组
|
||||
this.schedulingGroupMap = map[string]*SchedulingGroup{}
|
||||
for _, origin := range this.PrimaryOrigins {
|
||||
if len(origin.Domains) == 0 {
|
||||
group, ok := this.schedulingGroupMap[""]
|
||||
if !ok {
|
||||
group = &SchedulingGroup{}
|
||||
if this.Scheduling != nil {
|
||||
group.Scheduling = this.Scheduling.Clone()
|
||||
}
|
||||
this.schedulingGroupMap[""] = group
|
||||
}
|
||||
group.PrimaryOrigins = append(group.PrimaryOrigins, origin)
|
||||
} else {
|
||||
for _, domain := range origin.Domains {
|
||||
group, ok := this.schedulingGroupMap[domain]
|
||||
if !ok {
|
||||
group = &SchedulingGroup{}
|
||||
if this.Scheduling != nil {
|
||||
group.Scheduling = this.Scheduling.Clone()
|
||||
}
|
||||
this.schedulingGroupMap[domain] = group
|
||||
}
|
||||
group.PrimaryOrigins = append(group.PrimaryOrigins, origin)
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, origin := range this.BackupOrigins {
|
||||
if len(origin.Domains) == 0 {
|
||||
group, ok := this.schedulingGroupMap[""]
|
||||
if !ok {
|
||||
group = &SchedulingGroup{}
|
||||
if this.Scheduling != nil {
|
||||
group.Scheduling = this.Scheduling.Clone()
|
||||
}
|
||||
this.schedulingGroupMap[""] = group
|
||||
}
|
||||
group.BackupOrigins = append(group.BackupOrigins, origin)
|
||||
} else {
|
||||
for _, domain := range origin.Domains {
|
||||
group, ok := this.schedulingGroupMap[domain]
|
||||
if !ok {
|
||||
group = &SchedulingGroup{}
|
||||
if this.Scheduling != nil {
|
||||
group.Scheduling = this.Scheduling.Clone()
|
||||
}
|
||||
this.schedulingGroupMap[domain] = group
|
||||
}
|
||||
group.BackupOrigins = append(group.BackupOrigins, origin)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 初始化分组
|
||||
for _, group := range this.schedulingGroupMap {
|
||||
err := group.Init()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// 初始化Origin
|
||||
for _, origins := range [][]*OriginConfig{this.PrimaryOrigins, this.BackupOrigins} {
|
||||
for _, origin := range origins {
|
||||
// 覆盖参数设置
|
||||
@@ -131,54 +186,39 @@ func (this *ReverseProxyConfig) AddBackupOrigin(origin *OriginConfig) {
|
||||
|
||||
// NextOrigin 取得下一个可用的后端服务
|
||||
func (this *ReverseProxyConfig) NextOrigin(call *shared.RequestCall) *OriginConfig {
|
||||
this.schedulingLocker.Lock()
|
||||
defer this.schedulingLocker.Unlock()
|
||||
this.schedulingLocker.RLock()
|
||||
defer this.schedulingLocker.RUnlock()
|
||||
|
||||
if this.schedulingObject == nil {
|
||||
if len(this.schedulingGroupMap) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
if this.Scheduling != nil && call != nil && call.Options != nil {
|
||||
for k, v := range this.Scheduling.Options {
|
||||
call.Options[k] = v
|
||||
// 空域名
|
||||
if len(call.Domain) == 0 {
|
||||
group, ok := this.schedulingGroupMap[""]
|
||||
if ok {
|
||||
return group.NextOrigin(call)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
candidate := this.schedulingObject.Next(call)
|
||||
|
||||
// 末了重置状态
|
||||
defer func() {
|
||||
if candidate == nil {
|
||||
this.schedulingIsBackup = false
|
||||
}
|
||||
}()
|
||||
|
||||
if candidate == nil {
|
||||
// 启用备用服务器
|
||||
if !this.schedulingIsBackup {
|
||||
this.SetupScheduling(true, true, false)
|
||||
candidate = this.schedulingObject.Next(call)
|
||||
if candidate == nil {
|
||||
// 不检查主要源站
|
||||
this.SetupScheduling(false, false, false)
|
||||
candidate = this.schedulingObject.Next(call)
|
||||
if candidate == nil {
|
||||
// 不检查备用源站
|
||||
this.SetupScheduling(true, false, false)
|
||||
candidate = this.schedulingObject.Next(call)
|
||||
if candidate == nil {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
// 按域名匹配
|
||||
for domainPattern, group := range this.schedulingGroupMap {
|
||||
if len(domainPattern) > 0 && configutils.MatchDomain(domainPattern, call.Domain) {
|
||||
origin := group.NextOrigin(call)
|
||||
if origin != nil {
|
||||
return origin
|
||||
}
|
||||
}
|
||||
|
||||
if candidate == nil {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
return candidate.(*OriginConfig)
|
||||
// 再次查找没有设置域名的分组
|
||||
group, ok := this.schedulingGroupMap[""]
|
||||
if ok {
|
||||
return group.NextOrigin(call)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetupScheduling 设置调度算法
|
||||
@@ -188,40 +228,9 @@ func (this *ReverseProxyConfig) SetupScheduling(isBackup bool, checkOk bool, loc
|
||||
defer this.schedulingLocker.Unlock()
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
for _, group := range this.schedulingGroupMap {
|
||||
group.SetupScheduling(isBackup, checkOk)
|
||||
}
|
||||
|
||||
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()
|
||||
}
|
||||
|
||||
// FindSchedulingConfig 获取调度配置对象
|
||||
|
||||
60
pkg/serverconfigs/reverse_proxy_config_test.go
Normal file
60
pkg/serverconfigs/reverse_proxy_config_test.go
Normal file
@@ -0,0 +1,60 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
|
||||
package serverconfigs
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestReverseProxyConfig_Init(t *testing.T) {
|
||||
var config = &ReverseProxyConfig{}
|
||||
config.Scheduling = &SchedulingConfig{
|
||||
Code: "random",
|
||||
Options: nil,
|
||||
}
|
||||
config.AddPrimaryOrigin(&OriginConfig{
|
||||
Addr: &NetworkAddressConfig{Host: "127.0.0.1"},
|
||||
IsOn: true,
|
||||
})
|
||||
config.AddPrimaryOrigin(&OriginConfig{
|
||||
Addr: &NetworkAddressConfig{Host: "127.0.0.2"},
|
||||
IsOn: true,
|
||||
})
|
||||
config.AddPrimaryOrigin(&OriginConfig{
|
||||
Addr: &NetworkAddressConfig{Host: "127.0.0.3"},
|
||||
Domains: []string{"*.www.example.com", ".example.com"},
|
||||
IsOn: true,
|
||||
})
|
||||
config.AddBackupOrigin(&OriginConfig{
|
||||
Addr: &NetworkAddressConfig{Host: "127.0.0.4"},
|
||||
IsOn: true,
|
||||
})
|
||||
err := config.Init()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for domain, group := range config.schedulingGroupMap {
|
||||
for _, origin := range group.PrimaryOrigins {
|
||||
t.Log(domain, "primary", origin.Addr.Host)
|
||||
}
|
||||
for _, origin := range group.BackupOrigins {
|
||||
t.Log(domain, "backup", origin.Addr.Host)
|
||||
}
|
||||
}
|
||||
|
||||
//config.ResetScheduling()
|
||||
|
||||
nextOrigin := config.NextOrigin(&shared.RequestCall{
|
||||
Formatter: nil,
|
||||
Request: nil,
|
||||
Domain: "a.example.com",
|
||||
ResponseCallbacks: nil,
|
||||
Options: nil,
|
||||
})
|
||||
if nextOrigin == nil {
|
||||
t.Log("not found")
|
||||
} else {
|
||||
t.Log("result:", nextOrigin.Addr.Host)
|
||||
}
|
||||
}
|
||||
@@ -2,13 +2,21 @@ package serverconfigs
|
||||
|
||||
import "github.com/iwind/TeaGo/maps"
|
||||
|
||||
// 调度算法配置
|
||||
// SchedulingConfig 调度算法配置
|
||||
type SchedulingConfig struct {
|
||||
Code string `yaml:"code" json:"code"` // 类型
|
||||
Options maps.Map `yaml:"options" json:"options"` // 选项
|
||||
}
|
||||
|
||||
// 获取新对象
|
||||
// NewSchedulingConfig 获取新对象
|
||||
func NewSchedulingConfig() *SchedulingConfig {
|
||||
return &SchedulingConfig{}
|
||||
}
|
||||
|
||||
// Clone 克隆
|
||||
func (this *SchedulingConfig) Clone() *SchedulingConfig {
|
||||
return &SchedulingConfig{
|
||||
Code: this.Code,
|
||||
Options: maps.NewMap(this.Options),
|
||||
}
|
||||
}
|
||||
|
||||
124
pkg/serverconfigs/scheduling_group.go
Normal file
124
pkg/serverconfigs/scheduling_group.go
Normal file
@@ -0,0 +1,124 @@
|
||||
// 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
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
// SetupScheduling 设置调度算法
|
||||
func (this *SchedulingGroup) SetupScheduling(isBackup bool, checkOk bool) {
|
||||
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()
|
||||
}
|
||||
@@ -1,10 +1,10 @@
|
||||
package schedulingconfigs
|
||||
|
||||
// 候选对象接口
|
||||
// CandidateInterface 候选对象接口
|
||||
type CandidateInterface interface {
|
||||
// 权重
|
||||
// CandidateWeight 权重
|
||||
CandidateWeight() uint
|
||||
|
||||
// 代号
|
||||
// CandidateCodes 代号
|
||||
CandidateCodes() []string
|
||||
}
|
||||
|
||||
@@ -5,35 +5,35 @@ import (
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
// 调度算法接口
|
||||
// SchedulingInterface 调度算法接口
|
||||
type SchedulingInterface interface {
|
||||
// 是否有候选对象
|
||||
// HasCandidates 是否有候选对象
|
||||
HasCandidates() bool
|
||||
|
||||
// 添加候选对象
|
||||
// Add 添加候选对象
|
||||
Add(candidate ...CandidateInterface)
|
||||
|
||||
// 启动
|
||||
// Start 启动
|
||||
Start()
|
||||
|
||||
// 查找下一个候选对象
|
||||
// Next 查找下一个候选对象
|
||||
Next(call *shared.RequestCall) CandidateInterface
|
||||
|
||||
// 获取简要信息
|
||||
// Summary 获取简要信息
|
||||
Summary() maps.Map
|
||||
}
|
||||
|
||||
// 调度算法基础类
|
||||
// Scheduling 调度算法基础类
|
||||
type Scheduling struct {
|
||||
Candidates []CandidateInterface
|
||||
}
|
||||
|
||||
// 判断是否有候选对象
|
||||
// HasCandidates 判断是否有候选对象
|
||||
func (this *Scheduling) HasCandidates() bool {
|
||||
return len(this.Candidates) > 0
|
||||
}
|
||||
|
||||
// 添加候选对象
|
||||
// Add 添加候选对象
|
||||
func (this *Scheduling) Add(candidate ...CandidateInterface) {
|
||||
this.Candidates = append(this.Candidates, candidate...)
|
||||
}
|
||||
|
||||
@@ -6,19 +6,19 @@ import (
|
||||
"hash/crc32"
|
||||
)
|
||||
|
||||
// Hash调度算法
|
||||
// HashScheduling Hash调度算法
|
||||
type HashScheduling struct {
|
||||
Scheduling
|
||||
|
||||
count uint32
|
||||
}
|
||||
|
||||
// 启动
|
||||
// Start 启动
|
||||
func (this *HashScheduling) Start() {
|
||||
this.count = uint32(len(this.Candidates))
|
||||
}
|
||||
|
||||
// 获取下一个候选对象
|
||||
// Next 获取下一个候选对象
|
||||
func (this *HashScheduling) Next(call *shared.RequestCall) CandidateInterface {
|
||||
if this.count == 0 {
|
||||
return nil
|
||||
@@ -34,7 +34,7 @@ func (this *HashScheduling) Next(call *shared.RequestCall) CandidateInterface {
|
||||
return this.Candidates[sum%this.count]
|
||||
}
|
||||
|
||||
// 获取简要信息
|
||||
// Summary 获取简要信息
|
||||
func (this *HashScheduling) Summary() maps.Map {
|
||||
return maps.Map{
|
||||
"code": "hash",
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
// 随机调度算法
|
||||
// RandomScheduling 随机调度算法
|
||||
type RandomScheduling struct {
|
||||
Scheduling
|
||||
|
||||
@@ -16,7 +16,7 @@ type RandomScheduling struct {
|
||||
count uint // 实际总的服务器数
|
||||
}
|
||||
|
||||
// 启动
|
||||
// Start 启动
|
||||
func (this *RandomScheduling) Start() {
|
||||
sumWeight := uint(0)
|
||||
for _, c := range this.Candidates {
|
||||
@@ -55,7 +55,7 @@ func (this *RandomScheduling) Start() {
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
}
|
||||
|
||||
// 获取下一个候选对象
|
||||
// Next 获取下一个候选对象
|
||||
func (this *RandomScheduling) Next(call *shared.RequestCall) CandidateInterface {
|
||||
if this.count == 0 {
|
||||
return nil
|
||||
@@ -67,7 +67,7 @@ func (this *RandomScheduling) Next(call *shared.RequestCall) CandidateInterface
|
||||
return this.array[index]
|
||||
}
|
||||
|
||||
// 获取简要信息
|
||||
// Summary 获取简要信息
|
||||
func (this *RandomScheduling) Summary() maps.Map {
|
||||
return maps.Map{
|
||||
"code": "random",
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
"sync"
|
||||
)
|
||||
|
||||
// 轮询调度算法
|
||||
// RoundRobinScheduling 轮询调度算法
|
||||
type RoundRobinScheduling struct {
|
||||
Scheduling
|
||||
|
||||
@@ -19,7 +19,7 @@ type RoundRobinScheduling struct {
|
||||
locker sync.Mutex
|
||||
}
|
||||
|
||||
// 启动
|
||||
// Start 启动
|
||||
func (this *RoundRobinScheduling) Start() {
|
||||
lists.Sort(this.Candidates, func(i int, j int) bool {
|
||||
c1 := this.Candidates[i]
|
||||
@@ -41,7 +41,7 @@ func (this *RoundRobinScheduling) Start() {
|
||||
this.count = uint(len(this.Candidates))
|
||||
}
|
||||
|
||||
// 获取下一个候选对象
|
||||
// Next 获取下一个候选对象
|
||||
func (this *RoundRobinScheduling) Next(call *shared.RequestCall) CandidateInterface {
|
||||
if this.count == 0 {
|
||||
return nil
|
||||
@@ -69,7 +69,7 @@ func (this *RoundRobinScheduling) Next(call *shared.RequestCall) CandidateInterf
|
||||
return c
|
||||
}
|
||||
|
||||
// 获取简要信息
|
||||
// Summary 获取简要信息
|
||||
func (this *RoundRobinScheduling) Summary() maps.Map {
|
||||
return maps.Map{
|
||||
"code": "roundRobin",
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
// Sticky调度算法
|
||||
// StickyScheduling Sticky调度算法
|
||||
type StickyScheduling struct {
|
||||
Scheduling
|
||||
|
||||
@@ -16,7 +16,7 @@ type StickyScheduling struct {
|
||||
mapping map[string]CandidateInterface // code => candidate
|
||||
}
|
||||
|
||||
// 启动
|
||||
// Start 启动
|
||||
func (this *StickyScheduling) Start() {
|
||||
this.mapping = map[string]CandidateInterface{}
|
||||
for _, c := range this.Candidates {
|
||||
@@ -29,7 +29,7 @@ func (this *StickyScheduling) Start() {
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
}
|
||||
|
||||
// 获取下一个候选对象
|
||||
// Next 获取下一个候选对象
|
||||
func (this *StickyScheduling) Next(call *shared.RequestCall) CandidateInterface {
|
||||
if this.count == 0 {
|
||||
return nil
|
||||
@@ -95,7 +95,7 @@ func (this *StickyScheduling) Next(call *shared.RequestCall) CandidateInterface
|
||||
return c
|
||||
}
|
||||
|
||||
// 获取简要信息
|
||||
// Summary 获取简要信息
|
||||
func (this *StickyScheduling) Summary() maps.Map {
|
||||
return maps.Map{
|
||||
"code": "sticky",
|
||||
|
||||
@@ -5,22 +5,24 @@ import (
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// 请求调用
|
||||
// RequestCall 请求调用
|
||||
type RequestCall struct {
|
||||
Formatter func(source string) string
|
||||
Request *http.Request
|
||||
Formatter func(source string) string // 当前变量格式化函数
|
||||
Request *http.Request // 当前请求
|
||||
Domain string // 当前域名
|
||||
|
||||
ResponseCallbacks []func(resp http.ResponseWriter)
|
||||
Options maps.Map
|
||||
}
|
||||
|
||||
// 获取新对象
|
||||
// NewRequestCall 获取新对象
|
||||
func NewRequestCall() *RequestCall {
|
||||
return &RequestCall{
|
||||
Options: maps.Map{},
|
||||
}
|
||||
}
|
||||
|
||||
// 重置
|
||||
// Reset 重置
|
||||
func (this *RequestCall) Reset() {
|
||||
this.Formatter = nil
|
||||
this.Request = nil
|
||||
@@ -28,12 +30,12 @@ func (this *RequestCall) Reset() {
|
||||
this.Options = maps.Map{}
|
||||
}
|
||||
|
||||
// 添加响应回调
|
||||
// AddResponseCall 添加响应回调
|
||||
func (this *RequestCall) AddResponseCall(callback func(resp http.ResponseWriter)) {
|
||||
this.ResponseCallbacks = append(this.ResponseCallbacks, callback)
|
||||
}
|
||||
|
||||
// 执行响应回调
|
||||
// CallResponseCallbacks 执行响应回调
|
||||
func (this *RequestCall) CallResponseCallbacks(resp http.ResponseWriter) {
|
||||
for _, callback := range this.ResponseCallbacks {
|
||||
callback(resp)
|
||||
|
||||
Reference in New Issue
Block a user