Разработка и диагностика MBean
Создание Standard MBean
ERP использует стандартное соглашение JMX. Интерфейс должен:
-
быть публичным;
-
наследовать маркер
ru.bgcrm.jmx.MBean; -
называться
<ImplementationClass>MBeanс точным регистром; -
содержать только безопасные для частого чтения атрибуты и необходимые операции.
interface QueueStateMBean : MBean {
val size: Int
val isAvailable: Boolean
}
class QueueState(
private val queue: Queue<*>
) : QueueStateMBean {
override val size: Int
get() = queue.size
override val isAvailable: Boolean
get() = true
}
Kotlin-свойства будут опубликованы как атрибуты Size и Available. В Java используйте обычные getXxx()/isXxx() в интерфейсе QueueStateMBean.
Маркер MBean нужен для типизации MBeanHandler, но сам по себе не превращает произвольно названный интерфейс в Standard MBean. Соответствие имени интерфейса имени класса проверяет JMX.
Регистрация
Регистрируйте объект после MBeanHandler.init(), обычно при инициализации подсистемы:
MBeanHandler.register(
mBean = QueueState(queue),
type = "Queue",
name = "notifications",
description = "Notification delivery queue"
)
Результат:
BGCRM:type=Queue,name=notifications,description=Notification delivery queue
Для снятия используйте в точности те же три значения:
MBeanHandler.unregister(
type = "Queue",
name = "notifications",
description = "Notification delivery queue"
)
unregister не проверяет server.jmx.pools. Если объекта нет, ошибка записывается в лог.
Требования к именам
-
typeне должен быть пустым. -
Выбирайте короткие стабильные машинные значения; не включайте секреты, URL, токены и пользовательские данные.
-
Не различайте объекты только символами
*?:=,"или переводом строки: builder удаляет их, и два значения могут превратиться в одно имя. -
Считайте
descriptionчастью идентичности. При её изменении отдельно снимите MBean со старым значением. -
Для множества однотипных объектов оставляйте стабильный
type, а экземпляр кодируйте вname.
Требования к атрибутам
JMX-клиент или exporter может читать атрибуты часто и последовательно. Getter должен быть потокобезопасным, ограниченным по времени и по возможности не выполнять I/O.
Если вычисление дорогое:
-
перенесите сбор данных в фоновый процесс; или
-
кешируйте результат и задайте понятный TTL; или
-
исключите атрибут из массового scrape-конфига.
Не возвращайте пароли, ключи, персональные данные, полные тексты запросов и другие чувствительные значения. MBean нередко экспортируются в общую систему мониторинга.
Показывайте исходные значения, а не отформатированные строки: числа и boolean проще использовать в алертах. Единицы измерения фиксируйте в названии атрибута или документации.
Проверка
Для handler-а и построителя имён уже есть тесты:
-
MBeanHandlerTest— выключение, повторная регистрация, снятие и ошибки JMX; -
ObjectNameBuilderTest— формирование и очистка значенийObjectName; -
тесты фабрик API-компонентов проверяют передаваемые
type,nameиdescription.
Для нового MBean добавьте тест, который регистрирует реализацию в настоящем локальном MBeanServer или вызывает JMX introspector. Такой тест обнаружит несоответствие пары <Class>/<Class>MBean, которое mock-тест handler-а не видит.
После запуска ERP проверьте:
-
в логе есть
MBean '<objectName>' successfully registered; -
объект появился в домене
BGCRM; -
набор и типы атрибутов совпадают с интерфейсом;
-
повторное чтение не создаёт заметную нагрузку;
-
после пересоздания компонента значения относятся к новому экземпляру.
Диагностика
| Симптом | Что проверить |
|---|---|
Домен |
Значение |
Нет одного ленивого MBean |
Был ли инициализирован соответствующий Kotlin object или запрошен включённый API-компонент |
|
Публичность интерфейса, точное имя |
Есть два похожих объекта |
Не различается ли |
Повторная регистрация иногда пропадает |
Конкуренцию за одинаковое имя: внутренний lock ждёт 3 секунды и при таймауте не пишет сообщение |
Scrape стал медленным |
Время каждого getter-а и слишком широкое правило экспортера; не ограничивайтесь анализом домена |
Prometheus не видит атрибут |
Конфигурацию JMX-exporter, преобразование имени и фильтры. Наличие атрибута сначала подтвердите через JConsole/JMX |
Текущие технические долги
-
server.jmx.poolsследует переименовать или разделить на общий флаг и флаги подсистем. -
ObjectNameBuilderдолжен инициализировать логгер до обработки ошибочного имени. -
ClientEngineFactoryCachesMbeanтребуется переименовать вClientEngineFactoryCachesMBeanи покрыть реальной JMX-регистрацией. -
Для ожидания lock-а полезен warning, иначе пропуск регистрации не диагностируется.