Spectra
Нативный десктопный клиент панели Spectra для Windows и Linux, написанный на C#/.NET. Настоящий бинарник с доступом к системе, а не обернутый Chromium. Тот же вид, что и в вебе, но с нативной производительностью и интеграцией с рабочим столом.
Нативный административный клиент для хостинга игровых серверов Spectra на Windows и Linux, собранный на C#/.NET с Avalonia. Тот же вид, что и у веб-панели, но как настоящий бинарник, напрямую связанный с ядром платформы и её огромным API frozcore/frozmod - с доступом к системе, нативной скоростью и логикой, общей с остальной Spectra, а не переписанной второй раз.
Введение
Spectra - это бренд хостинга игровых серверов, для которого мы построили полный панельный бекенд. Этот кейс посвящён одной, но ключевой части этой головоломки: нативному десктопному клиенту для администраторов. Это не отдельное приложение, живущее рядом с панелью - это ещё одна оболочка над тем же ядром, общающаяся с тем же бекендом, что и веб-версия. Чтобы понять, почему это было вызовом, сначала нужно увидеть, насколько велика система под ним.
Десктопный клиент не рисует красивые экраны над пустотой. Он стоит на полноценной платформе: провижининг серверов, управление мощностью, файлы, базы данных, телеметрия, биллинг и права доступа. Наша задача была дать администратору нативное окно на всё это - без обёрнутого браузера и без дублирования логики, которая и так уже жила в веб-панели.
Панель, в которой вы сидите весь день
Администратор игровых серверов не заглядывает в панель раз в неделю. Он держит её открытой восемь часов, рядом с консолью, игровым клиентом и мессенджером. В таком режиме очередная вкладка браузера - не удобство, а пятое колесо в телеге: она теряется в толпе вкладок, у неё нет своего значка на панели задач, она не реагирует на системные сочетания клавиш и не видит локальных файлов.
Мы хотели дать тот же вид, что и веб, но как приложение, которое ведёт себя как остальные программы на рабочем столе. Одно жёсткое условие: никакого обёрнутого Chromium. Клиент, который добавляет 200 МБ памяти при старте только для того, чтобы показать ровно то же самое, промахивается мимо цели ещё до того, как успевает полностью запуститься. Раз администратор проводит здесь большую часть дня, приложение должно быть лёгким, мгновенным и "своим" на его системе, а не очередным окном браузера, притворяющимся программой.
В цифрах
| Метрика | Значение |
|---|---|
| Систем из одной кодовой базы | Windows и Linux |
| Типичный след памяти | ~40 МБ |
| Общее ядро с веб-панелью | одно |
| Видов, связанных с API | десятки |
Что на самом деле есть Spectra под спудом
Самое большое заблуждение в таком проекте - думать, что "это всего лишь панель". На самом деле панель - это тонкий слой над бекендом, который делает тяжёлую работу: запускает и останавливает игровые серверы, распределяет ресурсы, держит базы данных, транслирует логи и консоль в прямом эфире, следит за лимитами и биллингом. Этот бекенд - это обширный API семейства frozcore/frozmod - десятки эндпоинтов, события в реальном времени и модель прав доступа, которая решает, кто что видит и что может сделать.
Десктопный клиент должен общаться ровно с тем же API, что и веб-панель. Здесь нет "упрощённой десктопной версии": если администратор меняет лимит памяти сервера или перезапускает инстанс, он делает это через тот же контракт, через который это делает веб. Поэтому, прежде чем появился хоть один экран, нужно было понять и обуздать масштаб этого API - и это была реальная часть вызова, а не сам вид окна.
Консоль и поток логов работают в прямом эфире. Это не обновление каждые несколько секунд, а непрерывный поток событий с бекенда - десктопный клиент подписывается на него так же, как и веб, поэтому администратор видит вывод сервера в тот же момент, когда он возникает.
Одно ядро, две оболочки
Доменная логика - авторизация, модель сервера, команды питания, поток логов, отображение прав доступа на это API - живёт в одной библиотеке .NET. Веб-панель и десктопный клиент - это две оболочки над этим одним ядром, поэтому правка в правиле доступа или в обработке эндпоинта попадает в оба места сразу. Целый класс ошибок "на вебе работает, на десктопе сломано" просто исчезает.
Слой вида рисует Avalonia. Это не webview - контролы рендерятся напрямую через Skia, тем же путём на Windows и на Linux, поэтому приложение выглядит идентично на обоих. Заодно оно получает реальный доступ к файловой системе, буфер обмена и уведомлениям, которого обёрнутая страница никогда не имела.
Стек
| Слой | Выбор | Зачем так |
|---|---|---|
| Язык и runtime | C# / .NET | один язык на логику и UI, хорошие инструменты |
| Слой вида | Avalonia (Skia) | нативный рендер, идентичный на Windows и Linux |
| Доменное ядро | общая библиотека .NET | та же логика и тот же клиент API, что и веб-панель |
| Сетевой слой | типизированный клиент frozcore/frozmod | один контракт, веб и десктоп говорят одно и то же |
| Дистрибуция | self-contained publish | один бинарник, без установки runtime у клиента |
Интеграция с гигантским API
Это была самая тяжёлая часть. Бекенд Spectra выставляет десятки операций: жизненный цикл сервера, консоль, файлы, базы данных, расписания задач, резервные копии, пользователи и права доступа, телеметрия ресурсов. Чтобы десктопный клиент не превратился в клубок вызовов, мы обернули весь API в один типизированный клиент в ядре - с одним местом для авторизации, повторов и обработки ошибок.
все эндпоинты frozcore/frozmod за одним интерфейсом, с авторизацией и повторами в одном месте, чтобы ни веб, ни десктоп не повторяли эту логику.
консоль, логи и телеметрия как подписки на события, а не опрос в цикле; тот же механизм, что и в веб-панели.
то, что администратор может увидеть и сделать, вытекает из тех же правил, что и на вебе, вычисляемых на стороне ядра, а не "на глаз" в UI.
ответы API попадают прямо в нативные контролы Avalonia, без посредника в виде DOM.
Обернуть весь API в один клиент в ядре окупилось вдвойне: изменение контракта на стороне бекенда - это одна правка в библиотеке, которую веб и десктоп получают одним и тем же коммитом. Ноль расхождения версий, ноль "а у меня работает".
Производительность и нативность
Раз граничным условием было "без обёрнутого Chromium", производительность была не добавкой, а целью. Avalonia рисует интерфейс напрямую, без движка браузера внутри, поэтому бинарник с полной панелью весит долю того, что весил бы тот же вид в Electron, и стартует за долю секунды.
След памяти на старте (ориентировочно, МБ)
К этому добавляется то, чего браузер никогда не давал: реальный доступ к файловой системе (файлы сервера вы указываете прямо с диска, без их предварительной загрузки в браузер), системные сочетания клавиш, нативные уведомления и значок на панели задач. Для того, кто сидит в панели весь день, это не косметика, а ежедневная экономия времени.
Как мы всё это связали
Имея ядро с клиентом API и оболочку на Avalonia, всё собиралось повторяемым способом. Ключевым было то, чтобы один источник давал два самостоятельных бинарника, реально протестированных на обеих системах, а не просто компилирующихся под оба.
авторизация, модель сервера, команды и клиент API были отрезаны от веб-вида и перенесены в отдельную библиотеку, которая ничего не знает о том, кто её рисует.
та же раскладка экранов, что и веб, но в нативных контролах, связанная с ядром через обычные вызовы, а не через HTTP к самому себе.
publish на win-x64 и linux-x64 из одного источника, каждый как самостоятельный бинарник.
одно и то же запускается реально на Windows и на Linux, с подключением к настоящему бекенду, а не просто компилируется под оба.
Каков итоговый результат сотрудничества
Администратор получает программу, которая стартует за долю секунды, держится на панели задач как любое другое приложение и показывает ровно те же данные, что и веб-панель - потому что под спудом это тот же код и то же API. Системные сочетания клавиш работают, файлы с диска можно указать без их предварительной загрузки в браузер, консоль и логи летят в прямом эфире, а окно не теряется в гуще вкладок. Вместо "страницы в окне" администратор получает инструмент, который ощущается как часть его системы.
Со стороны Spectra выгода столь же конкретна и многолетняя. Одна логика и один клиент API вместо двух, поддерживаемых вручную в согласии, означают, что развитие платформы не умножается на число оболочек. Новое правило доступа, новый эндпоинт в бекенде или изменение в модели сервера попадает в веб и на десктоп одним и тем же коммитом. Целый класс ошибок синхронизации исчезает, а десктопный клиент перестаёт быть отдельным проектом для поддержки.
Самое важное всё же то, что десктоп - не "облегчённая версия". Он общается с тем же полным API frozcore/frozmod, что и веб-панель, поэтому администратору не нужно возвращаться в браузер за функциями, которых в приложении не хватило - потому что не хватило ни одной. Это разница между обёрнутой страницей и настоящим, нативным клиентом платформы: второй растёт вместе с бекендом, а не тащится за ним.
Больше проектов
Другие работы из той же категории - посмотрите, как мы решаем похожие задачи.
Есть похожий проект?
Напишите нам - смета бесплатна и приходит в течение часа.



