> 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/brauzer-serverov.md).

# Браузер серверов

Быстро начните работу с Server Browser и изучите примеры сценариев для разных жанров.

Server Browser — это управляемый сервис для [Развертывания](/ru/learn/orkestraciya/deployments.md#match-bound) и [Постоянные](/ru/learn/orkestraciya/persistentnost.md) серверы:

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

{% hint style="success" %}
Ищете способ подбирать игроков по строгим правилам, не позволяя выбирать сервер? Рассмотрите [Подбор игроков](/ru/learn/podbor-igrokov.md).
{% endhint %}

## ✔️ Подготовка

**Тестирование этого сервиса полностью бесплатно, кредитная карта не требуется.**

Бесплатный тариф предоставляет до 3 часов работы на нашем общем тестовом кластере после каждой перезагрузки.

В этом руководстве предполагается, что вы уже:

* [поняли модель развёртывания Edgegap](https://docs.edgegap.com/ru/learn/pages/4ad5d792bc82dceeaec6d7dd56165ae188da0417#id-1.-just-in-time-deployment-dedicated-servers),
* опубликовали ваше серверное приложение на Edgegap ([Unreal Engine](/ru/unreal-engine.md), [Unity](/ru/unity.md)),
* успешно подключились с игрового клиента к вашему серверу на Edgegap.

### Функции и поток

<figure><img src="https://3845012722-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FsR0dHSFv9ymoC0DO5G8J%2Fuploads%2Fnwlt2Ot2ahlyLvI7kdGx%2Fimage.png?alt=media&amp;token=14b5a6c8-48c8-4f23-a50a-0783acab14e3" alt=""><figcaption><p>Server Browser: поток и иерархия</p></figcaption></figure>

Server Browser предлагает две основные возможности:

[#start-browsing](#start-browsing "mention") с интеграцией клиента и сервера:

* Клиенты резервируют места одним методом и получают данные для подключения.
* Клиенты могут просматривать подходящие серверы и слоты, используя собственные фильтры (внутриигровой UI).
* Серверы проверяют подключения игроков на сервере с помощью [Федеративная идентификация](#user-content-fn-1)[^1].
* Серверы обновляют ёмкость слота и метаданные, чтобы изменить видимость или запустить масштабирование.

[#automated-scaling](#automated-scaling "mention") (необязательная функция) с политиками масштабирования:

* Отслеживайте доступные экземпляры серверов, слоты, ёмкость — по региону или по собственным критериям.
* Разворачивайте новые серверы, чтобы увеличить ёмкость с предварительным прогревом или масштабированием just-in-time.
* Автоматизируйте операции с изолированными политиками для событий ограниченного времени (QA-тест, турнир).

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

## ▶️ Начать просмотр

Узнайте о жизненном цикле сервера и игрока (клиента), чтобы обеспечить эффективное использование серверов.

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

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

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

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

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

Server Browser автоматически генерирует два типа токенов:

* **Токен сервера** - требуется для [API сервера](#server-lifecycle) методов, может быть [внедрён как переменная версии приложения](/ru/learn/orkestraciya/application-and-versions.md#injected-variables).
  * Даёт доступ ко всем методам API, удобно для тестирования, DevOps или собственного масштабирования.
* **Токен клиента** - требуется для [API мониторинга и API бронирования мест](#player-lifecycle) используется игровыми клиентами.

{% hint style="success" %}
Храните токен клиента в секретном хранилище бэкенда игры, чтобы упростить ротацию токенов в продакшене.
{% endhint %}

### Обнаружить экземпляр

Обнаружение — это процесс, при котором полностью инициализированный сервер уведомляет Server Browser и становится видимым [через поиск или автоматически назначаемые брони](#allocate-capacity).

{% hint style="warning" %}
**Новый** [Развертывания](/ru/learn/orkestraciya/deployments.md) **должен создать новый экземпляр** при инициализации, чтобы отслеживать добавленную ёмкость.
{% endhint %}

{% hint style="info" %}
См. [#automated-scaling](#automated-scaling "mention") чтобы узнать о политиках масштабирования и автоматически запускать развёртывания.
{% endhint %}

**Необходимая информация** для каждого экземпляра сервера включает:

* при инициализации экземпляра должно быть определено как минимум одно место,
* данные подключения к серверу — URL, IP, информация о порте и местоположение.

**Необязательные пользовательские параметры метаданных** для фильтрации, сортировки и просмотра игроками; например:

* информация о слотах — ёмкость команды и метаданные, специфичные для команды (например, название команды),
* имя и теги — настраиваемые, уникальные, человекочитаемые и доступные для поиска метки;
* данные совместимости — версия сервера или поддерживаемые версии клиента;
* критерии задержки — идентификаторы города и региона, а также назначенные [Ping-маяки](/ru/learn/orkestraciya/ping-beacons.md) сведения;
* игровые параметры — уровень/сцена/карта, режим игры, сложность, используемые моды;
* любой другой пользовательский параметр, чтобы помочь игрокам фильтровать и находить подходящий сервер.

{% hint style="info" %}
Приведённые выше параметры метаданных — лишь примеры, вы можете определить любое количество параметров по необходимости.
{% endhint %}

{% hint style="success" %}
Чтобы сериализовать вложенные объекты, кодируйте путь доступа к ним в ключе как `"object.child.property"`.
{% endhint %}

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

**Экземпляры сервера должны периодически отправлять keep-alive heartbeat** чтобы подтверждать их текущую доступность и не позволять игрокам подключаться к упавшим или офлайн-серверам. Пропуск heartbeat в течение настроенного периода истечения приведёт к автоматическому удалению экземпляра и любых ожидающих бронирований мест.

{% hint style="info" %}
См. [Персистентность](/ru/learn/orkestraciya/persistentnost.md) для управления постоянным состоянием мира и [Приложения и версии](/ru/learn/orkestraciya/application-and-versions.md#active-caching) для более быстрых развёртываний.
{% endhint %}

### Выделение ёмкости

Ёмкость экземпляра и слота может выделяться двумя способами, по отдельности или вместе:

* [#auto-assigned-reservation](#auto-assigned-reservation "mention") чтобы выбрать сервер, запущенный с определённой политикой масштабирования,
* [#search-and-browse](#search-and-browse "mention") позволяет игроку задать фильтры и просматривать подходящие серверы для ручного выбора.

{% hint style="success" %}
Рекомендуем начать с [#auto-assigned-reservation](#auto-assigned-reservation "mention") как с более простого варианта.
{% endhint %}

#### Автоматически назначаемая бронь

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

Игроки могут создать автоматически назначаемую бронь, указав только ID игроков и имя политики масштабирования. Server Browser автоматически найдёт слот экземпляра с достаточной доступной ёмкостью для присоединения и зарезервирует места, немедленно вернув данные подключения к экземпляру.

Если для этой брони нет подходящего слота экземпляра, ответ:

* **код статуса указывает состояние масштабирования политики** и если добавляется больше ёмкости,
* если масштабирование вверх, **заголовок `Retry-After`  указывает период ожидания (в секундах) перед повторной попыткой**.

После завершения бронирования вы можете перейти к [#connect-to-server](#connect-to-server "mention").

#### Поиск и просмотр

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

Игроки могут выводить список экземпляров серверов с собственными фильтрами и сортировкой, а [разбивать результаты на страницы](#pagination) чтобы найти сервер, к которому они хотели бы присоединиться. Слоты каждого экземпляра также могут быть найдены тем же способом.

Экземпляры и слоты можно фильтровать и сортировать с помощью встроенных параметров или [индексируемых метаданных](#configuration):

<table><thead><tr><th width="400">Свойство</th><th width="140">Тип данных</th><th width="105">Экземпляр</th><th width="105">Слот</th></tr></thead><tbody><tr><td><code>request_id</code></td><td><code>строка</code></td><td>✅</td><td>❌</td></tr><tr><td><code>total_joinable_seats</code>, <code>total_available_seats</code></td><td><code>целое число</code></td><td>✅</td><td>❌</td></tr><tr><td><code>name</code></td><td><code>строка</code></td><td>❌</td><td>✅</td></tr><tr><td><code>available_seats</code>, <code>reserved_seats</code></td><td><code>целое число</code></td><td>❌</td><td>✅</td></tr><tr><td><code>created_at</code>, <code>updated_at</code></td><td><code>строка</code></td><td>✅</td><td>✅</td></tr><tr><td><code>metadata.{index}</code> (пользовательское)</td><td><code>строка</code>, <code>целое число</code>, <code>число с плавающей точкой</code>, <code>логическое</code></td><td>✅</td><td>✅</td></tr></tbody></table>

Доступные операторы фильтрации зависят от типа данных фильтруемого свойства:

<table><thead><tr><th width="125">Параметр</th><th width="135">Операторы</th><th>Пример фильтра (на основе простого примера)</th></tr></thead><tbody><tr><td><code>строка</code></td><td><p><a data-footnote-ref href="#user-content-fn-3"><code>eq</code></a>  или <a data-footnote-ref href="#user-content-fn-4"><code>ne</code></a> или </p><p><a data-footnote-ref href="#user-content-fn-5"><code>lt</code></a>  или <a data-footnote-ref href="#user-content-fn-6"><code>le</code></a> или </p><p><a data-footnote-ref href="#user-content-fn-7"><code>gt</code></a>  или <a data-footnote-ref href="#user-content-fn-8"><code>ge</code></a>  или<br><code>содержит</code>  или<br></p></td><td><pre><code>?$filter=metadata.custom_name contains 'my game'
and metadata.server_version le '1.1.0'
and metadata.server_version ge '1.0.0'
&#x26;$order=metadata.custom_name asc
</code></pre></td></tr><tr><td><code>строка</code></td><td>буквальные значения<br><code>в</code>  (фильтр)<br><code>ранг</code>  (сортировка)</td><td><pre><code>?$filter=metadata.city in ('Chicago', 'Toronto')
&#x26;$order=rank(metadata.city, 'Chicago', 'Toronto')
</code></pre></td></tr><tr><td><code>целое число</code>, <code>число с плавающей точкой</code></td><td><p><a data-footnote-ref href="#user-content-fn-3"><code>eq</code></a>  или <a data-footnote-ref href="#user-content-fn-4"><code>ne</code></a> или </p><p><a data-footnote-ref href="#user-content-fn-5"><code>lt</code></a>  или <a data-footnote-ref href="#user-content-fn-6"><code>le</code></a> или </p><p><a data-footnote-ref href="#user-content-fn-7"><code>gt</code></a>  или <a data-footnote-ref href="#user-content-fn-8"><code>ge</code></a>  </p></td><td><pre><code>?$filter=metadata.xp_multiplier gt 1.0
&#x26;$order=metadata.xp_multiplier desc
</code></pre></td></tr><tr><td><code>логическое</code></td><td><a data-footnote-ref href="#user-content-fn-3"><code>eq</code></a>  или <a data-footnote-ref href="#user-content-fn-4"><code>ne</code></a></td><td><pre><code>?$filter=metadata.allows_new_connections eq true
</code></pre></td></tr></tbody></table>

{% hint style="success" %}
Фильтровать и сортировать по пользовательским `metadata.city`  для наилучшей задержки после измерения с помощью [Ping-маяки](/ru/learn/orkestraciya/ping-beacons.md).
{% endhint %}

{% hint style="info" %}
Узнайте о курсорной [#pagination](#pagination "mention") чтобы позволить пользователям получать больше результатов.
{% endhint %}

#### Зарезервировать места

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

Federated Identity: Игроки должны указать уникальный сторонний идентификатор игрока в своей брони. Как только они [#connect-to-server](#connect-to-server "mention"), отправьте тот же ID для серверной проверки.

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

**Брони, превышающие ёмкость присоединяемых мест слота, отклоняются** ([409 Conflict](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status/409)). Присоединяемые места — это любые доступные места, которые ещё не были зарезервированы другими игроками.

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

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

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

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

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

* **Развёртывание** **URL** указывающий на IP сервера, обычно в `NetworkManager`  компоненте.
* **Внешний порт** сопоставленный с [внутренним портом прослушивания сервера](https://docs.edgegap.com/learn/advanced-features/application-and-versions#port-mapping), обычно в компоненте Transport.

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

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

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

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

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

### Покинуть сервер

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

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

Читайте о [Персистентность](/ru/learn/orkestraciya/persistentnost.md#recovery-objectives) чтобы предотвратить раздражающие откаты постоянного сервера.

## 🚀 Автоматическое масштабирование

Server Browser совместим с несколькими различными методами автоскейлинга:

* **метод предварительного прогрева** - запускать серверы строго с политиками масштабирования Server Browser,
* **метод just-in-time** - запуск через [Подбор игроков](/ru/learn/podbor-igrokov.md) и [заполнение через Server Browser](#allocate-capacity),
* **собственный автоскейлер** - запуск через собственный игровой бэкенд и [заполнение через Server Browser](#allocate-capacity).

Следующее руководство сосредоточится на **предварительном прогреве с политиками масштабирования**.

<figure><img src="https://3845012722-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FsR0dHSFv9ymoC0DO5G8J%2Fuploads%2F0RCiModlkLY6BVAjcrFJ%2Fimage.png?alt=media&amp;token=7f7c5639-13ad-4780-9839-b9e4bd67fe80" alt=""><figcaption><p>UI политик масштабирования Server Browser</p></figcaption></figure>

{% hint style="success" %}
Останавливать развёртывания в [Unreal Engine](/ru/unreal-engine.md#stop-deployments), [Unity](/ru/unity.md#stop-deployments), или [с помощью API](/ru/docs/api/vydelennye-servery.md#delete-v1-self-stop-request_id-access_point_id) чтобы надёжно контролировать стоимость серверов.
{% endhint %}

### Мониторинг ёмкости

Server Browser будет обновлять список обнаруженных экземпляров каждые [`monitoring_interval`](#user-content-fn-9)[^9] .

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

{% hint style="info" %}
Каждая политика должна использовать фильтр (с помощью [синтаксиса фильтрации](#search-and-browse)) для мониторинга региональной ёмкости.
{% endhint %}

Ваш настроенный [`minimum_active_instances`](#user-content-fn-10)[^10]  значение может рассматриваться как:

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

#### Фиксированная ёмкость

Политики фиксированной ёмкости не должны использовать фильтры, связанные с местами.

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

В качестве альтернативы игры с [Персистентность](/ru/learn/orkestraciya/persistentnost.md) обычно хотят поддерживать долго работающие серверы, особенно когда предлагают игрокам развернуть [Персистентность](/ru/learn/orkestraciya/persistentnost.md#community-servers).

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

#### Резервный прогрев

Политики предварительного прогрева должны использовать фильтры присоединяемых мест для мониторинга использования ёмкости.

Запускайте ожидающие бездействующие серверы, чтобы опережать спрос игроков, если:

* вы запускаетесь глобально и ожидаете быстрого притока игроков за короткий промежуток времени,
* или инициализация сервера требует более 30 секунд ([не включая время развёртывания](#user-content-fn-11)[^11]),
* или серверы используют mesh-стратегии, требующие более сложной сетевой топологии.

### Развёртывание серверов

Новые развёртывания автоматически запускаются, когда количество обнаруженных экземпляр*ов* падает ниже минимума активных экземпляров политики. Развёртывания повторяются бесконечно через каждый интервал мониторинга после [`deployment_registration_period`](#user-content-fn-9)[^9]  истечения.

{% hint style="warning" %}
**Обязательно проверьте вашу** [**автообнаружение сервера**](#discover-instance) **интеграцию с фильтром вашей политики, иначе ваша политика может зациклиться бесконечно и создать огромное количество неиспользуемых развёртываний!**
{% endhint %}

{% hint style="info" %}
Развёртывания могут использовать [Частные парки серверов](/ru/learn/orkestraciya/chastnye-parki-serverov.md) (с Overflow to Cloud) или непосредственно Cloud.
{% endhint %}

Доступные параметры включают ([см. полную спецификацию API](/ru/docs/api/vydelennye-servery.md#private-fleets)):

* [**приложение и версия**](/ru/learn/orkestraciya/application-and-versions.md) - версия сборки, ресурсы и другие параметры оркестрации,
* **пользователи** - единый набор географических координат для предпочтительного [размещения сервера](/ru/learn/orkestraciya/deployments.md#regional-standby),
* [**приватные ID хостов**](/ru/learn/orkestraciya/chastnye-parki-serverov.md) - оставьте пустым для облака или укажите хосты в нужном регионе,
* [**tags**](/ru/learn/orkestraciya/deployments.md#dashboard-monitoring) - пометьте именем политики, чтобы позже находить развёртывания, запущенные с этой политикой,
* [**переменные окружения**](/ru/learn/orkestraciya/deployments.md#custom-variables) - передавайте серверам пользовательские параметры и секреты,
* [**вебхуки**](/ru/learn/orkestraciya/deployments.md#webhooks-and-postbacks) - уведомляйте ваш игровой бэкенд (или матчмейкер) о событиях жизненного цикла развёртывания,
* [**требуют кэшированных местоположений**](/ru/learn/orkestraciya/application-and-versions.md#active-caching) - если вы предпочитаете более быстрые развёртывания только в кэшированных местах.

### Примеры политик

Тестируйте и изменяйте любую из этих политик по мере необходимости. Большинству игр потребуется несколько политик.

{% tabs %}
{% tab title="🍀 QA-экземпляр" %}
Простая политика, чтобы всегда держать один сервер развёрнутым для тестирования.

<pre class="language-json" data-title=""><code class="lang-json">{
  "name": "sb-qa-pool",
<strong>  <a data-footnote-ref href="#user-content-fn-12">"filter"</a>: "metadata.policy_name eq 'sb-qa-pool'",
</strong>  "deployment_request": {
    "private_host_ids": [],
    "application": <a data-footnote-ref href="#user-content-fn-13">"my-game-server"</a>,
    "version": <a data-footnote-ref href="#user-content-fn-14">"2024.01.30-16.23.00-UTC"</a>,
    "users": [
      {
        "user_type": "geo_coordinates",
        "<a data-footnote-ref href="#user-content-fn-15">user_data</a>": {
<strong>          "latitude": 41.881832,
</strong><strong>          "longitude": -87.623177
</strong>        }
      }
    ],
<strong>    "tags": ["sb-qa-pool"],
</strong>    "environment_variables": [
      {
<strong>        "key": "SB_SCALING_POLICY_NAME",
</strong><strong>        "value": "sb-qa-pool",
</strong>        "is_hidden": false
      }
    ]
  },
<strong>  "minimum_active_instances": 1
</strong>}
</code></pre>

{% endtab %}

{% tab title="🌡️ Регион предварительного прогрева" %}
Запускайте 10x развёртывания в ожидании спроса. Копируйте для каждого региона.

<pre class="language-json" data-title=""><code class="lang-json">{
  "name": "sb-v1.0.0-chicago",
<strong>  <a data-footnote-ref href="#user-content-fn-16">"filter"</a>: "total_joinable_seats gt 0 and metadata.policy_name eq 'sb-v1.0.0-chicago'",
</strong>  "deployment_request": {
    "private_host_ids": [],
    "application": <a data-footnote-ref href="#user-content-fn-13">"my-game-server"</a>,
    "version": <a data-footnote-ref href="#user-content-fn-14">"2024.01.30-16.23.00-UTC"</a>,
    "users": [
      {
        "user_type": "geo_coordinates",
        "<a data-footnote-ref href="#user-content-fn-15">user_data</a>": {
<strong>          "latitude": 41.881832,
</strong><strong>          "longitude": -87.623177
</strong>        }
      }
    ],
<strong>    "tags": ["sb-v1.0.0-chicago"],
</strong>    "environment_variables": [
      {
<strong>        "key": "SB_SCALING_POLICY_NAME",
</strong><strong>        "value": "sb-v1.0.0-chicago",
</strong>        "is_hidden": false
      }
    ]
  },
<strong>  <a data-footnote-ref href="#user-content-fn-17">"minimum_active_instances"</a>: 10
</strong>}
</code></pre>

{% endtab %}

{% tab title="🔒 MMO" %}
Добавляйте развёртывания, если доступная ёмкость падает ниже порога. Копируйте для каждого региона.

<pre class="language-json" data-title=""><code class="lang-json">{
<strong>  "name": "sb-mmo-chicago",
</strong><strong>  <a data-footnote-ref href="#user-content-fn-18">"filter"</a>: "total_joinable_seats gt 5 and metadata.policy_name eq 'sb-mmo-chicago'",
</strong>  "deployment_request": {
<strong>    <a data-footnote-ref href="#user-content-fn-19">"private_host_ids"</a>: ["alpha-north-america-95fab093"],
</strong>    "application": <a data-footnote-ref href="#user-content-fn-13">"my-game-server"</a>,
    "version": <a data-footnote-ref href="#user-content-fn-14">"2024.01.30-16.23.00-UTC"</a>,
    "users": [
      {
        "user_type": "geo_coordinates",
        "<a data-footnote-ref href="#user-content-fn-15">user_data</a>": {
<strong>          "latitude": 41.881832,
</strong><strong>          "longitude": -87.623177
</strong>        }
      }
    ],
<strong>    "tags": ["sb-mmo-chicago"],
</strong>    "environment_variables": [
      {
<strong>        "key": "SB_SCALING_POLICY_NAME",
</strong><strong>        "value": "sb-mmo-chicago",
</strong>        "is_hidden": false
      }
    ],
<strong>    <a data-footnote-ref href="#user-content-fn-20">"webhook_on_terminated"</a>: {
</strong>      "url": "https://my-webhook.com"
    }
  },
<strong>  "minimum_active_instances": 3
</strong>}
</code></pre>

{% endtab %}

{% tab title="🔑 Сообщество" %}
Одна политика на владельца сервера, с передачей собственного пароля, заданного владельцем.

<pre class="language-json" data-title=""><code class="lang-json">{
<strong>  "name": "sb-owner-jnjnc8mid",
</strong><strong>  <a data-footnote-ref href="#user-content-fn-21">"filter"</a>: "metadata.policy_name eq 'sb-owner-jnjnc8mid'",
</strong>  "deployment_request": {
<strong>    <a data-footnote-ref href="#user-content-fn-19">"private_host_ids"</a>: ["alpha-north-america-95fab093"],
</strong>    "application": <a data-footnote-ref href="#user-content-fn-13">"my-game-server"</a>,
    "version": <a data-footnote-ref href="#user-content-fn-14">"2024.01.30-16.23.00-UTC"</a>,
    "users": [
      {
        "user_type": "geo_coordinates",
        "<a data-footnote-ref href="#user-content-fn-15">user_data</a>": {
<strong>          "latitude": 41.881832,
</strong><strong>          "longitude": -87.623177
</strong>        }
      }
    ],
<strong>    "tags": ["community", "sb-owner-jnjnc8mid"],
</strong>    "environment_variables": [
      {
<strong>        "key": "SB_SCALING_POLICY_NAME",
</strong><strong>        "value": "sb-owner-jnjnc8mid",
</strong>        "is_hidden": false
      },
      {
<strong>        "key": "SB_SERVER_PASSWORD",
</strong><strong>        "value": "password1234",
</strong>        "is_hidden": false
      }
    ],
<strong>    <a data-footnote-ref href="#user-content-fn-22">"webhook_on_ready"</a>: {
</strong>      "url": "https://my-webhook.com"
    },
<strong>    <a data-footnote-ref href="#user-content-fn-23">"webhook_on_error"</a>: {
</strong>      "url": "https://my-webhook.com"
    },
<strong>    <a data-footnote-ref href="#user-content-fn-20">"webhook_on_terminated"</a>: {
</strong>      "url": "https://my-webhook.com"
    }
  },
  "minimum_active_instances": 1
}
</code></pre>

{% endtab %}
{% endtabs %}

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

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

{% tabs %}
{% tab title="🍀 Простой пример" %}

<pre class="language-json" data-title="sb-simple-example-v1-1-0.json"><code class="lang-json">{
	"version": "1.1.0",
	"server_instances": {
		"expiration_period": "1m",
		"<a data-footnote-ref href="#user-content-fn-24">индексы</a>": {
			"policy_name": "string",
			"name": "string"
		}
	},
	"server_instance_slots": {
		"<a data-footnote-ref href="#user-content-fn-24">индексы</a>": {}
	},
	"seat_reservations": {
		"expiration_period": "30s"
	},
	"scaling_policies": {
		"monitoring_interval": "10s",
		"deployment_registration_period": "1m"
	},
  "rate_limits": {
    "per_client_ip": 5
  }
}
</code></pre>

{% endtab %}

{% tab title="🎈 Социальные игры" %}

<pre class="language-json" data-title="sb-social-example-v1-1-0.json"><code class="lang-json">{
	"version": "1.1.0",
	"server_instances": {
		"expiration_period": "15s",
		"<a data-footnote-ref href="#user-content-fn-24">индексы</a>": {
			"policy_name": "string",
			"name": "string",
			"third_party_id": "string",
			"level": "string",
			"mode": "string",
			"difficulty": "string",
			"seed": "string",
			"max_players": "int",
			"app_version": "string",
			"location.city": "string"
		}
	},
	"server_instance_slots": {
		"<a data-footnote-ref href="#user-content-fn-24">индексы</a>": {
			"third_party_id": "string",
			"max_players": "int",
			"avg_latency": "int",
			"player_ids": "string"
		}
	},
	"seat_reservations": {
		"expiration_period": "30s"
	},
	"scaling_policies": {
		"monitoring_interval": "10s",
		"deployment_registration_period": "30s"
	},
  "rate_limits": {
    "per_client_ip": 5
  }
}
</code></pre>

{% endtab %}

{% tab title="🤝 Кооперативные игры" %}

<pre class="language-json" data-title="sb-cooperative-example-v1-1-0.json"><code class="lang-json">{
	"version": "1.1.0",
	"server_instances": {
		"expiration_period": "15s",
		"<a data-footnote-ref href="#user-content-fn-24">индексы</a>": {
			"policy_name": "string",
			"name": "string",
			"third_party_id": "string",
			"level": "string",
			"mode": "string",
			"difficulty": "string",
			"avg_rank": "int",
			"max_players": "int",
			"app_version": "string",
			"tags": "string",
			"match_id": "string",
			"location.city": "string"
		}
	},
	"server_instance_slots": {
		"<a data-footnote-ref href="#user-content-fn-24">индексы</a>": {
			"third_party_id": "string",
			"max_players": "int",
			"player_ids": "string"
		}
	},
	"seat_reservations": {
		"expiration_period": "30s"
	},
	"scaling_policies": {
		"monitoring_interval": "10s",
		"deployment_registration_period": "30s"
	},
  "rate_limits": {
    "per_client_ip": 5
  }
}
</code></pre>

{% endtab %}

{% tab title="⚔️ Соревновательные игры" %}

<pre class="language-json" data-title="sb-competitive-example-v1-1-0.json"><code class="lang-json">{
	"version": "1.1.0",
	"server_instances": {
		"expiration_period": "15s",
		"<a data-footnote-ref href="#user-content-fn-24">индексы</a>": {
			"policy_name": "string",
			"name": "string",
			"third_party_id": "string",
			"avg_rank": "int",
			"max_players": "int",
			"is_ranked": "bool",
			"app_version": "string",
			"cpu_frequency": "int",
			"match_id": "string",
			"location.city": "string"
		}
	},
	"server_instance_slots": {
		"<a data-footnote-ref href="#user-content-fn-24">индексы</a>": {
			"third_party_id": "string",
			"max_players": "int",
			"avg_rank": "int",
			"avg_latency": "int"
		}
	},
	"seat_reservations": {
		"expiration_period": "30s"
	},
	"scaling_policies": {
		"monitoring_interval": "10s",
		"deployment_registration_period": "15s"
	},
  "rate_limits": {
    "per_client_ip": 5
  }

</code></pre>

{% endtab %}
{% endtabs %}

{% hint style="info" %}
Для лучшей производительности опускайте индексы, которые не используются для фильтрации или сортировки. Неиндексируемые параметры всё равно можно задавать и читать с помощью методов API или SDK, специфичного для движка.
{% endhint %}

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

Server Browser удобно размещается и управляется 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">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">200</td><td align="right">750</td><td align="right">2,000</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>

🌟 Обновите бесплатные экземпляры до частного кластера одним щелчком и получите высокодоступный хостинг, поддерживаемый командой Edgegap, с круглосуточной живой поддержкой для публично выпущенных игр.

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

* **количество игроков,** больше игроков ⇒ больше API-запросов и более высокая загрузка CPU,
* **запросов на игрока,** более частые повторные попытки ⇒ более высокое потребление ресурсов CPU,
* **количество серверов,** больше серверов ⇒ более высокая загрузка CPU и использование памяти,
* **логика резервного повторного запроса клиента** - повторные попытки без backoff с джиттером ⇒ [лавина запросов](https://en.wikipedia.org/wiki/Thundering_herd_problem),
* **средняя длительность матча** - более короткие сессии ⇒ более высокая частота событий жизненного цикла.

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

## 📗 API

**Рассмотрите наши SDK для** [**Unreal Engine**](/ru/unreal-engine/developer-tools.md) **или** [**Unity**](/ru/unity/brauzer-serverov.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 %}

{% file src="/files/ffccd4f3b6ecf3f56a51fda820bfa44d3d52ed88" %}

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

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

Чтобы защитить ваш экземпляр от превышения пикового лимита и сбоя, мы ограничиваем число клиентских запросов в секунду по публичному IP-адресу клиента.

Ограничение задается с помощью [#configuration](#configuration "mention") параметре `rate_limits.per_client_ip`.

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

{% hint style="success" %}
**Во время разработки мы рекомендуем тестировать поведение приложения с более низкими лимитами запросов (1 req/s).**
{% endhint %}

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

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

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

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

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

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

**Клиентские запросы** - если какой-либо клиент достигает заданного лимита req/s на IP, он получает `429 Слишком много запросов`  и должен сделать паузу (подождать) перед повторной попыткой.

**Запросы на развертывание** - если политики масштабирования запускают больше развертываний, чем разрешенный для вашей организации лимит req/s, ваш Server Browser будет автоматически повторять попытку каждый интервал мониторинга, используя взвешенную стратегию round-robin между всеми политиками экземпляров.

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

### Пагинация

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

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

Главный приоритет — помочь пользователям найти подходящий сервер на первой странице.

Для лучшего опыта мы рекомендуем показывать кэшированные результаты предыдущих страниц и обновлять результаты только тогда, когда пользователь нажимает «Поиск» или вручную запрашивает обновление.

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

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

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

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

{% hint style="info" %}
**Последняя версия server browser — `1.1.0`** . Следите за [обновлениями и объявлениями](/ru/docs/release-notes.md).
{% endhint %}

[^1]: сторонних идентификаторов игроков

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

[^3]: равно

[^4]: не равно

[^5]: меньше чем

[^6]: меньше или равно

[^7]: больше чем

[^8]: больше или равно

[^9]: см. Конфигурацию

[^10]: см. Примеры политик

[^11]: используйте активное кэширование, чтобы легко сократить время развёртывания

[^12]: * фиксированная ёмкость
    * предполагает, что экземпляры передают имя политики в метаданных из внедрённой переменной

[^13]: замените на собственное имя приложения

[^14]: замените на собственную версию приложения

[^15]: координаты Чикаго

[^16]: * разворачивается, когда найдено меньше 10 присоединяемых экземпляров
    * предполагает, что экземпляры передают имя политики в метаданных из внедрённой переменной

[^17]: мы ожидаем как минимум 10 развёртываний в регионе Чикаго

[^18]: * разворачивается, когда найдено менее 3 экземпляров с 5 или менее присоединяемыми местами
    * предполагает, что экземпляры передают имя политики в метаданных из внедрённой переменной

[^19]: предпочитать частный пул, если доступна емкость

[^20]: уведомлять игровой бэкенд при перезапуске сервера

[^21]: * не отслеживает емкость
    * предполагает, что экземпляры передают имя политики в метаданных из внедрённой переменной

[^22]: уведомлять игровой бэкенд, когда всё готово

[^23]: уведомлять игровой бэкенд, когда развертывание завершается сбоем

[^24]: индексы содержат ваши пользовательские параметры метаданных, используемые для фильтрации или сортировки
