Files
spring-integration/src/reference/docbook/jmx.xml
Artem Bilan d0fa88ac72 INT-3417: Polishing Docs for MessageHeaders
JIRA: https://jira.spring.io/browse/INT-3417

Polishing

Add note about using the accessor.
2014-07-03 15:19:49 -04:00

553 lines
24 KiB
XML

<?xml version="1.0" encoding="UTF-8"?>
<section version="5.0" xml:id="jmx" xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:ns5="http://www.w3.org/1999/xhtml"
xmlns:ns4="http://www.w3.org/1998/Math/MathML"
xmlns:ns3="http://www.w3.org/2000/svg"
xmlns:ns="http://docbook.org/ns/docbook">
<title id="jmx.title">JMX Support</title>
<para>
Spring Integration provides <emphasis>Channel Adapters</emphasis> for
receiving and publishing JMX Notifications. There is also an
<emphasis>Inbound Channel Adapter</emphasis> for
polling JMX MBean attribute values, and an <emphasis>Outbound Channel Adapter</emphasis>
for invoking JMX MBean operations.
</para>
<section id="jmx-notification-listening-channel-adapter">
<title>Notification Listening Channel Adapter</title>
<para>
The <emphasis>Notification-listening Channel Adapter</emphasis> requires
a JMX ObjectName for the MBean that publishes notifications to which
this listener should be registered. A very simple configuration might
look like this:
</para>
<programlisting language="xml"><![CDATA[<int-jmx:notification-listening-channel-adapter id="adapter"
channel="channel"
object-name="example.domain:name=publisher"/>]]></programlisting>
<tip>
The <emphasis>notification-listening-channel-adapter</emphasis>
registers with an <interfacename>MBeanServer</interfacename> at
startup, and the default bean name is <emphasis>mbeanServer</emphasis>
which happens to be the same bean name generated when using
Spring's <emphasis>&lt;context:mbean-server/&gt;</emphasis> element.
If you need to use a different name, be sure to include the
<emphasis>mbean-server</emphasis> attribute.
</tip>
<para>
The adapter can also accept a reference to a
<interfacename>NotificationFilter</interfacename> and a
<emphasis>handback</emphasis> Object to provide some context that is
passed back with each Notification. Both of those attributes are optional.
Extending the above example to include those attributes as well as an
explicit <interfacename>MBeanServer</interfacename> bean name would
produce the following:
</para>
<programlisting language="xml"><![CDATA[<int-jmx:notification-listening-channel-adapter id="adapter"
channel="channel"
mbean-server="someServer"
object-name="example.domain:name=somePublisher"
notification-filter="notificationFilter"
handback="myHandback"/>]]></programlisting>
<para>
The <emphasis>Notification-listening Channel Adapter</emphasis> is
event-driven and registered with the <interfacename>MBeanServer</interfacename>
directly. It does not require any poller configuration.
</para>
<note>
For this component only, the <emphasis>object-name</emphasis> attribute can contain an
ObjectName pattern (e.g. "org.foo:type=Bar,name=*") and the adapter will receive notifications
from all MBeans with ObjectNames that match the pattern. In addition, the <emphasis>object-name</emphasis>
attribute can contain a SpEL reference to a &lt;util:list/&gt; of ObjectName patterns:
<programlisting language="xml"><![CDATA[<jmx:notification-listening-channel-adapter id="manyNotificationsAdapter"
channel="manyNotificationsChannel"
object-name="#{patterns}"/>
<util:list id="patterns">
<value>org.foo:type=Foo,name=*</value>
<value>org.foo:type=Bar,name=*</value>
</util:list>]]></programlisting>
The names of the located MBean(s) will be logged when DEBUG level logging is enabled.
</note>
</section>
<section id="jmx-notification-publishing-channel-adapter">
<title>Notification Publishing Channel Adapter</title>
<para>
The <emphasis>Notification-publishing Channel Adapter</emphasis> is
relatively simple. It only requires a JMX ObjectName in its
configuration as shown below.
</para>
<programlisting language="xml"><![CDATA[<context:mbean-export/>
<int-jmx:notification-publishing-channel-adapter id="adapter"
channel="channel"
object-name="example.domain:name=publisher"/>]]></programlisting>
<para>
It does also require that an <classname>MBeanExporter</classname> be
present in the context. That is why the <emphasis>&lt;context:mbean-export/&gt;</emphasis>
element is shown above as well.
</para>
<para>
When Messages are sent to the channel for this adapter, the
Notification is created from the Message content. If the payload is a
String it will be passed as the <emphasis>message</emphasis> text
for the Notification. Any other payload type will be passed as the
<emphasis>userData</emphasis> of the Notification.
</para>
<para>
JMX Notifications also have a <emphasis>type</emphasis>, and it should be a
dot-delimited String. There are two ways to provide the
<emphasis>type</emphasis>. Precedence will always be given to a
Message header value associated with the <code>JmxHeaders.NOTIFICATION_TYPE</code>
key. On the other hand, you can rely on a fallback <emphasis>default-notification-type</emphasis>
attribute provided in the configuration.
</para>
<programlisting language="xml"><![CDATA[<context:mbean-export/>
<int-jmx:notification-publishing-channel-adapter id="adapter"
channel="channel"
object-name="example.domain:name=publisher"
default-notification-type="some.default.type"/>]]></programlisting>
</section>
<section id="jmx-attribute-polling-channel-adapter">
<title>Attribute Polling Channel Adapter</title>
<para>
The <emphasis>Attribute Polling Channel Adapter</emphasis> is useful
when you have a requirement, to periodically check on some value that
is available through an MBean as a managed attribute. The poller can
be configured in the same way as any other polling adapter in
Spring Integration (or it's possible to rely on the default poller).
The <emphasis>object-name</emphasis> and <emphasis>attribute-name</emphasis>
are required. An MBeanServer reference is also required, but it will
automatically check for a bean named <emphasis>mbeanServer</emphasis>
by default, just like the <emphasis>Notification-listening Channel Adapter</emphasis>
described above.
</para>
<programlisting language="xml"><![CDATA[<int-jmx:attribute-polling-channel-adapter id="adapter"
channel="channel"
object-name="example.domain:name=someService"
attribute-name="InvocationCount">
<int:poller max-messages-per-poll="1" fixed-rate="5000"/>
</int-jmx:attribute-polling-channel-adapter>]]></programlisting>
</section>
<section id="tree-polling-channel-adapter">
<title>Tree Polling Channel Adapter</title>
<para>
The <emphasis>Tree Polling Channel Adapter</emphasis> queries the JMX MBean tree and
sends a message with a payload that is the graph of objects that matches the query. By
default the MBeans are mapped to primitives and simple Objects like Map, List and arrays -
permitting simple transformation, for example, to JSON. An MBeanServer reference is also
required, but it will automatically check for a bean named <emphasis>mbeanServer</emphasis>
by default, just like the <emphasis>Notification-listening Channel Adapter</emphasis>
described above. A basic configuration would be:
</para>
<programlisting language="xml"><![CDATA[<int-jmx:tree-polling-channel-adapter id="adapter"
channel="channel"
query-name="example.domain:type=*">
<int:poller max-messages-per-poll="1" fixed-rate="5000"/>
</int-jmx:tree-polling-channel-adapter>]]></programlisting>
<para>
This will include all attributes on the MBeans selected. You can filter the attributes by
providing an <interfacename>MBeanObjectConverter</interfacename> that
has an appropriate filter configured. The converter can be provided as a reference to
a bean definition using the <code>converter</code> attribute, or as an
inner &lt;bean/&gt; definition. A <classname>DefaultMBeanObjectConverter</classname> is
provided which can take a <interfacename>MBeanAttributeFilter</interfacename> in
its constructor argument.
</para>
<para>
Two standard filters are provided; the <classname>NamedFieldsMBeanAttributeFilter</classname>
allows you to specify a list of attributes to include and the
<classname>NotNamedFieldsMBeanAttributeFilter</classname> allows you to specify a list
of attributes to exclude. You can also implement your own filter
</para>
</section>
<section id="jmx-operation-invoking-channel-adapter">
<title>Operation Invoking Channel Adapter</title>
<para>
The <emphasis>operation-invoking-channel-adapter</emphasis> enables
Message-driven invocation of any managed operation exposed by an MBean.
Each invocation requires the operation name to be invoked and the
ObjectName of the target MBean. Both of these must be explicitly provided
via adapter configuration:
</para>
<programlisting language="xml"><![CDATA[<int-jmx:operation-invoking-channel-adapter id="adapter"
object-name="example.domain:name=TestBean"
operation-name="ping"/>]]></programlisting>
<para>
Then the adapter only needs to be able to discover the <emphasis>mbeanServer</emphasis>
bean. If a different bean name is required, then provide the
<emphasis>mbean-server</emphasis> attribute with a reference.
</para>
<para>
The payload of the Message will be mapped to the parameters of the
operation, if any. A Map-typed payload with String keys is treated as
name/value pairs, whereas a List or array would be passed as a simple
argument list (with no explicit parameter names). If the operation
requires a single parameter value, then the payload can represent that
single value, and if the operation requires no parameters, then the
payload would be ignored.
</para>
<para>
If you want to expose a channel for a single common operation to be
invoked by Messages that need not contain headers, then that option
works well.
</para>
</section>
<section id="jmx-operation-invoking-outbound-gateway">
<title>Operation Invoking Outbound Gateway</title>
<para>
Similar to the <emphasis>operation-invoking-channel-adapter</emphasis>
Spring Integration also provides a <emphasis>operation-invoking-outbound-gateway</emphasis>,
which could be used when dealing with non-void operations and a return
value is required. Such return value will be sent as message payload
to the <emphasis>reply-channel</emphasis> specified by this Gateway.
</para>
<programlisting language="xml"><![CDATA[<int-jmx:operation-invoking-outbound-gateway request-channel="requestChannel"
reply-channel="replyChannel"
object-name="o.s.i.jmx.config:type=TestBean,name=testBeanGateway"
operation-name="testWithReturn"/>]]></programlisting>
<para>
If the <emphasis>reply-channel</emphasis> attribute is not provided,
the reply message will be sent to the channel that is identified
by the <interfacename>IntegrationMessageHeaderAccessor.REPLY_CHANNEL</interfacename>
header. That header is typically auto-created by the entry point
into a message flow, such as any <emphasis>Gateway</emphasis> component.
However, if the message flow was started by manually creating a
Spring Integration Message and sending it directly to a
<emphasis>Channel</emphasis>, then you must specify the message header
explicitly or use the provided <emphasis>reply-channel</emphasis> attribute.
</para>
</section>
<section id="jmx-mbean-exporter">
<title>MBean Exporter</title>
<para>
Spring Integration components themselves may be exposed as MBeans
when the <classname>IntegrationMBeanExporter</classname> is configured. To
create an instance of the <classname>IntegrationMBeanExporter</classname>,
define a bean and provide a reference to an <interfacename>MBeanServer</interfacename>
and a domain name (if desired). The domain can be left out, in which
case the default domain is <emphasis>org.springframework.integration</emphasis>.
</para>
<programlisting language="xml"><![CDATA[<int-jmx:mbean-export id="integrationMBeanExporter"
default-domain="my.company.domain" server="mbeanServer"/>
<bean id="mbeanServer" class="org.springframework.jmx.support.MBeanServerFactoryBean">
<property name="locateExistingServerIfPossible" value="true"/>
</bean>]]></programlisting>
<para>
Once the exporter is defined, start up your application with:
</para>
<screen> -Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.port=6969
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.authenticate=false</screen>
<para>
Then start JConsole (free with the JDK), and connect to the local process on
<literal>localhost:6969</literal> to get a look at the management
endpoints exposed. (The port and client are just examples to get you
started quickly, there are other JMX clients available and some offer more
sophisticated features than JConsole.)
</para>
<important>
<para>
The MBean exporter is orthogonal to the one provided in Spring core
- it registers message channels and message handlers, but not itself. You
can expose the exporter itself, and certain other components in Spring
Integration, using the standard <literal>&lt;context:mbean-export/&gt;</literal>
tag. The exporter has a some metrics attached to it, for
instance a count of the number of active handlers and the number of
queued messages.
</para>
<para>
It also has a useful operation, as discussed in <xref linkend="jmx-mbean-shutdown"/>.
</para>
</important>
<para>
Starting with <emphasis>Spring Integration 4.0</emphasis> the <code>@EnableIntegrationMBeanExport</code>
annotation has been introduced for convenient configuration of a default
(<code>integrationMbeanExporter</code>) bean of type
<classname>IntegrationMBeanExporter</classname> with several useful options
at the <code>@Configuration</code> class level. For example:
<programlisting language="java"><![CDATA[@Configuration
@EnableIntegration
@EnableIntegrationMBeanExport(server = "mbeanServer", managedComponents = "input")
public class ContextConfiguration {
@Bean
public MBeanServerFactoryBean mbeanServer() {
return new MBeanServerFactoryBean();
}
}]]></programlisting>
If there is a need to provide more options, or have several <classname>IntegrationMBeanExporter</classname> beans
e.g. for different MBean Servers, or to avoid conflicts with the standard Spring <classname>MBeanExporter</classname>
(e.g. via <code>@EnableMBeanExport</code>), you can simply configure an <classname>IntegrationMBeanExporter</classname>
as a generic bean.
</para>
<section id="jmx-mbean-features">
<title>MBean ObjectNames</title>
<para>
All the <interfacename>MessageChannel</interfacename>,
<interfacename>MessageHandler</interfacename> and
<interfacename>MessageSource</interfacename> instances
in the application are wrapped by the MBean exporter to provide
management and monitoring features. The generated JMX object names
for each component type are listed in the table below:
</para>
<table>
<title />
<tgroup cols="2">
<colspec colnum="1" colname="col1" colwidth="1*"/>
<colspec colnum="2" colname="col2" colwidth="3*"/>
<thead>
<row>
<entry align="center">Component Type</entry>
<entry align="center">ObjectName</entry>
</row>
</thead>
<tbody>
<row>
<entry>MessageChannel</entry>
<entry>o.s.i:type=MessageChannel,name=&lt;channelName&gt;</entry>
</row>
<row>
<entry>MessageSource</entry>
<entry>o.s.i:type=MessageSource,name=&lt;channelName&gt;,bean=&lt;source&gt;</entry>
</row>
<row>
<entry>MessageHandler</entry>
<entry>o.s.i:type=MessageSource,name=&lt;channelName&gt;,bean=&lt;source&gt;</entry>
</row>
</tbody>
</tgroup>
</table>
<para>
The <emphasis>bean</emphasis> attribute in the object names for
sources and handlers takes one of the values in the table below:
</para>
<table>
<title />
<tgroup cols="2">
<colspec colnum="1" colname="col1" colwidth="1*"/>
<colspec colnum="2" colname="col2" colwidth="3*"/>
<thead>
<row>
<entry align="center">Bean Value</entry>
<entry align="center">Description</entry>
</row>
</thead>
<tbody>
<row>
<entry>endpoint</entry>
<entry>The bean name of the enclosing endpoint (e.g.
&lt;service-activator&gt;) if there is one
</entry>
</row>
<row>
<entry>anonymous</entry>
<entry>An indication that the enclosing endpoint didn't have a
user-specified bean name, so the JMX name is the input channel
name
</entry>
</row>
<row>
<entry>internal</entry>
<entry>For well-known Spring Integration default
components
</entry>
</row>
<row>
<entry>handler</entry>
<entry>None of the above: fallback to the
<literal>toString()</literal> of the object being monitored
(handler or source)
</entry>
</row>
</tbody>
</tgroup>
</table>
<para>
Custom elements can be appended to the object name by providing a reference to a
<classname>Properties</classname> object in the <code>object-name-static-properties</code> attribute.
</para>
<para>
Also, since <emphasis>Spring Integration 3.0</emphasis>, you can use a custom
<ulink url="http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/jmx/export/naming/ObjectNamingStrategy.html"
>ObjectNamingStrategy</ulink>
using the <code>object-naming-strategy</code> attribute. This permits greater control over the naming of the
MBeans. For example, to group all Integration MBeans under
an 'Integration' type. A simple custom naming strategy implementation might be:
</para>
<programlisting language="java"><![CDATA[public class Namer implements ObjectNamingStrategy {
private final ObjectNamingStrategy realNamer = new KeyNamingStrategy();
@Override
public ObjectName getObjectName(Object managedBean, String beanKey) throws MalformedObjectNameException {
String actualBeanKey = beanKey.replace("type=", "type=Integration,componentType=");
return realNamer.getObjectName(managedBean, actualBeanKey);
}
}]]></programlisting>
<para>
The <code>beanKey</code> argument is a String containing the standard object name beginning with
the <code>default-domain</code> and including any additional static properties.
This example simply moves the standard <code>type</code> part to <code>componentType</code> and
sets the <code>type</code> to 'Integration',
enabling selection of all Integration MBeans in one query:
<code>"my.domain:type=Integration,*</code>. This also groups the beans under one tree entry under the
domain in tools like VisualVM.
</para>
<note>
The default naming strategy is a
<ulink url="http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/jmx/export/naming/MetadataNamingStrategy.html"
>MetadataNamingStrategy</ulink>. The exporter propagates the <code>default-domain</code> to that object to allow it
to generate a fallback object name if parsing of the bean key fails. If your custom naming strategy is a
<classname>MetadataNamingStrategy</classname> (or subclass), the exporter will <emphasis role="bold">not</emphasis>
propagate the <code>default-domain</code>; you will need to configure it on your strategy bean.
</note>
</section>
<section id="jmx-channel-features">
<title>MessageChannel MBean Features</title>
<para>
Message channels report metrics according to their concrete type.
If you are looking at a <classname>DirectChannel</classname>, you
will see statistics for the send operation. If it is a
<classname>QueueChannel</classname>, you will also see statistics for the
receive operation, as well as the count of messages that are currently
buffered by this <classname>QueueChannel</classname>. In both
cases there are some metrics that are simple counters (message
count and error count), and some that are estimates of averages
of interesting quantities. The algorithms used to calculate these
estimates are described briefly in the table below:
</para>
<table>
<title />
<tgroup cols="3">
<colspec colnum="1" colname="col1" colwidth="1*"/>
<colspec colnum="2" colname="col2" colwidth="1.5*"/>
<colspec colnum="3" colname="col3" colwidth="3*"/>
<thead>
<row>
<entry align="center">Metric Type</entry>
<entry align="center">Example</entry>
<entry align="center">Algorithm</entry>
</row>
</thead>
<tbody>
<row>
<entry>Count</entry>
<entry>Send Count</entry>
<entry>Simple incrementer. Increase by one when an event
occurs.
</entry>
</row>
<row>
<entry>Duration</entry>
<entry>Send Duration (method execution time in
milliseconds)
</entry>
<entry>Exponential Moving Average with decay factor 10. Average
of the method execution time over roughly the last 10
measurements.
</entry>
</row>
<row>
<entry>Rate</entry>
<entry>Send Rate (number of operations per second)</entry>
<entry>Inverse of Exponential Moving Average of the interval
between events with decay in time (lapsing over 60 seconds) and
per measurement (last 10 events).
</entry>
</row>
<row>
<entry>Ratio</entry>
<entry>Send Error Ratio (ratio of errors to total sends)</entry>
<entry>Estimate the success ratio as the Exponential Moving
Average of the series composed of values 1 for success and 0 for
failure (decaying as per the rate measurement over time and
events). Error ratio is 1 - success ratio.
</entry>
</row>
</tbody>
</tgroup>
</table>
<para>
A feature of the time-based average estimates is that they decay
with time if no new measurements arrive. To help interpret the behaviour
over time, the time (in seconds) since the last measurement is also
exposed as a metric.
</para>
<para>
There are two basic exponential models: decay per measurement
(appropriate for duration and anything where the number of measurements
is part of the metric), and decay per time unit (more suitable for rate
measurements where the time in between measurements is part of the
metric). Both models depend on the fact that
</para>
<screen>S(n) = sum(i=0,i=n) w(i) x(i)</screen>
<para>
has a special form when <literal>w(i) = r^i</literal>, with
<literal>r=constant</literal>:
</para>
<screen>S(n) = x(n) + r S(n-1)</screen>
<para>
(so you only have to store <literal>S(n-1)</literal>, not the whole series
<literal>x(i)</literal>, to generate a new metric estimate from the last
measurement). The algorithms used in the duration metrics use
<literal>r=exp(-1/M)</literal> with <literal>M=10</literal>. The net
effect is that the estimate <literal>S(n)</literal> is more heavily
weighted to recent measurements and is composed roughly of the last
<literal>M</literal> measurements. So <literal>M</literal> is the
"window" or lapse rate of the estimate In the case of the vanilla moving
average, <literal>i</literal> is a counter over the number of
measurements. In the case of the rate we interpret <literal>i</literal>
as the elapsed time, or a combination of elapsed time and a counter (so
the metric estimate contains contributions roughly from the last
<literal>M</literal> measurements and the last <literal>T</literal>
seconds).
</para>
</section>
<section id="jmx-mbean-shutdown">
<title>Orderly Shutdown Managed Operation</title>
<para>
The MBean exporter provides a JMX operation to shut down the application
in an orderly manner, intended for use before terminating the JVM.
</para>
<programlisting language="java"><![CDATA[public void stopActiveComponents(boolean force, long howLong)
]]></programlisting>
<para>
Its use and operation are described in <xref linkend="jmx-shutdown"/>.
</para>
</section>
</section>
</section>