mirror of
				https://github.com/TeaOSLab/EdgeCommon.git
				synced 2025-11-04 05:00:24 +08:00 
			
		
		
		
	反向代理源站实现使用域名分组
This commit is contained in:
		@@ -6,7 +6,7 @@ import (
 | 
				
			|||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// 从一组规则中匹配域名
 | 
					// MatchDomains 从一组规则中匹配域名
 | 
				
			||||||
// 支持的格式:example.com, www.example.com, .example.com, *.example.com, ~(\d+).example.com
 | 
					// 支持的格式:example.com, www.example.com, .example.com, *.example.com, ~(\d+).example.com
 | 
				
			||||||
// 更多参考:http://nginx.org/en/docs/http/ngx_http_core_module.html#server_name
 | 
					// 更多参考:http://nginx.org/en/docs/http/ngx_http_core_module.html#server_name
 | 
				
			||||||
func MatchDomains(patterns []string, domain string) (isMatched bool) {
 | 
					func MatchDomains(patterns []string, domain string) (isMatched bool) {
 | 
				
			||||||
@@ -14,19 +14,23 @@ func MatchDomains(patterns []string, domain string) (isMatched bool) {
 | 
				
			|||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	for _, pattern := range patterns {
 | 
						for _, pattern := range patterns {
 | 
				
			||||||
		if matchDomain(pattern, domain) {
 | 
							if MatchDomain(pattern, domain) {
 | 
				
			||||||
			return true
 | 
								return true
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return
 | 
						return
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// 匹配单个域名规则
 | 
					// MatchDomain 匹配单个域名规则
 | 
				
			||||||
func matchDomain(pattern string, domain string) (isMatched bool) {
 | 
					func MatchDomain(pattern string, domain string) (isMatched bool) {
 | 
				
			||||||
	if len(pattern) == 0 {
 | 
						if len(pattern) == 0 {
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if pattern == "*" {
 | 
				
			||||||
 | 
							return true
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// 正则表达式
 | 
						// 正则表达式
 | 
				
			||||||
	if pattern[0] == '~' {
 | 
						if pattern[0] == '~' {
 | 
				
			||||||
		reg, err := stringutil.RegexpCompile(strings.TrimSpace(pattern[1:]))
 | 
							reg, err := stringutil.RegexpCompile(strings.TrimSpace(pattern[1:]))
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -76,4 +76,8 @@ func TestMatchDomain(t *testing.T) {
 | 
				
			|||||||
		ok := MatchDomains([]string{"~^\\d+.example.com$"}, "123.example.com")
 | 
							ok := MatchDomains([]string{"~^\\d+.example.com$"}, "123.example.com")
 | 
				
			||||||
		a.IsTrue(ok)
 | 
							a.IsTrue(ok)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							ok := MatchDomains([]string{"*"}, "example.com")
 | 
				
			||||||
 | 
							a.IsTrue(ok)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -35,6 +35,7 @@ type Origin struct {
 | 
				
			|||||||
	Name        string          `protobuf:"bytes,3,opt,name=name,proto3" json:"name,omitempty"`
 | 
						Name        string          `protobuf:"bytes,3,opt,name=name,proto3" json:"name,omitempty"`
 | 
				
			||||||
	Addr        *NetworkAddress `protobuf:"bytes,4,opt,name=addr,proto3" json:"addr,omitempty"`
 | 
						Addr        *NetworkAddress `protobuf:"bytes,4,opt,name=addr,proto3" json:"addr,omitempty"`
 | 
				
			||||||
	Description string          `protobuf:"bytes,5,opt,name=description,proto3" json:"description,omitempty"`
 | 
						Description string          `protobuf:"bytes,5,opt,name=description,proto3" json:"description,omitempty"`
 | 
				
			||||||
 | 
						Domains     []string        `protobuf:"bytes,6,rep,name=domains,proto3" json:"domains,omitempty"`
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (x *Origin) Reset() {
 | 
					func (x *Origin) Reset() {
 | 
				
			||||||
@@ -104,6 +105,13 @@ func (x *Origin) GetDescription() string {
 | 
				
			|||||||
	return ""
 | 
						return ""
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (x *Origin) GetDomains() []string {
 | 
				
			||||||
 | 
						if x != nil {
 | 
				
			||||||
 | 
							return x.Domains
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var File_models_model_origin_proto protoreflect.FileDescriptor
 | 
					var File_models_model_origin_proto protoreflect.FileDescriptor
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var file_models_model_origin_proto_rawDesc = []byte{
 | 
					var file_models_model_origin_proto_rawDesc = []byte{
 | 
				
			||||||
@@ -111,7 +119,7 @@ var file_models_model_origin_proto_rawDesc = []byte{
 | 
				
			|||||||
	0x72, 0x69, 0x67, 0x69, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x02, 0x70, 0x62, 0x1a,
 | 
						0x72, 0x69, 0x67, 0x69, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x02, 0x70, 0x62, 0x1a,
 | 
				
			||||||
	0x22, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x2f, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x5f, 0x6e, 0x65,
 | 
						0x22, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x2f, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x5f, 0x6e, 0x65,
 | 
				
			||||||
	0x74, 0x77, 0x6f, 0x72, 0x6b, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x2e, 0x70, 0x72,
 | 
						0x74, 0x77, 0x6f, 0x72, 0x6b, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x2e, 0x70, 0x72,
 | 
				
			||||||
	0x6f, 0x74, 0x6f, 0x22, 0x8a, 0x01, 0x0a, 0x06, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x12, 0x0e,
 | 
						0x6f, 0x74, 0x6f, 0x22, 0xa4, 0x01, 0x0a, 0x06, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x12, 0x0e,
 | 
				
			||||||
	0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12,
 | 
						0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12,
 | 
				
			||||||
	0x0a, 0x04, 0x69, 0x73, 0x4f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x04, 0x69, 0x73,
 | 
						0x0a, 0x04, 0x69, 0x73, 0x4f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x04, 0x69, 0x73,
 | 
				
			||||||
	0x4f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09,
 | 
						0x4f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09,
 | 
				
			||||||
@@ -120,7 +128,9 @@ var file_models_model_origin_proto_rawDesc = []byte{
 | 
				
			|||||||
	0x6b, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x04, 0x61, 0x64, 0x64, 0x72, 0x12, 0x20,
 | 
						0x6b, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x04, 0x61, 0x64, 0x64, 0x72, 0x12, 0x20,
 | 
				
			||||||
	0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20,
 | 
						0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20,
 | 
				
			||||||
	0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e,
 | 
						0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e,
 | 
				
			||||||
	0x42, 0x06, 0x5a, 0x04, 0x2e, 0x2f, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
 | 
						0x12, 0x18, 0x0a, 0x07, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28,
 | 
				
			||||||
 | 
						0x09, 0x52, 0x07, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x73, 0x42, 0x06, 0x5a, 0x04, 0x2e, 0x2f,
 | 
				
			||||||
 | 
						0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var (
 | 
					var (
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -45,6 +45,7 @@ type CreateOriginRequest struct {
 | 
				
			|||||||
	IdleTimeoutJSON []byte          `protobuf:"bytes,8,opt,name=idleTimeoutJSON,proto3" json:"idleTimeoutJSON,omitempty"`
 | 
						IdleTimeoutJSON []byte          `protobuf:"bytes,8,opt,name=idleTimeoutJSON,proto3" json:"idleTimeoutJSON,omitempty"`
 | 
				
			||||||
	MaxConns        int32           `protobuf:"varint,9,opt,name=maxConns,proto3" json:"maxConns,omitempty"`
 | 
						MaxConns        int32           `protobuf:"varint,9,opt,name=maxConns,proto3" json:"maxConns,omitempty"`
 | 
				
			||||||
	MaxIdleConns    int32           `protobuf:"varint,10,opt,name=maxIdleConns,proto3" json:"maxIdleConns,omitempty"`
 | 
						MaxIdleConns    int32           `protobuf:"varint,10,opt,name=maxIdleConns,proto3" json:"maxIdleConns,omitempty"`
 | 
				
			||||||
 | 
						Domains         []string        `protobuf:"bytes,11,rep,name=domains,proto3" json:"domains,omitempty"`
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (x *CreateOriginRequest) Reset() {
 | 
					func (x *CreateOriginRequest) Reset() {
 | 
				
			||||||
@@ -149,6 +150,13 @@ func (x *CreateOriginRequest) GetMaxIdleConns() int32 {
 | 
				
			|||||||
	return 0
 | 
						return 0
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (x *CreateOriginRequest) GetDomains() []string {
 | 
				
			||||||
 | 
						if x != nil {
 | 
				
			||||||
 | 
							return x.Domains
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type CreateOriginResponse struct {
 | 
					type CreateOriginResponse struct {
 | 
				
			||||||
	state         protoimpl.MessageState
 | 
						state         protoimpl.MessageState
 | 
				
			||||||
	sizeCache     protoimpl.SizeCache
 | 
						sizeCache     protoimpl.SizeCache
 | 
				
			||||||
@@ -213,6 +221,7 @@ type UpdateOriginRequest struct {
 | 
				
			|||||||
	IdleTimeoutJSON []byte          `protobuf:"bytes,9,opt,name=idleTimeoutJSON,proto3" json:"idleTimeoutJSON,omitempty"`
 | 
						IdleTimeoutJSON []byte          `protobuf:"bytes,9,opt,name=idleTimeoutJSON,proto3" json:"idleTimeoutJSON,omitempty"`
 | 
				
			||||||
	MaxConns        int32           `protobuf:"varint,10,opt,name=maxConns,proto3" json:"maxConns,omitempty"`
 | 
						MaxConns        int32           `protobuf:"varint,10,opt,name=maxConns,proto3" json:"maxConns,omitempty"`
 | 
				
			||||||
	MaxIdleConns    int32           `protobuf:"varint,11,opt,name=maxIdleConns,proto3" json:"maxIdleConns,omitempty"`
 | 
						MaxIdleConns    int32           `protobuf:"varint,11,opt,name=maxIdleConns,proto3" json:"maxIdleConns,omitempty"`
 | 
				
			||||||
 | 
						Domains         []string        `protobuf:"bytes,12,rep,name=domains,proto3" json:"domains,omitempty"`
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (x *UpdateOriginRequest) Reset() {
 | 
					func (x *UpdateOriginRequest) Reset() {
 | 
				
			||||||
@@ -324,6 +333,13 @@ func (x *UpdateOriginRequest) GetMaxIdleConns() int32 {
 | 
				
			|||||||
	return 0
 | 
						return 0
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (x *UpdateOriginRequest) GetDomains() []string {
 | 
				
			||||||
 | 
						if x != nil {
 | 
				
			||||||
 | 
							return x.Domains
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// 查找单个源站信息
 | 
					// 查找单个源站信息
 | 
				
			||||||
type FindEnabledOriginRequest struct {
 | 
					type FindEnabledOriginRequest struct {
 | 
				
			||||||
	state         protoimpl.MessageState
 | 
						state         protoimpl.MessageState
 | 
				
			||||||
@@ -524,7 +540,7 @@ var file_service_origin_proto_rawDesc = []byte{
 | 
				
			|||||||
	0x64, 0x65, 0x6c, 0x5f, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x5f, 0x61, 0x64, 0x64, 0x72,
 | 
						0x64, 0x65, 0x6c, 0x5f, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x5f, 0x61, 0x64, 0x64, 0x72,
 | 
				
			||||||
	0x65, 0x73, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x19, 0x6d, 0x6f, 0x64, 0x65, 0x6c,
 | 
						0x65, 0x73, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x19, 0x6d, 0x6f, 0x64, 0x65, 0x6c,
 | 
				
			||||||
	0x73, 0x2f, 0x72, 0x70, 0x63, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2e, 0x70,
 | 
						0x73, 0x2f, 0x72, 0x70, 0x63, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2e, 0x70,
 | 
				
			||||||
	0x72, 0x6f, 0x74, 0x6f, 0x22, 0xdd, 0x02, 0x0a, 0x13, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4f,
 | 
						0x72, 0x6f, 0x74, 0x6f, 0x22, 0xf7, 0x02, 0x0a, 0x13, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4f,
 | 
				
			||||||
	0x72, 0x69, 0x67, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04,
 | 
						0x72, 0x69, 0x67, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04,
 | 
				
			||||||
	0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65,
 | 
						0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65,
 | 
				
			||||||
	0x12, 0x26, 0x0a, 0x04, 0x61, 0x64, 0x64, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12,
 | 
						0x12, 0x26, 0x0a, 0x04, 0x61, 0x64, 0x64, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12,
 | 
				
			||||||
@@ -546,71 +562,74 @@ var file_service_origin_proto_rawDesc = []byte{
 | 
				
			|||||||
	0x18, 0x09, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x6d, 0x61, 0x78, 0x43, 0x6f, 0x6e, 0x6e, 0x73,
 | 
						0x18, 0x09, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x6d, 0x61, 0x78, 0x43, 0x6f, 0x6e, 0x6e, 0x73,
 | 
				
			||||||
	0x12, 0x22, 0x0a, 0x0c, 0x6d, 0x61, 0x78, 0x49, 0x64, 0x6c, 0x65, 0x43, 0x6f, 0x6e, 0x6e, 0x73,
 | 
						0x12, 0x22, 0x0a, 0x0c, 0x6d, 0x61, 0x78, 0x49, 0x64, 0x6c, 0x65, 0x43, 0x6f, 0x6e, 0x6e, 0x73,
 | 
				
			||||||
	0x18, 0x0a, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0c, 0x6d, 0x61, 0x78, 0x49, 0x64, 0x6c, 0x65, 0x43,
 | 
						0x18, 0x0a, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0c, 0x6d, 0x61, 0x78, 0x49, 0x64, 0x6c, 0x65, 0x43,
 | 
				
			||||||
	0x6f, 0x6e, 0x6e, 0x73, 0x22, 0x32, 0x0a, 0x14, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4f, 0x72,
 | 
						0x6f, 0x6e, 0x6e, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x73, 0x18,
 | 
				
			||||||
	0x69, 0x67, 0x69, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1a, 0x0a, 0x08,
 | 
						0x0b, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x73, 0x22, 0x32,
 | 
				
			||||||
	0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08,
 | 
						0x0a, 0x14, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x52, 0x65,
 | 
				
			||||||
	0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x49, 0x64, 0x22, 0xf9, 0x02, 0x0a, 0x13, 0x55, 0x70, 0x64,
 | 
						0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e,
 | 
				
			||||||
	0x61, 0x74, 0x65, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
 | 
						0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e,
 | 
				
			||||||
	0x12, 0x1a, 0x0a, 0x08, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01,
 | 
						0x49, 0x64, 0x22, 0x93, 0x03, 0x0a, 0x13, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4f, 0x72, 0x69,
 | 
				
			||||||
	0x28, 0x03, 0x52, 0x08, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04,
 | 
						0x67, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x6f, 0x72,
 | 
				
			||||||
	0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65,
 | 
						0x69, 0x67, 0x69, 0x6e, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x6f, 0x72,
 | 
				
			||||||
	0x12, 0x26, 0x0a, 0x04, 0x61, 0x64, 0x64, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12,
 | 
						0x69, 0x67, 0x69, 0x6e, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02,
 | 
				
			||||||
	0x2e, 0x70, 0x62, 0x2e, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x41, 0x64, 0x64, 0x72, 0x65,
 | 
						0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x26, 0x0a, 0x04, 0x61, 0x64,
 | 
				
			||||||
	0x73, 0x73, 0x52, 0x04, 0x61, 0x64, 0x64, 0x72, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63,
 | 
						0x64, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x70, 0x62, 0x2e, 0x4e, 0x65,
 | 
				
			||||||
	0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64,
 | 
						0x74, 0x77, 0x6f, 0x72, 0x6b, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x04, 0x61, 0x64,
 | 
				
			||||||
	0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x77, 0x65,
 | 
						0x64, 0x72, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f,
 | 
				
			||||||
	0x69, 0x67, 0x68, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x77, 0x65, 0x69, 0x67,
 | 
						0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70,
 | 
				
			||||||
	0x68, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x69, 0x73, 0x4f, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08,
 | 
						0x74, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x05,
 | 
				
			||||||
	0x52, 0x04, 0x69, 0x73, 0x4f, 0x6e, 0x12, 0x28, 0x0a, 0x0f, 0x63, 0x6f, 0x6e, 0x6e, 0x54, 0x69,
 | 
						0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x12, 0x0a, 0x04,
 | 
				
			||||||
	0x6d, 0x65, 0x6f, 0x75, 0x74, 0x4a, 0x53, 0x4f, 0x4e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0c, 0x52,
 | 
						0x69, 0x73, 0x4f, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x04, 0x69, 0x73, 0x4f, 0x6e,
 | 
				
			||||||
	0x0f, 0x63, 0x6f, 0x6e, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x4a, 0x53, 0x4f, 0x4e,
 | 
						0x12, 0x28, 0x0a, 0x0f, 0x63, 0x6f, 0x6e, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x4a,
 | 
				
			||||||
	0x12, 0x28, 0x0a, 0x0f, 0x72, 0x65, 0x61, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x4a,
 | 
						0x53, 0x4f, 0x4e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0f, 0x63, 0x6f, 0x6e, 0x6e, 0x54,
 | 
				
			||||||
	0x53, 0x4f, 0x4e, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0f, 0x72, 0x65, 0x61, 0x64, 0x54,
 | 
						0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x4a, 0x53, 0x4f, 0x4e, 0x12, 0x28, 0x0a, 0x0f, 0x72, 0x65,
 | 
				
			||||||
	0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x4a, 0x53, 0x4f, 0x4e, 0x12, 0x28, 0x0a, 0x0f, 0x69, 0x64,
 | 
						0x61, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x4a, 0x53, 0x4f, 0x4e, 0x18, 0x08, 0x20,
 | 
				
			||||||
	0x6c, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x4a, 0x53, 0x4f, 0x4e, 0x18, 0x09, 0x20,
 | 
						0x01, 0x28, 0x0c, 0x52, 0x0f, 0x72, 0x65, 0x61, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74,
 | 
				
			||||||
	0x01, 0x28, 0x0c, 0x52, 0x0f, 0x69, 0x64, 0x6c, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74,
 | 
						0x4a, 0x53, 0x4f, 0x4e, 0x12, 0x28, 0x0a, 0x0f, 0x69, 0x64, 0x6c, 0x65, 0x54, 0x69, 0x6d, 0x65,
 | 
				
			||||||
	0x4a, 0x53, 0x4f, 0x4e, 0x12, 0x1a, 0x0a, 0x08, 0x6d, 0x61, 0x78, 0x43, 0x6f, 0x6e, 0x6e, 0x73,
 | 
						0x6f, 0x75, 0x74, 0x4a, 0x53, 0x4f, 0x4e, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0f, 0x69,
 | 
				
			||||||
	0x18, 0x0a, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x6d, 0x61, 0x78, 0x43, 0x6f, 0x6e, 0x6e, 0x73,
 | 
						0x64, 0x6c, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x4a, 0x53, 0x4f, 0x4e, 0x12, 0x1a,
 | 
				
			||||||
	0x12, 0x22, 0x0a, 0x0c, 0x6d, 0x61, 0x78, 0x49, 0x64, 0x6c, 0x65, 0x43, 0x6f, 0x6e, 0x6e, 0x73,
 | 
						0x0a, 0x08, 0x6d, 0x61, 0x78, 0x43, 0x6f, 0x6e, 0x6e, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x05,
 | 
				
			||||||
	0x18, 0x0b, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0c, 0x6d, 0x61, 0x78, 0x49, 0x64, 0x6c, 0x65, 0x43,
 | 
						0x52, 0x08, 0x6d, 0x61, 0x78, 0x43, 0x6f, 0x6e, 0x6e, 0x73, 0x12, 0x22, 0x0a, 0x0c, 0x6d, 0x61,
 | 
				
			||||||
	0x6f, 0x6e, 0x6e, 0x73, 0x22, 0x36, 0x0a, 0x18, 0x46, 0x69, 0x6e, 0x64, 0x45, 0x6e, 0x61, 0x62,
 | 
						0x78, 0x49, 0x64, 0x6c, 0x65, 0x43, 0x6f, 0x6e, 0x6e, 0x73, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x05,
 | 
				
			||||||
	0x6c, 0x65, 0x64, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
 | 
						0x52, 0x0c, 0x6d, 0x61, 0x78, 0x49, 0x64, 0x6c, 0x65, 0x43, 0x6f, 0x6e, 0x6e, 0x73, 0x12, 0x18,
 | 
				
			||||||
	0x12, 0x1a, 0x0a, 0x08, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01,
 | 
						0x0a, 0x07, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x73, 0x18, 0x0c, 0x20, 0x03, 0x28, 0x09, 0x52,
 | 
				
			||||||
	0x28, 0x03, 0x52, 0x08, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x49, 0x64, 0x22, 0x3f, 0x0a, 0x19,
 | 
						0x07, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x73, 0x22, 0x36, 0x0a, 0x18, 0x46, 0x69, 0x6e, 0x64,
 | 
				
			||||||
	0x46, 0x69, 0x6e, 0x64, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x4f, 0x72, 0x69, 0x67, 0x69,
 | 
						0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x52, 0x65, 0x71,
 | 
				
			||||||
	0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x22, 0x0a, 0x06, 0x4f, 0x72, 0x69,
 | 
						0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x49, 0x64,
 | 
				
			||||||
	0x67, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0a, 0x2e, 0x70, 0x62, 0x2e, 0x4f,
 | 
						0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x49, 0x64,
 | 
				
			||||||
	0x72, 0x69, 0x67, 0x69, 0x6e, 0x52, 0x06, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x22, 0x3c, 0x0a,
 | 
						0x22, 0x3f, 0x0a, 0x19, 0x46, 0x69, 0x6e, 0x64, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x4f,
 | 
				
			||||||
	0x1e, 0x46, 0x69, 0x6e, 0x64, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x4f, 0x72, 0x69, 0x67,
 | 
						0x72, 0x69, 0x67, 0x69, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x22, 0x0a,
 | 
				
			||||||
	0x69, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12,
 | 
						0x06, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0a, 0x2e,
 | 
				
			||||||
	0x1a, 0x0a, 0x08, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28,
 | 
						0x70, 0x62, 0x2e, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x52, 0x06, 0x4f, 0x72, 0x69, 0x67, 0x69,
 | 
				
			||||||
	0x03, 0x52, 0x08, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x49, 0x64, 0x22, 0x41, 0x0a, 0x1f, 0x46,
 | 
						0x6e, 0x22, 0x3c, 0x0a, 0x1e, 0x46, 0x69, 0x6e, 0x64, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64,
 | 
				
			||||||
	0x69, 0x6e, 0x64, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e,
 | 
						0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75,
 | 
				
			||||||
	0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1e,
 | 
						0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x49, 0x64, 0x18,
 | 
				
			||||||
	0x0a, 0x0a, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x4a, 0x53, 0x4f, 0x4e, 0x18, 0x01, 0x20, 0x01,
 | 
						0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x49, 0x64, 0x22,
 | 
				
			||||||
	0x28, 0x0c, 0x52, 0x0a, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x4a, 0x53, 0x4f, 0x4e, 0x32, 0xc1,
 | 
						0x41, 0x0a, 0x1f, 0x46, 0x69, 0x6e, 0x64, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x4f, 0x72,
 | 
				
			||||||
	0x02, 0x0a, 0x0d, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65,
 | 
					 | 
				
			||||||
	0x12, 0x41, 0x0a, 0x0c, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e,
 | 
					 | 
				
			||||||
	0x12, 0x17, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4f, 0x72, 0x69, 0x67,
 | 
					 | 
				
			||||||
	0x69, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x70, 0x62, 0x2e, 0x43,
 | 
					 | 
				
			||||||
	0x72, 0x65, 0x61, 0x74, 0x65, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f,
 | 
					 | 
				
			||||||
	0x6e, 0x73, 0x65, 0x12, 0x37, 0x0a, 0x0c, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4f, 0x72, 0x69,
 | 
					 | 
				
			||||||
	0x67, 0x69, 0x6e, 0x12, 0x17, 0x2e, 0x70, 0x62, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4f,
 | 
					 | 
				
			||||||
	0x72, 0x69, 0x67, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0e, 0x2e, 0x70,
 | 
					 | 
				
			||||||
	0x62, 0x2e, 0x52, 0x50, 0x43, 0x53, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x12, 0x50, 0x0a, 0x11,
 | 
					 | 
				
			||||||
	0x66, 0x69, 0x6e, 0x64, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x4f, 0x72, 0x69, 0x67, 0x69,
 | 
					 | 
				
			||||||
	0x6e, 0x12, 0x1c, 0x2e, 0x70, 0x62, 0x2e, 0x46, 0x69, 0x6e, 0x64, 0x45, 0x6e, 0x61, 0x62, 0x6c,
 | 
					 | 
				
			||||||
	0x65, 0x64, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
 | 
					 | 
				
			||||||
	0x1d, 0x2e, 0x70, 0x62, 0x2e, 0x46, 0x69, 0x6e, 0x64, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64,
 | 
					 | 
				
			||||||
	0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x62,
 | 
					 | 
				
			||||||
	0x0a, 0x17, 0x66, 0x69, 0x6e, 0x64, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x4f, 0x72, 0x69,
 | 
					 | 
				
			||||||
	0x67, 0x69, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x22, 0x2e, 0x70, 0x62, 0x2e, 0x46,
 | 
					 | 
				
			||||||
	0x69, 0x6e, 0x64, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e,
 | 
					 | 
				
			||||||
	0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e,
 | 
					 | 
				
			||||||
	0x70, 0x62, 0x2e, 0x46, 0x69, 0x6e, 0x64, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x4f, 0x72,
 | 
					 | 
				
			||||||
	0x69, 0x67, 0x69, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
 | 
						0x69, 0x67, 0x69, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
 | 
				
			||||||
	0x73, 0x65, 0x42, 0x06, 0x5a, 0x04, 0x2e, 0x2f, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74,
 | 
						0x73, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x4a, 0x53, 0x4f, 0x4e,
 | 
				
			||||||
	0x6f, 0x33,
 | 
						0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x4a, 0x53,
 | 
				
			||||||
 | 
						0x4f, 0x4e, 0x32, 0xc1, 0x02, 0x0a, 0x0d, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x53, 0x65, 0x72,
 | 
				
			||||||
 | 
						0x76, 0x69, 0x63, 0x65, 0x12, 0x41, 0x0a, 0x0c, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4f, 0x72,
 | 
				
			||||||
 | 
						0x69, 0x67, 0x69, 0x6e, 0x12, 0x17, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65,
 | 
				
			||||||
 | 
						0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e,
 | 
				
			||||||
 | 
						0x70, 0x62, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x52,
 | 
				
			||||||
 | 
						0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x37, 0x0a, 0x0c, 0x75, 0x70, 0x64, 0x61, 0x74,
 | 
				
			||||||
 | 
						0x65, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x12, 0x17, 0x2e, 0x70, 0x62, 0x2e, 0x55, 0x70, 0x64,
 | 
				
			||||||
 | 
						0x61, 0x74, 0x65, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
 | 
				
			||||||
 | 
						0x1a, 0x0e, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x50, 0x43, 0x53, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73,
 | 
				
			||||||
 | 
						0x12, 0x50, 0x0a, 0x11, 0x66, 0x69, 0x6e, 0x64, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x4f,
 | 
				
			||||||
 | 
						0x72, 0x69, 0x67, 0x69, 0x6e, 0x12, 0x1c, 0x2e, 0x70, 0x62, 0x2e, 0x46, 0x69, 0x6e, 0x64, 0x45,
 | 
				
			||||||
 | 
						0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x75,
 | 
				
			||||||
 | 
						0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x70, 0x62, 0x2e, 0x46, 0x69, 0x6e, 0x64, 0x45, 0x6e, 0x61,
 | 
				
			||||||
 | 
						0x62, 0x6c, 0x65, 0x64, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
 | 
				
			||||||
 | 
						0x73, 0x65, 0x12, 0x62, 0x0a, 0x17, 0x66, 0x69, 0x6e, 0x64, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65,
 | 
				
			||||||
 | 
						0x64, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x22, 0x2e,
 | 
				
			||||||
 | 
						0x70, 0x62, 0x2e, 0x46, 0x69, 0x6e, 0x64, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x4f, 0x72,
 | 
				
			||||||
 | 
						0x69, 0x67, 0x69, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
 | 
				
			||||||
 | 
						0x74, 0x1a, 0x23, 0x2e, 0x70, 0x62, 0x2e, 0x46, 0x69, 0x6e, 0x64, 0x45, 0x6e, 0x61, 0x62, 0x6c,
 | 
				
			||||||
 | 
						0x65, 0x64, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65,
 | 
				
			||||||
 | 
						0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x06, 0x5a, 0x04, 0x2e, 0x2f, 0x70, 0x62, 0x62, 0x06,
 | 
				
			||||||
 | 
						0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var (
 | 
					var (
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -11,4 +11,5 @@ message Origin {
 | 
				
			|||||||
	string name = 3;
 | 
						string name = 3;
 | 
				
			||||||
	NetworkAddress addr = 4;
 | 
						NetworkAddress addr = 4;
 | 
				
			||||||
	string description = 5;
 | 
						string description = 5;
 | 
				
			||||||
 | 
						repeated string domains = 6;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -33,6 +33,7 @@ message CreateOriginRequest {
 | 
				
			|||||||
	bytes idleTimeoutJSON = 8;
 | 
						bytes idleTimeoutJSON = 8;
 | 
				
			||||||
	int32 maxConns = 9;
 | 
						int32 maxConns = 9;
 | 
				
			||||||
	int32 maxIdleConns = 10;
 | 
						int32 maxIdleConns = 10;
 | 
				
			||||||
 | 
						repeated string domains = 11;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
message CreateOriginResponse {
 | 
					message CreateOriginResponse {
 | 
				
			||||||
@@ -52,6 +53,7 @@ message UpdateOriginRequest {
 | 
				
			|||||||
	bytes idleTimeoutJSON = 9;
 | 
						bytes idleTimeoutJSON = 9;
 | 
				
			||||||
	int32 maxConns = 10;
 | 
						int32 maxConns = 10;
 | 
				
			||||||
	int32 maxIdleConns = 11;
 | 
						int32 maxIdleConns = 11;
 | 
				
			||||||
 | 
						repeated string domains = 12;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// 查找单个源站信息
 | 
					// 查找单个源站信息
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -28,6 +28,8 @@ type OriginConfig struct {
 | 
				
			|||||||
	MaxConns     int                  `yaml:"maxConns" json:"maxConns"`       // 最大并发连接数
 | 
						MaxConns     int                  `yaml:"maxConns" json:"maxConns"`       // 最大并发连接数
 | 
				
			||||||
	MaxIdleConns int                  `yaml:"idleConns" json:"idleConns"`     // 最大空闲连接数
 | 
						MaxIdleConns int                  `yaml:"idleConns" json:"idleConns"`     // 最大空闲连接数
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Domains []string `yaml:"domains" json:"domains"` // 所属域名
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	StripPrefix string `yaml:"stripPrefix" json:"stripPrefix"` // 去除URL前缀
 | 
						StripPrefix string `yaml:"stripPrefix" json:"stripPrefix"` // 去除URL前缀
 | 
				
			||||||
	RequestURI  string `yaml:"requestURI" json:"requestURI"`   // 转发后的请求URI TODO
 | 
						RequestURI  string `yaml:"requestURI" json:"requestURI"`   // 转发后的请求URI TODO
 | 
				
			||||||
	RequestHost string `yaml:"requestHost" json:"requestHost"` // 自定义主机名 TODO
 | 
						RequestHost string `yaml:"requestHost" json:"requestHost"` // 自定义主机名 TODO
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,7 +2,6 @@ package serverconfigs
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"github.com/TeaOSLab/EdgeCommon/pkg/configutils"
 | 
						"github.com/TeaOSLab/EdgeCommon/pkg/configutils"
 | 
				
			||||||
	"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/schedulingconfigs"
 | 
					 | 
				
			||||||
	"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
 | 
						"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
 | 
				
			||||||
	"github.com/iwind/TeaGo/lists"
 | 
						"github.com/iwind/TeaGo/lists"
 | 
				
			||||||
	"sync"
 | 
						"sync"
 | 
				
			||||||
@@ -45,11 +44,8 @@ type ReverseProxyConfig struct {
 | 
				
			|||||||
	requestHostHasVariables bool
 | 
						requestHostHasVariables bool
 | 
				
			||||||
	requestURIHasVariables  bool
 | 
						requestURIHasVariables  bool
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	hasPrimaryOrigins  bool
 | 
						schedulingGroupMap map[string]*SchedulingGroup // domain => *SchedulingGroup
 | 
				
			||||||
	hasBackupOrigins   bool
 | 
						schedulingLocker   sync.RWMutex
 | 
				
			||||||
	schedulingIsBackup bool
 | 
					 | 
				
			||||||
	schedulingObject   schedulingconfigs.SchedulingInterface
 | 
					 | 
				
			||||||
	schedulingLocker   sync.Mutex
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	addXRealIPHeader         bool
 | 
						addXRealIPHeader         bool
 | 
				
			||||||
	addXForwardedForHeader   bool
 | 
						addXForwardedForHeader   bool
 | 
				
			||||||
@@ -64,9 +60,68 @@ func (this *ReverseProxyConfig) Init() error {
 | 
				
			|||||||
	this.requestHostHasVariables = configutils.HasVariables(this.RequestHost)
 | 
						this.requestHostHasVariables = configutils.HasVariables(this.RequestHost)
 | 
				
			||||||
	this.requestURIHasVariables = configutils.HasVariables(this.RequestURI)
 | 
						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 _, origins := range [][]*OriginConfig{this.PrimaryOrigins, this.BackupOrigins} {
 | 
				
			||||||
		for _, origin := range origins {
 | 
							for _, origin := range origins {
 | 
				
			||||||
			// 覆盖参数设置
 | 
								// 覆盖参数设置
 | 
				
			||||||
@@ -131,54 +186,39 @@ func (this *ReverseProxyConfig) AddBackupOrigin(origin *OriginConfig) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// NextOrigin 取得下一个可用的后端服务
 | 
					// NextOrigin 取得下一个可用的后端服务
 | 
				
			||||||
func (this *ReverseProxyConfig) NextOrigin(call *shared.RequestCall) *OriginConfig {
 | 
					func (this *ReverseProxyConfig) NextOrigin(call *shared.RequestCall) *OriginConfig {
 | 
				
			||||||
	this.schedulingLocker.Lock()
 | 
						this.schedulingLocker.RLock()
 | 
				
			||||||
	defer this.schedulingLocker.Unlock()
 | 
						defer this.schedulingLocker.RUnlock()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if this.schedulingObject == nil {
 | 
						if len(this.schedulingGroupMap) == 0 {
 | 
				
			||||||
		return nil
 | 
							return nil
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if this.Scheduling != nil && call != nil && call.Options != nil {
 | 
						// 空域名
 | 
				
			||||||
		for k, v := range this.Scheduling.Options {
 | 
						if len(call.Domain) == 0 {
 | 
				
			||||||
			call.Options[k] = v
 | 
							group, ok := this.schedulingGroupMap[""]
 | 
				
			||||||
 | 
							if ok {
 | 
				
			||||||
 | 
								return group.NextOrigin(call)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	candidate := this.schedulingObject.Next(call)
 | 
						// 按域名匹配
 | 
				
			||||||
 | 
						for domainPattern, group := range this.schedulingGroupMap {
 | 
				
			||||||
	// 末了重置状态
 | 
							if len(domainPattern) > 0 && configutils.MatchDomain(domainPattern, call.Domain) {
 | 
				
			||||||
	defer func() {
 | 
								origin := group.NextOrigin(call)
 | 
				
			||||||
		if candidate == nil {
 | 
								if origin != nil {
 | 
				
			||||||
			this.schedulingIsBackup = false
 | 
									return origin
 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	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
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					 | 
				
			||||||
		if candidate == nil {
 | 
					 | 
				
			||||||
			return nil
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return candidate.(*OriginConfig)
 | 
						// 再次查找没有设置域名的分组
 | 
				
			||||||
 | 
						group, ok := this.schedulingGroupMap[""]
 | 
				
			||||||
 | 
						if ok {
 | 
				
			||||||
 | 
							return group.NextOrigin(call)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// SetupScheduling 设置调度算法
 | 
					// SetupScheduling 设置调度算法
 | 
				
			||||||
@@ -188,40 +228,9 @@ func (this *ReverseProxyConfig) SetupScheduling(isBackup bool, checkOk bool, loc
 | 
				
			|||||||
		defer this.schedulingLocker.Unlock()
 | 
							defer this.schedulingLocker.Unlock()
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	this.schedulingIsBackup = isBackup
 | 
						for _, group := range this.schedulingGroupMap {
 | 
				
			||||||
 | 
							group.SetupScheduling(isBackup, checkOk)
 | 
				
			||||||
	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()
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// FindSchedulingConfig 获取调度配置对象
 | 
					// 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"
 | 
					import "github.com/iwind/TeaGo/maps"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// 调度算法配置
 | 
					// SchedulingConfig 调度算法配置
 | 
				
			||||||
type SchedulingConfig struct {
 | 
					type SchedulingConfig struct {
 | 
				
			||||||
	Code    string   `yaml:"code" json:"code"`       // 类型
 | 
						Code    string   `yaml:"code" json:"code"`       // 类型
 | 
				
			||||||
	Options maps.Map `yaml:"options" json:"options"` // 选项
 | 
						Options maps.Map `yaml:"options" json:"options"` // 选项
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// 获取新对象
 | 
					// NewSchedulingConfig 获取新对象
 | 
				
			||||||
func NewSchedulingConfig() *SchedulingConfig {
 | 
					func NewSchedulingConfig() *SchedulingConfig {
 | 
				
			||||||
	return &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
 | 
					package schedulingconfigs
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// 候选对象接口
 | 
					// CandidateInterface 候选对象接口
 | 
				
			||||||
type CandidateInterface interface {
 | 
					type CandidateInterface interface {
 | 
				
			||||||
	// 权重
 | 
						// CandidateWeight 权重
 | 
				
			||||||
	CandidateWeight() uint
 | 
						CandidateWeight() uint
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// 代号
 | 
						// CandidateCodes 代号
 | 
				
			||||||
	CandidateCodes() []string
 | 
						CandidateCodes() []string
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,35 +5,35 @@ import (
 | 
				
			|||||||
	"github.com/iwind/TeaGo/maps"
 | 
						"github.com/iwind/TeaGo/maps"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// 调度算法接口
 | 
					// SchedulingInterface 调度算法接口
 | 
				
			||||||
type SchedulingInterface interface {
 | 
					type SchedulingInterface interface {
 | 
				
			||||||
	// 是否有候选对象
 | 
						// HasCandidates 是否有候选对象
 | 
				
			||||||
	HasCandidates() bool
 | 
						HasCandidates() bool
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// 添加候选对象
 | 
						// Add 添加候选对象
 | 
				
			||||||
	Add(candidate ...CandidateInterface)
 | 
						Add(candidate ...CandidateInterface)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// 启动
 | 
						// Start 启动
 | 
				
			||||||
	Start()
 | 
						Start()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// 查找下一个候选对象
 | 
						// Next 查找下一个候选对象
 | 
				
			||||||
	Next(call *shared.RequestCall) CandidateInterface
 | 
						Next(call *shared.RequestCall) CandidateInterface
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// 获取简要信息
 | 
						// Summary 获取简要信息
 | 
				
			||||||
	Summary() maps.Map
 | 
						Summary() maps.Map
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// 调度算法基础类
 | 
					// Scheduling 调度算法基础类
 | 
				
			||||||
type Scheduling struct {
 | 
					type Scheduling struct {
 | 
				
			||||||
	Candidates []CandidateInterface
 | 
						Candidates []CandidateInterface
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// 判断是否有候选对象
 | 
					// HasCandidates 判断是否有候选对象
 | 
				
			||||||
func (this *Scheduling) HasCandidates() bool {
 | 
					func (this *Scheduling) HasCandidates() bool {
 | 
				
			||||||
	return len(this.Candidates) > 0
 | 
						return len(this.Candidates) > 0
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// 添加候选对象
 | 
					// Add 添加候选对象
 | 
				
			||||||
func (this *Scheduling) Add(candidate ...CandidateInterface) {
 | 
					func (this *Scheduling) Add(candidate ...CandidateInterface) {
 | 
				
			||||||
	this.Candidates = append(this.Candidates, candidate...)
 | 
						this.Candidates = append(this.Candidates, candidate...)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -6,19 +6,19 @@ import (
 | 
				
			|||||||
	"hash/crc32"
 | 
						"hash/crc32"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Hash调度算法
 | 
					// HashScheduling Hash调度算法
 | 
				
			||||||
type HashScheduling struct {
 | 
					type HashScheduling struct {
 | 
				
			||||||
	Scheduling
 | 
						Scheduling
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	count uint32
 | 
						count uint32
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// 启动
 | 
					// Start 启动
 | 
				
			||||||
func (this *HashScheduling) Start() {
 | 
					func (this *HashScheduling) Start() {
 | 
				
			||||||
	this.count = uint32(len(this.Candidates))
 | 
						this.count = uint32(len(this.Candidates))
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// 获取下一个候选对象
 | 
					// Next 获取下一个候选对象
 | 
				
			||||||
func (this *HashScheduling) Next(call *shared.RequestCall) CandidateInterface {
 | 
					func (this *HashScheduling) Next(call *shared.RequestCall) CandidateInterface {
 | 
				
			||||||
	if this.count == 0 {
 | 
						if this.count == 0 {
 | 
				
			||||||
		return nil
 | 
							return nil
 | 
				
			||||||
@@ -34,7 +34,7 @@ func (this *HashScheduling) Next(call *shared.RequestCall) CandidateInterface {
 | 
				
			|||||||
	return this.Candidates[sum%this.count]
 | 
						return this.Candidates[sum%this.count]
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// 获取简要信息
 | 
					// Summary 获取简要信息
 | 
				
			||||||
func (this *HashScheduling) Summary() maps.Map {
 | 
					func (this *HashScheduling) Summary() maps.Map {
 | 
				
			||||||
	return maps.Map{
 | 
						return maps.Map{
 | 
				
			||||||
		"code":        "hash",
 | 
							"code":        "hash",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,7 +8,7 @@ import (
 | 
				
			|||||||
	"time"
 | 
						"time"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// 随机调度算法
 | 
					// RandomScheduling 随机调度算法
 | 
				
			||||||
type RandomScheduling struct {
 | 
					type RandomScheduling struct {
 | 
				
			||||||
	Scheduling
 | 
						Scheduling
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -16,7 +16,7 @@ type RandomScheduling struct {
 | 
				
			|||||||
	count uint // 实际总的服务器数
 | 
						count uint // 实际总的服务器数
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// 启动
 | 
					// Start 启动
 | 
				
			||||||
func (this *RandomScheduling) Start() {
 | 
					func (this *RandomScheduling) Start() {
 | 
				
			||||||
	sumWeight := uint(0)
 | 
						sumWeight := uint(0)
 | 
				
			||||||
	for _, c := range this.Candidates {
 | 
						for _, c := range this.Candidates {
 | 
				
			||||||
@@ -55,7 +55,7 @@ func (this *RandomScheduling) Start() {
 | 
				
			|||||||
	rand.Seed(time.Now().UnixNano())
 | 
						rand.Seed(time.Now().UnixNano())
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// 获取下一个候选对象
 | 
					// Next 获取下一个候选对象
 | 
				
			||||||
func (this *RandomScheduling) Next(call *shared.RequestCall) CandidateInterface {
 | 
					func (this *RandomScheduling) Next(call *shared.RequestCall) CandidateInterface {
 | 
				
			||||||
	if this.count == 0 {
 | 
						if this.count == 0 {
 | 
				
			||||||
		return nil
 | 
							return nil
 | 
				
			||||||
@@ -67,7 +67,7 @@ func (this *RandomScheduling) Next(call *shared.RequestCall) CandidateInterface
 | 
				
			|||||||
	return this.array[index]
 | 
						return this.array[index]
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// 获取简要信息
 | 
					// Summary 获取简要信息
 | 
				
			||||||
func (this *RandomScheduling) Summary() maps.Map {
 | 
					func (this *RandomScheduling) Summary() maps.Map {
 | 
				
			||||||
	return maps.Map{
 | 
						return maps.Map{
 | 
				
			||||||
		"code":        "random",
 | 
							"code":        "random",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,7 +7,7 @@ import (
 | 
				
			|||||||
	"sync"
 | 
						"sync"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// 轮询调度算法
 | 
					// RoundRobinScheduling 轮询调度算法
 | 
				
			||||||
type RoundRobinScheduling struct {
 | 
					type RoundRobinScheduling struct {
 | 
				
			||||||
	Scheduling
 | 
						Scheduling
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -19,7 +19,7 @@ type RoundRobinScheduling struct {
 | 
				
			|||||||
	locker sync.Mutex
 | 
						locker sync.Mutex
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// 启动
 | 
					// Start 启动
 | 
				
			||||||
func (this *RoundRobinScheduling) Start() {
 | 
					func (this *RoundRobinScheduling) Start() {
 | 
				
			||||||
	lists.Sort(this.Candidates, func(i int, j int) bool {
 | 
						lists.Sort(this.Candidates, func(i int, j int) bool {
 | 
				
			||||||
		c1 := this.Candidates[i]
 | 
							c1 := this.Candidates[i]
 | 
				
			||||||
@@ -41,7 +41,7 @@ func (this *RoundRobinScheduling) Start() {
 | 
				
			|||||||
	this.count = uint(len(this.Candidates))
 | 
						this.count = uint(len(this.Candidates))
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// 获取下一个候选对象
 | 
					// Next 获取下一个候选对象
 | 
				
			||||||
func (this *RoundRobinScheduling) Next(call *shared.RequestCall) CandidateInterface {
 | 
					func (this *RoundRobinScheduling) Next(call *shared.RequestCall) CandidateInterface {
 | 
				
			||||||
	if this.count == 0 {
 | 
						if this.count == 0 {
 | 
				
			||||||
		return nil
 | 
							return nil
 | 
				
			||||||
@@ -69,7 +69,7 @@ func (this *RoundRobinScheduling) Next(call *shared.RequestCall) CandidateInterf
 | 
				
			|||||||
	return c
 | 
						return c
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// 获取简要信息
 | 
					// Summary 获取简要信息
 | 
				
			||||||
func (this *RoundRobinScheduling) Summary() maps.Map {
 | 
					func (this *RoundRobinScheduling) Summary() maps.Map {
 | 
				
			||||||
	return maps.Map{
 | 
						return maps.Map{
 | 
				
			||||||
		"code":        "roundRobin",
 | 
							"code":        "roundRobin",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,7 +8,7 @@ import (
 | 
				
			|||||||
	"time"
 | 
						"time"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Sticky调度算法
 | 
					// StickyScheduling Sticky调度算法
 | 
				
			||||||
type StickyScheduling struct {
 | 
					type StickyScheduling struct {
 | 
				
			||||||
	Scheduling
 | 
						Scheduling
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -16,7 +16,7 @@ type StickyScheduling struct {
 | 
				
			|||||||
	mapping map[string]CandidateInterface // code => candidate
 | 
						mapping map[string]CandidateInterface // code => candidate
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// 启动
 | 
					// Start 启动
 | 
				
			||||||
func (this *StickyScheduling) Start() {
 | 
					func (this *StickyScheduling) Start() {
 | 
				
			||||||
	this.mapping = map[string]CandidateInterface{}
 | 
						this.mapping = map[string]CandidateInterface{}
 | 
				
			||||||
	for _, c := range this.Candidates {
 | 
						for _, c := range this.Candidates {
 | 
				
			||||||
@@ -29,7 +29,7 @@ func (this *StickyScheduling) Start() {
 | 
				
			|||||||
	rand.Seed(time.Now().UnixNano())
 | 
						rand.Seed(time.Now().UnixNano())
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// 获取下一个候选对象
 | 
					// Next 获取下一个候选对象
 | 
				
			||||||
func (this *StickyScheduling) Next(call *shared.RequestCall) CandidateInterface {
 | 
					func (this *StickyScheduling) Next(call *shared.RequestCall) CandidateInterface {
 | 
				
			||||||
	if this.count == 0 {
 | 
						if this.count == 0 {
 | 
				
			||||||
		return nil
 | 
							return nil
 | 
				
			||||||
@@ -95,7 +95,7 @@ func (this *StickyScheduling) Next(call *shared.RequestCall) CandidateInterface
 | 
				
			|||||||
	return c
 | 
						return c
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// 获取简要信息
 | 
					// Summary 获取简要信息
 | 
				
			||||||
func (this *StickyScheduling) Summary() maps.Map {
 | 
					func (this *StickyScheduling) Summary() maps.Map {
 | 
				
			||||||
	return maps.Map{
 | 
						return maps.Map{
 | 
				
			||||||
		"code":        "sticky",
 | 
							"code":        "sticky",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,22 +5,24 @@ import (
 | 
				
			|||||||
	"net/http"
 | 
						"net/http"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// 请求调用
 | 
					// RequestCall 请求调用
 | 
				
			||||||
type RequestCall struct {
 | 
					type RequestCall struct {
 | 
				
			||||||
	Formatter         func(source string) string
 | 
						Formatter func(source string) string // 当前变量格式化函数
 | 
				
			||||||
	Request           *http.Request
 | 
						Request   *http.Request              // 当前请求
 | 
				
			||||||
 | 
						Domain    string                     // 当前域名
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ResponseCallbacks []func(resp http.ResponseWriter)
 | 
						ResponseCallbacks []func(resp http.ResponseWriter)
 | 
				
			||||||
	Options           maps.Map
 | 
						Options           maps.Map
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// 获取新对象
 | 
					// NewRequestCall 获取新对象
 | 
				
			||||||
func NewRequestCall() *RequestCall {
 | 
					func NewRequestCall() *RequestCall {
 | 
				
			||||||
	return &RequestCall{
 | 
						return &RequestCall{
 | 
				
			||||||
		Options: maps.Map{},
 | 
							Options: maps.Map{},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// 重置
 | 
					// Reset 重置
 | 
				
			||||||
func (this *RequestCall) Reset() {
 | 
					func (this *RequestCall) Reset() {
 | 
				
			||||||
	this.Formatter = nil
 | 
						this.Formatter = nil
 | 
				
			||||||
	this.Request = nil
 | 
						this.Request = nil
 | 
				
			||||||
@@ -28,12 +30,12 @@ func (this *RequestCall) Reset() {
 | 
				
			|||||||
	this.Options = maps.Map{}
 | 
						this.Options = maps.Map{}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// 添加响应回调
 | 
					// AddResponseCall 添加响应回调
 | 
				
			||||||
func (this *RequestCall) AddResponseCall(callback func(resp http.ResponseWriter)) {
 | 
					func (this *RequestCall) AddResponseCall(callback func(resp http.ResponseWriter)) {
 | 
				
			||||||
	this.ResponseCallbacks = append(this.ResponseCallbacks, callback)
 | 
						this.ResponseCallbacks = append(this.ResponseCallbacks, callback)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// 执行响应回调
 | 
					// CallResponseCallbacks 执行响应回调
 | 
				
			||||||
func (this *RequestCall) CallResponseCallbacks(resp http.ResponseWriter) {
 | 
					func (this *RequestCall) CallResponseCallbacks(resp http.ResponseWriter) {
 | 
				
			||||||
	for _, callback := range this.ResponseCallbacks {
 | 
						for _, callback := range this.ResponseCallbacks {
 | 
				
			||||||
		callback(resp)
 | 
							callback(resp)
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user