 | Уровень сложности: простой Пунит Шах, программист, IBM Сумит Чаула, сертифицированный IT-архитектор IBM и руководитель технической группы, Java Enablement, IBM
29.06.2009 Неудачный выбор размера "кучи" для 32-битовых Java-приложений на AIX может привести к конфликтной ситуации, когда два и более компонента процесса одновременно пытаются использовать один сегмент памяти. В этой статье на примере хорошо известных приложений показано, как распознать подобную ситуацию, а также даются рекомендации по изменениям, которые надо внести в конфигурацию, чтобы избежать таких конфликтов.
Введение
Одной из главных причин успеха Java на корпоративном рынке является возможность легкой интеграции этого языка программирования с многочисленными технологиями. Легкость конфигурирования Java для работы с многочисленными базами данных и приложениями middleware/backend часто скрывает от конечного пользователя детали функционирования аппаратного обеспечения и используемой ОС. Документация по программному обеспечению содержит описание некоторых ограничений, и если следовать всем указаниям по установке, изложенным в этой документации, то приложение будет нормально работать.
Однако для инженеров по интеграции, системных архитекторов, инженеров по производительности и сайзингу, администраторов использование такого подхода "черного ящика" будет непродуктивным. Важно не только видеть "общую картину", но и понимать, почему при настройке, отладке или масштабировании "кучи" имеют место те или иные, характерные для платформы, ограничения. Если технический консультант советует вам внести изменения в конфигурацию, и вы хотите узнать, зачем нужны эти изменения, эта статья поможет вам найти ответ на этот вопрос. Прежде чем продолжить изучений этой статьи, желательно прочитать статью Getting more memory in AIX for your Java applications.
В данной ситуации изучаются изменения в конфигурации, рекомендуемые при использовании Java-"куч" размером больше одного 1 ГБ для приложения, написанного на 32-битовой версии Java и работающего на AIX. При использовании таких больших "куч" есть шанс, что JVM (Java Virtual Machine - виртуальная Java-машина) и другое работающее приложение попытаются задействовать одно и тоже адресное пространство. Подобная ситуация называется "конфликт сегментов" ("segment collision"). В качестве реального примера ниже будут рассмотрены различные проблемы, которые могут возникнуть из-за несовместимости конфигураций в ситуации, когда Java-приложение подсоединяется к локальному серверу DB2.
Важно понимать, что такая ситуация не связана со спецификой DB2. В другом примере подобный конфликт сегментов возникает у систем Websphere MQ, которые могут попасть в проблему конфликта сегментов. Мы объясним, как избежать такой ситуации. Главное - это понять причины возникновения этой проблемы и найти возможные решения. Как только основные концепции будут освоены, их можно будет легко применить к любому другому промежуточному ПО или базе данных.
Сегменты в 32-битовом AIX
Термины "32-битовая Java" или "32-битовая AIX" используются для обозначения 32-битовой модели адресации, т.е. использования указателей размером в 32 бита. Адресное пространство в таком случае равняется 4 ГБ; операционная система AIX делит это адресное пространство на 16 сегментов по 256 MБ в каждом. Эти сегменты пронумерованы от 0 до F (в шестнадцатеричной системе счисления). Преимущество нумерации сегмента памяти с нуля состоит в том, что легко высчитать сегмент для конкретного адреса. Все, что необходимо, это взглянуть на первую цифру 8-цифрового шестнадцатеричного адреса (так как 256 MБ в шестнадцатеричной системе счисления равняется 0x100000000). Например, адрес 0x65745640 принадлежит шестому сегменту.
В разделе Ресурсы в конце этой статьи даны ссылки на несколько статей и другие источники информации о 32-битовой модели памяти в AIX и о том, как Java использует эту модель. Как указывается в статье Getting more memory in AIX for your Java applications, при попытке использовать более 1 ГБ "кучи" для Java в 32-битовом AIX Java переключается на механизм распределения памяти, который использует mmap() вместо malloc(). Используя svmon, можно определить, какие сегменты используются для Java-"кучи". При помощи MAXDATA можно точно контролировать, какие сегменты используются в JVM. Заметим, что все сегменты, необходимые для Java-"кучи", должны быть непрерывными. Таким образом, если для Java-"кучи" необходимо пять сегментов, нельзя запросить сегменты 5,6,7, 9 и A; следует запрашивать либо 5-9, либо 6-A.
Почему способ использования адресного пространства JVM должен повлиять на другое приложение, например, DB2? Ответ прост и понятен: он не может влиять, потому что адресное пространство процесса независимо, и все, что делается в адресном пространстве JVM, абсолютно невидимо для адресного пространства любого другого процесса (исключая совместно используемую память, как будет показано далее). Конфликт сегментов может возникнуть только между компонентами, которые выполняются в рамках одного процесса ("внутрипроцессные", "in-process"). Важно знать, что означает термин "внутрипроцессные", поскольку он является ключевым в рассуждениях оставшейся части статьи.
Когда JVM загружает объект общего использования (во многих операционных системах известный также как библиотека), он загружается "in-process" ("внутрипроцессно", "inproc"). Термин "inproc" просто означает, что библиотека отображена в адресном пространстве JVM. Данный факт является важным первым шагом к использованию любого кода/данных в объекте общего доступа; даже JVM состоит из небольшой "пусковой системы" и множества объектов коллективного доступа или библиотек. В ходе дискуссии в этой статье будут попеременно использоваться термины "библиотека" и "объект общего доступа".
Программный код библиотеки обычно находится в сегменте D, а его данные в - сегменте F. Далее показано примерное содержание обычного файла Javacore:
2XHLIBNAME /usr/WebSphere/AppServer/java/jre/bin/libjitc.a
3XHLIBSIZE filesize : 2735441
3XHLIBSTART text start : 0xD1717000
3XHLIBLDSIZE text size : 0x234EAC
3XHLIBLDORG data start : 0x36E8F708
3XHLIBLDDATASZ data size : 0xF6C4
2XHLIBNAME /usr/lib/libc.a
3XHLIBSIZE filesize : 6609447
3XHLIBSTART text start : 0xD01CA95C
3XHLIBLDSIZE text size : 0x1DA
3XHLIBLDORG data start : 0x36E8E95C
3XHLIBLDDATASZ data size : 0x0
------ Lines omitted -------
2XHLIBNAME /usr/lib/libC.a
3XHLIBSIZE filesize : 4303699
3XHLIBSTART text start : 0xD0A85C40
3XHLIBLDSIZE text size : 0x678D
3XHLIBLDORG data start : 0xF02F6640
3XHLIBLDDATASZ data size : 0xCB8
|
"text", или код библиотеки, был загружен в сегмент D (первая цифра шестнадцатеричного адреса, например, 0xD1717000 для libjitc.a). "Данные" ("data") распределяются начиная с сегмента 3 (поскольку используется malloc(), который использует сегмент 3 для модели больших данных) или сегмента F (который предназначен для данных общедоступных библиотек), как показано во второй части libc.a.
Большинство баз данных и промежуточного ПО предоставляют inproc-версию своих клиентов, в которой библиотека загружается в адресное пространство JVM. Библиотека присоединяется к общей памяти и использует ее для дальнейшего взаимодействия с сервером. Из термина "общая память" следует, что сервер должен работать на том же самом компьютере; данный подход является обычно оптимальным способом подсоединиться к локальному серверу, поскольку коммуникации сокращаются до локальных процедур чтения и записи. Однако это означает также и то, что теперь в процессе JVM возможно наличие нескольких претендентов на одно адресное пространство. Данная ситуация не является проблемой в языках программирования, подобных С, в которых за управление памятью (и адресным пространством) отвечает сам программист. Но в Java адресное пространство не является прозрачным настолько, насколько этого хотелось бы программисту. Когда любая загруженная библиотека пытается распределять память или манипулировать адресным пространством, работа JVM зависит от операционной системы, которая устанавливает границы между адресным пространством, управляемым JVM, и адресным пространством других процессов. И в этот момент может возникнуть "конфликт сегментов".
Так что же может вызвать конфликт сегментов? Есть по крайней мере две причины, зависящие от того, умышленный это конфликт сегментов или нет.
Первую возможную причину конфликта сегментов легко исправить, но иногда очень трудно локализовать. Это ошибка в программном коде одной или несколько библиотек, связанная с повторным использованием свободного указателя (freed pointer) или переписыванием части памяти, которая им не принадлежит (например, попытка записи за пределы массива). Это может привести к периодическому "зависанию" программы, смерти потоков или более серьезным сбоям; достаточно трудно идентифицировать эти конфликты, только если они не вызывают SIGILL (некорректную инструкцию выполнения, причиной которой является неправильный код указателей), SIGSEGV (ошибка сегментации, связанная с неправильными указателями на данные) или другие подобные ошибки.
Конфликт сегментов может возникнуть и в ситуации, когда библиотеки должны использовать определенные участки адресного пространства в качестве памяти общего доступа. Поэтому, если используемое промежуточное ПО требует, чтобы для него зарезервировали сегмент 9, то размер "кучи" для Java-процесса не может превышать 1,5 ГБ. О том, как было получено это значение, можно узнать в статье Getting more memory in AIX for your Java applications. Более распространенной ситуацией является несовпадение конфигураций, при котором библиотека использует сегмент 9, поскольку никто не изменил настройки по умолчанию. Результат возникновения подобного конфликта сегментов гораздо более очевиден: обычно это сообщение об ошибке или диагностический программный код. Решение заключается в поиске сообщения об ошибке в соответствующей документации и выполнении указанных в ней действий.
Проблемы, возникающие из-за дефектов программного кода, должны быть отлажены, а сам код исправлен. Мы не будем рассматривать такие проблемы, а сосредоточимся на проблемах, возникающих из-за несовпадения конфигураций, и объяснении сути предлагаемых решений.
Реальное приложение: DB2
Этот раздел содержит практические упражнения. Настоятельно рекомендуется попрактиковаться в применении различных команд и методик, описанных в этой статье. Для иллюстрации концепций этой статьи используется база данных DB2 и клиентское JDBC-приложение. Похожие решения и обходные пути применительно к Websphere MQ рассмотрены в следующем разделе. Применить изученные действия к этому или любому другому ПО не должно составить труда.
Пример приложения
Приложение "ShowDB", используемое далее, является простым приложением JDBC, псевдокод которого приведен на рисунке 1. Стоит заметить, что это приложение служит примером того, как не следует писать JDBC-приложения. В нем намеренно игнорируется пулинг и другие приемы правильного программирования, чтобы получить желаемое поведение.
Рисунок 1. Псевдокод приложения "ShowDB"
Parameters: tableName and threadCount
do the following code threadCount times
create a new thread that will
open a JDBC connection to the DB2 server
query the tableName for its contents, printing the data retrieved
sleep for a few seconds
close the JDBC connection
exit thread
done
|
Приложение принимает два аргумента командной строки: имя таблицы и число потоков, которые должны быть запущены. Следующая команда
создаст 50 потоков, которые одновременно подсоединятся к DB2-серверу, запросят таблицу "STAFF" и выведут на печать ее содержимое. Информация о типе драйвера, имени DB2-сервера и т.д. считываются из входного файла. Для переключения с одного типа JDBC-драйвера на другой (например, со второго типа драйверов на четвертый) необходимо переключить входные файлы.
Для достижения желаемого поведения было применено два архитектурных решения. Первое решение: каждый поток заставляют создать новое соединение с базой данных и держать его открытым до тех пор, пока все записи не будут распечатаны. Второе решение: добавляется задержка перед закрытием JDBC-соединений, поэтому приложение еще несколько секунд поддерживает рабочее соединение. Это дает достаточно времени для мониторинга адресного пространства процесса при помощи svmon.
Трассировки, приведенные ниже, были получены на системе AIX 5.1 с сервером DB2 (DB2 Enterprise Server Edition v8.1, DB2 Server). Для создания простой тестовой базы данных использовалась программа db2sampl, доступная во всех DB2-системах. Для JDBC-приложения использовалась Java 1.3.1 (32-bit) версии ca131-20030630a с классом драйвера "COM.ibm.db2.jdbc.app.DB2Driver", который является драйвером второго типа или "app"-драйвером (строка драйвера JDBC описана в статье "Application Development Guide: Programming Client Applications" в разделе "Application Development" на сайте технической поддержки DB2).
Непонятная проблема
Рассматривая описанную выше конфигурацию, выясним, сколько JDBC-соединений можно установить одновременно. Начнем с пяти, для чего надо ввести следующую команду:
Но вместо создания пяти потоков будут выведены три сообщения об ошибке:
SQLException:
SQLState: 08001
Message: [IBM][CLI Driver] SQL1224N A database agent could not be started to
service a request, or was terminated as a result of a database system shutdown or
a force command. SQLSTATE=55032
Vendor: -1224 |
Из пяти попыток создания потоков три попытки соединения с DB2-сервером были неудачными. Два других потока установили соединение с базой данных и правильно распечатали данные, поэтому проблема не может заключаться в настройке JDBC или базы данных. Так что же было неправильно?
Дальнейшее исследование
На данном этапе, конечно, можно посмотреть описание ошибки SQL1224N. Но сделаем это немного позже. Так как известно, что суть проблемы заключается в использовании адресного пространства, то используем svmon для получения информации о состоянии адресного пространства JVM. Результаты работы svmon для JVM (процесс 69938 в трассировке ниже) на используемом компьютере следующие:
$ svmon -P 68938 -m
-------------------------------------------------------------------------------
Pid Command Inuse Pin Pgsp Virtual 64-bit Mthrd LPage
68938 java 23652 1833 778 22118 N Y N
Vsid Esid Type Description LPage Inuse Pin Pgsp Virtual
15015 d work shared library text - 12346 0 3 14162
0 0 work kernel seg - 4380 1822 775 4380
f2ad 3 work shmat/mmap - 3380 0 0 3380
f1ed f work shared library data - 108 0 0 108
1c59c 2 work process private - 49 2 0 49
10590 1 pers code,/dev/hd2:331803 - 8 0 - -
1c11e b work shmat/mmap - 2 0 0 2
72a5 e work shared text ovfl - 2 0 0 2
15177 c work shmat/mmap - 1 0 0 1
c2ce 7 work shmat/mmap - 0 0 0 0
1f27d 6 work shmat/mmap - 0 0 0 0
c24e 4 work shmat/mmap - 0 0 0 0
1c27e 9 work shmat/mmap - 0 0 0 0
17275 8 work shmat/mmap - 0 0 0 0
d22f 5 work shmat/mmap - 0 0 0 0
c40e a work shmat/mmap - 0 0 0 0
|
Стоит отметить, что на самом деле svmon выдает больше информации, , чем в предыдущем примере. Но для краткости в выводе svmon опущены строки, для которых "Esid" установлено в "-" (если только они не потребуются по ходу обсуждения).
Из статьи Getting more memory in AIX for your Java applications известно, что если используется размер "кучи" меньше чем 1 ГБ то JVM не использует для распределения "кучи" метод mmap(). Вместо этого JVM использует malloc(). MAXDATA установлено в 8. Поэтому в качестве "кучи" для JVM будут использоваться сегменты с номера 3 по A. Однако значения "Inuse" сегментов B и C установлены в 2 и 1 соответственно. Поскольку "Inuse"-значения находятся в блоках по 4 KБ, то в JVM используются 8 KБ из сегмента B и 4 KБ из сегмента C. Также используется сегмент E. Но JVM не использует эти сегменты. Тогда кто же их использует? Может быть, драйвер DB2 App?
Чтобы проверить эту гипотезу, необходимо запустить приложение с только одним подключением к базе данных. Выводы svmon будут следующими:
$ svmon -P 68858 -m
-------------------------------------------------------------------------------
Pid Command Inuse Pin Pgsp Virtual 64-bit Mthrd LPage
68858 java 23214 1829 778 21680 N Y N
Vsid Esid Type Description LPage Inuse Pin Pgsp Virtual
15015 d work shared library text - 12346 0 3 14162
0 0 work kernel seg - 4380 1822 775 4380
71c5 3 work shmat/mmap - 2960 0 0 2960
1c59c f work shared library data - 108 0 0 108
1c27e 2 work process private - 49 2 0 49
10590 1 pers code,/dev/hd2:331803 - 8 0 - -
1c11e b work shmat/mmap - 2 0 0 2
15177 c work shmat/mmap - 1 0 0 1
172d5 9 work shmat/mmap - 0 0 0 0
1f27d 4 work shmat/mmap - 0 0 0 0
d22f 8 work shmat/mmap - 0 0 0 0
c40e 6 work shmat/mmap - 0 0 0 0
c24e a work shmat/mmap - 0 0 0 0
7245 7 work shmat/mmap - 0 0 0 0
17275 5 work shmat/mmap - 0 0 0 0 |
При одном работающем подключении видно, что сегменты b и c все еще используются, а сегмент e более не используется. Ясно, что при одном работающем потоке прекращается использование (по крайней мере) одного сегмента. Если для этих соединений выделить больше сегментов, можно ли поддерживать больше соединений? Понятно, что небольшое тестовое приложение не использует даже один сегмент "кучи", поэтому не имеет смысла держать зарезервированными для него восемь сегментов. Используя знания, полученные из Getting more memory in AIX for your Java applications, можно изменить модель памяти JVM на модель по умолчанию (установите значение MAXDATA в 0) и перезапустить программу:
LDR_CNTRL=MAXDATA=0x00000000 java ShowDB Staff
|
Она работает. Фактически, если взглянуть на вывод svmon, можно заметить, что все еще не используются сегменты с 8 по b и e:
$ svmon -P 44424 -m
-------------------------------------------------------------------------------
Pid Command Inuse Pin Pgsp Virtual 64-bit Mthrd LPage
44424 java 23654 1807 778 22119 N Y N
Vsid Esid Type Description LPage Inuse Pin Pgsp Virtual
15015 d work shared library text - 12347 0 3 14162
0 0 work kernel seg - 4380 1796 775 4380
11f50 2 work process private - 3424 2 0 3424
1817a f work shared library data - 108 0 0 108
10590 1 pers code,/dev/hd2:331803 - 8 0 - -
51e7 7 work shmat/mmap - 2 0 0 2
151d7 4 work shmat/mmap - 2 0 0 2
21e0 6 work shmat/mmap - 2 0 0 2
1a218 5 work shmat/mmap - 2 0 0 2
15197 3 work shmat/mmap - 2 0 0 2
e50e c work shmat/mmap - 1 0 0 1
|
Поэтому фактически можно установить 10 одновременных соединений. Попробуйте сделать это и увидите, что при MAXDATA=0 работают 10 соединений.
Из трассировок svmon видно, что для каждого JDBC-соединения используется один сегмент. Значение "Inuse" указывает, что используется только 8 KБ из 256 MБ. Один дополнительный сегмент, содержащий Inuse = 1, предназначен для трассировки DB2, и присутствует независимо от числа подключений JDBC, поэтому может быть проигнорирован.
Этот небольшой эксперимент позволил перейти от двух соединений к 10. Несмотря на то, что это несомненный прогресс, существуют две проблемы, которые делают данное решение неприемлемым. Первая проблема: данное решение подразумевает, что используется очень маленькая "куча" Java, а статья Getting more memory in AIX for your Java applications объясняет, почему не стоит устанавливать MAXDATA=0. Вторая проблема: 10 одновременных соединений - это слишком мало. Поэтому пришло время сделать то, что нужно было сделать в первую очередь: искать информацию о полученной ошибке.
Проблема
Если вернуться назад, сообщение о сбое содержит код ошибки, возникающей, когда нельзя установить соединение с DB2-сервером. Код ошибки был SQL1224N. Как следует из справочника по сообщениям (Message Reference), который находится на сайте технической поддержки DB2, существует несколько возможных причин возникновения этой ошибки. Наиболее вероятная причина:
The application is using multiple contexts with local protocol. In this case the number
of connections is limited by the number of shared memory segments to which a single
process can be attached. For example, on AIX, the limit is ten shared memory segments
per process.
Приложение использует несколько контекстов с локальным протоколом.
В этом случае число подключений ограничено числом сегментов распределенной памяти,
к которым может быть подключен отдельный процесс.
Например, для AIX предел - 10 сегментов распределенной памяти на процесс.
|
Это как раз то, что наблюдалось при экспериментах с MAXDATA. Продолжаем читать:
If the application is using multiple contexts with local protocol, then either
reduce the number of connections in the application, or switch to another protocol
(for example, TCP/IP). For users on AIX version 4.2.1 or newer, the environment
variable EXTSHM can be set to ON to increase the number of shared memory
segments to which a single process can be attached.
Если приложение использует несколько контекстов в локальном протоколе,
то необходимо либо снизить число подключений в приложении,
либо переключиться на другой протокол, например, TCP/IP.
Для пользователей AIX 4.2.1 и более новых версий переменная окружения EXTSHM
может быть установлена в ON, чтобы увеличить число сегментов распределенной памяти,
к которым может быть подключен отдельный процесс.
|
Исключая очевидное решение, заключающееся в сокращении числа подключений, доступны два варианта действий: использовать другой протокол или использовать EXTSHM. Исследуем оба решения.
Использование другого протокола
Простейшее решение проблемы - использовать драйвер четвертого типа. С драйвером четвертого типа совместная память для любых локальных подключений не используется. Чтобы удостовериться, что не используются сегменты коллективного доступа, можно распределить "кучу" размером 2560 MБ. Это означает, что Java задействует все 10 сегментов, ничего не оставляя для JDBC-драйвера. Данное действие было бы невозможным с драйвером второго типа, но не для драйвера четвертого типа.
Драйверы четвертого типа доступны только для DB2-версии 8 и более новых. А что делать, если используется седьмая DB2-версия? Можно сконфигурировать драйвер второго типа для применения сетевого протокола TCP/IP путем каталогизации базы данных DB2 для использования внутрисетевого IP-адреса. Более подробная информация об этом содержится в разделе Command Reference сайта технической поддержки DB2.
Применение EXTSHM=ON
В качестве альтернативы можно продолжать использовать сегменты общей памяти и одновременно поддерживать много соединений. Для этого нужно использовать EXTSHM=ON.
Применение EXTSHM описано в документации AIX. Одна из статей, описывающих EXTSHM , находится по этой ссылке; с нее и можно начать изучение данного вопроса. Как было сказано ранее, значение "Inuse" для каждого из сегментов, используемых DB2, равнялось 2; это означает что необходимо только 8 KБ адресного пространства. Но каждое соединение все еще занимает весь сегмент размером 256 MБ, поэтому требуется способ распределить несколько соединений по одному сегменту, и EXTSHM предназначен как раз для этой цели.
Чтобы увидеть результат этого изменения, необходимо задать переменную окружения для клиента и сервера. Порядок выполнения этой операции описан в Application Development Guide: Programming Client Applications в разделе "Application Development" на сайте технической поддержки DB2. После того как в базу данных будут внесены необходимые изменения, можно проверить работоспособность приложения:
$ svmon -P 46014 -m
-------------------------------------------------------------------------------
Pid Command Inuse Pin Pgsp Virtual 64-bit Mthrd LPage
46014 java 24227 1812 778 22662 N Y N
Vsid Esid Type Description LPage Inuse Pin Pgsp Virtual
15015 d work shared library text - 12438 0 3 14225
0 0 work kernel seg - 4380 1796 775 4380
21e0 3 work shmat/mmap - 3856 0 0 3856
1d4fd f work shared library data - 108 0 0 108
17517 2 work process private - 48 2 0 48
10590 1 pers code,/dev/hd2:331803 - 8 0 - -
18518 - work - 1 0 0 1
b62b 9 work shmat/mmap - 0 0 0 0
184d8 5 work shmat/mmap - 0 0 0 0
1a1f8 c mmap mapped to sid 18518 - 0 0 - -
828a 7 work shmat/mmap - 0 0 0 0
6506 8 work shmat/mmap - 0 0 0 0
1b2b9 4 work shmat/mmap - 0 0 0 0
22c0 6 work shmat/mmap - 0 0 0 0
1f27d a work shmat/mmap - 0 0 0 0 |
В примере выше было установлено 10 одновременных подключений к DB2-серверу. Так как сегмент С отображен в sid 18518, sid 18518 был показан в трассировке выше. Но нужная информация из представленного вывода svmon заключается в том, что число сегментов, используемых на стороне клиента, значительно снизилось.
EXTSHM не является рекомендованным решением, поскольку из-за использования данной переменной некоторые приложения могут "упасть", и, кроме того, еще не устранено использование совместной памяти в приложении. Об этой опции было рассказано только ради общего представления о проблеме. Кроме того, следует помнить, что вывод svmon показывает зависящую от реализации информацию, которая может целиком измениться в будущем. Документация DB2 является основным руководством, и рассмотренный выше пример должен использоваться только для усвоения принципов (или для изучения методик поиска ответа на вопрос, как приложения используют совместную память).
Websphere MQ
Теперь должно быть понятно, что проблема распределения сегментов возникает из-за сегментированной архитектуры AIX и способа, которым JVM распределяет "кучу" размером более 1 ГБ. В качестве другого примера будет рассмотрено приложение, использующее MQSeries. Данное приложение может столкнуться с рассмотренной ранее проблемой.
Когда приложение устанавливает соединение-привязку (не клиентское) к менеджеру запросов, MQSeries v5.2 (и предыдущие версии) для присоединения к общей памяти и завершения соединения используют сегмент 8. Если сегмент 8 недоступен, соединение будет оборвано с кодом ошибки MQRC_Q_MGR_NOT_AVAILABLE (2059), а приложение создаст FDC-файл в каталоге /var/mqm/errors, содержащий сообщения "Probe Id of XY341019" и "Component of RetryConnectToSharedSubpool".
Настойчивость при обращении к сегменту 8 означает, что Java не может выйти за пределы пяти сегментов или 1280 MБ, отводимых под "кучу". Чтобы соответствовать ситуациям, в которых Java-приложениям нужна "куча" больших размеров, MQSeries 5.2 вводит новый параметр для элемента QueueManager в файле /var/mqm/mqs.ini. Параметр IPCCBaseAddress присваивает имя дополнительному сегменту общей памяти MQSeries (любому из 4, 5, 8, 9, 10, 11 или 12). Различные менеджеры запросов могут использовать различные значения:
QueueManager:
Name=HOBBES
Prefix=/var/mqm
Directory=HOBBES
IPCCBaseAddress=11 |
Данное действие все еще требует подсчета размера "кучи" Java и значений MAXDATA. Более простая альтернатива заключается в использовании возможностей клиента по передаче данных. Между прочим, при использовании EXTSHM, MQ 5.3 убирает зависимость от общей памяти. Подробная информация о MQ Series приведена в руководствах.
Заключение
При выделении более 1 ГБ памяти для Java-"кучи" в AIX необходимо брать в свои руки процесс размещения "кучи" в адресном пространстве JVM. Во многих современных приложениях Java является только одной из многих используемых технологий middleware. В этой статье была рассмотрена ситуация, когда нужно всего лишь изменить настройки двух известных приложений, чтобы у этих приложений не возникали конфликты из-за изменений адресного пространства JVM. Мы надеемся, что информация, приведенная в этой статье, поможет в понимании причин и способов конфигурации адресного пространства.
Ресурсы
Об авторах  | |  | Прямыми обязанностями Пунита Шаха (Punit Shah) является внедрение новейших технологий для System p в связующее программное обеспечение IBM. Он работал в области разработки и производительности приложений и является автором и соавтором нескольких статей в этой области. Адрес его электронной почты - punit@us.ibm.com. |
 | |  | Самит Чаула (Sumit Chawla) руководит инициативной группой Java Enablement для IBM eServer (для AIX, Windows и Linux), а также работает консультантом в организации Independent Software Vendors по направлению серверов IBM. Самит имеет степень магистра в области вычислительной техники, обладает более чем 10-летним опытом работы в IT-индустрии, сертифицирован IBM по курсу Application Architect. Он часто пишет статьи для раздела developerWorks eServer. С ним можно связаться по адресу sumitc@us.ibm.com. |
Выскажите мнение об этой странице
|  |