Kaynağa Gözat

Increase read timeout on HTTP server, try to not run out of sockets in stress test

Jakob Borg 11 yıl önce
ebeveyn
işleme
e0265aed05
2 değiştirilmiş dosya ile 63 ekleme ve 32 silme
  1. 1 1
      cmd/syncthing/gui.go
  2. 62 31
      test/httpstress_test.go

+ 1 - 1
cmd/syncthing/gui.go

@@ -158,7 +158,7 @@ func startGUI(cfg config.GUIConfiguration, assetDir string, m *model.Model) erro
 
 
 	srv := http.Server{
 	srv := http.Server{
 		Handler:     handler,
 		Handler:     handler,
-		ReadTimeout: 2 * time.Second,
+		ReadTimeout: 10 * time.Second,
 	}
 	}
 
 
 	go func() {
 	go func() {

+ 62 - 31
test/httpstress_test.go

@@ -49,6 +49,8 @@ func TestStressHTTP(t *testing.T) {
 		t.Fatal(err)
 		t.Fatal(err)
 	}
 	}
 
 
+	// Create a client with reasonable timeouts on all stages of the request.
+
 	tc := &tls.Config{InsecureSkipVerify: true}
 	tc := &tls.Config{InsecureSkipVerify: true}
 	tr := &http.Transport{
 	tr := &http.Transport{
 		TLSClientConfig:       tc,
 		TLSClientConfig:       tc,
@@ -60,72 +62,101 @@ func TestStressHTTP(t *testing.T) {
 		Transport: tr,
 		Transport: tr,
 		Timeout:   10 * time.Second,
 		Timeout:   10 * time.Second,
 	}
 	}
-	var wg sync.WaitGroup
-	t0 := time.Now()
 
 
-	var counter int
-	var lock sync.Mutex
+	var (
+		requestsOK    = map[string]int{}
+		requestsError = map[string]int{}
+		firstError    error
+		lock          sync.Mutex
+	)
+
+	gotError := func(ctx string, err error) {
+		lock.Lock()
+		requestsError[ctx]++
+		if firstError == nil {
+			firstError = err
+		}
+		lock.Unlock()
+	}
+
+	requestOK := func(ctx string) {
+		lock.Lock()
+		requestsOK[ctx]++
+		lock.Unlock()
+	}
+
+	log.Println("Testing...")
 
 
-	errChan := make(chan error, 2)
+	var wg sync.WaitGroup
+	t0 := time.Now()
 
 
 	// One thread with immediately closed connections
 	// One thread with immediately closed connections
 	wg.Add(1)
 	wg.Add(1)
 	go func() {
 	go func() {
+		defer wg.Done()
 		for time.Since(t0).Seconds() < 30 {
 		for time.Since(t0).Seconds() < 30 {
 			conn, err := net.Dial("tcp", "localhost:8082")
 			conn, err := net.Dial("tcp", "localhost:8082")
 			if err != nil {
 			if err != nil {
-				log.Println(err)
-				errChan <- err
-				return
+				gotError("Dial", err)
+			} else {
+				requestOK("Dial")
+				conn.Close()
 			}
 			}
-			conn.Close()
+
+			// At most 100 connects/sec
+			time.Sleep(10 * time.Millisecond)
 		}
 		}
-		wg.Done()
 	}()
 	}()
 
 
-	// 50 threads doing HTTP and HTTPS requests
+	// 50 threads doing mixed HTTP and HTTPS requests
 	for i := 0; i < 50; i++ {
 	for i := 0; i < 50; i++ {
 		i := i
 		i := i
 		wg.Add(1)
 		wg.Add(1)
 		go func() {
 		go func() {
+			defer wg.Done()
 			for time.Since(t0).Seconds() < 30 {
 			for time.Since(t0).Seconds() < 30 {
 				proto := "http"
 				proto := "http"
 				if i%2 == 0 {
 				if i%2 == 0 {
 					proto = "https"
 					proto = "https"
 				}
 				}
-				resp, err := client.Get(proto + "://localhost:8082/")
+				url := proto + "://localhost:8082/"
+				resp, err := client.Get(url)
+
 				if err != nil {
 				if err != nil {
-					errChan <- err
-					return
+					gotError("Get "+proto, err)
+					continue
 				}
 				}
-				bs, _ := ioutil.ReadAll(resp.Body)
+
+				bs, err := ioutil.ReadAll(resp.Body)
 				resp.Body.Close()
 				resp.Body.Close()
+
+				if err != nil {
+					gotError("Read "+proto, err)
+					continue
+				}
+
 				if !bytes.Contains(bs, []byte("</html>")) {
 				if !bytes.Contains(bs, []byte("</html>")) {
-					log.Printf("%s", bs)
-					errChan <- errors.New("Incorrect response")
-					return
+					err := errors.New("Incorrect response")
+					gotError("Get "+proto, err)
+					continue
 				}
 				}
 
 
-				lock.Lock()
-				counter++
-				lock.Unlock()
+				requestOK(url)
+
+				// At most 100 requests/sec
+				time.Sleep(10 * time.Millisecond)
 			}
 			}
-			wg.Done()
 		}()
 		}()
 	}
 	}
 
 
-	go func() {
-		wg.Wait()
-		errChan <- nil
-	}()
+	wg.Wait()
+	t.Logf("OK: %v reqs", requestsOK)
+	t.Logf("Err: %v reqs", requestsError)
 
 
-	err = <-errChan
-	if err != nil {
-		t.Error(err)
+	if firstError != nil {
+		t.Error(firstError)
 	}
 	}
 
 
-	t.Logf("%.01f reqs/sec", float64(counter)/time.Since(t0).Seconds())
-
 	err = sender.stop()
 	err = sender.stop()
 	if err != nil {
 	if err != nil {
 		t.Error(err)
 		t.Error(err)