#java #spring-boot
#java #spring-boot
Вопрос:
Я работаю над проектом массового приема около 5 миллионов документов (размером от 200 КБ до 3 МБ каждый) на открытом воздухе с использованием REST API и Spring Boot. Мой fat jar будет работать так в среде разработки и тестирования без каких-либо проблем:
java -Xms64m -Xmx1G -jar MyApplication.jar --spring.config.location=file:///Users/home/config/jdbc.properties
Для среды Prod на сервере доступно 16 ГБ памяти. Как мне определить минимальный и максимальный размер кучи, учитывая размер каждого документа (200 КБ — 3 МБ) и их объем — 5 миллионов. Я имею в виду, каким должен быть «нормальный» минимальный максимальный размер кучи?
java -Xms?? -Xmx?? -jar MyApplication.jar --spring.config.location=file:///Users/home/config/jdbc.properties
Неопределенный вопрос: если я использую -Xms64m -Xmx1G
, означает ли это, что в пиковое время (когда jvm полностью разогнана) моя jvm не будет обрабатывать пакет документов размером более 1 ГБ в любой момент времени? Или, проще говоря, где этот 1 ГБ будет сожжен в этой ситуации? Или как JVM будет использовать этот 1 ГБ?
Любая соответствующая информация / ссылки в этом отношении будут высоко оценены.
Обновить:
Согласно комментариям Вишну, я нашел это (все еще пытаюсь понять): https://alvinalexander.com/blog/post/java/java-xmx-xms-memory-heap-size-control/https://www.baeldung.com/jvm-configure-stack-sizes
https://alvinalexander.com/java/java-stack-heap-definitions-memory /
А затем я попробовал пару параметров ss, как показано ниже:
java -Xss1k -jar MyApplication.jar
результаты в:
The Java thread stack size specified is too small. Specify at least 136k
Error: Could not create the Java Virtual Machine.
Error: A fatal exception has occurred. Program will exit.
И когда я попробую это:
java -Xss136k -jar MyApplication.jar
Я понимаю это:
Exception in thread "main" java.lang.StackOverflowError
at org.springframework.boot.loader.data.RandomAccessDataFile$FileAccess.access$400(RandomAccessDataFile.java:205)
at org.springframework.boot.loader.data.RandomAccessDataFile.read(RandomAccessDataFile.java:117)
at org.springframework.boot.loader.data.RandomAccessDataFile.read(RandomAccessDataFile.java:102)
at org.springframework.boot.loader.jar.CentralDirectoryFileHeader.load(CentralDirectoryFileHeader.java:82)
at org.springframework.boot.loader.jar.CentralDirectoryFileHeader.fromRandomAccessData(CentralDirectoryFileHeader.java:183)
at org.springframework.boot.loader.jar.JarFileEntries.getEntry(JarFileEntries.java:321)
at org.springframework.boot.loader.jar.JarFileEntries.getEntry(JarFileEntries.java:307)
at org.springframework.boot.loader.jar.JarFileEntries.doGetEntry(JarFileEntries.java:295)
at org.springframework.boot.loader.jar.JarFileEntries.getEntry(JarFileEntries.java:250)
at org.springframework.boot.loader.jar.JarFileEntries.containsEntry(JarFileEntries.java:206)
at org.springframework.boot.loader.jar.JarFile.containsEntry(JarFile.java:240)
at org.springframework.boot.loader.jar.JarURLConnection.get(JarURLConnection.java:263)
at org.springframework.boot.loader.jar.Handler.openConnection(Handler.java:83)
at java.base/java.net.URL.openConnection(URL.java:1074)
at java.base/jdk.internal.loader.URLClassPath$Loader.getResource(URLClassPath.java:643)
at java.base/jdk.internal.loader.URLClassPath.getResource(URLClassPath.java:314)
at java.base/java.net.URLClassLoader$1.run(URLClassLoader.java:455)
at java.base/java.net.URLClassLoader$1.run(URLClassLoader.java:452)
at java.base/java.security.AccessController.doPrivileged(Native Method)
at java.base/java.net.URLClassLoader.findClass(URLClassLoader.java:451)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:589)
at org.springframework.boot.loader.LaunchedURLClassLoader.loadClass(LaunchedURLClassLoader.java:151)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522)
at java.base/java.lang.ClassLoader.defineClass1(Native Method)
at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1017)
at java.base/java.security.SecureClassLoader.defineClass(SecureClassLoader.java:174)
at java.base/java.net.URLClassLoader.defineClass(URLClassLoader.java:550)
at java.base/java.net.URLClassLoader$1.run(URLClassLoader.java:458)
at java.base/java.net.URLClassLoader$1.run(URLClassLoader.java:452)
at java.base/java.security.AccessController.doPrivileged(Native Method)
at java.base/java.net.URLClassLoader.findClass(URLClassLoader.java:451)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:589)
at org.springframework.boot.loader.LaunchedURLClassLoader.loadClass(LaunchedURLClassLoader.java:151)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522)
at java.base/java.lang.ClassLoader.defineClass1(Native Method)
at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1017)
at java.base/java.security.SecureClassLoader.defineClass(SecureClassLoader.java:174)
at java.base/java.net.URLClassLoader.defineClass(URLClassLoader.java:550)
at java.base/java.net.URLClassLoader$1.run(URLClassLoader.java:458)
at java.base/java.net.URLClassLoader$1.run(URLClassLoader.java:452)
at java.base/java.security.AccessController.doPrivileged(Native Method)
at java.base/java.net.URLClassLoader.findClass(URLClassLoader.java:451)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:589)
at org.springframework.boot.loader.LaunchedURLClassLoader.loadClass(LaunchedURLClassLoader.java:151)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522)
at java.base/java.lang.Class.getDeclaredMethods0(Native Method)
at java.base/java.lang.Class.privateGetDeclaredMethods(Class.java:3166)
at java.base/java.lang.Class.getDeclaredMethod(Class.java:2473)
at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:47)
at org.springframework.boot.loader.Launcher.launch(Launcher.java:107)
at org.springframework.boot.loader.Launcher.launch(Launcher.java:58)
at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:88)
И это привело к вышеуказанной ошибке SOF от 136-240 тыс., но работало>
250 тыс.
Я знаю комментарии Вишну, и эта ошибка пытается указать на то, что происходит у меня в голове. Что это? Могу ли я получить простой (более простой или простой, будет лучше: P) ответ здесь, пожалуйста?
Опять же, я пытаюсь получить «нормальный» или «наилучший» возможный размер кучи для jar моего приложения.
Заранее большое спасибо за чтение такой пространной информации и вашу любезную помощь.
Комментарии:
1. Почему вы выбрали REST API, а не инструмент массового импорта, например?
2. Есть куча вещей, которые мы делаем на лету. Вот почему.
Ответ №1:
Сначала вам нужно решить, сколько потоков может выполняться параллельно, память стека потоков, выделенная с помощью параметра -Xss . Я думаю, что в версии 1.8 на 64 бит каждый поток имеет память по умолчанию в 1 МБ.
Попробуйте использовать параллельный GC в Java Opts, который поможет уменьшить кучу.
Комментарии:
1. Чувак.. вы действительно заставили меня почесать голову. Однако я добавил еще немного информации. Пожалуйста, взгляните и предложите с учетом вашего опыта. Спасибо.
Ответ №2:
значение -Xss, равное 1 мб, подходит для использования. при запуске приложения включите приведенную ниже команду, это поможет уменьшить размер кучи.
-XX: UseConcMarkSweepGC
Поскольку ваш хост имеет максимальный объем 16 ГБ, вы можете установить максимальный размер кучи на 4 ГБ, что все равно даст вам некоторое пространство для расширения во время пика, если потребуется.