perf(cmpp): isolate inbound transport capacity
This commit is contained in:
@@ -50,13 +50,15 @@ func main() {
|
||||
|
||||
go func() {
|
||||
log.Printf("cmpp gateway inbound server listening on %s", cmppAddr)
|
||||
inboundConcurrency := positiveEnvInt("GATEWAY_CMPP_INBOUND_MAX_CONCURRENCY", 64)
|
||||
if err := (inbound.Server{
|
||||
Addr: cmppAddr,
|
||||
APIBaseURL: apiBaseURL,
|
||||
HTTPClient: inbound.NewAPIHTTPClient(inboundConcurrency),
|
||||
PresenceStore: presenceStore,
|
||||
RecoveryStore: recoveryStore,
|
||||
GatewayInstanceID: getenv("GATEWAY_INSTANCE_ID", hostname()),
|
||||
MaxSubmitConcurrency: positiveEnvInt("GATEWAY_CMPP_INBOUND_MAX_CONCURRENCY", 64),
|
||||
MaxSubmitConcurrency: inboundConcurrency,
|
||||
SecurityEventToken: os.Getenv("SECURITY_EVENT_TOKEN"),
|
||||
}).ListenAndServe(); err != nil {
|
||||
log.Fatalf("gateway inbound server stopped: %v", err)
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
package inbound
|
||||
|
||||
import (
|
||||
"net"
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
|
||||
// NewAPIHTTPClient keeps enough loopback connections warm for the bounded CMPP
|
||||
// Submit window. Go's default of two idle connections per host otherwise causes
|
||||
// connection churn exactly when SubmitResp latency matters most.
|
||||
func NewAPIHTTPClient(maxConcurrency int) *http.Client {
|
||||
if maxConcurrency < 1 {
|
||||
maxConcurrency = 64
|
||||
}
|
||||
transport := http.DefaultTransport.(*http.Transport).Clone()
|
||||
transport.MaxIdleConns = maxConcurrency + 16
|
||||
transport.MaxIdleConnsPerHost = maxConcurrency
|
||||
transport.MaxConnsPerHost = maxConcurrency
|
||||
transport.IdleConnTimeout = 90 * time.Second
|
||||
transport.DialContext = (&net.Dialer{
|
||||
Timeout: 3 * time.Second,
|
||||
KeepAlive: 30 * time.Second,
|
||||
}).DialContext
|
||||
return &http.Client{Transport: transport, Timeout: defaultHTTPTimeout}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package inbound
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestNewAPIHTTPClientMatchesBoundedSubmitConcurrency(t *testing.T) {
|
||||
client := NewAPIHTTPClient(48)
|
||||
transport, ok := client.Transport.(*http.Transport)
|
||||
if !ok {
|
||||
t.Fatalf("expected *http.Transport, got %T", client.Transport)
|
||||
}
|
||||
if transport.MaxConnsPerHost != 48 || transport.MaxIdleConnsPerHost != 48 {
|
||||
t.Fatalf("unexpected host connection bounds: max=%d idle=%d", transport.MaxConnsPerHost, transport.MaxIdleConnsPerHost)
|
||||
}
|
||||
if client.Timeout != defaultHTTPTimeout {
|
||||
t.Fatalf("unexpected client timeout: %s", client.Timeout)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewAPIHTTPClientUsesSafeDefault(t *testing.T) {
|
||||
client := NewAPIHTTPClient(0)
|
||||
transport := client.Transport.(*http.Transport)
|
||||
if transport.MaxConnsPerHost != 64 {
|
||||
t.Fatalf("expected default max connections 64, got %d", transport.MaxConnsPerHost)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user