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
+65 -4
View File
@@ -1,6 +1,7 @@
package upstream
import (
"cmpp-platform/gateway/internal/protocollog"
"cmpp-platform/gateway/internal/queue"
"context"
"fmt"
@@ -19,6 +20,8 @@ const (
defaultReconnectInitialDelay = 5 * time.Second
defaultReconnectMaximumDelay = 5 * time.Minute
defaultAuthReconnectDelay = 5 * time.Minute
maximumConnections = 8
maximumWindowSize = 64
)
type Manager struct {
@@ -26,6 +29,14 @@ type Manager struct {
EventAPIBaseURL string
HTTPClient *http.Client
SubmitSegmentPublisher SubmitSegmentPublisher
EventPublisher interface {
PublishReceipt(context.Context, queue.ReceiptEvent) error
PublishUplink(context.Context, queue.UplinkEvent) error
}
ProtocolLogPublisher interface {
Publish(context.Context, protocollog.Event) error
}
GatewayInstanceID string
mu sync.Mutex
conns map[string]*connectionPool
@@ -72,8 +83,14 @@ func (m *Manager) ConnectChannel(ctx context.Context, command queue.ConnectChann
WindowSize: command.Channel.WindowSize,
HeartbeatIntervalSeconds: command.Channel.HeartbeatIntervalSeconds,
HeartbeatMissThreshold: command.Channel.HeartbeatMissThreshold,
ConnectionWarmupSeconds: command.Channel.ConnectionWarmupSeconds,
ConnectionDrainSeconds: command.Channel.ConnectionDrainSeconds,
SubmitTimeoutSeconds: command.Channel.SubmitTimeoutSeconds,
FailureCooldownSeconds: command.Channel.FailureCooldownSeconds,
})
if pool == nil || !pool.matches(config) {
if pool != nil && !pool.matches(config) && pool.sameEndpoint(config) {
pool.reconfigure(config)
} else if pool == nil || !pool.matches(config) {
if pool != nil {
pool.close()
}
@@ -130,7 +147,9 @@ func (m *Manager) connectionFor(cmd queue.SubmitCommand) (*connectionPool, error
m.ensureDefaultsLocked()
pool := m.conns[cmd.ChannelID]
if pool == nil || !pool.matches(cmd.Upstream) {
if pool != nil && !pool.matches(cmd.Upstream) && pool.sameEndpoint(cmd.Upstream) {
pool.reconfigure(cmd.Upstream)
} else if pool == nil || !pool.matches(cmd.Upstream) {
if pool != nil {
pool.close()
}
@@ -170,6 +189,27 @@ func (m *Manager) ConnectionCounts() (desired int, connected int) {
return desired, connected
}
func (m *Manager) WindowCounts() (configured int, inFlight int) {
m.mu.Lock()
pools := make([]*connectionPool, 0, len(m.conns))
for _, pool := range m.conns {
pools = append(pools, pool)
}
m.mu.Unlock()
for _, pool := range pools {
pool.mu.Lock()
conns := append([]*connection(nil), pool.conns...)
pool.mu.Unlock()
for _, conn := range conns {
conn.mu.Lock()
configured += max(1, conn.windowLimit)
inFlight += len(conn.window)
conn.mu.Unlock()
}
}
return configured, inFlight
}
func (m *Manager) newConnectionPool(channelID string, connectionID string, config queue.UpstreamConfig) *connectionPool {
eventAPIBaseURL := m.EventAPIBaseURL
if eventAPIBaseURL == "" {
@@ -184,8 +224,11 @@ func (m *Manager) newConnectionPool(channelID string, connectionID string, confi
reporter: func(ctx context.Context, state ConnectionState) error {
return m.post(ctx, "/admin/gateway/connections", state)
},
reconnectSignal: make(chan struct{}, 1),
stopCh: make(chan struct{}),
protocolLogPublisher: m.ProtocolLogPublisher,
gatewayInstanceID: m.GatewayInstanceID,
eventPublisher: m.EventPublisher,
reconnectSignal: make(chan struct{}, 1),
stopCh: make(chan struct{}),
}
}
@@ -202,6 +245,12 @@ func validateConnectChannelCommand(command queue.ConnectChannelCommand) error {
if command.Channel.Account == "" || command.Channel.PasswordCipher == "" {
return fmt.Errorf("account and passwordCipher are required")
}
if command.DesiredConnections < 1 || command.DesiredConnections > maximumConnections {
return fmt.Errorf("desiredConnections must be between 1 and %d", maximumConnections)
}
if command.Channel.WindowSize != 0 && (command.Channel.WindowSize < 1 || command.Channel.WindowSize > maximumWindowSize) {
return fmt.Errorf("windowSize must be between 1 and %d", maximumWindowSize)
}
return nil
}
@@ -222,5 +271,17 @@ func normalizeUpstreamConfig(config queue.UpstreamConfig) queue.UpstreamConfig {
if config.HeartbeatMissThreshold <= 0 {
config.HeartbeatMissThreshold = defaultHeartbeatMissThreshold
}
if config.ConnectionWarmupSeconds < 0 {
config.ConnectionWarmupSeconds = 30
}
if config.ConnectionDrainSeconds <= 0 {
config.ConnectionDrainSeconds = 60
}
if config.SubmitTimeoutSeconds <= 0 {
config.SubmitTimeoutSeconds = 60
}
if config.FailureCooldownSeconds <= 0 {
config.FailureCooldownSeconds = 30
}
return config
}