Нагрузочная проверка InkVault

Отчет для владельцев XMPP-сервера на VPS: будет ли сервер корректно работать с InkVault, сколько пользователей он выдержит и что проверить в настройках.

attributes

project
InkVault
repo
https://github.com/tzx1z/inkvault-loadtest
server
Prosody 13.0.7, Lua 5.4
storage
SQLite, журнал delete, synchronous FULL
dataset
100 пользователей по 200 записей, шифротекст записи 900 байт
rate_limit
10 КБ/с на подключение
date
2026-10-20

Вывод

VPS с 1 ядром, 1 ГиБ памяти и каналом 200 Мбит/с справляется с InkVault. Для личного сервера, семьи и небольшой группы, примерно до 100 пользователей, ресурсов хватает с большим запасом.

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

  • Prosody хранит данные в SQLite (storage = "sql"), как на стенде проверки
  • В хранилище до 256 записей, это лимит по умолчанию
  • Диск VPS на SSD
  • 0ошибок на 307 977 операций
  • 0потерянных уведомлений о новых записях
  • 37 мс99% запросов быстрее при 100 операциях в секунду
  • 30 МиБпамяти занимает Prosody с 50 подключенными клиентами

Как InkVault работает с сервером

InkVault хранит записи на вашем XMPP-сервере через PEP (XEP-0163), стандартный механизм личных данных учетной записи. Записи шифруются на устройстве, сервер хранит только шифротекст и служебные поля: идентификатор записи и версию ключа. Отдельный сервер или база для InkVault не нужны.

Устройства подключаются к Prosody, сервер хранит записи в узле PEP и в базе SQLite, при подключении отдает все записи, при сохранении принимает одну запись и рассылает уведомление другим устройствам владельцаAndroidшифрует записиВеб-клиентшифрует записиТерминалшифрует записиXMPP-сервер Prosodyна вашем VPSPEP: хранилище InkVaulturn:inkvault:vault:0до 256 записей по умолчаниюдоступ только у владельцазапись + fsyncчтениеSQLiteprosody.sqlite2Сохранение записиодна запись, около 1.8 КБ1Подключениевсе записи, около 270 КБ3Уведомлениезапись с другого устройства
1: при каждом подключении устройство загружает все записи хранилища. 2: при изменении устройство отправляет на сервер одну запись. 3: сервер пересылает ее другим подключенным устройствам владельца. Другие пользователи сервера и контакты записи не получают.

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

Как проверяли

Генератор нагрузки вел себя как клиенты InkVault: подключался к Prosody по XMPP с TLS, загружал хранилища, сохранял и читал записи. Размер и формат записей такие же, как у InkVault.

Стенд проверки: генератор нагрузки с 50-500 подключениями, Prosody 13.0.7, база SQLite со 100 пользователями по 200 записейГенератор нагрузки50-500 подключенийкак клиенты InkVaultXMPP + TLSProsody 13.0.7один процесс, один потоклимит скорости 10 КБ/сSQLSQLite100 пользователейпо 200 записей20 000 записей, 55 МБ
Стенд проверки. Генератор и сервер работали на одной машине, поэтому сетевая задержка до клиентов в результатах не учитывается.
ПроверкаНагрузкаДлительностьРезультат
Обычная нагрузка, 2 прогона50 клиентов, 100 операций в секундупо 5 мин100 оп/с выдержаны, ошибок 0
Стресс500 клиентов, рост до 3000 операций в секунду15 минпредел сервера 260-280 оп/с, ошибок 0

Операция - один запрос клиента: загрузка всего хранилища (8% запросов), сохранение записи (20%) или чтение одной записи (72%).

Время ответа и нагрузка

До 180 операций в секунду время ответа почти не меняется. Дальше запросы начинают ждать друг друга, а при 260-280 операциях в секунду сервер выходит на предел: обрабатывать больше он не успевает, и растет только время ответа.

  • Медиана: половина запросов быстрее
  • 1 из 100: самые медленные запросы
Время ответа почти не меняется до 180 операций в секунду, затем растет; при 340 операциях в секунду медиана 863 мс, самые медленные запросы 1168 мс. Нагрузка личного сервера меньше 1 операции в секунду.Запросы не ждутОчередь растетПерегрузка03006009001200050100150200250300350Время ответа, мсНагрузка, операций в секундуЛичный сервер на 100 пользователей: меньше 1 оп/с1168 мс863 мсНагрузка 20 оп/с: медиана 3.7 мс, 1 из 100: 44 мсНагрузка 60 оп/с, обработано 59 оп/с: медиана 5.2 мс, 1 из 100: 38 мсНагрузка 100 оп/с: медиана 7.1 мс, 1 из 100: 78 мсНагрузка 140 оп/с, обработано 138 оп/с: медиана 7.5 мс, 1 из 100: 79 мсНагрузка 180 оп/с: медиана 18.7 мс, 1 из 100: 131 мсНагрузка 220 оп/с: медиана 87 мс, 1 из 100: 219 мсНагрузка 260 оп/с, обработано 253 оп/с: медиана 79 мс, 1 из 100: 285 мсНагрузка 300 оп/с, обработано 263 оп/с: медиана 263 мс, 1 из 100: 395 мсНагрузка 340 оп/с, обработано 274 оп/с: медиана 863 мс, 1 из 100: 1168 мс
Данные графика
Нагрузка, оп/сОбработано, оп/сМедиана, мс1 из 100, мс
20203.744
60595.238
1001007.178
1401387.579
18018018.7131
22022087219
26025379285
300263263395
3402748631168
Время ответа на стенде при росте нагрузки, стресс-проверка с 500 клиентами. На медленном процессоре VPS кривая сдвигается влево, и предел наступает примерно со 110 операций в секунду. Нагрузка личного сервера остается у левого края графика.
  • 0.9 мсмедиана при 100 операциях в секунду
  • 37 мс99% запросов быстрее
  • 117 мссамый долгий запрос за 5 минут
  • не растетвремя ответа за 5 минут работы

Что нагружает сервер

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

Запросы стоят в одной очереди, Prosody выполняет их по одному; пока идет загрузка хранилища, остальные запросы ждутЗапросы всех пользователей ждут своей очередивходчтениесохранениесообщениеProsodyсейчас выполняет:загрузка хранилища30-100 мс на 256 записейSQLSQLite
Все запросы сервера проходят через одну очередь, включая обычные сообщения и статусы. Поэтому время ответа зависит от того, насколько занят сервер, а не только от скорости одной операции.

Самая долгая операция - загрузка всего хранилища при подключении устройства. В тесте это 8% запросов, но половина времени работы сервера.

  • Загрузка хранилища
  • Сохранение записи
  • Чтение одной записи
Загрузка хранилища: 8% запросов и 50% времени сервера; сохранение: 20% запросов и 35% времени; чтение одной записи: 72% запросов и 15% времениДоля запросовДоля запросов: загрузка хранилища 8%8%Доля запросов: сохранение записи 20%20%Доля запросов: чтение одной записи 72%72%Доля времени сервераДоля времени сервера: загрузка хранилища 50%50%Доля времени сервера: сохранение записи 35%35%Доля времени сервера: чтение одной записи 15%15%
Данные графика
ОперацияДоля запросовДоля времени сервера
Загрузка хранилища8%50%
Сохранение записи20%35%
Чтение одной записи72%15%
Доля запросов и доля времени работы сервера по типам операций при нагрузке 100 операций в секунду. Время сервера оценено по времени выполнения каждой операции.

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

Время загрузки хранилища: 256 записей - 28-95 мс, 1000 записей - 0.11-0.37 с, 10 000 записей - 1.1-3.7 с10 мс100 мс1 с10 с256 записейпо умолчанию256 записей: 28 мс на быстром процессоре, 95 мс на медленном28-95 мс1000 записей1000 записей: 110 мс на быстром процессоре, 370 мс на медленном0.11-0.37 с10 000 записей10 000 записей: 1100 мс на быстром процессоре, 3700 мс на медленном1.1-3.7 с
Данные графика
ЗаписейБыстрый процессорМедленный процессор
25628 мс95 мс
1000110 мс370 мс
10 0001100 мс3700 мс
Время работы сервера на одну загрузку хранилища в зависимости от числа записей. Нижняя граница получена на процессоре стенда, верхняя соответствует медленному процессору VPS. Шкала логарифмическая: каждое деление в 10 раз больше предыдущего.

Хватит ли ресурсов VPS

Расчет для VPS с 1 ядром, 1 ГиБ памяти и каналом 200 Мбит/с. 100 пользователей InkVault, у каждого 2-3 устройства, 10-30 подключений и около 5 сохранений в сутки, до 256 записей.

  • Процессор: до 4 мин в сутки

    Сервер занят запросами InkVault от 30 секунд до 4 минут в сутки, меньше 0.3% времени. Второе ядро не нужно: Prosody работает в одном потоке.

  • Память: 250-400 МБ из 1 ГиБ

    Система 150-250 МБ, Prosody 30-60 МБ, кеш базы около 70 МБ. Свободно больше половины памяти.

  • Диск: база около 70 МБ

    2.8 КБ на запись вместе с индексами. Одно сохранение записывает на диск до 400 КБ: страницы базы и журнал транзакции. Для SSD при личном использовании это незначительный объем.

  • Сеть: около 4 с после перезапуска

    В обычной работе InkVault использует доли процента канала. После перезапуска сервера 300 устройств загружают около 105 МБ, это около 4 секунд работы канала 200 Мбит/с.

  • После перезапуска: 7-22 с

    За это время все 300 устройств снова загружают хранилища. Сервер выполняет загрузки по очереди, поэтому в эти секунды он отвечает медленнее обычного. Для 500 пользователей это уже от 35 секунд до 2 минут.

Сколько пользователей выдержит такой VPS

  • 1-100 пользователей

    Подходит с большим запасом.

  • 100-500 пользователей

    Вероятно, подходит. Проверьте на своем VPS: многое зависит от скорости его процессора.

  • Больше 500 пользователей

    Не проверялось. Нужна отдельная проверка на целевом сервере.

Что будет при перегрузке

В стресс-проверке сервер получал запросов в 10 раз больше, чем мог обработать.

  • 3000операций в секунду запрошено
  • 264операции в секунду обработано
  • 0ошибок и потерянных уведомлений
  • около 2 свремя ответа вместо миллисекунд

Сервер не завершился с ошибкой и не потерял данные: все запросы выполнены, все уведомления доставлены, ответы замедлились. После снижения нагрузки накопленная очередь обработана. Нагрузка личного сервера в сотни раз ниже этого уровня.

Что проверить на сервере

Настройки в файле prosody.cfg.lua. После изменения перезапустите Prosody.

Хранилище SQLite

Выводы отчета относятся к хранилищу SQLite. По умолчанию Prosody хранит данные в файлах (internal), этот вариант не проверялся. Переключение на SQLite:

storage = "sql"
sql = { driver = "SQLite3", database = "prosody.sqlite" }

Нужен пакет LuaDBI для SQLite, в Debian и Ubuntu это lua-dbi-sqlite3. Существующие данные переносятся утилитой prosody-migrator.

Лимит записей хранилища

Лимит задает pep_max_items. Значение по умолчанию 256 совпадает с лимитом хранилища InkVault по умолчанию. Если записей нужно больше, увеличьте лимит:

pep_max_items = 10000

Модуль PEP

Модуль pep входит в стандартную конфигурацию Prosody и обычно уже включен в modules_enabled. Проверка проводилась на Prosody 13.0.7.

Скорость диска

Скорость сохранения зависит от того, как быстро диск подтверждает запись. Проверка для опытных пользователей, файл создается рядом с базой Prosody и удаляется после теста:

  1. fio --name=fsync --filename=/var/lib/prosody/fio-test --rw=write --bs=4k --size=16m --fsync=1 --ioengine=sync
  2. rm /var/lib/prosody/fio-test

Если в блоке sync percentiles значение 99.00th не больше 3000 usec, диск подходит.

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

Если на сервере включено ограничение скорости подключений (модуль limits, например 10 КБ/с), первый импорт 256 записей займет около 50 секунд. Это работа ограничения, а не ошибка.

Резервная копия

Хранилище InkVault находится в базе Prosody. Копию можно сделать без остановки сервера:

  1. sqlite3 /var/lib/prosody/prosody.sqlite ".backup '/var/backups/prosody.sqlite'"

Путь к базе зависит от установки.

SQLite и PostgreSQL

Все выводы отчета получены на стенде с SQLite и 100 пользователями. Для небольшого сервера SQLite достаточно.

PostgreSQL стоит выбрать для сервера на сотни пользователей и больше. В контрольном замере на этом же стенде с PostgreSQL сервер записывал на диск в 4-5 раз меньше на одно сохранение. Время ответа и нагрузка на процессор были близки к SQLite: Prosody выполняет запросы к любой базе по одному в своем потоке, поэтому на число запросов в секунду выбор базы влияет мало.

Контрольный замер, 100 оп/сSQLitePostgreSQL
Запись на диск на одно сохранение394 КБ85 КБ
Процессор Prosody43%43%
Время ответа: медиана / 1 из 1006.3 / 77 мс7.3 / 159 мс

Проект InkVault