mirror of
https://github.com/TeaOSLab/EdgeCommon.git
synced 2026-04-22 04:55:29 +08:00
阶段性提交
This commit is contained in:
@@ -11,9 +11,9 @@ var regexpSinglePort = regexp.MustCompile(`^\d+$`)
|
||||
|
||||
// 网络地址配置
|
||||
type NetworkAddressConfig struct {
|
||||
Protocol string `yaml:"protocol" json:"protocol"` // 协议,http、tcp、tcp4、tcp6、unix、udp等
|
||||
Host string `yaml:"host" json:"host"` // 主机地址或主机名
|
||||
PortRange string `yaml:"portRange" json:"portRange"` // 端口范围,支持 8080、8080-8090、8080:8090
|
||||
Protocol Protocol `yaml:"protocol" json:"protocol"` // 协议,http、tcp、tcp4、tcp6、unix、udp等
|
||||
Host string `yaml:"host" json:"host"` // 主机地址或主机名
|
||||
PortRange string `yaml:"portRange" json:"portRange"` // 端口范围,支持 8080、8080-8090、8080:8090
|
||||
|
||||
minPort int
|
||||
maxPort int
|
||||
@@ -58,13 +58,13 @@ func (this *NetworkAddressConfig) Init() error {
|
||||
|
||||
func (this *NetworkAddressConfig) FullAddresses() []string {
|
||||
if this.Protocol == ProtocolUnix {
|
||||
return []string{this.Protocol + ":" + this.Host}
|
||||
return []string{this.Protocol.String() + ":" + this.Host}
|
||||
}
|
||||
|
||||
result := []string{}
|
||||
for i := this.minPort; i <= this.maxPort; i++ {
|
||||
host := this.Host
|
||||
result = append(result, this.Protocol+"://"+host+":"+strconv.Itoa(i))
|
||||
result = append(result, this.Protocol.String()+"://"+host+":"+strconv.Itoa(i))
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
@@ -22,19 +22,13 @@ type OriginServerConfig struct {
|
||||
Description string `yaml:"description" json:"description"` // 描述 TODO
|
||||
Code string `yaml:"code" json:"code"` // 代号 TODO
|
||||
|
||||
Weight uint `yaml:"weight" json:"weight"` // 权重 TODO
|
||||
IsBackup bool `yaml:"backup" json:"isBackup"` // 是否为备份 TODO
|
||||
ConnTimeout shared.TimeDuration `yaml:"failTimeout" json:"failTimeout"` // 连接失败超时 TODO
|
||||
ReadTimeout shared.TimeDuration `yaml:"readTimeout" json:"readTimeout"` // 读取超时时间 TODO
|
||||
IdleTimeout shared.TimeDuration `yaml:"idleTimeout" json:"idleTimeout"` // 空闲连接超时时间 TODO
|
||||
MaxFails int32 `yaml:"maxFails" json:"maxFails"` // 最多失败次数 TODO
|
||||
CurrentFails int32 `yaml:"currentFails" json:"currentFails"` // 当前已失败次数 TODO
|
||||
MaxConns int32 `yaml:"maxConns" json:"maxConns"` // 最大并发连接数 TODO
|
||||
CurrentConns int32 `yaml:"currentConns" json:"currentConns"` // 当前连接数 TODO
|
||||
MaxIdleConns int32 `yaml:"idleConns" json:"idleConns"` // 最大空闲连接数 TODO
|
||||
|
||||
IsDown bool `yaml:"down" json:"isDown"` // 是否下线 TODO
|
||||
DownTime time.Time `yaml:"downTime,omitempty" json:"downTime,omitempty"` // 下线时间 TODO
|
||||
Weight uint `yaml:"weight" json:"weight"` // 权重 TODO
|
||||
ConnTimeout shared.TimeDuration `yaml:"failTimeout" json:"failTimeout"` // 连接失败超时 TODO
|
||||
ReadTimeout shared.TimeDuration `yaml:"readTimeout" json:"readTimeout"` // 读取超时时间 TODO
|
||||
IdleTimeout shared.TimeDuration `yaml:"idleTimeout" json:"idleTimeout"` // 空闲连接超时时间 TODO
|
||||
MaxFails int `yaml:"maxFails" json:"maxFails"` // 最多失败次数 TODO
|
||||
MaxConns int `yaml:"maxConns" json:"maxConns"` // 最大并发连接数 TODO
|
||||
MaxIdleConns int `yaml:"idleConns" json:"idleConns"` // 最大空闲连接数 TODO
|
||||
|
||||
RequestURI string `yaml:"requestURI" json:"requestURI"` // 转发后的请求URI TODO
|
||||
Host string `yaml:"host" json:"host"` // 自定义主机名 TODO
|
||||
@@ -172,5 +166,5 @@ func (this *OriginServerConfig) Connect() (net.Conn, error) {
|
||||
|
||||
// TODO 支持从Unix、Pipe、HTTP、HTTPS中读取数据
|
||||
|
||||
return nil, errors.New("invalid scheme '" + this.Addr.Protocol + "'")
|
||||
return nil, errors.New("invalid scheme '" + this.Addr.Protocol.String() + "'")
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package serverconfigs
|
||||
|
||||
type Protocol = string
|
||||
type Protocol string
|
||||
|
||||
const (
|
||||
ProtocolHTTP Protocol = "http"
|
||||
@@ -27,3 +27,52 @@ const (
|
||||
func AllProtocols() []Protocol {
|
||||
return []Protocol{ProtocolHTTP, ProtocolHTTPS, ProtocolTCP, ProtocolTLS, ProtocolUnix, ProtocolUDP, ProtocolHTTP4, ProtocolHTTP6, ProtocolHTTPS4, ProtocolHTTPS6, ProtocolTCP4, ProtocolTCP6, ProtocolTLS4, ProtocolTLS6}
|
||||
}
|
||||
|
||||
func (this Protocol) IsHTTPFamily() bool {
|
||||
return this == ProtocolHTTP || this == ProtocolHTTP4 || this == ProtocolHTTP6
|
||||
}
|
||||
|
||||
func (this Protocol) IsHTTPSFamily() bool {
|
||||
return this == ProtocolHTTPS || this == ProtocolHTTPS4 || this == ProtocolHTTPS6
|
||||
}
|
||||
|
||||
func (this Protocol) IsTCPFamily() bool {
|
||||
return this == ProtocolTCP || this == ProtocolTCP4 || this == ProtocolTCP6
|
||||
}
|
||||
|
||||
func (this Protocol) IsTLSFamily() bool {
|
||||
return this == ProtocolTLS || this == ProtocolTLS4 || this == ProtocolTLS6
|
||||
}
|
||||
|
||||
func (this Protocol) IsUnixFamily() bool {
|
||||
return this == ProtocolUnix
|
||||
}
|
||||
|
||||
func (this Protocol) IsUDPFamily() bool {
|
||||
return this == ProtocolUDP
|
||||
}
|
||||
|
||||
// 主协议
|
||||
func (this Protocol) Primary() Protocol {
|
||||
switch this {
|
||||
case ProtocolHTTP, ProtocolHTTP4, ProtocolHTTP6:
|
||||
return ProtocolHTTP
|
||||
case ProtocolHTTPS, ProtocolHTTPS4, ProtocolHTTPS6:
|
||||
return ProtocolHTTPS
|
||||
case ProtocolTCP, ProtocolTCP4, ProtocolTCP6:
|
||||
return ProtocolTCP
|
||||
case ProtocolTLS, ProtocolTLS4, ProtocolTLS6:
|
||||
return ProtocolTLS
|
||||
case ProtocolUnix:
|
||||
return ProtocolUnix
|
||||
case ProtocolUDP:
|
||||
return ProtocolUDP
|
||||
default:
|
||||
return this
|
||||
}
|
||||
}
|
||||
|
||||
// 转换为字符串
|
||||
func (this Protocol) String() string {
|
||||
return string(this)
|
||||
}
|
||||
|
||||
22
pkg/serverconfigs/protocol_test.go
Normal file
22
pkg/serverconfigs/protocol_test.go
Normal file
@@ -0,0 +1,22 @@
|
||||
package serverconfigs
|
||||
|
||||
import (
|
||||
"github.com/iwind/TeaGo/assert"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestProtocol_IsHTTPFamily(t *testing.T) {
|
||||
a := assert.NewAssertion(t)
|
||||
t.Log(ProtocolHTTP.String(), ProtocolHTTPS.String(), ProtocolTCP)
|
||||
a.IsTrue(ProtocolHTTP.IsHTTPFamily())
|
||||
a.IsTrue(ProtocolHTTP4.IsHTTPFamily())
|
||||
a.IsTrue(ProtocolHTTP6.IsHTTPFamily())
|
||||
a.IsTrue(ProtocolHTTPS.IsHTTPSFamily())
|
||||
a.IsTrue(ProtocolHTTPS4.IsHTTPSFamily())
|
||||
a.IsTrue(ProtocolHTTPS6.IsHTTPSFamily())
|
||||
a.IsTrue(ProtocolTCP.IsTCPFamily())
|
||||
a.IsTrue(ProtocolTCP.IsTCPFamily())
|
||||
a.IsTrue(ProtocolTCP6.IsTCPFamily())
|
||||
a.IsTrue(ProtocolUnix.IsUnixFamily())
|
||||
a.IsTrue(ProtocolUDP.IsUDPFamily())
|
||||
}
|
||||
@@ -1,28 +1,38 @@
|
||||
package serverconfigs
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/scheduling"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/schedulingconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// 反向代理设置
|
||||
type ReverseProxyConfig struct {
|
||||
IsOn bool `yaml:"isOn" json:"isOn"` // 是否启用 TODO
|
||||
Origins []*OriginServerConfig `yaml:"origins" json:"origins"` // 源站列表
|
||||
Scheduling *SchedulingConfig `yaml:"scheduling" json:"scheduling"` // 调度算法选项
|
||||
IsOn bool `yaml:"isOn" json:"isOn"` // 是否启用 TODO
|
||||
PrimaryOrigins []*OriginServerConfig `yaml:"primaryOrigins" json:"primaryOrigins"` // 主要源站列表
|
||||
BackupOrigins []*OriginServerConfig `yaml:"backupOrigins" json:"backupOrigins"` // 备用源站列表
|
||||
Scheduling *SchedulingConfig `yaml:"scheduling" json:"scheduling"` // 调度算法选项
|
||||
|
||||
hasOrigins bool
|
||||
hasPrimaryOrigins bool
|
||||
hasBackupOrigins bool
|
||||
schedulingIsBackup bool
|
||||
schedulingObject scheduling.SchedulingInterface
|
||||
schedulingObject schedulingconfigs.SchedulingInterface
|
||||
schedulingLocker sync.Mutex
|
||||
}
|
||||
|
||||
// 初始化
|
||||
func (this *ReverseProxyConfig) Init() error {
|
||||
this.hasOrigins = len(this.Origins) > 0
|
||||
this.hasPrimaryOrigins = len(this.PrimaryOrigins) > 0
|
||||
this.hasBackupOrigins = len(this.BackupOrigins) > 0
|
||||
|
||||
for _, origin := range this.Origins {
|
||||
for _, origin := range this.PrimaryOrigins {
|
||||
err := origin.Init()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
for _, origin := range this.BackupOrigins {
|
||||
err := origin.Init()
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -35,6 +45,16 @@ func (this *ReverseProxyConfig) Init() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// 添加主源站配置
|
||||
func (this *ReverseProxyConfig) AddPrimaryOrigin(origin *OriginServerConfig) {
|
||||
this.PrimaryOrigins = append(this.PrimaryOrigins, origin)
|
||||
}
|
||||
|
||||
// 添加备用源站配置
|
||||
func (this *ReverseProxyConfig) AddBackupOrigin(origin *OriginServerConfig) {
|
||||
this.BackupOrigins = append(this.BackupOrigins, origin)
|
||||
}
|
||||
|
||||
// 取得下一个可用的后端服务
|
||||
func (this *ReverseProxyConfig) NextOrigin(call *shared.RequestCall) *OriginServerConfig {
|
||||
this.schedulingLocker.Lock()
|
||||
@@ -79,23 +99,27 @@ func (this *ReverseProxyConfig) SetupScheduling(isBackup bool) {
|
||||
this.schedulingIsBackup = isBackup
|
||||
|
||||
if this.Scheduling == nil {
|
||||
this.schedulingObject = &scheduling.RandomScheduling{}
|
||||
this.schedulingObject = &schedulingconfigs.RandomScheduling{}
|
||||
} else {
|
||||
typeCode := this.Scheduling.Code
|
||||
s := scheduling.FindSchedulingType(typeCode)
|
||||
s := schedulingconfigs.FindSchedulingType(typeCode)
|
||||
if s == nil {
|
||||
this.Scheduling = nil
|
||||
this.schedulingObject = &scheduling.RandomScheduling{}
|
||||
this.schedulingObject = &schedulingconfigs.RandomScheduling{}
|
||||
} else {
|
||||
this.schedulingObject = s["instance"].(scheduling.SchedulingInterface)
|
||||
this.schedulingObject = s["instance"].(schedulingconfigs.SchedulingInterface)
|
||||
}
|
||||
}
|
||||
|
||||
for _, origin := range this.Origins {
|
||||
if origin.IsOn && !origin.IsDown {
|
||||
if isBackup && origin.IsBackup {
|
||||
if !isBackup {
|
||||
for _, origin := range this.PrimaryOrigins {
|
||||
if origin.IsOn {
|
||||
this.schedulingObject.Add(origin)
|
||||
} else if !isBackup && !origin.IsBackup {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for _, origin := range this.BackupOrigins {
|
||||
if origin.IsOn {
|
||||
this.schedulingObject.Add(origin)
|
||||
}
|
||||
}
|
||||
@@ -103,3 +127,11 @@ func (this *ReverseProxyConfig) SetupScheduling(isBackup bool) {
|
||||
|
||||
this.schedulingObject.Start()
|
||||
}
|
||||
|
||||
// 获取调度配置对象
|
||||
func (this *ReverseProxyConfig) FindSchedulingConfig() *SchedulingConfig {
|
||||
if this.Scheduling == nil {
|
||||
this.Scheduling = &SchedulingConfig{Code: "random"}
|
||||
}
|
||||
return this.Scheduling
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package scheduling
|
||||
package schedulingconfigs
|
||||
|
||||
// 候选对象接口
|
||||
type CandidateInterface interface {
|
||||
@@ -1,4 +1,4 @@
|
||||
package scheduling
|
||||
package schedulingconfigs
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
|
||||
@@ -1,4 +1,4 @@
|
||||
package scheduling
|
||||
package schedulingconfigs
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
|
||||
@@ -39,7 +39,7 @@ func (this *HashScheduling) Summary() maps.Map {
|
||||
return maps.Map{
|
||||
"code": "hash",
|
||||
"name": "Hash算法",
|
||||
"description": "根据自定义的键值的Hash值分配后端服务器",
|
||||
"description": "根据自定义的键值的Hash值分配源站",
|
||||
"networks": []string{"http"},
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package scheduling
|
||||
package schedulingconfigs
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
@@ -1,4 +1,4 @@
|
||||
package scheduling
|
||||
package schedulingconfigs
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
|
||||
@@ -72,7 +72,7 @@ func (this *RandomScheduling) Summary() maps.Map {
|
||||
return maps.Map{
|
||||
"code": "random",
|
||||
"name": "Random随机算法",
|
||||
"description": "根据权重设置随机分配后端服务器",
|
||||
"description": "根据权重设置随机分配源站",
|
||||
"networks": []string{"http", "tcp"},
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package scheduling
|
||||
package schedulingconfigs
|
||||
|
||||
import (
|
||||
"sync"
|
||||
@@ -1,4 +1,4 @@
|
||||
package scheduling
|
||||
package schedulingconfigs
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
|
||||
@@ -74,7 +74,7 @@ func (this *RoundRobinScheduling) Summary() maps.Map {
|
||||
return maps.Map{
|
||||
"code": "roundRobin",
|
||||
"name": "RoundRobin轮询算法",
|
||||
"description": "根据权重,依次分配后端服务器",
|
||||
"description": "根据权重,依次分配源站",
|
||||
"networks": []string{"http", "tcp"},
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package scheduling
|
||||
package schedulingconfigs
|
||||
|
||||
import "testing"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package scheduling
|
||||
package schedulingconfigs
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
|
||||
@@ -100,7 +100,7 @@ func (this *StickyScheduling) Summary() maps.Map {
|
||||
return maps.Map{
|
||||
"code": "sticky",
|
||||
"name": "Sticky算法",
|
||||
"description": "利用Cookie、URL参数或者HTTP Header来指定后端服务器",
|
||||
"description": "利用Cookie、URL参数或者HTTP Header来指定源站",
|
||||
"networks": []string{"http"},
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package scheduling
|
||||
package schedulingconfigs
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
|
||||
@@ -29,14 +29,14 @@ func TestStickyScheduling_NextArgument(t *testing.T) {
|
||||
|
||||
t.Log(s.mapping)
|
||||
|
||||
req, err := http.NewRequest("GET", "http://www.example.com/?backend=c", nil)
|
||||
req, err := http.NewRequest("GET", "http://www.example.com/?origin=c", nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
options := maps.Map{
|
||||
"type": "argument",
|
||||
"param": "backend",
|
||||
"param": "origin",
|
||||
}
|
||||
call := shared.NewRequestCall()
|
||||
call.Request = req
|
||||
@@ -67,19 +67,19 @@ func TestStickyScheduling_NextCookie(t *testing.T) {
|
||||
|
||||
t.Log(s.mapping)
|
||||
|
||||
req, err := http.NewRequest("GET", "http://www.example.com/?backend=c", nil)
|
||||
req, err := http.NewRequest("GET", "http://www.example.com/?origin=c", nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
req.AddCookie(&http.Cookie{
|
||||
Name: "backend",
|
||||
Name: "origin",
|
||||
Value: "c",
|
||||
})
|
||||
|
||||
options := maps.Map{
|
||||
"type": "cookie",
|
||||
"param": "backend",
|
||||
"param": "origin",
|
||||
}
|
||||
call := shared.NewRequestCall()
|
||||
call.Request = req
|
||||
@@ -110,15 +110,15 @@ func TestStickyScheduling_NextHeader(t *testing.T) {
|
||||
|
||||
t.Log(s.mapping)
|
||||
|
||||
req, err := http.NewRequest("GET", "http://www.example.com/?backend=c", nil)
|
||||
req, err := http.NewRequest("GET", "http://www.example.com/?origin=c", nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
req.Header.Set("backend", "c")
|
||||
req.Header.Set("origin", "c")
|
||||
|
||||
options := maps.Map{
|
||||
"type": "header",
|
||||
"param": "backend",
|
||||
"param": "origin",
|
||||
}
|
||||
call := shared.NewRequestCall()
|
||||
call.Request = req
|
||||
@@ -1,4 +1,4 @@
|
||||
package scheduling
|
||||
package schedulingconfigs
|
||||
|
||||
import "github.com/iwind/TeaGo/maps"
|
||||
|
||||
@@ -2,11 +2,13 @@ package serverconfigs
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/sslconfigs"
|
||||
)
|
||||
|
||||
type ServerConfig struct {
|
||||
Id string `yaml:"id" json:"id"` // ID
|
||||
Id int64 `yaml:"id" json:"id"` // ID
|
||||
Type string `yaml:"type" json:"type"` // 类型
|
||||
IsOn bool `yaml:"isOn" json:"isOn"` // 是否开启
|
||||
Components []*ComponentConfig `yaml:"components" json:"components"` // 组件
|
||||
Filters []*FilterConfig `yaml:"filters" json:"filters"` // 过滤器
|
||||
@@ -94,7 +96,7 @@ func (this *ServerConfig) Init() error {
|
||||
}
|
||||
|
||||
func (this *ServerConfig) FullAddresses() []string {
|
||||
result := []Protocol{}
|
||||
result := []string{}
|
||||
if this.HTTP != nil && this.HTTP.IsOn {
|
||||
result = append(result, this.HTTP.FullAddresses()...)
|
||||
}
|
||||
@@ -190,3 +192,16 @@ func (this *ServerConfig) SSLConfig() *sslconfigs.SSLConfig {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// 根据条件查找ReverseProxy
|
||||
func (this *ServerConfig) FindAndCheckReverseProxy(dataType string) (*ReverseProxyConfig, error) {
|
||||
switch dataType {
|
||||
case "server":
|
||||
if this.ReverseProxy == nil {
|
||||
return nil, errors.New("reverse proxy not been configured")
|
||||
}
|
||||
return this.ReverseProxy, nil
|
||||
default:
|
||||
return nil, errors.New("invalid data type:'" + dataType + "'")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ func (this *ServerGroup) FullAddr() string {
|
||||
// 获取当前分组的协议
|
||||
func (this *ServerGroup) Protocol() Protocol {
|
||||
for _, p := range AllProtocols() {
|
||||
if strings.HasPrefix(this.fullAddr, p+":") {
|
||||
if strings.HasPrefix(this.fullAddr, p.String()+":") {
|
||||
return p
|
||||
}
|
||||
}
|
||||
@@ -35,9 +35,9 @@ func (this *ServerGroup) Protocol() Protocol {
|
||||
func (this *ServerGroup) Addr() string {
|
||||
protocol := this.Protocol()
|
||||
if protocol == ProtocolUnix {
|
||||
return strings.TrimPrefix(this.fullAddr, protocol+":")
|
||||
return strings.TrimPrefix(this.fullAddr, protocol.String()+":")
|
||||
}
|
||||
return strings.TrimPrefix(this.fullAddr, protocol+"://")
|
||||
return strings.TrimPrefix(this.fullAddr, protocol.String()+"://")
|
||||
}
|
||||
|
||||
// 判断当前分组是否为HTTP
|
||||
|
||||
Reference in New Issue
Block a user