Skip to content

perf: cache parsed CRL as a compact revocation index - #231

Merged
malikzh merged 1 commit into
ncanode-kz:masterfrom
aidoskz:perf/xml-verify
Sep 16, 2026
Merged

malikzh merged 1 commit into
ncanode-kz:masterfrom
aidoskz:perf/xml-verify

Conversation

@aidoskz

@aidoskz aidoskz commented Sep 16, 2026

Copy link
Copy Markdown
Contributor

perf: cache parsed CRL as a compact revocation index

Что изменено

При POST /xml/verify с проверкой через CRL каждый запрос повторно разбирал все CRL-файлы. Основной GOST CRL размером около 19 МБ:

  • разбирался заново на каждом запросе;
  • занимал около 218 МБ в виде X509CRL;
  • создавал основную задержку при проверке подписи.

Теперь CrlService один раз строит для каждой версии CRL компактный CrlWrapper — индекс:

издатель → отсортированные серийные номера + дата и причина отзыва

Последующие проверки выполняются бинарным поиском без повторного разбора DER. Размер индекса — около 34 МБ вместо 218 МБ.

Инвалидация кэша

Версия файла определяется по:

  • каталогу;
  • имени;
  • времени изменения;
  • размеру.

При удалении или успешной перезаписи CRL индекс дополнительно инвалидируется явно. Индексы удалённых и устаревших файлов очищаются.

Совместимость

Поведение X509CRL сохранено:

  • поиск по издателю и серийному номеру;
  • поддержка certificateIssuer для indirect CRL;
  • сохранение даты и причины отзыва;
  • при повторяющейся паре «издатель + серийный номер» используется прежний путь через X509CRL, чтобы не менять результат в неоднозначном случае.

API и формат ответа не изменялись.

Результаты A/B-теста

Старая версия:
2.048, 1.912, 1.531, 1.500, 1.554 с

Новая версия:
2.980, 0.080, 0.066, 0.061, 0.077 с

Первый запрос новой версии строит индекс, поэтому занимает около 3 секунд. Последующие запросы используют готовый индекс.

Медиана прогретых запросов:

1.55 с → 0.071 с

Ускорение — примерно в 22 раза.

Обе версии вернули одинаковый результат: подпись валидна, сертификат не отозван.

Проверка

  • Полный ./gradlew test проходит.
  • Добавлены тесты на:
    • эквивалентность результатов X509CRL;
    • повторное использование индекса;
    • замену и удаление CRL;
    • явную инвалидизацию после перезаписи;
    • indirect CRL через certificateIssuer;
    • fallback при дублирующихся записях.

Изменение локализовано в CrlService и новом CrlWrapper; внешнее поведение сервиса не меняется.

До

Screenshot 2026-09-16 at 14 31 22

После

Screenshot 2026-09-16 at 14 31 46

@codecov

codecov Bot commented Sep 16, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

При проверке отзыва в `/xml/verify` каждый запрос заново разбирал все CRL-файлы. Основной GOST CRL в рабочем наборе имеет размер около 19 МБ, а разобранный `X509CRL` занимал около 218 МБ памяти.

`CrlService` теперь один раз строит для каждой версии файла компактный `CrlWrapper`: индекс «издатель → отсортированные серийные номера с датами и причинами отзыва». Индекс занимает около 34 МБ, а дальнейший поиск выполняется бинарно без повторного разбора DER.

Ключ кэша включает каталог, имя, время изменения и размер файла. При удалении или успешной перезаписи CRL индекс дополнительно инвалидируется явно. Индексы исчезнувших и старых версий файлов очищаются. Если CRL содержит повторяющуюся пару «издатель + серийный номер», используется прежний путь через `X509CRL`, чтобы не менять неоднозначную семантику результата.

Сохранена совместимость с `X509CRL`: поиск выполняется по издателю и серийному номеру, поддерживается `certificateIssuer` для косвенных CRL, возвращаются прежние дата и причина отзыва.

A/B-проверка выполнялась на Java 25 через настоящий `POST /xml/verify` с `revocationCheck=["CRL"]`, валидным сертификатом 2026–2027, одинаковым 19-МБ CRL-кэшем и отдельным Jaeger для каждой версии. Фоновые обращения к PKI были завершены до измерений; трассы фильтровались по серверной операции `http post /xml/verify` и содержали только XML-, certificate- и CRL-проверку.

Старая: 2.048, 1.912, 1.531, 1.500, 1.554 с
Новая:  2.980, 0.080, 0.066, 0.061, 0.077 с

первый запрос 2,980 с на однократное построение индекса
Медиана прогретых запросов сократилась примерно с 1,55 с до 0,071 с (около 22 раз). Обе версии вернули одинаковый результат проверки: подпись валидна, сертификат не отозван.
@malikzh
malikzh merged commit 305148a into ncanode-kz:master Sep 16, 2026
2 checks passed
@aidoskz
aidoskz deleted the perf/xml-verify branch September 16, 2026 12:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants