perf: use fasthttp for health checks; upgrade go to 1.25.3

This commit is contained in:
yusing
2025-10-17 22:50:13 +08:00
parent 3e73be60a1
commit 5a91db8d10
12 changed files with 172 additions and 144 deletions

View File

@@ -15,6 +15,7 @@ import (
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
"github.com/valyala/fasthttp"
"github.com/yusing/godoxy/agent/pkg/certs"
"github.com/yusing/goutils/version"
)
@@ -25,10 +26,10 @@ type AgentConfig struct {
Version version.Version `json:"version"`
Runtime ContainerRuntime `json:"runtime"`
httpClient *http.Client
httpClientHealthCheck *http.Client
tlsConfig tls.Config
l zerolog.Logger
httpClient *http.Client
fasthttpClientHealthCheck *fasthttp.Client
tlsConfig tls.Config
l zerolog.Logger
} // @name Agent
const (
@@ -107,8 +108,7 @@ func (cfg *AgentConfig) StartWithCerts(ctx context.Context, ca, crt, key []byte)
cfg.httpClient = cfg.NewHTTPClient()
applyNormalTransportConfig(cfg.httpClient)
cfg.httpClientHealthCheck = cfg.NewHTTPClient()
applyHealthCheckTransportConfig(cfg.httpClientHealthCheck)
cfg.fasthttpClientHealthCheck = cfg.NewFastHTTPHealthCheckClient()
ctx, cancel := context.WithTimeout(ctx, 5*time.Second)
defer cancel()
@@ -188,6 +188,25 @@ func (cfg *AgentConfig) NewHTTPClient() *http.Client {
}
}
func (cfg *AgentConfig) NewFastHTTPHealthCheckClient() *fasthttp.Client {
return &fasthttp.Client{
Dial: func(addr string) (net.Conn, error) {
if addr != AgentHost+":443" {
return nil, &net.AddrError{Err: "invalid address", Addr: addr}
}
return net.Dial("tcp", cfg.Addr)
},
TLSConfig: &cfg.tlsConfig,
ReadTimeout: 5 * time.Second,
WriteTimeout: 3 * time.Second,
DisableHeaderNamesNormalizing: true,
DisablePathNormalizing: true,
NoDefaultUserAgentHeader: true,
ReadBufferSize: 1024,
WriteBufferSize: 1024,
}
}
func (cfg *AgentConfig) Transport() *http.Transport {
return &http.Transport{
DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
@@ -220,13 +239,3 @@ func applyNormalTransportConfig(client *http.Client) {
transport.ReadBufferSize = 16384
transport.WriteBufferSize = 16384
}
func applyHealthCheckTransportConfig(client *http.Client) {
transport := client.Transport.(*http.Transport)
transport.DisableKeepAlives = true
transport.DisableCompression = true
transport.MaxIdleConns = 1
transport.MaxIdleConnsPerHost = 1
transport.ReadBufferSize = 1024
transport.WriteBufferSize = 1024
}

View File

@@ -2,10 +2,14 @@ package agent
import (
"context"
"fmt"
"io"
"net/http"
"time"
"github.com/bytedance/sonic"
"github.com/gorilla/websocket"
"github.com/valyala/fasthttp"
httputils "github.com/yusing/goutils/http"
"github.com/yusing/goutils/http/reverseproxy"
)
@@ -30,15 +34,44 @@ func (cfg *AgentConfig) Forward(req *http.Request, endpoint string) (*http.Respo
return resp, nil
}
func (cfg *AgentConfig) DoHealthCheck(ctx context.Context, endpoint string) (*http.Response, error) {
req, err := http.NewRequestWithContext(ctx, "GET", APIBaseURL+endpoint, nil)
if err != nil {
return nil, err
}
req.Header.Set("Accept-Encoding", "identity")
req.Header.Set("Connection", "close")
type HealthCheckResponse struct {
Healthy bool `json:"healthy"`
Detail string `json:"detail"`
Latency time.Duration `json:"latency"`
}
return cfg.httpClientHealthCheck.Do(req)
func (cfg *AgentConfig) DoHealthCheck(timeout time.Duration, query string) (ret HealthCheckResponse, err error) {
req := fasthttp.AcquireRequest()
defer fasthttp.ReleaseRequest(req)
resp := fasthttp.AcquireResponse()
defer fasthttp.ReleaseResponse(resp)
req.SetRequestURI(APIBaseURL + EndpointHealth + "?" + query)
req.Header.SetMethod(fasthttp.MethodGet)
req.Header.Set("Accept-Encoding", "identity")
req.SetConnectionClose()
start := time.Now()
err = cfg.fasthttpClientHealthCheck.DoTimeout(req, resp, timeout)
ret.Latency = time.Since(start)
if err != nil {
return ret, err
}
if status := resp.StatusCode(); status != http.StatusOK {
// clone body since fasthttp response will be released
body := resp.Body()
cloneBody := make([]byte, len(body))
copy(cloneBody, body)
return ret, fmt.Errorf("HTTP %d %s", status, cloneBody)
} else {
err = sonic.Unmarshal(resp.Body(), &ret)
if err != nil {
return ret, err
}
}
return ret, nil
}
func (cfg *AgentConfig) fetchString(ctx context.Context, endpoint string) (string, int, error) {