我正在尝试编写一个多线程客户端来测试我的服务器。当我使用 2 个 goroutine 时,一切都很好,我得到 50k RPS,我的 CPU 负载是正常的,但是当我创建超过 2 个时,RPS 下降到 3K,但是我的 CPU 负载超过了。虽然当我多次运行我的客户端代码时(例如同时在 3 个控制台上运行相同的代码)我得到了更多的 RPS,比如 80k RPS。
这是我的客户端代码
package main
import (
"fmt"
"net/http"
"os"
"sync"
"time"
)
func main() {
requestURL := fmt.Sprintf("http://localhost:%d/home", 3333)
var wg sync.WaitGroup
wg.Add(4)
req, err := http.NewRequest(http.MethodGet, requestURL, nil)
if err != nil {
fmt.Printf("client: could not create request: %s\n", err)
os.Exit(1)
}
for i := 0; i < 4; i++ {
go func() {
defer wg.Done()
client := http.Client{
Timeout: 30 * time.Second,
}
for {
client.Do(req)
}
}()
}
wg.Wait()
}
这是我的服务器端代码
package main
import (
"errors"
"fmt"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
"log"
"net/http"
"os"
"sync"
)
// log handling
func openLogFile(path string) (*os.File, error) {
logFile, err := os.OpenFile(path, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0644)
if err != nil {
return nil, err
}
return logFile, nil
}
// variables of counter in metric
var okStatusCounter = prometheus.NewCounter(
prometheus.CounterOpts{
Name: "ok_request_count",
Help: "Number of 200",
},
)
func listener(serverLog *log.Logger) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
//metric
okStatusCounter.Inc()
w.WriteHeader(http.StatusOK)
}
}
func main() {
//metric
prometheus.MustRegister(okStatusCounter)
//log handling
fileSimpleServerLog, err := openLogFile("simpleServer/simpleServerLog.log")
if err != nil {
log.Fatal(err)
}
serverLog := log.New(fileSimpleServerLog, "[simple server]", log.LstdFlags|log.Lshortfile|log.Lmicroseconds)
var wg sync.WaitGroup
wg.Add(1)
//server:
go func() {
defer wg.Done()
mux := http.NewServeMux()
mux.HandleFunc("/home", listener(serverLog))
mux.Handle("/metrics", promhttp.Handler())
server := http.Server{
Addr: fmt.Sprintf(":%d", 3333),
Handler: mux,
}
if err := server.ListenAndServe(); err != nil {
if !errors.Is(err, http.ErrServerClosed) {
serverLog.Printf("error running http server: %s\n", err)
}
}
}()
wg.Wait()
}
起初我以为 go 可能对所有客户端连接使用一个端口,但是当我用 netstat 检查它时它使用了多个端口。我试图搜索,但我找不到任何合适的答案
我试过 sync.Mutex :
var mu sync.Mutex
...
for i := 0; i < 1000; i++ {
go func() {
defer wg.Done()
client := http.Client{
//Timeout: 30 * time.Second,
}
for {
mu.Lock()
_, err := client.Do(req)
if err != nil {
clientLog.Printf("client: error making http request: %s\n", err)
os.Exit(1)
}
mu.Unlock()
}
}()
}
wg.Wait()
...
通过上面的更改,我得到 13k RPS,我的 CPU 负载是正常的,但这根本不够