> For the complete documentation index, see [llms.txt](https://docs.edgegap.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.edgegap.com/ru/learn/matchmeiking/matchmaker-in-depth.md).

# Подробный обзор

Узнайте подробнее о концепциях no-code матчмейкера Edgegap и настройте его под свои нужды.

{% hint style="info" %}
Если вам нужна помощь, [свяжитесь с нами через Discord](https://discord.gg/MmJf8fWjnt). Для поддержки по играм в реальном времени см. нашу [систему тикетов](https://edgegap.atlassian.net/servicedesk/customer/portal/3).
{% endhint %}

## ✔️ Введение

Матчмейкинг в играх, основанных на матчах, как правило, стремится к следующему:

* **найти других игроков** на основе таких критериев, как регион, задержка, навыки или параметры игры;
* **найти серверы** чтобы подключиться к ним в зависимости от доступной вместимости \[или пинга, региона, навыков, карты, режима];
* **запустить новый сервер** если существующие серверы заполнены или не соответствуют критериям игрока.

Опыт игрока стоит на первом месте, определяя наши основные цели:

* высокая заполняемость матчей и интеграция социальных функций (игра с друзьями в группах),
* быстрые матчи с контролируемым качеством матчей (низкая задержка, общие предпочтения),
* надежный и предсказуемый процесс матчмейкинга с глобальной доступностью.

{% hint style="success" %}
В качестве альтернативы, позвольте игрокам **выбрать постоянный (всегда онлайн) сервер** из списка с [Браузер серверов](/ru/learn/brauzer-serverov.md).
{% endhint %}

**Начните за 5 минут и бесплатно протестируйте все функции, без кредитной карты.**

Перейдите на более мощный приватный (выделенный) кластер, когда будете готовы. Нативная интеграция с Edgegap [Развертывания](/ru/learn/orkestraciya/deployments.md) обеспечивает лучший в своем классе пинг, где бы ни находились ваши игроки.

{% hint style="info" %}
Бесплатный тариф позволяет 3 часа работы после каждого перезапуска. Ваш матчмейкер будет работать на общей инфраструктуре с ограниченными ресурсами, подходящими для тестирования. **После публичного релиза матчмейкер должен работать 24/7.**
{% endhint %}

В каждом матчмейкере есть три ключевые концепции:

* [#hosting-cluster](#hosting-cluster "mention") - базовая серверная инфраструктура, полностью управляемая и обслуживаемая Edgegap.
* [#configuration](#configuration "mention") - набор правил и настроек, определяющих, как работает матчмейкер.
* 🌐 Экземпляр сервиса **-** работающий сервис матчмейкинга, работающий 24/7 на кластере, использующий конфигурацию для объединения игроков и назначения развертываний (серверов).

{% hint style="success" %}
[Регулярно обновляйте версию матчмейкера](#changelog) в **чтобы пользоваться новыми функциями и исправлениями ошибок.**
{% endhint %}

## ▶️ Начать матчмейкинг

**Быстро начните работу — добавьте наш SDK в свою игру**:

* Unreal Engine [Инструменты разработчика](/ru/unreal-engine/developer-tools.md#integration-kit):
  * [прочитайте документацию](https://egik.betide.studio/) от Betide Studios,
  * [установите из Fab Marketplace](https://www.fab.com/listings/ff17ad88-12a1-49cf-9a41-31695ed11e16) (бесплатно для личного использования).
* Unity [Инструменты разработчика](/ru/unity/developer-tools.md#software-development-kit):
  * [установите пакет бесплатно с помощью Unity Package Manager](https://github.com/edgegap/edgegap-unity-sdk),
  * [изучите наше руководство для начала работы и полные примеры](/ru/unity/matchmaking.md).

Изучите процесс матчмейкинга, чтобы настраивать, устранять неполадки и оптимизировать интеграцию игры:

<figure><img src="https://3845012722-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FsR0dHSFv9ymoC0DO5G8J%2Fuploads%2Fm4U4bgwucX6iGEieMISU%2Fimage.png?alt=media&amp;token=39b97619-700b-4062-9dd9-73fa08fb96c2" alt=""><figcaption><p>Последовательность матчмейкинга</p></figcaption></figure>

1. [Аутентифицировать игрока](#authenticate) - не позволяет пиратским копиям играть онлайн,
2. [Создать лобби](#create-group) - объединяйтесь с друзьями и делитесь предпочтениями игрока/матча,
3. [**Собраться в группу**](#group-up) **- зарегистрируйте свое лобби как группу матчмейкинга,**
4. [**Найти матч**](#find-match) **- подготовьтесь и начните искать матч (новый или существующий),**
   1. Назначить сервер и внедрить тикеты — сервер назначается автоматически через несколько секунд,
5. [**Подключиться и аутентифицироваться**](#connect-to-server) **- попытка безопасного подключения к игровому серверу,**
   1. Подтвердить личность — сервер проверяет личность игрового клиента с помощью сторонних токенов,
   2. Принять игрока или выгнать игрока — сервер решает, разрешено ли игроку присоединиться.

### Аутентификация

Все запросы должны отправлять `Authorization`  HTTP-заголовок с вашим секретом **Токен аутентификации:**

<pre><code>Авторизация: <a data-footnote-ref href="#user-content-fn-1">xxxxxxxx-e458-4592-b607-c2c28afd8b62</a>
</code></pre>

{% hint style="warning" %}
**Храните ваши токены в секрете и в безопасности! Сотрудники Edgegap никогда не будут просить у вас ваши токены.**
{% endhint %}

{% hint style="info" %}
Токен Matchmaker и токены Server Browser являются отдельными от токенов Edgegap API.
{% endhint %}

{% hint style="success" %}
**Этот токен можно безопасно встроить в ваш игровой клиент, поскольку он не дает доступа к API Edgegap.**
{% endhint %}

Отдельных игроков можно идентифицировать по их ID тикета, доступному на клиенте и сервере. При желании добавьте собственную аутентификацию или ограничения с помощью пользовательского прокси, используя [#server-to-server-api](#server-to-server-api "mention") API.

### Собраться в группу

Создание группы гарантирует, что игроки вместе с друзьями попадут в одну команду и на один сервер.

{% hint style="success" %}
Создайте группу, отмеченную как готовую, чтобы [#find-match](#find-match "mention") быстро, как **одинокий игрок без участников группы**.
{% endhint %}

<figure><img src="https://3845012722-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FsR0dHSFv9ymoC0DO5G8J%2Fuploads%2FO79XVv9r9uZQ7ZI1kbFv%2FUntitled-2024-12-04-1155.png?alt=media&amp;token=9cf9caab-236d-4127-bb0f-4d50e1915f47" alt=""><figcaption><p>Диаграмма активности жизненного цикла группы</p></figcaption></figure>

#### Лобби и группа

Лобби и группа — похожие, но немного разные термины, относящиеся к [Сеансы игроков](/ru/learn/orkestraciya/seansy-igrokov.md).

Используйте сервис лобби, если дизайн вашей игры требует настройки предпочтений матчмейкинга, управляемых игроком (например, выбор персонажа, сложность, карта и т. д.). По мере того как игроки присоединяются к лобби и покидают его, они также обновляют группу матчмейкинга, чтобы подготовиться к поиску матча позже.

{% hint style="success" %}
**Нет времени на сервис лобби?** Подскажите игрокам делиться ID группы через Discord или личные сообщения.
{% endhint %}

<table data-search="false"><thead><tr><th width="390">Дизайн игры — функция / требование</th><th>Предматчевое лобби</th><th>Группа матчмейкера</th></tr></thead><tbody><tr><td><a data-footnote-ref href="#user-content-fn-2">приглашать друзей играть со мной</a></td><td>✅</td><td>✅</td></tr><tr><td>изменять мои предпочтения игрока/матча</td><td>✅</td><td>❌</td></tr><tr><td>просматривать предпочтения других участников лобби</td><td>✅</td><td>❌</td></tr><tr><td>хранить и управлять пользовательскими данными key-value</td><td>✅</td><td>❌</td></tr><tr><td>уведомлять участников группы, что я готов играть</td><td>❌</td><td>✅</td></tr><tr><td>показывать прогресс матчмейкинга и искать матч</td><td>❌</td><td>✅</td></tr><tr><td>получать назначение команды для игрока/группы</td><td>❌</td><td>✅</td></tr><tr><td>получать данные для подключения к игровому серверу</td><td>❌</td><td>✅</td></tr></tbody></table>

Наш кроссплатформенный матчмейкер поддерживает все коммерческие и пользовательские сервисы лобби:

<table data-search="false"><thead><tr><th width="414">Игровой бэкенд (включая сторонний сервис лобби)</th><th width="120" data-type="checkbox">Unreal Engine</th><th width="75" data-type="checkbox">Unity</th><th data-type="checkbox">Godot</th></tr></thead><tbody><tr><td><a href="https://dev.epicgames.com/docs/game-services/lobbies-and-sessions/lobbies/lobbies-intro">Лобби Epic Online Services</a><br>(Epic Games)</td><td>true</td><td>true</td><td>true</td></tr><tr><td><a href="https://partner.steamgames.com/doc/features/multiplayer/matchmaking#friends">Лобби Steamworks</a><br>(Valve Corporation)</td><td>true</td><td>true</td><td>true</td></tr><tr><td><a href="https://heroiclabs.com/docs/nakama/concepts/groups/">Группа Nakama</a><br>(Heroic Labs)</td><td>true</td><td>true</td><td>true</td></tr><tr><td><a href="https://learn.microsoft.com/en-us/gaming/playfab/community/associations/groups/quickstart">Лобби Playfab</a><br>(Microsoft)</td><td>true</td><td>true</td><td>true</td></tr><tr><td><a href="https://docs.braincloudservers.com/learn/key-concepts/multiplayer/lobbies/#lobby-experience">Лобби brainCloud</a><br>(bitHeads)</td><td>true</td><td>true</td><td>true</td></tr><tr><td><a href="https://github.com/foxssake/noray">noray</a><br>(Netfox)</td><td>false</td><td>false</td><td>true</td></tr><tr><td><a href="https://developer.apple.com/documentation/gamekit/connecting-players-with-their-friends-in-your-game">Друзья Gamekit</a><br>(Apple)</td><td>true</td><td>true</td><td>false</td></tr><tr><td>Пользовательское лобби<br>(ваша компания)</td><td>true</td><td>true</td><td>true</td></tr></tbody></table>

Владелец лобби (игрок, отправляющий приглашения) также должен создать группу матчмейкинга.

**Сохраните ID вашей группы в общих данных лобби**, чтобы другие участники лобби могли легко найти и присоединиться к группе матчмейкинга, связанной со сторонним лобби. Игроки, приглашенные в группу, используют ID группы, чтобы **создавать свои членства (присоединяться)**, а также чтобы **безопасно хранить свои** [**атрибуты матчмейкинга**](#matchmaking-rules)**.**

{% hint style="warning" %}
**После начала матчмейкинга к группе нельзя присоединиться.** [#abandon-queue](#abandon-queue "mention") и создать новую.
{% endhint %}

#### Оптимизация пинга

Если [#configuration](#configuration "mention") включает [`задержки` правило](#rule-example-elo_rating) все участники группы отправляют свои [Пинг-маяки](/ru/learn/orkestraciya/ping-beacons.md) отправляют свои измерения, чтобы **не допустить подбора игроков из удаленных регионов** или с гораздо более высоким/низким пингом (задержкой).

{% code title="Пример измерений пинга игрового клиента в миллисекундах" %}

```json
{
  "Chicago": 224.4,
  "Frankfurt": 23.2,
  "Tokyo": 167.4
}
```

{% endcode %}

#### **Покинуть очередь**

Владелец группы может удалить группу, автоматически удалив все членства группы. Удаление группы после начала матчмейкинга отменит все членства и удалит их вскоре после этого.

Участники группы (кроме владельца) могут удалить свои членства (покинуть группу) в любой момент до [#find-match](#find-match "mention"). После этого удаление членства отменит матчмейкинг для всей группы.

{% hint style="info" %}
После отмены матчмейкинга участники [автоматически удаляются из матчмейкинга](#matchmaking-profiles) и уведомляются через членство `status:CANCELLED`  в следующем ответе опроса статуса.
{% endhint %}

После отмены, если группа захочет перезапустить матчмейкинг, владелец группы должен заново создать группу, передать новый ID группы участникам и попросить их заново создать свои членства.

**После того как матч найден, группу нельзя удалить** (`409 Conflict`), и будут [автоматически удалены](#connect-to-server). Ваш сервер должен дать игрокам некоторое время (например, 60 с) на подключение, прежде чем считать, что игрок покинул игру.

Если ваш сервер помечает игрока как покинувшего игру, вы можете:

* заменить ушедшего игрока персонажем ИИ, чтобы сразу начать матч,
* или создать [добор](#backfill-match) для поиска нового игрока на замену ушедшему,
* или продолжить без замены ушедшего игрока, если дизайн вашей игры допускает переменное количество игроков.

### Найти матч

Чтобы начать поиск матча, все участники и владелец должны отметить себя как готовых.

{% hint style="success" %}
Чтобы позволить владельцу группы **немедленно начать матчмейкинг, отмечайте членства как готовые при создании**. Как только владелец отметит себя как готового, матчмейкинг начнется, поскольку все готовы.
{% endhint %}

{% hint style="info" %}
Для наилучшего опыта, **предоставляйте игрокам обновления статуса через внутриигровой интерфейс**.
{% endhint %}

**Все игроки должны регулярно опрашивать свое членство** (рекомендуется каждые 3–5 с), чтобы определить начало матчмейкинга и передавать прогресс матчмейкинга через внутриигровой интерфейс.

Игроки должны **постоянно сохранять свои ID членства и группы**, что позволяет им перезапустить игру и продолжить без потери прогресса матчмейкинга в случае сбоя игрового клиента.

Удаление членства на этом этапе приведет к отмене всех членств группы, а все остальные группы, назначенные в ту же команду, вернутся к `status:SEARCHING` .

Игроки ищут матчи, используя пересекающиеся значения среди своих групп (или среднее значение в случае `number_difference` ) до тех пор, пока не будут собраны достаточное количество игроков и команд. Членства обозначают это ответом  `status:MATCH_FOUND` , что означает, что ваш [развертывание запускается](https://docs.edgegap.com/ru/learn/matchmeiking/pages/4ad5d792bc82dceeaec6d7dd56165ae188da0417#id-1.-start-a-deployment).

Игроки могут перейти из `status:MATCH_FOUND`  обратно к `status:SEARCHING`  в случае, если все попытки развертывания (как настроено) исчерпаны без успеха.

#### Частичные матчи

Если конфигурация вашего матчмейкера допускает динамический размер команды (разные минимальное и максимальное значения), некоторые игроки могут оказаться в частичном матче — с меньшим количеством игроков, чем определено максимумом.&#x20;

**Матчмейкер не будет создавать матчи с количеством игроков меньше заданного минимума размера команды.**

Единственные сценарии, в которых разрешены частичные матчи:

1. один или несколько игроков в очереди достигают [#rule-expansion](#rule-expansion "mention") (если задано),
2. один или несколько игроков в очереди достигают времени истечения тикета.

Попытка частичного матча предпринимается ровно один раз. Несоответствующие игроки получают `status:CANCELLED`.

{% hint style="info" %}
Столкнулись с долгим временем ожидания в очереди во время тестирования или с игроками из менее популярных регионов? Установите более короткий период истечения тикета (например, 30 с) и заново создавайте группу (или тикеты) на стороне клиента по истечении срока.
{% endhint %}

{% hint style="success" %}
Храните `team_id`  и `match_id` в бэкенде игры, чтобы отображать информацию об участниках команды в игре.
{% endhint %}

Каждый игрок получает **уникальный ID тикета, который можно использовать для** [#authenticate](#authenticate "mention") **с игровыми серверами.**

Если игрок найден в матче и назначен на игровой сервер, его тикет удаляется автоматически. Игроки, покинувшие очередь после `status:HOST_ASSIGNED`  могут быть заменены на [добор](#backfill-match).

Как только игроки получают `status:HOST_ASSIGNED`  они переходят к [#connect-to-server](#connect-to-server "mention").

### Подключиться к серверу

Через несколько секунд после нахождения совпадения участники переходят к `status:HOST_ASSIGNED`  что означает, что ваш [развертывание уже готово, а ваш игровой сервер инициализируется](https://docs.edgegap.com/ru/learn/matchmeiking/pages/4ad5d792bc82dceeaec6d7dd56165ae188da0417#id-3.-deployment-ready).

Каждый игрок читает свой `ticket_id`  и  `назначение`  и пытаются подключиться, используя [**FQDN**](#user-content-fn-3)[^3] **(URL развертывания)** и **внешний порт**. В этот момент ваш игровой сервер может все еще инициализироваться, поэтому **игрокам нужно повторять попытку подключения несколько раз**, пока не будет превышено обычное время инициализации сервера:

{% tabs %}
{% tab title="Unreal Engine" %}
Чтобы **подключение из PIE (редактора)** во время разработки и тестирования нажмите клавишу тильды `~`  и введите `open {URL}:{port}`  и дождитесь, пока редактор загрузит карту.

Чтобы **подключение из сборки игрового клиента** (и в рабочей production-среде) попробуйте

* Unreal Engine [⚡ Integration Kit](https://docs.edgegap.com/learn/unreal-engine-games/developer-tools#integration-kit):
  * [установить из Fab Marketplace](https://www.fab.com/listings/ff17ad88-12a1-49cf-9a41-31695ed11e16) (бесплатно для личного использования),
  * [импортировать простой пример blueprint](https://blueprintue.com/blueprint/m33u1okj/) и настроить под свои нужды.

{% hint style="success" %}
В случае неудачного подключения или черного экрана обратитесь к нашему [руководству по устранению неполадок](/ru/unreal-engine.md#troubleshooting-and-faq).
{% endhint %}
{% endtab %}

{% tab title="Unity" %}
Чтобы **подключите ваш Unity Editor** или **игровой клиент** к вашему облачному развертыванию, укажите:

* **Развертывание** **URL** указывающий на IP-адрес сервера, обычно в `NetworkManager` компоненте.
* **внешний порт** сопоставленный с [внутренним портом прослушивания сервера](/ru/learn/orkestraciya/application-and-versions.md#port-mapping), обычно в компоненте Transport.

{% hint style="success" %}
В случае тайм-аута подключения или других проблем обратитесь к нашему [руководству по устранению неполадок](/ru/unity.md#troubleshooting-and-faq-4).
{% endhint %}
{% endtab %}
{% endtabs %}

{% hint style="info" %}
Мы не просим игроков подтверждать матч, поскольку стремимся обеспечить как можно более короткое время до начала игры, высокий процент заполнения матчей и минимизировать уклонение от очереди и отмены матчей.
{% endhint %}

Игровые клиенты должны **сохранять свой ID назначения в постоянном хранилище между перезапусками игры**, чтобы в случае сбоя игрового клиента они могли получить данные подключения и попытаться переподключиться.

### Матч с добором

При необходимости у некоторых игр могут быть особые требования к подбору игроков, например:

* позволять новым игрокам присоединяться к идущим играм (друзья или "случайные игроки"),
* заменять игроков, которые выходят (leavers) после запуска сервера, чтобы избежать перезапуска матча,
* позволять зрителям присоединяться и наблюдать за турнирными или дружескими матчами (киберспорт),
* собирать игроков на более крупных серверах, чтобы обеспечить больше социальных взаимодействий (MMO).

Бэкфилл — это **серверный билет, представляющий игроков, в данный момент подключённых к серверу.** Это гарантирует, что вновь добавленные игроки будут соблюдать ваши правила подбора при сопоставлении с текущими игроками.

{% hint style="warning" %}
[Подробный обзор](/ru/learn/matchmeiking/matchmaker-in-depth.md#backfill-match) для замены сессий Seat/Match. Матчмейкер поддерживает только сессию Default.
{% endhint %}

<figure><img src="https://3845012722-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FsR0dHSFv9ymoC0DO5G8J%2Fuploads%2FJhdLAJYga4z2sjxLj6LM%2FUntitled-2024-10-29-1018.png?alt=media&amp;token=279136ba-a15e-46b0-a119-8419b8aca044" alt=""><figcaption><p>Визуализация сценариев бэкфилла</p></figcaption></figure>

{% hint style="success" %}
**Бэкфиллы игнорируют** `player_count`  **правило и всегда сопоставляют ровно одну группу**. `backfill_group_size`  контролирует вместимость команды по стратегии round-robin, равномерно и управляемо заполняя команды.
{% endhint %}

**Шаги для успешного выполнения бэкфилла:**

1. Сервер должен создать по одному Backfill для каждой команды, которой не хватает игроков, используя значения из:
   * Реальные `назначение`  данные, полученные из [Развертывания](/ru/learn/orkestraciya/deployments.md#injected-environment-variables) (развёртывания).
   * Текущих подключённых игроков' `билеты`:
     * из [Подробный обзор](/ru/learn/matchmeiking/matchmaker-in-depth.md#injected-variables) (матчмейкера), предыдущих бэкфиллов' `assigned_ticket` ответа или тестовых данных, изменённых для соответствия конкретным игрокам,
     * замените `backfill_group_size`  значения на возможные размеры группы [до доступной вместимости](#user-content-fn-4)[^4],
2. Игровые клиенты создают новые билеты (членства) и включают `backfill_group_size`  значения:
   * `"1"`  если игрок подбирается в одиночку.
   * [`"2"`  если игрок является частью группы подбора с общим количеством участников 2x](#user-content-fn-5)[^5].
   * `"new"`  если игроки включили возможность начинать новые игры в дополнение к присоединению к идущим играм.
3. Игровые клиенты переходят к [Подробный обзор](/ru/learn/matchmeiking/matchmaker-in-depth.md#find-match) и сопоставляют игроков с подходящим бэкфиллом.
4. Если бэкфилленая группа не полностью заполнила команду, сервер может повторить этот процесс с билетами недавно добавленных игроков, чтобы добавить больше игроков и достичь нужного размера команды.

{% hint style="success" %}
Бэкфиллы игнорируют правила размера команды и всегда сопоставляют 1x бэкфилл с 1x группой. **Чтобы сопоставлять только с бэкфиллами и отключить сопоставление с другими игроками в очереди, задайте `min_team_size: 999999` .**
{% endhint %}

<details>

<summary>🥛 Пример бэкфилла (демонстрация бэкфилла)</summary>

```json
{
  "profile": "backfill-example",
  "атрибуты": {
    "assignment": {
      "request_id": "cd28e6c66554",
      "fqdn": "cd28e6c66554.pr.edgegap.net",
      "public_ip": "192.168.2.14",
      "ports": {
        "game": {
          "internal": 7777,
          "external": 56890,
          "link": "cd28e6c66554.pr.edgegap.net:56890",
          "protocol": "UDP"
        },
        "web": {
          "internal": 22,
          "external": 57440,
          "link": "cd28e6c66554.pr.edgegap.net:57440",
          "protocol": "TCP"
        },
        "server": {
          "internal": 80,
          "external": 50110,
          "link": "cd28e6c66554.pr.edgegap.net:50110",
          "protocol": "TCP"
        }
      },
      "location": {
        "city": "Montreal",
        "country": "Canada",
        "continent": "North America",
        "administrative_division": "Quebec",
        "timezone": "America/Toronto"
      }
    }
  },
  "tickets": {
    "c3d057h5h6f7j889fk43": {
      "player_ip": "174.25.48.238",
      "атрибуты": {
        "маяки": {
          "New York": 12.2,
          "Los Angeles": 45.3,
          "Paris": 78.3
        },
        "backfill_group_size": [
          "2",
          "1"
        ]
      },
      "group_id": "192bb97e-7fd6-4d86-8ce4-61c53c9fef16",
      "id": "c3d057h5h6f7j889fk43",
      "created_at": "2024-08-20T13:38:05.251393+00:00"
    },
    "cqg0bg9583s738h9dkf6": {
      "player_ip": "217.34.85.142",
      "атрибуты": {
        "маяки": {
          "New York": 21.0,
          "Los Angeles": 30.2,
          "Paris": 101.1
        },
        "backfill_group_size": [
          "2",
          "1"
        ]
      },
      "group_id": "aea7df3c-d391-4ea3-a3ec-dded422fe7c8",
      "id": "cqg0bg9583s738h9dkf6",
      "created_at": "2024-08-20T13:38:05.251393+00:00"
    }
  },
  "assigned_ticket": null
}
```

</details>

<details>

<summary>🥛 Пример назначения бэкфилла (демонстрация бэкфилла)</summary>

```json
{
  "profile": "backfill-example",
  "атрибуты": {
    "assignment": {
      "request_id": "cd28e6c66554",
      "fqdn": "cd28e6c66554.pr.edgegap.net",
      "public_ip": "192.168.2.14",
      "ports": {
        "game": {
          "internal": 7777,
          "external": 56890,
          "link": "cd28e6c66554.pr.edgegap.net:56890",
          "protocol": "UDP"
        },
        "web": {
          "internal": 22,
          "external": 57440,
          "link": "cd28e6c66554.pr.edgegap.net:57440",
          "protocol": "TCP"
        },
        "server": {
          "internal": 80,
          "external": 50110,
          "link": "cd28e6c66554.pr.edgegap.net:50110",
          "protocol": "TCP"
        }
      },
      "location": {
        "city": "Montreal",
        "country": "Canada",
        "continent": "North America",
        "administrative_division": "Quebec",
        "timezone": "America/Toronto"
      }
    }
  },
  "tickets": {
    "c3d057h5h6f7j889fk43": {
      "player_ip": "174.25.48.238",
      "атрибуты": {
        "маяки": {
          "New York": 12.2,
          "Los Angeles": 45.3,
          "Paris": 78.3
        },
        "backfill_group_size": [
          "2",
          "1"
        ]
      },
      "group_id": "192bb97e-7fd6-4d86-8ce4-61c53c9fef16",
      "id": "c3d057h5h6f7j889fk43",
      "created_at": "2024-08-20T13:38:05.251393+00:00"
    },
    "cqg0bg9583s738h9dkf6": {
      "player_ip": "217.34.85.142",
      "атрибуты": {
        "маяки": {
          "New York": 21.0,
          "Los Angeles": 30.2,
          "Paris": 101.1
        },
        "backfill_group_size": [
          "2",
          "1"
        ]
      },
      "group_id": "aea7df3c-d391-4ea3-a3ec-dded422fe7c8",
      "id": "cqg0bg9583s738h9dkf6",
      "created_at": "2024-08-20T13:38:05.251393+00:00"
    }
  },
  "assigned_ticket": {
    "profile": "backfill-example",
    "player_ip": "244.13.201.244",
    "атрибуты": {
      "маяки": {
        "New York": 30.2,
        "Los Angeles": 10.5,
        "Paris": 123.9
      },
      "backfill_group_size": [
        "new",
        "1"
      ]
    },
    "id": "cqg0bg550h7uujd77khg",
    "group_id": "e0cf41c0-f88f-456e-a032-03b1d6821a9a",
    "created_at": "2024-08-20T13:38:08.251393+00:00",
    "status": "HOST_ASSIGNED"
  }
}
```

</details>

{% hint style="info" %}
См. [Управление местами Mirror](https://docs.edgegap.com/docs/sample-projects/mirror-on-edgegap#bonus-seat-sessions-management) и [Управление местами FishNet](https://docs.edgegap.com/docs/sample-projects/fishnet-on-edgegap#bonus-seat-sessions-management) для **мониторинга подключений игроков**.
{% endhint %}

После завершения инициализации игрового сервера, **ваш сервер должен**:

* **Запускайте таймер покидания для каждого нового игрока.** Мы рекомендуем показывать подключенным игрокам прогресс загрузки с помощью сцены/уровня загрузки — полноценной 3D-сцены, социального интерфейса в стиле лобби или экрана загрузки с полосой прогресса.
* **Отслеживайте новые подключения игроков или уход существующих игроков с течением времени**:
  1. Новые игроки должны сообщать серверу ID тикета для аутентификации и сопоставления своего подключения с матчмейкером [#injected-variables](#injected-variables "mention") или `assigned_ticket` (если был выполнен добор).
  2. Создавайте новые доборы для неиспользованной вместимости игроков (ушедших) на протяжении всего срока службы сервера.
  3. Обновляйте просроченные доборы, которые удаляются после `ticket_expiration_period`.
* **Очищайте (удаляйте) все оставшиеся доборы** как только [/pages/4ad5d792bc82dceeaec6d7dd56165ae188da0417#id-5.-deployment-stopped](https://docs.edgegap.com/ru/learn/matchmeiking/pages/4ad5d792bc82dceeaec6d7dd56165ae188da0417#id-5.-deployment-stopped "mention"):
  * Unity - [`OnApplicationQuit`](https://docs.unity3d.com/6000.0/Documentation/ScriptReference/MonoBehaviour.OnApplicationQuit.html) callback или пользовательского callback завершения игры,
  * Unreal Engine - [`OnWorldDestroyed`](https://forums.unrealengine.com/t/call-function-before-quit-game/344954/2) , [`PreExit`](https://forums.unrealengine.com/t/event-on-close/298087/2) , или пользовательского callback завершения игры.

{% hint style="info" %}
Используйте [GetEnvironmentVariable в C#](https://learn.microsoft.com/en-us/dotnet/api/system.environment.getenvironmentvariable?view=net-8.0) или [GetEnvironmentVariable в C++](https://dev.epicgames.com/documentation/en-us/unreal-engine/API/Runtime/Core/GenericPlatform/FGenericPlatformMisc/GetEnvironmentVariable) чтобы получить значения переменных.
{% endhint %}

Для Backfill можно использовать любой профиль, если указано корректное назначение сервера и предоставлен хотя бы один тикет. См. [Матчмейкинг](/ru/learn/matchmeiking.md#backfill-showcase) для минимального примера.

## ⚙️ Конфигурация

API матчмейкера генерируется из JSON-конфигурации, указанной при создании нового (или быстром перезапуске) матчмейкера. Вы можете указать любое количество профилей с разными правилами и расширениями:

{% hint style="success" %}
См. [Матчмейкинг](/ru/learn/matchmeiking.md) для наших SDK и подробных примеров сценариев.
{% endhint %}

<details>

<summary>🍀 Простой пример (минимально рекомендуемая конфигурация)</summary>

<pre class="language-json"><code class="lang-json">{
  "version": "3.3.3",
  "inspect": true,
  "max_deployment_retry_count": 3,
  "profiles": {
    "simple-example": {
      "ticket_expiration_period": "5m",
      "ticket_removal_period": "1m",
      "group_inactivity_removal_period": "5m",
      "application": {
        "name": "<a data-footnote-ref href="#user-content-fn-6">my-game-server</a>",
        "version": "<a data-footnote-ref href="#user-content-fn-7">2024.01.30-16.23.00-UTC</a>"
      },
      "rules": {
        "initial": {
          "match_size": {
            "type": "player_count",
            "attributes": {
              "team_count": 1,
              "min_team_size": 2,
              "max_team_size": 2
            }
          },
          "beacons": {
            "type": "latencies",
            "attributes": {
              "difference": 100,
              "max_latency": 200
            }
          }
        },
        "expansions": {}
      }
    }
  }
}
</code></pre>

</details>

<details>

<summary>🏁 Расширенный пример (Полная конфигурация примера)</summary>

```json
{
  "version": "3.3.3",
  "inspect": true,
  "max_deployment_retry_count": 3,
  "allowed_cors_origins": [
    "https://*.my-game-server.com"
  ],
  "profiles": {
    "advanced-example": {
      "ticket_expiration_period": "5m",
      "ticket_removal_period": "1m",
      "group_inactivity_removal_period": "5m"
      "application": {
        "name": "my-game-server",
        "version": "2024.01.30-16.23.00-UTC"
      },
      "rules": {
        "initial": {
          "match_size": {
            "type": "player_count",
            "attributes": {
              "team_count": 1,
              "min_team_size": 4,
              "max_team_size": 4
            }
          },
          "beacons": {
            "type": "latencies",
            "attributes": {
              "difference": 125,
              "max_latency": 125
            }
          },
          "elo_rating": {
            "type": "number_difference",
            "attributes": {
              "max_difference": 50
            }
          },
          "selected_game_mode": {
            "type": "string_equality"
          },
          "selected_map": {
            "type": "intersection",
            "attributes": {
              "overlap": 1
            }
          },
          "backfill_group_size": {
            "type": "intersection",
            "attributes": {
              "overlap": 1
            }
          }
        },
        "expansions": {
          "30": {
            "elo_rating": {
              "max_difference": 150
            },
            "beacons": {
              "difference": 125,
              "max_latency": 250
            }
          },
          "60": {
            "elo_rating": {
              "max_difference": 200
            }
          },
          "180": {
            "match_size": {
              "team_count": 1,
              "min_team_size": 1,
              "max_team_size": 4
            },
            "beacons": {
              "difference": 99999,
              "max_latency": 99999
            }
          }
        }
      }
    }
  }
}
```

</details>

<details>

<summary><span data-gb-custom-inline data-tag="emoji" data-code="1f95b">🥛</span> Пример конфигурации backfill</summary>

```json
{
  "version": "3.3.3",
  "inspect": true,
  "max_deployment_retry_count": 3,
  "profiles": {
    "backfill-example": {
      "ticket_expiration_period": "30s",
      "ticket_removal_period": "1m",
      "group_inactivity_removal_period": "5m",
      "application": {
        "name": "my-game-server",
        "version": "2024.01.30-16.23.00-UTC"
      },
      "rules": {
        "initial": {
          "match_size": {
            "type": "player_count",
            "attributes": {
              "team_count": 1,
              "min_team_size": 4,
              "max_team_size": 4
            }
          },
          "beacons": {
            "type": "latencies",
            "attributes": {
              "difference": 100,
              "max_latency": 200
            }
          },
          "backfill_group_size": {
            "type": "intersection",
            "attributes": {
              "overlap": 1
            }
          }
        },
        "expansions": {}
      }
    }
  }
}
```

</details>

<details>

<summary>⚔️ Пример соревновательной игры</summary>

```json
{
  "version": "3.3.3",
  "inspect": true,
  "max_deployment_retry_count": 3,
  "profiles": {
    "casual-example": {
      "ticket_expiration_period": "5m",
      "ticket_removal_period": "1m",
      "group_inactivity_removal_period": "5m",
      "application": {
        "name": "my-game-server",
        "version": "2024.01.30-16.23.00-UTC"
      },
      "rules": {
        "initial": {
          "match_size": {
            "type": "player_count",
            "attributes": {
              "team_count": 2,
              "min_team_size": 5,
              "max_team_size": 5
            }
          },
          "beacons": {
            "type": "latencies",
            "attributes": {
              "difference": 125,
              "max_latency": 150
            }
          },
          "selected_maps": {
            "type": "intersection",
            "attributes": {
              "overlap": 1
            }
          },
          "backfill_group_size": {
            "type": "intersection",
            "attributes": {
              "overlap": 1
            }
          }
        },
        "expansions": {
          "30": {
            "beacons": {
              "difference": 125,
              "max_latency": 250
            }
          },
          "180": {
            "beacons": {
              "difference": 99999,
              "max_latency": 99999
            }
          }
        }
      }
    },
    "competitive-example": {
      "ticket_expiration_period": "5m",
      "ticket_removal_period": "1m",
      "group_inactivity_removal_period": "5m"
      "application": {
        "name": "my-game-server",
        "version": "2024.01.30-16.23.00-UTC"
      },
      "rules": {
        "initial": {
          "match_size": {
            "type": "player_count",
            "attributes": {
              "team_count": 2,
              "min_team_size": 5,
              "max_team_size": 5
            }
          },
          "beacons": {
            "type": "latencies",
            "attributes": {
              "difference": 125,
              "max_latency": 150
            }
          },
          "versus_ranks": {
            "type": "intersection",
            "attributes": {
              "overlap": 1
            }
          }
        },
        "expansions": {
          "120": {
            "beacons": {
              "difference": 125,
              "max_latency": 250
            }
          }
        }
      }
    },
    "challenger-example": {
      "ticket_expiration_period": "5m",
      "ticket_removal_period": "1m",
      "group_inactivity_removal_period": "5m"
      "application": {
        "name": "my-game-server",
        "version": "2024.01.30-16.23.00-UTC"
      },
      "rules": {
        "initial": {
          "match_size": {
            "type": "player_count",
            "attributes": {
              "team_count": 2,
              "min_team_size": 5,
              "max_team_size": 5
            }
          },
          "beacons": {
            "type": "latencies",
            "attributes": {
              "difference": 125,
              "max_latency": 150
            }
          },
          "elo_rating": {
            "type": "number_difference",
            "attributes": {
              "max_difference": 50
            }
          }
        },
        "expansions": {
          "120": {
            "beacons": {
              "difference": 125,
              "max_latency": 250
            }
          }
        }
      }
    }
  }
}
```

</details>

<details>

<summary>🤝 Пример кооперативной игры</summary>

```json
{
  "version": "3.3.3",
  "inspect": true,
  "max_deployment_retry_count": 3,
  "profiles": {
    "cooperative-example": {
      "ticket_expiration_period": "3m",
      "ticket_removal_period": "1m",
      "group_inactivity_removal_period": "5m",
      "application": {
        "name": "my-game-server",
        "version": "2024.01.30-16.23.00-UTC"
      },
      "rules": {
        "initial": {
          "match_size": {
            "type": "player_count",
            "attributes": {
              "team_count": 1,
              "min_team_size": 4,
              "max_team_size": 4
            }
          },
          "beacons": {
            "type": "latencies",
            "attributes": {
              "difference": 125,
              "max_latency": 150
            }
          },
          "selected_difficulty": {
            "type": "string_equality"
          },
          "selected_map": {
            "type": "intersection",
            "attributes": {
              "overlap": 1
            }
          },
          "player_level": {
            "type": "number_difference",
            "attributes": {
              "max_difference": 10
            }
          },
          "backfill_group_size": {
            "type": "intersection",
            "attributes": {
              "overlap": 1
            }
          },
          "moderation_flags": {
            "type": "intersection",
            "attributes": {
              "overlap": 1
            }
          }
        },
        "expansions": {
          "30": {
            "beacons": {
              "difference": 125,
              "max_latency": 250
            },
            "player_level": {
              "max_difference": 20
            }
          },
          "60": {
            "match_size": {
              "team_count": 1,
              "min_team_size": 2,
              "max_team_size": 4
            }
          },
          "150": {
            "match_size": {
              "team_count": 1,
              "min_team_size": 1,
              "max_team_size": 4
            }
          }
        }
      }
    }
  }
}
```

</details>

<details>

<summary>🎈 Пример социальной игры</summary>

```json
{
  "version": "3.3.3",
  "inspect": true,
  "max_deployment_retry_count": 3,
  "profiles": {
    "social-example": {
      "ticket_expiration_period": "3m",
      "ticket_removal_period": "1m",
      "group_inactivity_removal_period": "5m",
      "application": {
        "name": "my-game-server",
        "version": "2024.01.30-16.23.00-UTC"
      },
      "rules": {
        "initial": {
          "match_size": {
            "attributes": {
              "team_count": 1,
              "min_team_size": 50,
              "max_team_size": 50
            },
            "type": "player_count"
          },
          "beacons": {
            "attributes": {
              "difference": 125,
              "max_latency": 150
            },
            "type": "latencies"
          },
          "selected_mode": {
            "type": "intersection",
            "attributes": {
              "overlap": 1
            }
          },
          "backfill_group_size": {
            "type": "intersection",
            "attributes": {
              "overlap": 1
            }
          },
          "moderation_flags": {
            "type": "intersection",
            "attributes": {
              "overlap": 1
            }
          }
        },
        "expansions": {
          "15": {
            "beacons": {
              "difference": 125,
              "max_latency": 250
            },
            "match_size": {
              "team_count": 1,
              "min_team_size": 20,
              "max_team_size": 50
            }
          },
          "30": {
            "match_size": {
              "team_count": 1,
              "min_team_size": 10,
              "max_team_size": 50
            }
          },
          "150": {
            "match_size": {
              "team_count": 1,
              "min_team_size": 1,
              "max_team_size": 50
            }
          }
        }
      }
    }
  }
}
```

</details>

{% hint style="warning" %}
Редактирование работающего матчмейкера **вызовет быструю перезагрузку**, удалив все тикеты и вызвав короткий простой.
{% endhint %}

<details>

<summary><code>Конфигурация приложения недействительна для профиля XYZ.</code></summary>

* Мы не смогли найти ваш [Приложения и версии](/ru/learn/orkestraciya/application-and-versions.md), пожалуйста, проверьте `приложение`  значения.

</details>

<details>

<summary><code>Docker-образ для '2024.01.30-16.23.00-UTC' не кэширован.</code></summary>

[**🌟 Обновитесь до тарифа Pay as You Go**](https://app.edgegap.com/user-settings?tab=memberships) **чтобы разблокировать** [**мгновенные развёртывания с кэшированием**](https://docs.edgegap.com/ru/learn/matchmeiking/pages/4ad5d792bc82dceeaec6d7dd56165ae188da0417#id-1.-start-a-deployment)**.**

* Некэшированные образы размером 4 ГБ и более могут дольше развёртываться, что приведёт к [/pages/4ad5d792bc82dceeaec6d7dd56165ae188da0417#id-4.-deployment-error](https://docs.edgegap.com/ru/learn/matchmeiking/pages/4ad5d792bc82dceeaec6d7dd56165ae188da0417#id-4.-deployment-error "mention"). Рассмотрите возможность оптимизации размера образа сервера ([Unreal Engine](/ru/unreal-engine.md#optimize-server-build-size) / [Unity](/ru/unity.md#optimize-server-build-size)).
* Вы всё равно можете продолжить, хотя мы рекомендуем протестировать время развёртывания.

</details>

### Профили (очереди) <a href="#matchmaking-profiles" id="matchmaking-profiles"></a>

Профили представляют собой полностью отдельные очереди матчмейкинга, использующие одну и ту же версию матчмейкера. Вы можете **настроить любое количество профилей для каждого матчмейкера.** Разделение вашей базы игроков на несколько профилей может привести к более длительному ожиданию в очереди для ваших игроков.

Каждый профиль матчмейкера использует [Версию приложения](/ru/learn/orkestraciya/application-and-versions.md) в качестве шаблона для запуска новых развертываний (серверов).

{% hint style="success" %}
Некоторым режимам игры может требоваться больше vCPU / RAM, особенно если они поддерживают большее количество игроков. Каждый **матчмейкер может включать несколько профилей**, каждый из которых связан с версией приложения с настроенными ресурсами.
{% endhint %}

### Правила <a href="#matchmaking-rules" id="matchmaking-rules"></a>

Каждый игрок и группа присоединяются к очереди матчмейкинга и находят матчи, используя  `начальные` правила сначала.

Каждая запись в профиле по пути `.rules.initial` представляет собой правило, где:

* **key** — строковое значение, с помощью которого вы можете назвать правило как угодно; например `match_size` и
* **value** — объект, определяющий тип и атрибуты правила в соответствии с нашим стандартным набором правил.

{% hint style="info" %}
Все правила должны выполняться одновременно, чтобы инициировать назначение хоста и начать или найти развертывание.
{% endhint %}

**Операторы (тип правила)**

**`player_count`** — специальное правило, определяющее, сколько игроков должно совпасть, чтобы инициировать назначение.

{% hint style="warning" %}
Правило `player_count`  **— обязательно и может быть определено только один раз** в начальных правилах конфигурации.
{% endhint %}

Матчмейкер всегда стремится максимизировать заполняемость матча до заданных `max_team_size` :

1. если достигнут максимальный размер команды, матч создается немедленно,
2. в противном случае игроки ждут в очереди, чтобы заполнить матч, пока [расширение](#rule-expansion) (или истечение срока) не будет близко к завершению,
3. незадолго до [расширения](#rule-expansion) (или истечения), если частичный матч возможен (≥ min и < max размера команды), этот матч будет создан со всеми игроками на одной и той же стадии расширения (при условии, что остальные правила пройдены).

{% hint style="success" %}
Для кооперативных, каждый сам за себя или асимметричных режимов с размером команды установите `"team_count": 1` .
{% endhint %}

Количество команд можно настроить, чтобы формировать несколько сбалансированных команд для соревновательных игр:

* **атрибуты группы рассчитываются как среднее/пересечение** атрибутов группы **игроков,**
* **атрибуты команды рассчитываются как среднее/пересечение** атрибутов команды **группы.**

Предположим фиксированный размер команды в 4 игрока:

<figure><img src="https://3845012722-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FsR0dHSFv9ymoC0DO5G8J%2Fuploads%2FSFEzBayk3XNEUTIynjNd%2Fimage.png?alt=media&amp;token=11a43fdf-3a99-4caa-8d2b-639e0f3cc06f" alt=""><figcaption><p>Примеры сценариев матча</p></figcaption></figure>

{% hint style="info" %}
**Группы подбираются в команды без переполнения,** только если у команды достаточно вместимости, чтобы вместить всю группу.
{% endhint %}

**`string_equality`** сопоставляет игроков с точно таким же строковым значением.

<details>

<summary>Пример правила: <code>selected_game_mode</code></summary>

`selected_game_mode`  правило будет сопоставлять игроков с учетом регистра:

:white\_check\_mark: Алиса + Боб + Дэйв могут совпасть,

:x: Алиса + Эрин или Чарли + Фрэнк никогда не совпадут.

| "Каждый сам за себя" | "Захват флага" | "захват флага" |
| -------------------- | -------------- | -------------- |
| Алиса                | Эрин           | Фрэнк          |
| Боб                  | Чарли          |                |
| Дэйв                 |                |                |

</details>

**`number_difference`** сопоставляет игроков, у которых абсолютная числовая разница друг с другом находится в пределах.

<details>

<summary>Пример правила: <code>elo_rating</code></summary>

`elo_rating`  правило выше с `"max_difference": 50` изначально:

:white\_check\_mark: Алиса + Боб могут совпасть, или Боб + Чарли могут совпасть,

:x: Алиса + Боб + Чарли никогда не совпадут.

<figure><img src="https://3845012722-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FsR0dHSFv9ymoC0DO5G8J%2Fuploads%2FxtTxZ7TPSa8a8WtnGNAE%2Fimage.png?alt=media&amp;token=c48b843b-c4e5-47bf-9154-07254a788067" alt=""><figcaption></figcaption></figure>

</details>

**`задержки`** — это специальное правило, оптимизирующее пинг матчей игроков:

* уменьшить задержку между клиентом и сервером, удаляя регионы с высокой задержкой (выше порога),
* повысить справедливость матчей, группируя игроков с похожей задержкой (ниже разницы).

<details>

<summary>Пример правила: <code>маяки</code></summary>

`маяки` правило, настроенное с `"difference": 100, "max_latency": 200`  будет сопоставлять:

:white\_check\_mark: Алиса и Боб могут быть сопоставлены:

* Токио отбрасывается (>200 мс),
* задержка для Чикаго в пределах абсолютной разницы 100 мс.

<table><thead><tr><th width="180">Город маяка</th><th width="80">Матч</th><th width="132">abs(A - B) [мс]</th><th width="164">Алиса [мс]</th><th width="164">Боб [мс]</th></tr></thead><tbody><tr><td>Чикаго</td><td><span data-gb-custom-inline data-tag="emoji" data-code="2705">✅</span></td><td>75.0</td><td>12.3</td><td>87.3</td></tr><tr><td>Лос-Анджелес</td><td><span data-gb-custom-inline data-tag="emoji" data-code="274c">❌</span></td><td><a data-footnote-ref href="#user-content-fn-8">113.2</a> <span data-gb-custom-inline data-tag="emoji" data-code="274c">❌</span></td><td>145.6</td><td>32.4</td></tr><tr><td><del>Токио</del></td><td>н/д</td><td>н/д</td><td><a data-footnote-ref href="#user-content-fn-9"><del>233.2</del></a> <span data-gb-custom-inline data-tag="emoji" data-code="274c">❌</span></td><td><a data-footnote-ref href="#user-content-fn-9"><del>253.2</del></a> <span data-gb-custom-inline data-tag="emoji" data-code="274c">❌</span></td></tr></tbody></table>

:x: Алиса и Чарли никогда не будут сопоставлены:

* нет маяков с задержкой < 200 мс для обоих игроков,
* Алиса живет в Северной Америке — Иллинойс,
* Чарли живет в Азии — Япония.

<table><thead><tr><th width="180">Город маяка</th><th width="80">Матч</th><th width="132">abs(A - B) [мс]</th><th width="164">Алиса [мс]</th><th width="164">Чарли [мс]</th></tr></thead><tbody><tr><td><del>Чикаго</del></td><td>н/д</td><td>н/д</td><td>12.3</td><td><a data-footnote-ref href="#user-content-fn-9"><del>215.6</del></a> <span data-gb-custom-inline data-tag="emoji" data-code="274c">❌</span></td></tr><tr><td><del>Лос-Анджелес</del></td><td>н/д</td><td>н/д</td><td>145.6</td><td><a data-footnote-ref href="#user-content-fn-9"><del>238.3</del></a> <span data-gb-custom-inline data-tag="emoji" data-code="274c">❌</span></td></tr><tr><td><del>Токио</del></td><td>н/д</td><td>н/д</td><td><a data-footnote-ref href="#user-content-fn-9"><del>233.2</del></a> <span data-gb-custom-inline data-tag="emoji" data-code="274c">❌</span></td><td>24.2</td></tr></tbody></table>

</details>

{% hint style="warning" %}
Правило `задержки`  — это **является необязательным и может быть определено только один раз в вашей начальной конфигурации** правила.
{% endhint %}

Некоторые игроки с высоким пингом ко всем маякам из-за провайдера[^10] проблем или медленного соединения (например, беспроводного/мобильного) могут вызывать лаги и ухудшать игровой опыт других. Чтобы смягчить эту проблему:

* Постепенно расширяйте максимально допустимую задержку и разницу (см. [Пример расширенной конфигурации](/ru/learn/matchmeiking.md#advanced-example)),
  * игрокам с высоким пингом, возможно, придется ждать дольше обычного, чтобы найти матч.
* В качестве альтернативы разрешите игрокам переопределять измерение вручную, выбирая регион, и отправляйте поддельные значения пинга только для выбранных игроком регионов (например, 25 мс для быстрого матча),
  * это может отрицательно повлиять на опыт игры товарищей по команде и соперников.

{% hint style="info" %}
**Высокий пинг до маяка не всегда приводит к высокому пингу до сервера**. Развертывания доступны в большем количестве локаций, чем маяки. Маяки оркеструются в реальном времени для приоритизации глобального покрытия и надежности.
{% endhint %}

{% hint style="success" %}
См. [Матчмейкинг](/ru/learn/matchmeiking.md) для **автоматизированное измерение пинга с помощью наших SDK**.
{% endhint %}

{% hint style="danger" %}
Маяки автоматически масштабируются в реальном времени — добавляются/удаляются/заменяются существующие маяки. Ваши клиенты и бэкенд должны учитывать это и **перезагружать список маяков перед каждым раундом подбора игроков**.
{% endhint %}

**`пересечения`** сопоставляет игроков с одним или несколькими пересекающимися строковыми значениями с учетом регистра.

<details>

<summary>Пример правила: <code>selected_map</code></summary>

`selected_map` правило выше с `"overlap": 1`  будет совпадать:

:white\_check\_mark: Алиса + Боб + Чарли могут совпасть, или Алиса + Боб + Дэйв могут совпасть,

:x: Алиса + Боб + Чарли + Дэйв никогда не совпадут.

<figure><img src="https://3845012722-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FsR0dHSFv9ymoC0DO5G8J%2Fuploads%2FcQSUAnRkZKVyuGjFWSYL%2Fimage.png?alt=media&amp;token=bf1a4e28-230a-4c9a-9ef6-a0dea4dbecdb" alt=""><figcaption></figcaption></figure>

</details>

#### Расширение правила

При желании, **`расширения`**  изменяют атрибуты правила после того, как в очереди прошло некоторое время, чтобы ослабить ограничения и расширить пул игроков, которых можно сопоставить, **что приводит к более быстрым матчам**.

В конфигурации расширения задаются с использованием секунд относительно создания тикета каждого игрока. Каждое расширение должно быть меньше времени истечения тикета, чтобы активироваться.

<details>

<summary>Пример сценария: расширения</summary>

[Изначально нам нужна 1 команда, состоящая ровно из 4 игроков (возможно, разделенных на группы)](/ru/learn/matchmeiking.md#advanced-example) с:

* максимальной задержкой 125 мс относительно одного и того же (любого одного) маяка,
* разницей задержки 125 мс или меньше между минимальным и максимальным значением для одного и того же маяка,
* разницей рейтинга навыка 50 очков или меньше между игроком с самым низким и самым высоким рейтингом,
* точно таким же (с учетом регистра) выбранным игровым режимом,
* как минимум одним совпадающим выбором карты (с учетом регистра) среди игроков,
* как минимум одним совпадающим [размером группы добора](#backfill-match) значением среди игроков.

В примере выше мы **расширяем поиск, изменяя атрибуты** после:

<table data-view="cards"><thead><tr><th></th><th></th></tr></thead><tbody><tr><td>30 секунд:</td><td><ul><li>4 игрока</li><li><strong>диапазон рейтинга навыка 150</strong></li><li><strong>макс. задержка 250 мс</strong></li></ul></td></tr><tr><td>60 секунд:</td><td><ul><li>4 игрока</li><li><strong>диапазон рейтинга навыка 200</strong></li><li>макс. задержка 250 мс</li></ul></td></tr><tr><td>3 минуты (180 с):</td><td><ul><li><strong>1–4 игрока</strong></li><li>диапазон рейтинга навыка 200</li><li><strong>любая задержка</strong></li></ul></td></tr></tbody></table>

</details>

{% hint style="warning" %}
Расширения любого атрибута правила **перезапишут предыдущие значения** этого атрибута.
{% endhint %}

{% hint style="success" %}
[**Узнайте о распространенных ошибках**](https://edgegap.com/blog/how-session-fill-rate-affects-your-multiplayer-hosting-costs)**и** [**оптимизируйте заполняемость матча с помощью нашего руководства**](https://edgegap.com/blog/how-to-optimize-session-fill-rate-in-your-matchmaker)**.**
{% endhint %}

## 📌 Внедренные переменные

Вашему серверу могут понадобиться сведения о его игроках. Атрибуты игроков, вычисленные значения матча и другие значения внедряются в ваше развертывание вместе с обычными [Приложения и версии](/ru/learn/orkestraciya/application-and-versions.md#injected-variables).

Предпросмотр без форматирования **🏁 Переменные расширенного примера:**

```
MM_MATCH_PROFILE=advanced-example
MM_EXPANSION=initial
MM_TICKET_IDS=["cusfn10msflc73beiik0","cusfn18msflc73beiil0"]
MM_TICKET_cusfn10msflc73beiik0={"id":"cusfn10msflc73beiik0","created_at":"2025-02-21T22:17:42.3886970Z","player_ip":"174.93.233.25","group_id":"b2080c27-19c9-4fb0-8fe7-4bf1e5d285d1","team_id":"cusfn1gmsflc73beiim0","attributes":{"beacons":{"Chicago":12.3,"LosAngeles":145.6,"Tokyo":233.2},"elo_rating":1337,"selected_game_mode":"quickplay","selected_map":["DustII","Airport","BankVault"],"backfill_group_size":["new","1"]}}
MM_TICKET_cusfn18msflc73beiil0={"id":"cusfn18msflc73beiil0","created_at":"2025-02-21T22:17:42.2548390Z","player_ip":"174.93.233.23","group_id":"015d4dc8-6c79-4b5c-bbc6-f309b9787c8f","team_id":"cusfn1gmsflc73beiim0","attributes":{"beacons":{"Chicago":87.3,"LosAngeles":32.4,"Tokyo":253.2},"elo_rating":1339,"selected_game_mode":"quickplay","selected_map":["Island","Airport"],"backfill_group_size":["new","1"]}}
MM_GROUPS={"b2080c27-19c9-4fb0-8fe7-4bf1e5d285d1":["cusfn10msflc73beiik0"],"015d4dc8-6c79-4b5c-bbc6-f309b9787c8f":["cusfn18msflc73beiil0"]}
MM_TEAMS={"cusfn1gmsflc73beiim0":["b2080c27-19c9-4fb0-8fe7-4bf1e5d285d1","015d4dc8-6c79-4b5c-bbc6-f309b9787c8f"]}
MM_MATCH_ID=advanced-example_initial-2025-02-21T22:17:43.3886970Z
MM_INTERSECTION={"selected_map":["Airport"],"backfill_group_size":["new","1"]}
MM_EQUALITY={"selected_game_mode":"quickplay"}
```

{% hint style="info" %}
Переменные окружения: **хранятся как JSON в виде строк**, разбирайте их с помощью наших SDK или собственного метода.
{% endhint %}

{% hint style="success" %}
**Серверы могут сопоставлять подключения игроков с группами и атрибутами** после того, как игрок отправит свой ID билета на сервер.
{% endhint %}

## 🧵 Отслеживание игроков

Если у ваших игроков возникают какие-либо проблемы, может помочь отслеживание их пути по журналам сервера. Каждый Matchmaker **развертывание** **будет помечен назначенными ID билетов игроков** чтобы вы могли легко [Развертывания](/ru/learn/orkestraciya/deployments.md#filter-deployments) и найти [Развертывания](/ru/learn/orkestraciya/deployments.md#container-logs) чтобы помочь вам устранить неполадки.

{% hint style="success" %}
**Отображать ID билетов и ID развертываний в интерфейсе истории матчей клиента** для отслеживания игроков при устранении неполадок.
{% endhint %}

{% hint style="info" %}
См. [Развертывания](/ru/learn/orkestraciya/deployments.md#connection-quality) чтобы узнать об устранении неполадок развертывания.
{% endhint %}

## 👀 Аналитика

Получайте сведения о нагрузке и производительности вашего matchmaker без кода и настройки.

🌟 [**Обновите Matchmaker до уровня Enterprise**](https://app.edgegap.com/matchmaker-management-v2/matchmakers/list) **чтобы разблокировать метрики и аналитические сведения по подбору матчей:**

<figure><img src="https://3845012722-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FsR0dHSFv9ymoC0DO5G8J%2Fuploads%2Fhb8NmB4ELuG7ayGLTeHs%2Fimage.png?alt=media&amp;token=e3e0371e-c33f-48c8-bd15-5c11448dc633" alt=""><figcaption></figcaption></figure>

<figure><img src="https://3845012722-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FsR0dHSFv9ymoC0DO5G8J%2Fuploads%2Fl0zTNccJASUTkJfTYxss%2Fimage.png?alt=media&amp;token=0d061320-9524-4b12-83e6-ea9112ef1409" alt=""><figcaption></figcaption></figure>

## ☁️ Кластер хостинга

Matchmaker удобно размещается и управляется Edgegap круглосуточно, 24/7.

Выберите вариант хостинга, который лучше всего подходит вашей цели:

* **Бесплатный кластер (общий)** чтобы протестировать все функции и исследовать синергии с вашим дизайном,
  * автоматически отключается через 3 часа, для продолжения тестирования требуется перезапуск.
* **Приватный кластер** **(выделенный)** чтобы обеспечить стабильную среду для ваших производственных нужд,
  * выберите ваш регион и получите круглосуточную поддержку живых игр для выпуска с уверенностью.

#### Уровни частного кластера

В настоящее время мы предлагаем [3 уровня частных кластеров](https://edgegap.com/resources/pricing#managed-infrastructure) для любых потребностей:

<table><thead><tr><th width="160">Уровень</th><th align="right">Любительский уровень</th><th align="right">Студийный уровень</th><th align="right">Корпоративный уровень</th></tr></thead><tbody><tr><td>Лучше всего подходит для</td><td align="right">энтузиасты,<br>разработчики-одиночки</td><td align="right">коммерческие релизы</td><td align="right">запуски с высоким трафиком</td></tr><tr><td>Ограничение частоты запросов (запросов/с)</td><td align="right">200</td><td align="right">750</td><td align="right">2,000</td></tr><tr><td>Ресурсы</td><td align="right">1 vCPU + 2 ГБ ОЗУ</td><td align="right">6 vCPU + 12 ГБ ОЗУ</td><td align="right">18 vCPU + 48 ГБ ОЗУ</td></tr><tr><td>Резервирование</td><td align="right">1 виртуальный узел</td><td align="right">3 виртуальных узла</td><td align="right">3 виртуальных узла</td></tr><tr><td>Цена, за час</td><td align="right">$0.0312</td><td align="right"> $0.146</td><td align="right">$0.548</td></tr><tr><td><strong>Цена, за 30 дней</strong><br>(непрерывное использование)</td><td align="right"><strong>$22.464</strong></td><td align="right"><strong>$105.12</strong></td><td align="right"><strong>$394.56</strong></td></tr></tbody></table>

Обновитесь до частного кластера в один клик. Изменение уровней частного кластера после запуска без простоя для игроков также возможно с [#rolling-updates-and-ab-tests](#rolling-updates-and-ab-tests "mention"). Управляемые кластеры обеспечивают хостинг высокодоступного сервиса, поддерживаемый Edgegap, с круглосуточной живой поддержкой 24/7 для публично выпущенных игр.

Требования к ресурсам для вашего экземпляра будут зависеть от факторов:

* **количество игроков** - больше игроков приводит к большему числу билетов и запросов API,
* **количество запросов на одного игрока** - более частые повторные попытки увеличивают нагрузку на сервис и потребляют ресурсы,
* **сложность конфигурации** - правила пересечения и расширения особенно требовательны,
* **средняя длительность матча** - более короткие сессии заставляют игроков чаще возвращаться в подбор матчей,
* **сроки истечения и удаления** - устаревшие билеты накапливаются со временем и потребляют ресурсы,
* **логика запасных повторных попыток клиента** - повторные попытки с джиттерным backoff помогают распределить пиковые всплески трафика.

{% hint style="warning" %}
**Подготовьтесь к успеху и оптимизируйте после запуска, чтобы не блокировать игроков в день релиза.** Используйте [Инструменты разработчика](/ru/unity/developer-tools.md#matchmaking-sdk) или **реализуйте экспоненциальный джиттерный backoff** чтобы восстанавливаться после высокой нагрузки.
{% endhint %}

{% hint style="info" %}
Наши кластеры используют облачные машины с процессорами AMD/Intel с тактовой частотой до 3,7 ГГц.
{% endhint %}

## ⏩ Пошаговые обновления <a href="#rolling-updates-and-ab-tests" id="rolling-updates-and-ab-tests"></a>

Отслеживать совместимость между версиями сервера и клиента может быть сложно. Следуйте нашим советам для надежных релизов, обновлений и предотвращения простоя или проблем совместимости.

**URL вашего Matchmaker и токен аутентификации всегда останутся прежними после перезапуска.**

{% hint style="danger" %}
**Создайте отдельные matchmaker для dev и production** среды, чтобы безопасно экспериментировать.
{% endhint %}

#### ⚠️ **Перед выходом в продакшн**

Мы рекомендуем заранее создать несколько копий вашего matchmaker: `зелёный`, `синий` и `оранжевый`. Вы можете поочерёдно менять, какой matchmaker используется, по мере выпуска обновлений ([стратегия blue/green](https://en.wikipedia.org/wiki/Blue%E2%80%93green_deployment)).

**Выберите разные регионы для каждого экземпляра, чтобы предотвратить простой** во время локальных сбоев.

<figure><img src="https://3845012722-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FsR0dHSFv9ymoC0DO5G8J%2Fuploads%2Flzy4elHYDPBMpjSMG1HS%2Fimage.png?alt=media&amp;token=7da795fc-ae6c-490f-b65c-5f8dda635503" alt=""><figcaption><p>Пример среды DevOps Blue/Green</p></figcaption></figure>

#### **🔃 Обновление клиента + сервера**

**Необходимые условия:** В этом разделе предполагается, что вы уже выполнили [#before-going-live](#before-going-live "mention").

Чтобы **выпускать обновления клиента игры + сервера**, вы можете:

1. Подготовьте новую версию серверного приложения `v1.2.0-rc` в Edgegap:
   1. отправить новый тег образа в ваш реестр контейнеров `t1.2.0`,
   2. создать новую версию приложения `v1.2.0-rc`,
2. Проведите любые dev-тесты, выполнив [развертывание новой версии приложения](https://app.edgegap.com/deployment-management/deployments/list) `v1.2.0-rc`:
   1. подключить Editor вашего игрового движка к предоставленному URL + внешнему порту,
3. Обновите неиспользуемый matchmaker `синий` чтобы привязать его к новому тегу образа `t1.2.0`,
   1. включить кэширование для новой версии приложения `v1.2.0-rc` , включение кэша для этой версии гарантирует, что образ также будет закэширован для версии `v-blue`  поскольку они ссылаются на один и тот же тег,
   2. дождитесь индикатора кэширования в версии `v1.2.0-rc`  достигнет :green\_circle: зелёного,
4. Обновите ваш новый игровой клиент `c2` чтобы использовать новую версию `v-blue` при создании билетов:
   1. обновите базовый URL и токен авторизации в игровом клиенте,
5. Проведите QA-тесты и финальные проверки вашего нового игрового клиента `c2`:
   1. если вы найдёте и устраните какие-либо проблемы, повторите процесс с начала,
   2. подождите 3–7 дней, чтобы изменения DNS matchmaker распространились по ISP по всему миру после остановки matchmaker (быстрый перезапуск не требует обновления DNS или периода ожидания),
6. Выпустите обновление вашего нового игрового клиента `c2` на игровых платформах распространения,
7. Дайте время новому игровому клиенту `c2` распространиться на устройства игроков (обычно до 3–7 дней):
   1. отслеживать устаревшие игровые клиенты `c1`  используя развертывание [Развертывания](/ru/learn/orkestraciya/deployments.md#analytics),
8. Очистите неиспользуемые ресурсы в вашем аккаунте Edgegap:
   1. удалите тег образа `t1.0.0` чтобы освободить место в Container Registry,
   2. удалите тег образа `t1.1.0` чтобы освободить место в Container Registry,
   3. выключите ваш `зелёный`  matchmaker, чтобы приостановить начисление платы до следующего обновления.

{% hint style="success" %}
**Для вашего следующего обновления**, увеличьте номера версий и замените `зелёный` и `синий` ключевые слова в руководстве.
{% endhint %}

#### **⚡ Срочный серверный патч**

**Необходимые условия:** В этом разделе предполагается, что вы уже выполнили [#before-going-live](#before-going-live "mention").

Чтобы **выпустить серверный патч без необходимости обновления игрового клиента**, вы можете:

1. Подготовьте новую версию серверного приложения `v1.2.0-rc` в Edgegap:
   1. отправить новый тег образа в ваш реестр контейнеров `t1.2.0`,
   2. создать новую версию приложения `v1.2.0-rc`,
2. Выполните тесты и проверки, используя [развертывание новой версии приложения](https://app.edgegap.com/deployment-management/deployments/list) `v1.2.0-rc`:
   1. подключить Editor вашего игрового движка к предоставленному URL + внешнему порту,
   2. если вы найдёте и устраните какие-либо проблемы, повторите процесс с начала,
   3. включить кэширование для новой версии приложения `v1.2.0-rc` , включение кэша для этой версии гарантирует, что образ также будет закэширован для версии `v-green`  позже, поскольку они будут ссылаться на один и тот же тег,
   4. дождитесь индикатора кэширования в версии `v1.2.0-rc`  достигнет :green\_circle: зелёного,
3. Обновите версию `v-green`  чтобы привязать его к новому тегу образа `t1.2.0`,
   1. новые матчи автоматически начнут назначение с обновлённым тегом `t1.2.0`,
   2. отслеживать устаревшие игровые клиенты `c1`  используя развертывание [Развертывания](/ru/learn/orkestraciya/deployments.md#analytics),
4. Очистка неиспользуемых ресурсов в вашем аккаунте Edgegap:
   1. удалите тег образа `t1.1.0` чтобы освободить место в Container Registry.

## 📗 API <a href="#matchmaking-api" id="matchmaking-api"></a>

Клиенты и серверы могут вызывать API напрямую или с помощью SDK игровых движков, см. также [Матчмейкинг](/ru/learn/matchmeiking.md).

{% hint style="info" %}
Unity/Android — рассмотрите возможность [использования подстановки в сырой строке](https://www.c-sharpcorner.com/article/convert-string-to-json-in-c-sharp/) чтобы предотвратить удаление кода жестко заданных JSON-файлов.
{% endhint %}

{% hint style="success" %}
**Веб-интерфейс Swagger**: при развертывании вашего управляемого сервиса генерируется спецификация OpenAPI и удобный веб-интерфейс, полезный для тестирования крайних случаев или проверки структуры полезных данных.
{% endhint %}

{% tabs fullWidth="false" %}
{% tab title="🍀 Простой пример" %}
{% file src="/files/7d0f90dc43c3b7d145adac1ad73250ee407bb816" %}
{% endtab %}

{% tab title="🏁 Продвинутый пример" %}
{% file src="/files/174cc4ac8b555f73c277175e8e15173e226b8ed9" %}
{% endtab %}

{% tab title="🎾 Пользовательский лобби" %}
{% file src="/files/11e2695177f3949632a909a5baf2c4d45c2ebfdc" %}
{% endtab %}

{% tab title="🥛 Демонстрация подбора игроков" %}
{% file src="/files/db149be8a4616a601a799ce1f015caace9ee1e03" %}
{% endtab %}

{% tab title="⚔️ Соревновательные игры" %}
{% file src="/files/4438d60914c9c7a4b475bb5bc172ebe487125bbd" %}
{% endtab %}

{% tab title="🤝 Кооперативные игры" %}
{% file src="/files/5794324ea05f7587619d5cc384394d352fb718d8" %}
{% endtab %}

{% tab title="🎈 Социальные игры" %}
{% file src="/files/17d42dcf1fc9846bdbb74a6d6303005d408f851e" %}
{% endtab %}
{% endtabs %}

Импортировать спецификацию API в [Веб-клиент Scalar API](https://client.scalar.com/workspace/default/request/default) или [Swagger Editor](https://editor.swagger.io/) для изучения деталей.

### Ограничения по скорости

Чтобы защитить ваш кластер от превышения пиковых возможностей и сбоев, мы ограничиваем число запросов в секунду на основе наших внутренних нагрузочных тестов, используя [Матчмейкинг](/ru/learn/matchmeiking.md#advanced-example) конфигурацию.

<table><thead><tr><th>конечная точка API</th><th width="130">Бесплатный тариф</th><th width="130">Тариф для любителей</th><th width="130">Тариф для студий</th><th width="130">Тариф Enterprise</th></tr></thead><tbody><tr><td><strong>Общий лимит</strong></td><td><strong>100</strong></td><td><strong>200</strong></td><td><strong>750</strong></td><td><strong>2,000</strong></td></tr><tr><td>Создать развертывание</td><td>5</td><td>10</td><td>30</td><td>30</td></tr><tr><td>Список маяков</td><td>10</td><td>20</td><td>75</td><td>200</td></tr><tr><td>Создать группу<br>+ Создать билет<br>+ Создать групповой билет</td><td>10</td><td>20</td><td>75</td><td>200</td></tr><tr><td>Читать членство<br>+ Читать группу<br>+ Читать билет</td><td>10</td><td>120</td><td>450</td><td>1,300</td></tr><tr><td>Создать дозаполнение</td><td>5</td><td>10</td><td>37</td><td>100</td></tr></tbody></table>

Ограничения по скорости выражаются в **совокупном числе запросов в секунду к указанному набору конечных точек API**.

{% hint style="warning" %}
Если ваши игровые клиенты не повторяют запросы при получении ответа `429 Слишком много запросов` **в ваших развертываниях могут отсутствовать игроки** во время коротких всплесков и пиковых периодов трафика.
{% endhint %}

#### Нагрузочное тестирование

Нагрузочное тестирование в среде, похожей на производственную, связано со стоимостью хостинга развертывания. См. ресурсы и цены, связанные с каждым уровнем, на [нашей странице с тарифами](https://edgegap.com/resources/pricing#matchmaker).

{% hint style="warning" %}
**Используйте** [**частные кластеры**](#private-cluster-tiers) **для стресс-тестирования.** Бесплатные экземпляры строго ограничены и предназначены только для тестирования в разработке.
{% endhint %}

При проектировании нагрузочного теста, **пожалуйста, учитывайте реалистичные модели поведения игроков**:

| Реалистичный сценарий                                                                                      | Нереалистичный шаблон трафика                                                                   |
| ---------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------- |
| ✅ Игроки постепенно присоединяются к игре, увеличивая число запросов в секунду в течение нескольких часов. | ❌ Все игроки скоординированно обращаются к API в одну и ту же секунду.                          |
| ✅ Игроки ждут всё больше времени между повторными попытками (например, 1 с – 5 с – 10 с – 10 с).           | ❌ Все игроки повторяют попытку немедленно при получении `429 Слишком много запросов`  ответа.   |
| ✅ Большинство игроков получат свои назначения в течение короткого времени (10–60 с) и прекратят опрос.     | ❌ Все игроки продолжают опрашивать в течение заданного времени даже после получения назначения. |
| ✅ Большинство игроков завершают свою игру (это занимает время), прежде чем начать новую сессию.            | ❌ Все игроки немедленно перезапускают свою сессию сразу после получения назначения сервера.     |
| ✅ Пиковый трафик сохраняется примерно 6 часов в день, после чего часть часовых поясов отключается.         | ❌ Пиковый трафик сохраняется 24 часа в сутки, и все игроки играют и днём и ночью.               |

#### Поведение под нагрузкой

Если matchmaker испытывает высокую нагрузку:

* если CPU троттлится, подбор матчей может замедлиться,
* если у matchmaker закончится память, он перезапустится без потери информации о билетах, в надежде, что клиенты реализуют экспоненциальный backoff и всплеск будет распределён на более длительный период времени.

#### Совместное использование ресурсов между источниками (CORS)

Для игр WebGL, размещённых на сторонних платформах распространения (например, [itch.io](http://itch.io/)), отправка любых запросов к Matchmaker из игрового клиента может привести к [Совместное использование ресурсов между источниками](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) нарушению политики. Большинство современных веб-браузеров отправляют [предварительный запрос](https://developer.mozilla.org/en-US/docs/Glossary/Preflight_request) чтобы проверить, что серверный сервис (Matchmaker) понимает и принимает связь от вашего игрового клиента.

Неудачная предварительная проверка (по умолчанию по соображениям безопасности) может привести к [одной из нескольких возможных ошибок, связанных с CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS/Errors/CORSMissingAllowOrigin), чаще всего `Отсутствует заголовок CORS 'Access-Control-Allow-Origin'` .

Чтобы устранить эту ошибку, добавьте **`allowed_cors_origin`** параметр в вашу конфигурацию, чтобы либо:

* добавить в белый список точные домены, на которых размещён ваш клиент:

<details>

<summary>🍀 Простой пример (пример с конкретными доменами)</summary>

<pre class="language-json"><code class="lang-json">{
  "version": "3.2.3",
  "allowed_cors_origins": [
    "https://dev.my-game-server.com",
    "https://prod.my-game-server.com"
  ],
  "profiles": {
      <a data-footnote-ref href="#user-content-fn-11">...</a>
  }
}
</code></pre>

</details>

* или добавьте в белый список домен с подстановочным знаком (включая все поддомены):

<details>

<summary>🍀 Простой пример (пример с доменом с подстановочным знаком)</summary>

<pre class="language-json"><code class="lang-json">{
  "version": "3.2.3",
  "allowed_cors_origins": ["https://*.my-game-server.com"],
  "profiles": {
      <a data-footnote-ref href="#user-content-fn-11">...</a>
  }
}
</code></pre>

</details>

{% hint style="info" %}
**Для предварительных запросов Matchmaker учетные данные не требуются**, если домены настроены правильно.
{% endhint %}

### Сервер-сервер <a href="#server-to-server-api" id="server-to-server-api"></a>

Добавьте расширенный или настраиваемый контроль над потоком подбора матчей — реализуйте собственный прокси, используя наш [Managed Clusters](/ru/learn/advanced-features/managed-clusters.md) или любую облачную FaaS[^12] вычислительную платформу, чтобы реализовать любое из следующего:

* прикреплять конфиденциальные атрибуты игрока — такие как флаги читера, рейтинги навыка или подобное,
* предоставлять контекст команды и матча в игре — перечислять моих товарищей по команде и соперников во время загрузки,
* ограничивать конкретные крайние случаи — напр., разрешать только 1 группу на игрока в любой момент,
* добавлять кэширование или ограничение скорости API — уменьшать число запросов и нагрузку на matchmaker,
* настраивать интеграцию лобби и группы — создавать асимметричные/ролевые лобби перед подбором матчей.

{% hint style="success" %}
**Включите параметр `player_ip`  с публичным IP-адресом участника** чтобы обеспечить минимально возможную задержку для игрока и воспользоваться [/pages/4ad5d792bc82dceeaec6d7dd56165ae188da0417#id-1.-server-score-strategy-best-practice](https://docs.edgegap.com/ru/learn/matchmeiking/pages/4ad5d792bc82dceeaec6d7dd56165ae188da0417#id-1.-server-score-strategy-best-practice "mention").
{% endhint %}

{% hint style="info" %}
Игровые клиенты могут использовать [ipify.org](http://ipify.org/) бесплатный сервис для определения своих публичных IP. VPN может скрывать публичный IP-адрес.
{% endhint %}

<figure><img src="https://3845012722-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FsR0dHSFv9ymoC0DO5G8J%2Fuploads%2FzLfA3fEBgwaziGtp2yMO%2Fimage.png?alt=media&amp;token=3d551e74-4a60-47a6-9d79-a506f961663d" alt=""><figcaption><p>Диаграмма активности подбора матчей сервер-сервер</p></figcaption></figure>

## 🚨 Устранение неполадок

**Ваш успех — наш приоритет.** Если вы хотите отправить собственные запросы, попросить о недостающих критически важных функциях или высказать любые мысли, [свяжитесь с нами в нашем Community Discord](https://discord.gg/MmJf8fWjnt).

<details>

<summary><code>Конфигурация приложения недействительна для профиля XYZ.</code></summary>

* Мы не смогли найти ваш [Приложения и версии](/ru/learn/orkestraciya/application-and-versions.md), пожалуйста, проверьте `приложение`  значения.

</details>

<details>

<summary><code>Docker-образ для '2024.01.30-16.23.00-UTC' не кэширован.</code></summary>

[**🌟 Обновитесь до тарифа Pay as You Go**](https://app.edgegap.com/user-settings?tab=memberships) **чтобы разблокировать** [**мгновенные развёртывания с кэшированием**](https://docs.edgegap.com/ru/learn/matchmeiking/pages/4ad5d792bc82dceeaec6d7dd56165ae188da0417#id-1.-start-a-deployment)**.**

* Некэшированные образы размером 4 ГБ и более могут дольше развёртываться, что приведёт к [/pages/4ad5d792bc82dceeaec6d7dd56165ae188da0417#id-4.-deployment-error](https://docs.edgegap.com/ru/learn/matchmeiking/pages/4ad5d792bc82dceeaec6d7dd56165ae188da0417#id-4.-deployment-error "mention"). Рассмотрите возможность оптимизации размера образа сервера ([Unreal Engine](/ru/unreal-engine.md#optimize-server-build-size) / [Unity](/ru/unity.md#optimize-server-build-size)).
* Вы всё равно можете продолжить, хотя мы рекомендуем протестировать время развёртывания.

</details>

<details>

<summary>Почему я получаю ошибки при попытке создать новый matchmaker?</summary>

* Пожалуйста, прочитайте сообщение об ошибке: возможно, вы неправильно написали идентификатор, правило или оператор. - Используйте [JSONLint](https://jsonlint.com/) для проверки форматирования JSON; возможно, вы пропустили запятую или скобку. - Обратитесь через [наш Community Discord](https://discord.gg/MmJf8fWjnt) за помощью — мы будем рады помочь. 🙏

</details>

<details>

<summary>Почему мой matchmaker автоматически выключился через 3 часа?</summary>

* Matchmaker в Free Tier предназначены для первоначальных тестов и автоматически выключаются через 3 часа. Чтобы продолжить тестирование, вы можете [перезапустить ваш matchmaker](https://app.edgegap.com/matchmaker-management-v2/matchmakers/list).
* Рассмотрите возможность перехода на платный тариф для неограниченного времени работы.

</details>

<details>

<summary>Почему я не могу запустить второе развертывание в своём аккаунте?</summary>

* В Free Tier можно запускать только 1 одновременное развертывание.
* Пожалуйста, рассмотрите переход на платный тариф для неограниченного числа развертываний.

</details>

<details>

<summary>Почему я получаю назначение/развертывание в случайные моменты, игнорируя <code>player_count</code>?</summary>

* Вы или другой участник команды могли создать билеты во время предыдущей тестовой сессии, которые не были назначены. Пожалуйста, [перезапустить ваш matchmaker](https://app.edgegap.com/matchmaker-management-v2/matchmakers/list).

</details>

<details>

<summary>Мой билет застрял в <code>ПОИСК</code> .</summary>

* Пожалуйста, проверьте, что вы создали достаточное количество совпадающих билетов, соответствующих вашей конфигурации.

</details>

<details>

<summary>Мой билет застрял, переключаясь между <code>MATCH_FOUND</code>  и <code>ПОИСК</code>  повторно.</summary>

* Аккаунты Free Tier ограничены 1 развертыванием одновременно.
* Пожалуйста, рассмотрите возможность обновления тарифа или остановите текущее развертывание, чтобы начать новое.

</details>

<details>

<summary>Мой билет сразу переходит в <code>ОТМЕНЕНО</code>.</summary>

* Ваш билет достиг срока истечения. Создайте новый билет или увеличьте срок истечения в вашей конфигурации для целей тестирования.

</details>

<details>

<summary>Я получаю <code>HTTP 404 Не найдено</code> при проверке моего билета.</summary>

* Ваш билет был удалён либо запросом DELETE, либо по достижении периода удаления (начинается после истечения срока билета и определяется в вашей конфигурации). Создайте новый билет заново или увеличьте сроки истечения/удаления в вашей конфигурации для целей тестирования.

</details>

<details>

<summary>Мой matchmaker показывает ошибку, что мне делать?</summary>

* Если это development- или testing-экземпляр, сначала попробуйте перезапустить ваш matchmaker. - Сообщайте о любых проблемах через [наш Community Discord](https://discord.gg/MmJf8fWjnt).
* Если эта проблема влияет на живую игру, создайте [срочный запрос в поддержку](https://edgegap.atlassian.net/servicedesk/customer/portal/3).

</details>

## 🔖 Журнал изменений

Пожалуйста, см.  [Примечания к релизам](/ru/docs/release-notes.md) актуальный журнал изменений этого сервиса.

#### Семантическое версионирование

Наши инструменты разработчика и управляемые сервисы используют официальную [Семантическое версионирование](https://semver.org/), указывая, какие обновления ✅ безопасны (минорные, патч), а какие могут содержать ⚠️ ломающие изменения (мажорные).

**После выпуска версии она никогда не будет модифицирована/изменена**.

{% hint style="warning" %}
**Чтобы обновить версию сервиса — остановите, измените, перезапустите.** Быстрый перезапуск не применит изменения версии.
{% endhint %}

Ваш файл конфигурации будет проверяться в зависимости от используемой версии matchmaker; убедитесь, что ваши правила соответствуют возможностям версии matchmaker.

[^1]: пример значения

[^2]: игровые клиенты присоединяются к лобби, чтобы получить ID группы матчмейкинга и присоединиться к группе

[^3]: Fully Qualified Domain Name

[^4]: например, для 3 свободных слотов = \["3", "2", "1"]

[^5]: замените "2" на количество фактических участников группы

[^6]: замените на имя вашего приложения

[^7]: замените на версию вашего приложения

[^8]: превышена максимальная разница

[^9]: превышена максимальная задержка

[^10]: поставщик интернет-услуг

[^11]: см. другие примеры

[^12]: [Функция как услуга](https://www.ibm.com/think/topics/faas)
