perf: expand gateway capacity and prevent receipt replay

This commit is contained in:
hectorzhao
2026-08-25 16:08:30 +08:00
parent 761c123b65
commit 9292352be1
48 changed files with 2001 additions and 144 deletions
+28 -2
View File
@@ -13,6 +13,7 @@ import (
"cmpp-platform/gateway/internal/health"
"cmpp-platform/gateway/internal/inbound"
platformmetrics "cmpp-platform/gateway/internal/metrics"
"cmpp-platform/gateway/internal/protocollog"
"cmpp-platform/gateway/internal/queue"
"cmpp-platform/gateway/internal/ratelimit"
"cmpp-platform/gateway/internal/resultoutbox"
@@ -33,7 +34,17 @@ func main() {
}
apiBaseURL := os.Getenv("API_BASE_URL")
callbackBaseURL := getenv("GATEWAY_CALLBACK_API_BASE_URL", apiBaseURL)
upstreamManager := &upstream.Manager{APIBaseURL: apiBaseURL, EventAPIBaseURL: callbackBaseURL}
gatewayInstanceID := getenv("GATEWAY_INSTANCE_ID", hostname())
protocolLogPublisher, protocolLogErr := protocollog.New(os.Getenv("REDIS_URL"))
if protocolLogErr != nil {
log.Printf("gateway protocol log Redis publisher init failed: %v", protocolLogErr)
} else {
protocolLogPublisher.Stream = getenv("GATEWAY_PROTOCOL_LOG_STREAM", "gateway.protocol.logs")
protocolLogPublisher.GatewayInstanceID = gatewayInstanceID
protocolLogPublisher.SuccessSampleRate = positiveEnvInt("GATEWAY_PROTOCOL_LOG_SUCCESS_SAMPLE_PERCENT", 10)
protocolLogPublisher.MaxLen = int64(positiveEnvInt("GATEWAY_PROTOCOL_LOG_STREAM_MAX_LEN", 200000))
}
upstreamManager := &upstream.Manager{APIBaseURL: apiBaseURL, EventAPIBaseURL: callbackBaseURL, ProtocolLogPublisher: protocolLogPublisher, GatewayInstanceID: gatewayInstanceID}
var worker *submitworker.Worker
var resultOutbox *resultoutbox.Outbox
channelLimiter, err := ratelimit.New(os.Getenv("REDIS_URL"))
@@ -59,9 +70,10 @@ func main() {
SubmitHTTPClient: inbound.NewAPIHTTPClient(inboundConcurrency),
PresenceStore: presenceStore,
RecoveryStore: recoveryStore,
GatewayInstanceID: getenv("GATEWAY_INSTANCE_ID", hostname()),
GatewayInstanceID: gatewayInstanceID,
MaxSubmitConcurrency: inboundConcurrency,
SecurityEventToken: os.Getenv("SECURITY_EVENT_TOKEN"),
ProtocolLogPublisher: protocolLogPublisher,
}).ListenAndServe(); err != nil {
log.Fatalf("gateway inbound server stopped: %v", err)
}
@@ -83,8 +95,14 @@ func main() {
resultOutbox.Consumer = getenv("GATEWAY_SUBMIT_RESULT_CONSUMER", "gateway-1")
resultOutbox.APIBaseURL = callbackBaseURL
resultOutbox.Concurrency = positiveEnvInt("GATEWAY_SUBMIT_RESULT_WORKER_CONCURRENCY", 8)
resultOutbox.BatchEnabled = os.Getenv("GATEWAY_CALLBACK_BATCH_ENABLED") != "false"
resultOutbox.BatchSize = positiveEnvInt("GATEWAY_CALLBACK_BATCH_SIZE", 50)
resultOutbox.BatchWait = time.Duration(positiveEnvInt("GATEWAY_CALLBACK_BATCH_WAIT_MS", 10)) * time.Millisecond
resultOutbox.GatewayInstanceID = gatewayInstanceID
resultOutbox.DeadLetterStream = getenv("GATEWAY_CALLBACK_DEAD_LETTER_STREAM", "gateway.submit.results.dead")
worker.ResultOutbox = resultOutbox
upstreamManager.SubmitSegmentPublisher = resultOutbox
upstreamManager.EventPublisher = resultOutbox
go func() {
log.Printf("cmpp gateway submit worker consuming stream=%s group=%s consumer=%s", worker.Stream, worker.Group, worker.Consumer)
if err := worker.Run(context.Background()); err != nil {
@@ -108,6 +126,13 @@ func main() {
UpstreamDesired: desired, UpstreamConnected: connected,
DownstreamConnected: inbound.ActiveConnectionCount(), SubmitWorkerUp: worker != nil,
}
snapshot.UpstreamWindowConfigured, snapshot.UpstreamWindowInFlight = upstreamManager.WindowCounts()
if protocolLogPublisher != nil {
snapshot.ProtocolLogPublished, snapshot.ProtocolLogSampled, snapshot.ProtocolLogErrors = protocolLogPublisher.Counts()
if length, err := protocolLogPublisher.Redis.XLen(ctx, protocolLogPublisher.StreamName()).Result(); err == nil {
snapshot.ProtocolLogQueueLength = length
}
}
if worker != nil {
snapshot.SubmitWorkerConcurrency = worker.ConfiguredConcurrency()
snapshot.SubmitWorkerInFlight = worker.InFlight()
@@ -116,6 +141,7 @@ func main() {
snapshot.ResultWorkerUp = true
snapshot.ResultWorkerConcurrency = resultOutbox.ConfiguredConcurrency()
snapshot.ResultWorkerInFlight = resultOutbox.InFlight()
snapshot.CallbackBatchRequests, snapshot.CallbackBatchEvents, snapshot.CallbackBatchRetries, snapshot.CallbackDeadLetters = resultOutbox.BatchCounts()
}
snapshot.InboundSubmitConcurrency, snapshot.InboundSubmitInFlight = inbound.SubmitSlotSnapshot()
if worker == nil || worker.Redis == nil {