Ver Fonte

Add expectedResponseCode to BurstObservatory

yuhan6665 há 11 meses atrás
pai
commit
8c111180d2

+ 23 - 11
app/observatory/burst/config.pb.go

@@ -1,6 +1,6 @@
 // Code generated by protoc-gen-go. DO NOT EDIT.
 // versions:
-// 	protoc-gen-go v1.35.1
+// 	protoc-gen-go v1.35.2
 // 	protoc        v5.28.2
 // source: app/observatory/burst/config.proto
 
@@ -89,7 +89,8 @@ type HealthPingConfig struct {
 	// sampling count is the amount of recent ping results which are kept for calculation
 	SamplingCount int32 `protobuf:"varint,4,opt,name=samplingCount,proto3" json:"samplingCount,omitempty"`
 	// ping timeout, int64 values of time.Duration
-	Timeout int64 `protobuf:"varint,5,opt,name=timeout,proto3" json:"timeout,omitempty"`
+	Timeout              int64   `protobuf:"varint,5,opt,name=timeout,proto3" json:"timeout,omitempty"`
+	ExpectedResponseCode []int32 `protobuf:"varint,6,rep,packed,name=expectedResponseCode,proto3" json:"expectedResponseCode,omitempty"`
 }
 
 func (x *HealthPingConfig) Reset() {
@@ -157,6 +158,13 @@ func (x *HealthPingConfig) GetTimeout() int64 {
 	return 0
 }
 
+func (x *HealthPingConfig) GetExpectedResponseCode() []int32 {
+	if x != nil {
+		return x.ExpectedResponseCode
+	}
+	return nil
+}
+
 var File_app_observatory_burst_config_proto protoreflect.FileDescriptor
 
 var file_app_observatory_burst_config_proto_rawDesc = []byte{
@@ -173,7 +181,7 @@ var file_app_observatory_burst_config_proto_rawDesc = []byte{
 	0x2e, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x6f, 0x72, 0x79, 0x2e, 0x62, 0x75, 0x72,
 	0x73, 0x74, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x50, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e,
 	0x66, 0x69, 0x67, 0x52, 0x0a, 0x70, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x22,
-	0xb4, 0x01, 0x0a, 0x10, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x50, 0x69, 0x6e, 0x67, 0x43, 0x6f,
+	0xe8, 0x01, 0x0a, 0x10, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x50, 0x69, 0x6e, 0x67, 0x43, 0x6f,
 	0x6e, 0x66, 0x69, 0x67, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74,
 	0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x74, 0x69,
 	0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x22, 0x0a, 0x0c, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63,
@@ -184,14 +192,18 @@ var file_app_observatory_burst_config_proto_rawDesc = []byte{
 	0x6e, 0x67, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, 0x73,
 	0x61, 0x6d, 0x70, 0x6c, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x18, 0x0a, 0x07,
 	0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x74,
-	0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x42, 0x70, 0x0a, 0x1e, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72,
-	0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x6f,
-	0x72, 0x79, 0x2e, 0x62, 0x75, 0x72, 0x73, 0x74, 0x50, 0x01, 0x5a, 0x2f, 0x67, 0x69, 0x74, 0x68,
-	0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61, 0x79,
-	0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x61, 0x70, 0x70, 0x2f, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76,
-	0x61, 0x74, 0x6f, 0x72, 0x79, 0x2f, 0x62, 0x75, 0x72, 0x73, 0x74, 0xaa, 0x02, 0x1a, 0x58, 0x72,
-	0x61, 0x79, 0x2e, 0x41, 0x70, 0x70, 0x2e, 0x4f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x6f,
-	0x72, 0x79, 0x2e, 0x42, 0x75, 0x72, 0x73, 0x74, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
+	0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, 0x32, 0x0a, 0x14, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74,
+	0x65, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x18, 0x06,
+	0x20, 0x03, 0x28, 0x05, 0x52, 0x14, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x52, 0x65,
+	0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x42, 0x70, 0x0a, 0x1e, 0x63, 0x6f,
+	0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x6f, 0x62, 0x73, 0x65, 0x72,
+	0x76, 0x61, 0x74, 0x6f, 0x72, 0x79, 0x2e, 0x62, 0x75, 0x72, 0x73, 0x74, 0x50, 0x01, 0x5a, 0x2f,
+	0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f,
+	0x78, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x61, 0x70, 0x70, 0x2f, 0x6f, 0x62,
+	0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x6f, 0x72, 0x79, 0x2f, 0x62, 0x75, 0x72, 0x73, 0x74, 0xaa,
+	0x02, 0x1a, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x41, 0x70, 0x70, 0x2e, 0x4f, 0x62, 0x73, 0x65, 0x72,
+	0x76, 0x61, 0x74, 0x6f, 0x72, 0x79, 0x2e, 0x42, 0x75, 0x72, 0x73, 0x74, 0x62, 0x06, 0x70, 0x72,
+	0x6f, 0x74, 0x6f, 0x33,
 }
 
 var (

+ 1 - 0
app/observatory/burst/config.proto

@@ -26,4 +26,5 @@ message HealthPingConfig {
   int32 samplingCount = 4;
   // ping timeout, int64 values of time.Duration
   int64 timeout = 5;
+  repeated int32 expectedResponseCode = 6;
 }

+ 14 - 10
app/observatory/burst/healthping.go

@@ -13,11 +13,12 @@ import (
 
 // HealthPingSettings holds settings for health Checker
 type HealthPingSettings struct {
-	Destination   string        `json:"destination"`
-	Connectivity  string        `json:"connectivity"`
-	Interval      time.Duration `json:"interval"`
-	SamplingCount int           `json:"sampling"`
-	Timeout       time.Duration `json:"timeout"`
+	Destination          string        `json:"destination"`
+	Connectivity         string        `json:"connectivity"`
+	Interval             time.Duration `json:"interval"`
+	SamplingCount        int           `json:"sampling"`
+	Timeout              time.Duration `json:"timeout"`
+	ExpectedResponseCode []int32       `json:"expectedResponseCode"`
 }
 
 // HealthPing is the health checker for balancers
@@ -36,11 +37,12 @@ func NewHealthPing(ctx context.Context, config *HealthPingConfig) *HealthPing {
 	settings := &HealthPingSettings{}
 	if config != nil {
 		settings = &HealthPingSettings{
-			Connectivity:  strings.TrimSpace(config.Connectivity),
-			Destination:   strings.TrimSpace(config.Destination),
-			Interval:      time.Duration(config.Interval),
-			SamplingCount: int(config.SamplingCount),
-			Timeout:       time.Duration(config.Timeout),
+			Connectivity:         strings.TrimSpace(config.Connectivity),
+			Destination:          strings.TrimSpace(config.Destination),
+			Interval:             time.Duration(config.Interval),
+			SamplingCount:        int(config.SamplingCount),
+			Timeout:              time.Duration(config.Timeout),
+			ExpectedResponseCode: config.ExpectedResponseCode,
 		}
 	}
 	if settings.Destination == "" {
@@ -48,6 +50,7 @@ func NewHealthPing(ctx context.Context, config *HealthPingConfig) *HealthPing {
 		// https://github.com/chromium/chromium/blob/main/components/safety_check/url_constants.cc#L10
 		// https://chromium.googlesource.com/chromium/src/+/refs/heads/main/components/safety_check/url_constants.cc#10
 		settings.Destination = "https://connectivitycheck.gstatic.com/generate_204"
+		settings.ExpectedResponseCode = []int32{ 204 }
 	}
 	if settings.Interval == 0 {
 		settings.Interval = time.Duration(1) * time.Minute
@@ -152,6 +155,7 @@ func (h *HealthPing) doCheck(tags []string, duration time.Duration, rounds int)
 			h.Settings.Destination,
 			h.Settings.Timeout,
 			handler,
+			h.Settings.ExpectedResponseCode,
 		)
 		for i := 0; i < rounds; i++ {
 			delay := time.Duration(0)

+ 23 - 7
app/observatory/burst/ping.go

@@ -5,26 +5,30 @@ import (
 	"net/http"
 	"time"
 
+	"github.com/xtls/xray-core/common/errors"
 	"github.com/xtls/xray-core/common/net"
 	"github.com/xtls/xray-core/transport/internet/tagged"
 )
 
 type pingClient struct {
-	destination string
-	httpClient  *http.Client
+	destination          string
+	httpClient           *http.Client
+	expectedResponseCode []int32
 }
 
-func newPingClient(ctx context.Context, destination string, timeout time.Duration, handler string) *pingClient {
+func newPingClient(ctx context.Context, destination string, timeout time.Duration, handler string, expectedResponseCode []int32) *pingClient {
 	return &pingClient{
-		destination: destination,
-		httpClient:  newHTTPClient(ctx, handler, timeout),
+		destination:          destination,
+		httpClient:           newHTTPClient(ctx, handler, timeout),
+		expectedResponseCode: expectedResponseCode,
 	}
 }
 
 func newDirectPingClient(destination string, timeout time.Duration) *pingClient {
 	return &pingClient{
-		destination: destination,
-		httpClient:  &http.Client{Timeout: timeout},
+		destination:          destination,
+		httpClient:           &http.Client{Timeout: timeout},
+		expectedResponseCode: []int32{},
 	}
 }
 
@@ -63,6 +67,18 @@ func (s *pingClient) MeasureDelay() (time.Duration, error) {
 	if err != nil {
 		return rttFailed, err
 	}
+	if len(s.expectedResponseCode) > 0 {
+		found := false
+		for _, c := range s.expectedResponseCode {
+			if c == int32(resp.StatusCode) {
+				found = true
+				break
+			}
+		}
+		if !found {
+			return rttFailed, errors.New("Unexpected response code: ", resp.StatusCode, " expected: ", s.expectedResponseCode)
+		}
+	}
 	// don't wait for body
 	resp.Body.Close()
 	return time.Since(start), nil

+ 12 - 10
infra/conf/router_strategy.go

@@ -46,20 +46,22 @@ type strategyLeastLoadConfig struct {
 
 // healthCheckSettings holds settings for health Checker
 type healthCheckSettings struct {
-	Destination   string            `json:"destination"`
-	Connectivity  string            `json:"connectivity"`
-	Interval      duration.Duration `json:"interval"`
-	SamplingCount int               `json:"sampling"`
-	Timeout       duration.Duration `json:"timeout"`
+	Destination          string            `json:"destination"`
+	Connectivity         string            `json:"connectivity"`
+	Interval             duration.Duration `json:"interval"`
+	SamplingCount        int               `json:"sampling"`
+	Timeout              duration.Duration `json:"timeout"`
+	ExpectedResponseCode []int32           `json:"expectedResponseCode"`
 }
 
 func (h healthCheckSettings) Build() (proto.Message, error) {
 	return &burst.HealthPingConfig{
-		Destination:   h.Destination,
-		Connectivity:  h.Connectivity,
-		Interval:      int64(h.Interval),
-		Timeout:       int64(h.Timeout),
-		SamplingCount: int32(h.SamplingCount),
+		Destination:          h.Destination,
+		Connectivity:         h.Connectivity,
+		Interval:             int64(h.Interval),
+		Timeout:              int64(h.Timeout),
+		SamplingCount:        int32(h.SamplingCount),
+		ExpectedResponseCode: h.ExpectedResponseCode,
 	}, nil
 }