Zurück zum Blog

Engineering Hybrid Matchmaking: Wie Call of Dutys Queue-Split moderne Game Matchmaking Architecture offenbart

Veröffentlicht am 24. Juli 2026
Engineering Hybrid Matchmaking: Wie Call of Dutys Queue-Split moderne Game Matchmaking Architecture offenbart

Kurz und knapp

Die Aufteilung von Spielerbasen in mehrere Matchmaking-Queues wie bei Call of Duty: Black Ops 7 erhöht den infrastrukturellen Backend-Overhead drastisch. Um Pool-Fragmentierung und hohe Queue-Zeiten zu vermeiden, erfordern moderne Architekturen dynamische Regel-Expansions-Algorithmen, atomares Ticket-Locking sowie asynchrone Dedicated-Server-Orchestrierung. Dieser Artikel analysiert die mathematischen und technischen Trade-offs von SBMM, Ping-First und Hybrid-Ansätzen inklusive einer C#-Referenzimplementierung.

Als Activision ankündigte, dass Call of Duty: Black Ops 7 seine Spielerbasis auf drei verschiedene Matchmaking-Queues aufteilen würde – Skill-Based Matchmaking (SBMM), Classic Connection-Based und Hybrid –, rückte eine langjährige Backend-Engineering-Debatte direkt in den Fokus. Bei Competitive-Titeln ist die Entscheidung, wie Spieler gematcht werden, nicht bloß eine Game-Design-Präferenz. Es ist ein komplexes Problem der Game Matchmaking Architecture, das Sub-Millisekunden-Netzwerk-Constraints, mathematische Skill-Varianz, Pool-Fragmentierung und Cloud-Compute-Kosten gegeneinander abwägt.

Die Aufteilung eines Matchmaking-Systems in mehrere separate Queues klingt an der Oberfläche nach einem einfachen Feature für Spielerpräferenzen. In der Realität verdoppelt oder verdreifacht es jedoch den Engineering-Overhead Ihrer Backend-Infrastruktur. Wenn Sie eine gleichzeitige Spielerbasis (CCU) in separate Queues unterteilen, bricht die Ticket-Dichte drastisch ein, die Queue-Zeiten explodieren in Regionen mit geringer Dichte exponentiell und Server-Allocation-Algorithmen sind erhöhtem Churn ausgesetzt.

In diesem Artikel analysieren wir die technischen Trade-offs von SBMM gegenüber Connection-First-Matchmaking, sezieren die Mathematik hinter der dynamischen Hybrid-Queue-Expansion, untersuchen echten Backend-C#-Code für das Ticket-Processing und beleuchten, wie man resilientere Matchmaking-Pools baut, die sauber skalieren.


Das unveränderliche Matchmaking-Trilemma

Jede moderne Game Matchmaking Architecture muss ein Constraint-Optimierungsproblem lösen, das an drei konkurrierende Variablen gebunden ist:

  1. Latenz (RTT): Die Round-Trip-Time zwischen dem Player-Client und der zugewiesenen Dedicated-Server-Instanz (gemessen in Millisekunden).
  2. Skill Delta ($\Delta$MMR): Die mathematische Abweichung der Skill-Repräsentation (MMR, Elo oder TrueSkill) zwischen Spielern in einer gegebenen Lobby.
  3. Queue Duration ($T_{queue}$): Die Gesamtzeit, die ein Spieler im Zustand wartender Queue-Friction verbringt, bevor ein gültiges Matchmaking-Ticket in eine aktive Server-Allocation übergeht.
                    Latency (RTT)
                      /       \
                     /         \
                    /   Ideal   \
                   /    Match    \
                  /               \
Skill Delta (ΔMMR) --------------- Queue Duration (T_queue)

Sie können problemlos zwei dieser Variablen auf Kosten der dritten optimieren:

  • Low Latency + Low Skill Delta: Führt zu langen Queue-Zeiten, da die Engine nach seltenen, perfekt passenden Spielern suchen muss, die sich zudem in der Nähe desselben Cloud-Rechenzentrums befinden.
  • Low Queue Time + Low Skill Delta: Führt zu hoher Latenz, da der Matchmaker seinen geografischen Suchradius weltweit erweitern muss, um Gegner auf gleichem Skill-Niveau zu finden.
  • Low Queue Time + Low Latency: Führt zu hoher Skill-Varianz (das klassische „Connection-First“-Public-Match-Erlebnis), da der Matchmaker sofort die nächstgelegenen verfügbaren Clients wählt – unabhängig von deren Performance-Metriken.

Wenn ein Titel wie Black Ops 7 drei separate Queue-Modi einführt, zwingt dies die zugrundeliegende Matchmaking-Architektur dazu, drei parallele Rule-Evaluation-Loops über fragmentierte Memory-Pools hinweg aufrechtzuerhalten.

Wenn die Zahl der Concurrent Users (CCU) in einer bestimmten Region – beispielsweise in Südamerika um 04:00 Uhr morgens – unter 2.000 aktive Spieler fällt, reduziert die Aufteilung dieser Spieler auf drei separate Pools die lokale Dichte pro Queue auf nur noch wenige hundert Spieler. Die Folge: Connection-First-Queues finden keine Dedicated Server mit niedrigem Ping und SBMM-Queues geraten ins Stocken.


Dekonstruktion: SBMM vs. Ping-First vs. Hybrid-Queues

Um ein Backend zu bauen, das Millionen von Match-Tickets verarbeiten kann, muss man verstehen, wie die einzelnen Architekturmodelle unter der Haube funktionieren.

1. Connection-Based (Ping-First) Architecture

In einer Connection-First-Engine sind Skill-Matrizen zweitrangig oder werden komplett ignoriert. Das primäre Ziel ist die Minimierung von Netzwerk-Degradierung (Jitter, Packet Loss, hoher RTT).

  • Client Ping Probing: Beim Betreten der Queue sendet der Spielclient ICMP- oder UDP-Ping-Beacons an eine Reihe regionaler Edge Gateways (z. B. us-east-1, eu-central-1, ap-southeast-1).
  • Ping Vector Generation: Der Client erstellt einen Latenz-Vektor: [ us-east: 24ms, us-west: 78ms, eu-central: 142ms ] und hängt diesen an den Matchmaking-Payload an.
  • Spatial Indexing: Der Matchmaker teilt Spieler anhand akzeptabler Latenz-Schwellenwerte (z. B. $RTT < 50ms$) strikt in Regions-Hashes ein.

Da die Netzwerktopologie die Match-Erstellung diktiert, sind die Search-Buckets der Spieler vorhersagbar. Dadurch können Tickets in $O(1)$-Zeit mithilfe einfacher räumlicher FIFO-Queues (First-In, First-Out) aufgelöst werden.

2. Skill-Based Matchmaking (SBMM) Architecture

SBMM priorisiert die Fairness von Matches, indem es die Spielerfähigkeiten mithilfe mehrdimensionaler Gauß-Verteilungen (z. B. TrueSkill 2) oder angepasster Elo-Varianten modelliert. Wichtige Inputs sind Win/Loss-Ratios, Kill/Death-Ratios, Damage per Minute sowie die Performance-Entwicklung der letzten Matches.

  • Distance Evaluation: Der Matchmaker berechnet die euklidische Distanz oder die Mahalanobis-Distanz zwischen den Vektoren der Kandidaten im $N$-dimensionalen Skill-Raum.
  • Sorting Cost: Matchmaker können sich nicht auf einfache FIFO-Queues verlassen. Sie müssen sortierte Sets oder räumliche Bäume (wie KD-Bäume) von Ticket-Profilen verwalten, um rasch Kandidaten innerhalb einer akzeptablen Skill-Varianz $\sigma$ zu finden.
  • Search Space Contraction: Mit steigendem Skill (z. B. den obersten 0,5 % der Spieler) schrumpft der Pool passender Kandidaten drastisch. Das zwingt das System dazu, Tickets entweder unbegrenzt zu halten oder die Parameter für die Skill-Strenge langsam aufzuweichen.

3. Dynamic Hybrid Architecture

Anstatt Spieler in hartkodierte Queue-Optionen zu zwängen, implementieren moderne Production-Backends häufig ein Dynamic Hybrid-Modell. In diesem Setup startet jedes Match-Ticket mit striktem SBMM und niedrigen Latenzgrenzen. Wenn $T_{queue}$ steigt, erweitert eine Rule-Decay-Funktion kontinuierlich das akzeptable Skill Delta ($\Delta MMR$) und das Latenzlimit ($RTT_{max}$)...

$$\Delta MMR_{allowed}(t) = \Delta MMR_{base} + \alpha \cdot t^{\gamma}$$

$$RTT_{allowed}(t) = \min\left(RTT_{max_cap}, RTT_{base} + \beta \cdot \lfloor t / \Delta t_{step} \rfloor\right)$$

Wobei $\alpha$ und $\beta$ Expansionskoeffizienten sind, $\gamma$ die Steilheit der exponentiellen Kurve steuert und $t$ die verstrichene Queue-Dauer in Sekunden darstellt.

Durch die Nutzung dynamischer Lockerung verhindern Sie unendliche Queue-Hänger, während Sie in Peak-CCU-Zeiten eine hohe Match-Qualität aufrechterhalten.


Code-Implementierung: Dynamic Rule Expansion Engine

Nachfolgend finden Sie eine praxiserprobte C#-Implementierung einer Dynamic Matchmaking Rule Expansion Engine. Dieser Service evaluiert eingehende Tickets gegenüber aktiven Queue-Pools und berechnet Echtzeit-Ping-Kompatibilitätsmatrizen sowie dynamische MMR-Varianz-Caps.

using System;
using System.Collections.Generic;
using System.Linq;

namespace Horizon.Matchmaking.Engine
{
    public class MatchmakingTicket
    {
        public string TicketId { get; set; } = Guid.NewGuid().ToString();
        public string PlayerId { get; set; }
        public double SkillRating { get; set; } // Elo/MMR representation
        public Dictionary<string, int> RegionalPingMap { get; set; } = new(); // e.g., "us-east": 28
        public DateTime EnqueuedAtUtc { get; set; }
    }

    public class DynamicMatchRules
    {
        public double MaxAllowedMmrDelta { get; set; }
        public int MaxAllowedPingMs { get; set; }
    }

    public class MatchmakingEvaluator
    {
        private const double BaseMmrDelta = 50.0;
        private const double MaxMmrCap = 600.0;
        private const int BasePingMs = 35;
        private const int AbsoluteMaxPingMs = 180;
        private const double PingStepIntervalSeconds = 4.0;

        /// <summary>
        /// Calculates the expanded criteria for a ticket based on elapsed queue time.
        /// </summary>
        public DynamicMatchRules GetRelaxedRules(MatchmakingTicket ticket, DateTime currentUtc)
        {
            double elapsedTime = (currentUtc - ticket.EnqueuedAtUtc).TotalSeconds;

            // Exponential expansion for skill tolerance to ensure high-skill players eventually match
            double mmrExpansion = Math.Pow(elapsedTime, 1.35) * 4.5;
            double calculatedMmrDelta = Math.Min(MaxMmrCap, BaseMmrDelta + mmrExpansion);

            // Step-wise discrete expansion for latency tolerance (prevents constant server hopping)
            int pingSteps = (int)Math.Floor(elapsedTime / PingStepIntervalSeconds);
            int calculatedPingLimit = Math.Min(AbsoluteMaxPingMs, BasePingMs + (pingSteps * 15));

            return new DynamicMatchRules
            {
                MaxAllowedMmrDelta = calculatedMmrDelta,
                MaxAllowedPingMs = calculatedPingLimit
            };
        }

        /// <summary>
        /// Evaluates whether two tickets can be paired into a match session.
        /// </summary>
        public bool CanMatchTickets(MatchmakingTicket ticketA, MatchmakingTicket ticketB, DateTime currentUtc, out string selectedRegion)
        {
            selectedRegion = null;

            DynamicMatchRules rulesA = GetRelaxedRules(ticketA, currentUtc);
            DynamicMatchRules rulesB = GetRelaxedRules(ticketB, currentUtc);

            // 1. Evaluate Skill Delta
            double actualMmrDelta = Math.Abs(ticketA.SkillRating - ticketB.SkillRating);
            if (actualMmrDelta > rulesA.MaxAllowedMmrDelta || actualMmrDelta > rulesB.MaxAllowedMmrDelta)
            {
                return false; // Skill variance too wide for current queue age
            }

            // 2. Evaluate Common Datacenter Ping Compatibility
            int lowestCombinedPing = int.MaxValue;

            foreach (var (region, pingA) in ticketA.RegionalPingMap)
            {
                if (ticketB.RegionalPingMap.TryGetValue(region, out int pingB))
                {
                    // Match must satisfy BOTH players' dynamic ping limits
                    if (pingA <= rulesA.MaxAllowedPingMs && pingB <= rulesB.MaxAllowedPingMs)
                    {
                        int combinedPing = pingA + pingB;
                        if (combinedPing < lowestCombinedPing)
                        {
                            lowestCombinedPing = combinedPing;
                            selectedRegion = region;
                        }
                    }
                }
            }

            return selectedRegion != null;
        }
    }
}

Wichtige technische Aspekte dieser Implementierung:

  • Asymmetrische Regelprüfung: Die Methode stellt sicher, dass die sich erweiternden Constraints beider Spieler berücksichtigt werden (pingA <= rulesA.MaxAllowedPingMs && pingB <= rulesB.MaxAllowedPingMs). Ein neuer Spieler, der erst seit 2 Sekunden in der Queue ist, wird nicht auf einen Server mit 150 ms Ping gezogen, nur weil der andere Spieler seit 90 Sekunden wartet.
  • Diskrete Ping-Stufen: Latenzgrenzen erweitern sich über diskrete Zeitschritte (PingStepIntervalSeconds) statt über kontinuierliche Kurven. Dies vermeidet unnötige Reassignments an Edge-Routern bei jedem Tick-Loop.
  • Spatial Intersection: Das Matching basiert auf der Schnittmenge von Dictionary-Keys über regionale Maps hinweg und wählt das Rechenzentrum mit der geringsten kumulativen Round-Trip-Latenz aus.

Backend-Infrastruktur-Herausforderungen: Concurrency, Lock Contention und Dedicated Server Provisioning

Das Schreiben von Matchmaking-Algorithmen in Isolation ist geradlinig. Die eigentliche Engineering-Herausforderung entsteht, wenn Sie dieses System über verteilte Node-Cluster hinweg ausführen, die hunderte tausende gleichzeitige Tickets verarbeiten.

[Player Clients]
       │ (WebSockets / Low Latency)
       ▼
[Ingress Load Balancers]
       │
       ▼
[Distributed Ticket Pool (e.g., Redis Cluster / Memory Grid)]
       │
  ┌────┴────────────────────────┬────────────────────────┐
  ▼                             ▼                        ▼
[Worker Node 1]           [Worker Node 2]          [Worker Node 3]
  │                             │                        │
  └────┬────────────────────────┴────────────────────────┘
       │ (Atomic Claim / Lua Mutex Lock)
       ▼
[Server Orchestration API] ──► Spin up Agones / Fleet Instances

1. Distributed Ticket Lock Contention

Wenn mehrere parallele Matchmaker-Prozesse denselben zentralen Ticket-Pool scannen, kommt es zwangsläufig zu Race Conditions. Zwei separate Worker-Threads könnten gleichzeitig Ticket #1042 evaluieren und versuchen, es in zwei völlig unterschiedlichen Lobbies unterzubringen.

Um dies zu lösen, müssen Entwickler atomare Lock-Claims mittels verteilter Primitiven (wie Redis-Lua-Skripten oder atomaren Memory-Grid-Operationen) ausführen, bevor eine Match-Zuweisung erfolgt. Ist ein Ticket durch einen anderen Match-Worker gesperrt, gibt der Thread seinen Status sofort frei und führt ein Backtracking durch.

2. High-Frequency Real-Time Communication

Matchmaking-Status-Updates können nicht auf Standard-HTTP-Polling setzen, ohne enorme Compute-Ressourcen für nutzlose Verbindungs-Handshakes zu verschwenden. Um Clients über geschätzte Queue-Dauern und dynamische Ping-Suchen auf dem Laufenden zu halten, müssen Backends persistente, bidirektionale WebSockets oder langlebige gRPC-Streams aufrechterhalten.

Wenn Sie für Ihren Multiplayer-State derzeit auf inefficientes Polling setzen, lesen Sie unseren Leitfaden dazu, wie Sie HTTP-Polling durch Unreal Engine WebSockets in Real-time-Backends ersetzen.

3. Server Allocation Handshakes & Fleet Provisioning

Das Matchmaking der Spieler ist nur die halbe Miete. Sobald eine gültige Ticket-Gruppe gebildet wurde:

  1. Der Matchmaker kontaktiert einen Dedicated-Server-Orchestrator (z. B. Agones, benutzerdefinierte Kubernetes-Controller).
  2. Eine frische Game-Server-Instanz muss im ausgewählten Rechenzentrum innerhalb einer strikten Deadline (typischerweise $< 1500ms$) gecovert bzw. allokiert werden.
  3. Der Server fährt hoch, bindet seinen listening UDP-Port und gibt das IP/Port-Address-Payload zurück.
  4. Der Matchmaker übermittelt die Verbindungsdetails an alle Client-WebSockets.

Das manuelle Bauen verteilter Ticket-Pools, das Handling von Lock Contention, das Verwalten regionsbasierter Socket-Cluster und das Orchestrieren von Dedicated-Server-Lebenszyklen erfordert monatelange Infrastrukturarbeit.

Hier eliminiert horizOn massiven Engineering-Overhead. Anstatt Redis-Ticket-Stores zusammenzubauen, eigene Agones-Cluster-Wrapper zu schreiben und Scaling-Skripte für Server-Fleets zu verwalten, bietet horizOn voll verwaltete Matchmaking-Queues mit extrem niedriger Latenz sowie Server-Fleet-Orchestrierung out-of-the-box. Sie schreiben Ihre Matchmaking-Regelsets – horizOn kümmert sich nahtlos um globale Verteilung, atomares Ticket-Locking und automatische Server-Allocation.


5 Best Practices für den Aufbau moderner Game Matchmaking Architecture

Egal, ob Sie einen hochkompetitiven Shooter oder einen Casual-Indie-Titel entwickeln, folgen Sie diesen praxiserprobten Architekturprinzipien:

1. Mandate Client Ping Vectors Before Ticket Submission

Verlassen Sie sich niemals auf Geo-IP-Lookups der Client-IP, um die Nähe zu Ihren Rechenzentren zu bestimmen. Geo-IP-Datenbanken sind für Edge-Routing bekanntlich ungenau und ignorieren Echtzeit-ISP-Überlastungen. Zwingen Sie die Client-Engine immer dazu, die direkte Latenz über UDP-Ping-Probes zu allen regionalen Endpunkten zu messen, bevor der Enqueue-Endpunkt aufgerufen wird.

2. Guard Against Pool Fragmentation

Vermeiden Sie es, separate Queues für untergeordnete Spielmodi zu erstellen, es sei denn, Ihre aktive Spielerbasis rechtfertigt dies eindeutig. Die Aufteilung der Spielerbasis auf verschiedene Spielmodi, Map-Präferenzen und SBMM-Schärfegrade verstärkt die Pool-Degradierung. Wenn Ihre aktiven CCU pro Queue in einer Region unter 1.000 Spieler fallen, schalten Sie automatisch auf dynamische Single-Queue-Fallback-Modi um.

3. Decouple Server Provisioning from Match Evaluation

Stellen Sie sicher, dass Ihre Matchmaker-Threads asynchron zu Ihrer Fleet-Orchestrierungsschicht arbeiten. Halten Sie niemals einen aktiven Matchmaker-Worker-Loop offen, während Sie darauf warten, dass eine virtuelle Server-Instanz bootet. Nutzen Sie non-blocking Pub/Sub-Message-Queues, um Server-Allokationen anzufordern und Verbindungs-Payloads zuzustellen, sobald Instanzen einen Healthy-Status melden.

4. Optimize Idle Server Costs with Smart Hibernation

Matchmaking-Anfragen steigen in Peak-Zeiten unvorhersehbar an und fallen Off-Peak drastisch ab. Hunderte ungenutzte Game-Server-Instanzen leer laufen zu lassen, verbrennt erhebliche Betriebskosten. Implementieren Sie dynamische Fleet-Warm-up- und Server-Hibernation-Muster. Für eine tiefgehende technische Analyse zur Optimierung der Auslastung von Leerlauf-Servern lesen Sie unseren Beitrag über Zero-Waste-Server-Architekturen und Optimierungsvorschläge für Fortnite-Server.

5. Benchmark Netcode and Replication Under High Latency

Selbst die fortschrittlichste Matchmaking-Architektur wird in Off-Peak-Zeiten gelegentlich Spieler über moderate Latenzunterschiede ($100-120ms$) hinweg matchen. Stellen Sie sicher, dass Ihr Server-Netcode auf solide Client-Prediction, Lag-Compensation und State-Reconciliation setzt, um Paketverzögerungen sauber abzufangen. Wenn Spielerpositionen bei High-Ping-Matches springen oder desynchronisieren, lesen Sie unseren Guide zu Behebung von Player-Location-Desync im Unreal-Engine-Multiplayer.


Fazit & Nächste Schritte

Die Entscheidung von Activision, in Call of Duty: Black Ops 7 explizit SBMM-, Connection-First- und Hybrid-Queues anzubieten, verdeutlicht, wie entscheidend die Matchmaking-Architektur für die Spielerzufriedenheit ist. Das Aufteilen von Queues erfordert jedoch immense Spielerdichte, Low-Latency-Socket-Networking, dynamische Rule-Decay-Algorithmen und atomares Ticket-Handling.

Wenn Sie Ihr nächstes Multiplayer-Spiel entwickeln, verschwenden Sie keine Monate damit, Backend-Infrastruktur, Socket-Server und Fleet-Allocation-Logik von Grund auf neu zu schreiben. Erfahren Sie, wie horizOn Entwicklern dabei hilft, skalierbare Multiplayer-Game-Backends, automatisiertes Matchmaking und Server-Orchestrierung in Minuten zu deployen. Testen Sie horizOn noch heute kostenlos oder erkunden Sie die horizOn-Dokumentation, um Ihren Backend-Workflow zu beschleunigen.


Quelle: Call of Duty: Black Ops 7 will very soon offer three different matchmaking systems, and you'd be right to be confused