Воспроизвели проблему.
1. Процессы java -jar jsign-5.0.jar ..., действительно, падают с ошибкой о нехватке памяти. Судя по дампу ошибки, проблема вызвана нехваткой виртуальной памяти (RAM + swap). Нагуглил: значение по умолчанию для Initial Heap Size в jdk22 (и ранее как будто тоже) -- 1/64 от физической RAM (https://docs.oracle.com/en/java/javase/ … CBD9FAE781). Так что падение от нехватки памяти выглядит ожидаемым.
2. Наблюдаю: некоторые процессы упали не на запуске, а в процессе выполнения (опять же из-за исчерпания heap). Считаю справедливым предположение, что нативные библиотеки используют не тот Heap, который выделился на этапе запуска JVM (это heap, управляемый GC java-машины), а общий Heap процесса (отъедают виртуальной памяти). Соответственно, если по 1/64 физической RAM на java-процесс в виртуальной памяти зарезервировано, и возникают попытки еще аллоцировать виртуальной памяти, в какой-то момент одна из попыток аллокации завершится ошибкой. В самом неудачном случае это происходит в тот момент, когда токен выполняет неразрывную "цепочку" APDU-команд. Ошибка выделения памяти в процессе, как правило, является ситуацией, в которой ничего нельзя поделать, и поэтому грациозно завершить цепочку не удается.
3. Удалось параллельно запускать 200+ процессов java -jar jsign-5.0.jar ... при условии указания опции -Xms (Initial Heap Size), например:
java -Xms128m -jar ../jsign-5.0.jar --keystore ../eToken.cfg --alias "Rutoken Plugin" --storetype PKCS11 --storepass 12345678 --alg SHA-256 --tsaurl http://timestamp.globalsign.com/tsa/r6advanced1 --tsmode RFC3161 ${FILELIST}&
256 процессов по 128Mb -- это 32 Gb виртуальной памяти. Если RAM и swap меньше, стоит указывать меньшие значения (-Xms64m, -Xms32m) или же запускать меньше параллельных процессов java -jar jsign-5.0.jar ....
cy пишет:1. какие ограничения, на параллельное подписывание?
Со стороны нашего middleware ограничений на параллельное его использование нет.
Со стороны timestamp сервера можно огрести (воспроизвелось):
jsign: Couldn't sign File197_0.exe
net.jsign.timestamp.TimestampingException: Unable to complete the timestamping after 3 attempts
at net.jsign.timestamp.Timestamper.timestamp(Timestamper.java:122)
at net.jsign.AuthenticodeSigner.createSignedData(AuthenticodeSigner.java:393)
at net.jsign.AuthenticodeSigner.sign(AuthenticodeSigner.java:348)
at net.jsign.SignerHelper.sign(SignerHelper.java:394)
at net.jsign.JsignCLI.execute(JsignCLI.java:132)
at net.jsign.JsignCLI.main(JsignCLI.java:40)
Suppressed: java.io.IOException: Unable to complete the timestamping due to HTTP error: 429 - Too Many Requests
at net.jsign.timestamp.RFC3161Timestamper.timestamp(RFC3161Timestamper.java:69)
at net.jsign.timestamp.Timestamper.timestamp(Timestamper.java:127)
... 5 more
Suppressed: java.io.IOException: Unable to complete the timestamping due to HTTP error: 429 - Too Many Requests
at net.jsign.timestamp.RFC3161Timestamper.timestamp(RFC3161Timestamper.java:69)
at net.jsign.timestamp.Timestamper.timestamp(Timestamper.java:127)
... 5 more
Suppressed: java.io.IOException: Unable to complete the timestamping due to HTTP error: 429 - Too Many Requests
at net.jsign.timestamp.RFC3161Timestamper.timestamp(RFC3161Timestamper.java:69)
at net.jsign.timestamp.Timestamper.timestamp(Timestamper.java:127)
... 5 more
Try `java -jar jsign.jar --help' for more information.
Со стороны документации jsign есть намек на то, что много файлов стоит подписывать в одном вызове, а не в нескольких (https://ebourg.github.io/jsign/):
Implementation note: Jsign performs an extra call to the signing API to retrieve the current certificate chain before signing. When signing multiple files it's recommended to invoke Jsign only once with the list of files to avoid doubling the quota usage.
2. есть ли программный способ вернуть токен в рабочее состояние?, найденное на текущий момент решение: физическое отключение подключение.
Зависит от версии токена (скриншот окна "Информация о Рутокен" Панели управления Рутокен поможет уточнить).
3. есть ли какие-то варианты ускорения? при последовательном подписывании, подпись с сертификатом на рутокен, в 3-4 раза медленнее чем с сертификатом на SafeNet eToken.
Для некоторых моделей Рутокен ЭЦП RSA-подпись -- не самая быстрая операция. Чтобы понять, каких значений скорости подписи можно достичь, опять же нужно знать версию используемого токена. Сам токен параллельно выполнять операции подписи не умеет (это специфика любой смарт-карты), так что ускорение при параллельном вызове java -jar jsign-5.0.jar ... может быть связано только с тем, что в промежутках между обращением к токену за подписью jsign выполняет какие-то еще операции.
Текущие опыты паралелльной подписи показывают, что подпись 256 файлов в два параллельных запуска java -jar jsign-5.0.jar ... с батчами по 128 файлов показывает улучшение в скорости подписания в 1.5 -- 2 раза по сравнению с запуском java -jar jsign-5.0.jar ... с одним батчем из 256 файлов. Между вариантами "запустить 256 процессов подписи по одному файлу" и "запустить 2 процесса подписи по 128 файлов" разница в выполнении незначительна (от запуска к запуску плавает в пользу одного из вариантов).
Если есть возможность (не знаю, можно ли в случае выпуска сертификата у Globalsign этим управлять), стоит запрашивать сертификат подписи с ECDSA-ключами, а не RSA-ключами. ECDSA-подпись на Рутокен в подавляющем большинстве моделей быстрее подписи RSA4096.
Резюмирую про варианты ускорения:
1. Подписывать в несколько параллельных запусков jsign (двух может быть достаточно).
2. Подбор/приобретение модели токена с самой быстрой подписью (нужно знать, каким алгоритмом вы подписываете).
3. Использование ECDSA, а не RSA (если у Globalsign есть такая опция).