Files
DragonCoreSSH-NewWEB/xray_native_tuning.go
T
2026-07-24 10:08:06 -03:00

140 lines
5.9 KiB
Go

package main
import (
"runtime"
"sync/atomic"
"time"
)
type XrayNativeTuning struct {
RuntimeGOMAXPROCS int `json:"runtime_gomaxprocs,omitempty"`
MuxGlobalSessions int `json:"mux_global_sessions,omitempty"`
MaxConcurrentConnections int `json:"max_concurrent_connections,omitempty"`
MaxConcurrentXHTTPRequests int `json:"max_concurrent_xhttp_requests,omitempty"`
XHTTPMaxSessions int `json:"xhttp_max_sessions,omitempty"`
TracePackets bool `json:"trace_packets,omitempty"`
}
const (
defaultNativeRuntimeGOMAXPROCS = 0
defaultNativeMuxGlobalSessions = 32768
// Transport sockets, XHTTP requests, and XHTTP sessions are VPN traffic, not
// website requests. Keep the legacy JSON fields for config compatibility, but
// always normalize them to unlimited. Actual resource protection is provided by
// socket/HTTP flow control and the bounded byte queues in xray_xhttp.go.
defaultNativeMaxConnections = -1
defaultNativeMaxXHTTPRequests = -1
fixedNativeMuxMaxSessions = 64
fixedNativeMuxUDPIdleMS = 120000
fixedNativeMuxUDPReadBuffer = 256 * 1024
fixedNativeMuxUDPWriteBuffer = 256 * 1024
defaultNativeXHTTPMaxSessions = -1
// Packet-up posts are also protected by byte budgets in xray_xhttp.go. Keep
// the default reorder queue modest so thousands of unauthenticated sessions
// cannot consume large amounts of memory merely by allocating empty channel
// buffers. Operators may request more, up to the hard cap enforced there.
defaultNativeXHTTPBufferedPosts = 64
// These are simultaneous resource-safety windows, not request-rate limits.
// They are deliberately far above the expected 6-8K connected-user load, but
// finite so a reconnect storm, broken CDN, or hostile client cannot retain an
// unbounded number of sockets, HTTP handlers, sessions, and goroutine stacks.
// Transport Accept waits at capacity (kernel backpressure); XHTTP overloads
// receive 503 rather than the web-rate-limit semantics of 429.
fixedNativeMaxTransportConnections = 65536
fixedNativeMaxXHTTPRequests = 65536
fixedNativeMaxXHTTPSessions = 65536
fixedNativeHTTP2ConcurrentStreams = 4096
fixedNativeXHTTPWriteTimeoutMS = 60 * 1000
// Backstop reaper for connected XHTTP VPN sessions. The stream-down GET's
// request context is the primary lifetime owner, but behind a CDN that context
// frequently never fires when a client silently drops (mobile networks, CDN
// connection pooling, half-open TCP). When it doesn't, an idle SSH backend
// never errors either, so the session, its goroutines, socket/fd, and SSH
// connection leak until the whole process restarts. That accumulation is what
// drove the recurring XHTTP 502s that only a reboot cleared: the origin slowly
// ran out of fds/memory and could no longer serve new stream-down GETs.
//
// This sweeper only ever reaps sessions with genuinely stale lastSeen. lastSeen
// is refreshed on every successful read OR write via nativeXHTTPConn.onActivity,
// so any tunnel still passing data or keepalives is never touched -- only a
// session with zero bytes in BOTH directions for the full window (i.e. one that
// looks dead) is closed. 20 minutes is generous enough not to disturb a
// genuinely idle-but-alive tunnel while still bounding resource growth under
// heavy 6-8K-user churn. Zero disables the connected-session sweeper.
fixedNativeXHTTPIdleMS = 20 * 60 * 1000
)
var (
nativeTuneRuntimeGOMAXPROCS atomic.Int64
nativeTuneMuxGlobalSessions atomic.Int64
nativeTuneTracePackets atomic.Bool
)
func init() {
applyNativeXrayTuning(nil)
}
func normalizeNativeXrayTuning(t *XrayNativeTuning) XrayNativeTuning {
if t == nil {
t = &XrayNativeTuning{}
}
out := *t
if out.RuntimeGOMAXPROCS < 0 {
out.RuntimeGOMAXPROCS = defaultNativeRuntimeGOMAXPROCS
}
if out.MuxGlobalSessions <= 0 {
out.MuxGlobalSessions = defaultNativeMuxGlobalSessions
}
// Ignore every old positive/zero admission ceiling. This migration is
// deliberately unconditional so upgrading an existing server immediately
// removes the old 4K/8K/32K web-style caps without requiring a panel save.
out.MaxConcurrentConnections = defaultNativeMaxConnections
out.MaxConcurrentXHTTPRequests = defaultNativeMaxXHTTPRequests
out.XHTTPMaxSessions = defaultNativeXHTTPMaxSessions
return out
}
func applyNativeXrayTuning(t *XrayNativeTuning) XrayNativeTuning {
out := normalizeNativeXrayTuning(t)
gomax := out.RuntimeGOMAXPROCS
if gomax <= 0 {
gomax = runtime.NumCPU()
}
if gomax < 1 {
gomax = 1
}
runtime.GOMAXPROCS(gomax)
nativeTuneRuntimeGOMAXPROCS.Store(int64(gomax))
nativeTuneMuxGlobalSessions.Store(int64(out.MuxGlobalSessions))
nativeTuneTracePackets.Store(out.TracePackets)
return out
}
func nativeRuntimeGOMAXPROCS() int { return int(nativeTuneRuntimeGOMAXPROCS.Load()) }
func nativeMuxGlobalSessionLimit() int { return int(nativeTuneMuxGlobalSessions.Load()) }
func nativeTracePacketsEnabled() bool { return nativeTuneTracePackets.Load() }
func nativeMuxMaxSessionLimit() int { return fixedNativeMuxMaxSessions }
func nativeMuxUDPReadBufferSize() int { return fixedNativeMuxUDPReadBuffer }
func nativeMuxUDPWriteBufferSize() int { return fixedNativeMuxUDPWriteBuffer }
func nativeXHTTPBufferedPostLimit() int { return defaultNativeXHTTPBufferedPosts }
func nativeHTTP2MaxConcurrentStreams() uint32 {
return fixedNativeHTTP2ConcurrentStreams
}
func nativeTransportConnectionLimit() int { return fixedNativeMaxTransportConnections }
func nativeXHTTPRequestLimit() int { return fixedNativeMaxXHTTPRequests }
func nativeXHTTPSessionLimit() int { return fixedNativeMaxXHTTPSessions }
func nativeXHTTPWriteTimeout() time.Duration {
return fixedNativeXHTTPWriteTimeoutMS * time.Millisecond
}
func nativeMuxUDPIdleTimeout() time.Duration {
return fixedNativeMuxUDPIdleMS * time.Millisecond
}
func nativeXHTTPIdleTimeout() time.Duration {
return fixedNativeXHTTPIdleMS * time.Millisecond
}