10 декабря GlassFish v3 GA распространит мир. Как вы знаете, маркетинговым средством для этого выпуска будет Java EE 6 и тот факт, что GlassFish теперь является полноценной средой выполнения OSGi / контейнером !!! Оба являются инновационными технологиями, но они не спасут вашу жизнь, когда вы запустите GlassFish в производство, поэтому это руководство по выживанию :-). В конце концов, как только ваше приложение OSGi / EE 6 будет готово, вы все равно захотите иметь такую же великолепную производительность, как и у GlassFish v2. В этом блоге даются некоторые советы о том, как настроить GlassFish v3 и подготовить его к использованию.
Новая архитектура
В версии 3 роль Grizzly Web Framework значительно возросла по сравнению с версией 2. В версии 2 его роль заключалась в том, чтобы обслуживать HTTP-запросы перед WebContainer на основе Tomcat. В версии 3 Grizzly используется в качестве расширяемого микроядра, которое обрабатывает практически все операции в реальном времени, включая отправку HTTP-запросов к веб-расширениям Grizzly (контейнер статических ресурсов, контейнер сервлетов, контейнер JRuby, контейнер Python, контейнер Grails), административные расширения ( Поддержка Java WebStart, Admin CLI), расширение WebService (EJB) и расширения REST для мониторинга и управления.
Во время выполнения Grizzly сделает следующее
Если вы знакомы с внутренностями Гризли
Как видите, очень важно правильно настроить GlassFish, чтобы получить ожидаемую производительность для вашего приложения и GlassFish в целом.
Отладка GlassFish
Прежде чем переходить к деталям, я рекомендую всегда запускать GlassFish, используя следующее свойство, которое отображается в журнале сервера внутренней конфигурации Grizzly как для NIO, так и для Web Framework.
-Dcom.sun.grizzly.displayConfiguration=true or
network-config.network-listeners.network-listener.transport#display-configuration
Если вам нужно посмотреть, что Grizzly делает изнутри, например, полученный заголовок запроса, написанный ответ и т. Д., Вы можете включить snoop, чтобы вам не приходилось использовать Wireshark или ngrep.
-Dcom.sun.grizzly.enableSnoop=true or
network-config.network-listeners.network-listener.transport#enable-snoop
Обратите внимание, что если вы включите этот механизм, производительность значительно снизится, поэтому используйте его только для целей отладки.
Конфигурирование ВМ
Обеспечивает удаление в domain.xml следующих jvm-параметров:
-Xmx512 -client
и заменить его на
-server -XX:+AggressiveHeap -Xmx3500m -Xms3500m -Xss128k
-XX:+DisableExplicitGC
Для всего, кроме Solaris / SPARC, 3500м должно быть 1400м. На многопроцессорной машине добавьте:
-XX:ParallelGCThreads=N -XX:+UseParallelOldGC
где N — это количество процессоров, если <8 (так что в этом случае вы можете вообще не указывать), а N = количество процессоров / 2 в противном случае. На Ниагаре добавьте:
-XX:LargePageSizeInBytes=256m
Вы также можете установить 64-битную JVM и использовать
-XX:+UseCompressedOops
с JDK 6u16 и позже. 64-битная JVM с
-XX:+UseCompressedOops
позволит вам определять большие кучи Java, особенно полезно в Windows x64, где вы ограничены примерно
-Xmx1400m
макс кучи Java. Обратите внимание, что 64-битная JVM будет означать, что вам потребуется 64-битная операционная система. Это не проблема с Solaris. Многие люди, работающие под Linux, используют только 32-битную версию Linux. А для пользователей Windows им потребуется 64-битная Windows, чтобы использовать 64-битную Windows JVM. 64-битная JVM с -XX: + UseCompressedOops предоставит вам большие кучи Java с 32-битной производительностью. 64-разрядные JVM также предоставляют дополнительные регистры ЦП, которые будут доступны на платформах Intel / AMD.
Настройка пула потоков
Убедитесь, что вы взглянули на «что изменилось» начиная с v2 и как вы можете правильно настроить Grizzly в v3. Тот, кого вы должны заботиться, являются акцепторами
network-config.transports.transport.tcp#acceptor-threads
и количество рабочих потоков
network-config.thread-pools.http-threadpool
Рекомендуемое значение для acceptors-thread должно быть числом ядра / процессора, доступным на машине, на которой вы развернули. Я рекомендую вам всегда запускать тест производительности здравомыслия, используя значение по умолчанию (1) и количество ядер, просто чтобы убедиться. Далее необходимо определить количество потоков, необходимых для каждого порта HTTP. В GlassFish v2 конфигурация пула потоков распределялась между всеми портами HTTP, что было проблематично, поскольку некоторым портам / прослушивателям не требовалось иметь столько потоков, как порт 8080. Мы исправили это в v3, чтобы можно было настроить пул потоков для слушатель. Теперь идеальное значение для GlassFish v3 всегда должно быть максимум от 20 до 500, так как Grizzly использует не блокирующую стратегию ввода-вывода под капотом, и вам не нужно столько потоков, как если бы вы использовали блокирующий сервер ввода-вывода, такой как Кот. Здесь я не могу рекомендовать конкретный номер,это всегда основано на том, что делает ваше приложение. Например, если вы делаете много запросов к базе данных, вы можете захотеть иметь большее количество потоков на тот случай, если пул соединений / jdbc блокирует базу данных и «тратит» потоки, пока они не разблокируются. В GlassFish v2 мы видели множество приложений, которые зависали, потому что все рабочие потоки были заблокированы пулом соединений / jdbc. Хорошая вещь в v3 состоит в том, что те «потраченные впустую» потоки в конечном счете истечут, что было недоступно в v2. Значение по умолчанию составляет 5 минут, и это настраиваетсямы видели множество приложений, которые зависали, потому что все рабочие потоки были заблокированы пулом соединений / jdbc. Хорошая вещь в v3 состоит в том, что те «потраченные впустую» потоки в конечном счете истечут, что было недоступно в v2. Значение по умолчанию составляет 5 минут, и это настраиваетсямы видели множество приложений, которые зависали, потому что все рабочие потоки были заблокированы пулом соединений / jdbc. Хорошая вещь в v3 состоит в том, что те «потраченные впустую» потоки в конечном счете истечут, что было недоступно в v2. Значение по умолчанию составляет 5 минут, и это настраивается
configs.config.server-config.thread-pools.thread-pool.http-thread-pool.idle-thread-timeout-seconds
Стратегия ввода / вывода и конфигурация буфера
С точки зрения буферов, используемых Grizzly для чтения и записи операций ввода / вывода, значение по умолчанию (8192) должно быть правильным значением, но вы всегда можете поиграть с числом
network-config.protocols.protocol.http#header-buffer-length-byte
network-config.protocols.protocol.http#send-buffer-size
Если ваше приложение выполняет много операций ввода-вывода, таких как запись, вы также можете указать Grizzly использовать асинхронную стратегию
-Dcom.sun.grizzly.http.asyncwrite.enabled=true
При использовании этой стратегии вся запись ввода / вывода будет выполняться с использованием выделенного потока, освобождая рабочий поток, выполнивший операцию. Опять же, это может иметь большое значение. Также можно рассмотреть альтернативу, если вы заметили, что некоторые операции записи, по-видимому, занимают больше времени, чем ожидалось. Вы можете попытаться увеличить пул «процессора записи», увеличив число селекторов NIO:
-Dcom.sun.grizzly.maxSelectors=XXX
Убедитесь, что это число никогда не меньше числа рабочих потоков, поскольку это приведет к катастрофическим результатам производительности. Вы должны увеличить это число, если ваше приложение использует новый Async API Servlet 3.0, Grizzly Comet Framework или Atmosphere (
рекомендуется ). Когда используется асинхронный API, GlassFish потребуется больше «процессора записи», чем без
Пусть Гризли волшебным образом настроит себя
Теперь Grizzly поддерживает два «неподдерживаемых» свойства в GlassFish, которые всегда можно использовать для автоматической настройки GlassFish. Эти свойства могут иметь или не иметь значение, но вы всегда можете попробовать их с вашей конфигурацией и без нее. Первый из них настроит для вас буферы, акцепторные потоки и рабочие потоки:
-Dcom.sun.grizzly.autoConfigure=true
Второй скажет Гризли изменить стратегию потоков на лидера / последователя
-Dcom.sun.grizzly.useLeaderFollower=true
Это может или не может иметь значение, но стоит попробовать. Вы также можете заставить Grizzly завершить все свои операции ввода-вывода, используя специальный поток
com.sun.grizzly.finishIOUsingCurrentThread=false
Это может иметь значение, если ваше приложение выполняет небольшое количество операций ввода-вывода под нагрузкой.
Кэшируйте ваши статические ресурсы!
Теперь по умолчанию кэширование файлов HTTP Grizzly отключено. Чтобы получить приличную производительность статических ресурсов, я настоятельно рекомендую вам включить ее (это имеет огромное значение)
network-config.protocols.protocol.http.file-cache#enabled
Только для JDK 7
Теперь, если вы планируете использовать JDK 7, я рекомендую вам переключить стратегию Grizzly ByteBuffer и выделить память вне кучи виртуальной машины с помощью прямого байтового буфера
-Dcom.sun.grizzly.useDirectByteBuffer=true
Только в JDK 7, как и в JDK 6, использование выделенного буфера динамической памяти дает лучшую производительность, чем собственный. Теперь, если вы понимаете, что GlassFish выделяет слишком много собственной памяти, просто добавьте
-Dcom.sun.grizzly.useByteBufferView=false
Это должно уменьшить использование собственной памяти.
WAP и медленная сеть
Если ваше приложение будет использоваться телефоном по протоколу WP или из медленной сети, вы можете настроить увеличение времени ожидания по умолчанию, когда Grizzly выполняет операции ввода-вывода:
-Dcom.sun.grizzly.readTimeout or
network-config.network-listeners.network-listener.transport#read-timeout
для чтения и
com.sun.grizzly.writeTimeout or
network-config.network-listeners.network-listener.transport#write-timeout
для записи. Значение по умолчанию для обоих составляет 30 секунд. Это означает, что Grizzly будет ждать 30 секунд, пока не поступят входящие байты от клиента при обработке запроса, и 30 секунд, когда записывает байты обратно клиенту, прежде чем закрывать соединение. В медленной сети 30 секунд для выполнения операций чтения может быть недостаточно, и некоторые клиенты могут не иметь возможности выполнять запросы. Но будьте особенно осторожны при изменении значения по умолчанию, так как если оно слишком велико, рабочий поток будет заблокирован в ожидании байтов, и у вас может закончиться нехватка рабочих потоков. Заметьте, что злонамеренный клиент может вызвать отказ в обслуживании, отправляя байты очень медленно. Может потребоваться 5 минут (см. Конфигурацию времени ожидания потока выше), прежде чем Grizzly восстановит рабочие потоки. Если вы испытываете время записи, e.Если удаленный клиент не читает байты, которые отправляет сервер, вы также можете увеличить значение, но вместо этого я бы порекомендовал вам включить описанную выше стратегию асинхронного ввода-вывода, чтобы избежать блокировки рабочего потока.
Настройка механизма поддержки активности a-la-Tomcat
Стратегия, которую Grizzly использует для поддержания открытого удаленного соединения, заключается в создании пула файлового дескриптора, связанного с соединением, и при выполнении операций ввода-вывода получить описание файла из пула и создать поток для выполнения операции ввода-вывода. Как видите, Grizzly не блокирует поток, ожидающий операции ввода-вывода (следующий запрос клиента). Стратегия Tomcat отличается, например, когда запросы Tomcat обрабатывают, выделенный поток будет блокироваться между клиентскими запросами в течение максимум 30 секунд. Это дает действительно хорошую производительность, но не очень хорошо масштабируется, так как вам нужно один поток на соединение. Но если в вашей ОС доступно множество потоков, вы всегда можете настроить Grizzly для использования аналогичной стратегии:
-Dcom.sun.grizzly.keepAliveLockingThread=true
Tomcat также имеет алгоритм, который сокращает время ожидания, которое Поток может заблокировать в ожидании новых операций ввода / вывода, поэтому потоки под нагрузкой не блокируются слишком долго, передавая изменения другим запросам для выполнения. Вы можете включить аналогичный алгоритм с Grizzly:
-Dcom.sun.grizzly.useKeepAliveAlgorithm=true
В зависимости от того, что делает ваше приложение, вы можете получить хорошее улучшение производительности, включив эти свойства.
Задавать вопросы!
Как я описал здесь , я больше не буду работать над GlassFish, когда вы будете читать этот блог, поэтому обязательно задавайте свои вопросы, используя список рассылки GlassFish ( [email protected] ), или вы всегда можете подписаться на меня в Twitter! и задать вопрос там!