35 KiB
Management
Apache ActiveMQ Artemis has an extensive management API that allows a user to modify a server configuration, create new resources (e.g. addresses and queues), inspect these resources (e.g. how many messages are currently held in a queue) and interact with it (e.g. to remove messages from a queue). Apache ActiveMQ Artemis also allows clients to subscribe to management notifications.
There are numerous ways to access Apache ActiveMQ Artemis management API:
-
Using JMX -- JMX is the standard way to manage Java applications
-
Using Jolokia -- Jolokia exposes the JMX API of an application through an HTTP interface
-
Using the Core Client -- management operations are sent to Apache ActiveMQ Artemis server using Core Client messages
-
Using any JMS Client -- management operations are sent to Apache ActiveMQ Artemis server using JMS Client messages
-
Web Console -- a web application which provides a graphical interface to the management API.
Although there are four different ways to manage Apache ActiveMQ Artemis, each API supports the same functionality. If it is possible to manage a resource using JMX it is also possible to achieve the same result using Core messages.
Besides these four management interfaces, a Web Console and a Command Line management utility are also available to administrators of ActiveMQ Artemis.
The choice depends on your requirements, your application settings, and your environment to decide which way suits you best.
The Management API
Regardless of the way you invoke management operations, the management API is the same.
For each managed resource, there exists a Java interface describing what operations can be invoked for this type of resource.
To learn about available management operations, see the Javadoc for these
interfaces. They are located in the
org.apache.activemq.artemis.api.core.management
package and they are named
with the word Control
at the end.
Server Management
The ActiveMQServerControl
interface is the entry point for broker management.
-
Listing, creating, deploying and destroying queues
A list of deployed queues can be retrieved using the
getQueueNames()
method.Queues can be created or destroyed using the management operations
createQueue()
ordeployQueue()
ordestroyQueue()
.createQueue
will fail if the queue already exists whiledeployQueue
will do nothing. -
Listing and closing remote connections
Client's remote addresses can be retrieved using
listRemoteAddresses()
. It is also possible to close the connections associated with a remote address using thecloseConnectionsForAddress()
method.Alternatively, connection IDs can be listed using
listConnectionIDs()
and all the sessions for a given connection ID can be listed usinglistSessions()
. -
Transaction heuristic operations
In case of a server crash, when the server restarts, it possible that some transaction requires manual intervention. The
listPreparedTransactions()
method lists the transactions which are in the prepared states (the transactions are represented as opaque Base64 Strings.) To commit or rollback a given prepared transaction, thecommitPreparedTransaction()
orrollbackPreparedTransaction()
method can be used to resolve heuristic transactions. Heuristically completed transactions can be listed using thelistHeuristicCommittedTransactions()
andlistHeuristicRolledBackTransactions
methods. -
Enabling and resetting Message counters
Message counters can be enabled or disabled using the
enableMessageCounters()
ordisableMessageCounters()
method. To reset message counters, it is possible to invokeresetAllMessageCounters()
andresetAllMessageCounterHistories()
methods. -
Retrieving the server configuration and attributes
The
ActiveMQServerControl
exposes Apache ActiveMQ Artemis server configuration through all its attributes (e.g.getVersion()
method to retrieve the server's version, etc.) -
Listing, creating and destroying Core bridges and diverts
A list of deployed core bridges (resp. diverts) can be retrieved using the
getBridgeNames()
(resp.getDivertNames()
) method.Core bridges (resp. diverts) can be created or destroyed using the management operations
createBridge()
anddestroyBridge()
(resp.createDivert()
anddestroyDivert()
).Diverts can be updated using the management operation
updateDivert()
. -
It is possible to stop the server and force failover to occur with any currently attached clients.
To do this use the
forceFailover()
operation.Note:
Since this method actually stops the server you will probably receive some sort of error depending on which management service you use to call it.
Address Management
Individual addresses can be managed using the AddressControl
interface.
-
Modifying roles and permissions for an address
You can add or remove roles associated to a queue using the
addRole()
orremoveRole()
methods. You can list all the roles associated to the queue with thegetRoles()
method -
Pausing and resuming an Address
The
AddressControl
can pause and resume an address and all the queues that are bound to it. Newly added queue will be paused too until the address is resumed. Thus all messages sent to the address will be received but not delivered. When it is resumed, delivering will occur again. -
Blocking and un blocking an Address
The
AddressControl
can block and unblock an address. A blocked address will not issue any more credit to existing producers. New producers will not be granted any credit. When the address is unblocked, credit granting will resume. In this way, it is possible to drain all the queues associated with an address to quiesce a broker in a managed way.
Queue Management
The bulk of the management API deals with queues. The QueueControl
interface
defines the queue management operations.
Most of the management operations on queues take either a single message ID (e.g. to remove a single message) or a filter (e.g. to expire all messages with a given property.)
Note:
Passing
null
or an empty string in thefilter
parameter means that the management operation will be performed on all messages in a queue.
-
Expiring, sending to a dead letter address and moving messages
Messages can be expired from a queue by using the
expireMessages()
method. If an expiry address is defined, messages will be sent to it, otherwise they are discarded.Messages can also be sent to a dead letter address with the
sendMessagesToDeadLetterAddress()
method. It returns the number of messages which are sent to the dead letter address. If a dead letter address is not defined, message are removed from the queue and discarded.Messages can also be moved from a queue to another queue by using the
moveMessages()
method. -
Listing and removing messages
Messages can be listed from a queue by using the
listMessages()
method which returns an array ofMap
, oneMap
for each message.Messages can also be removed from the queue by using the
removeMessages()
method which returns aboolean
for the single message ID variant or the number of removed messages for the filter variant. TheremoveMessages()
method takes afilter
argument to remove only filtered messages. Setting the filter to an empty string will in effect remove all messages. -
Counting messages
The number of messages in a queue is returned by the
getMessageCount()
method. Alternatively, thecountMessages()
will return the number of messages in the queue which match a given filter. -
Changing message priority
The message priority can be changed by using the
changeMessagesPriority()
method which returns aboolean
for the single message ID variant or the number of updated messages for the filter variant. -
Message counters
Message counters can be listed for a queue with the
listMessageCounter()
andlistMessageCounterHistory()
methods (see Message Counters section). The message counters can also be reset for a single queue using theresetMessageCounter()
method. -
Retrieving the queue attributes
The
QueueControl
exposes queue settings through its attributes (e.g.getFilter()
to retrieve the queue's filter if it was created with one,isDurable()
to know whether the queue is durable or not, etc.) -
Pausing and resuming Queues
The
QueueControl
can pause and resume the underlying queue. When a queue is paused, it will receive messages but will not deliver them. When it's resumed, it'll begin delivering the queued messages, if any. -
Disabling and Enabling Queues
The
QueueControl
can disable and enable the underlying queue. When a queue is disabled, it will not longer have messages routed to it. When it's enabled, it'll begin having messages routed to it again.This is useful where you may need to disable message routing to a queue but wish to keep consumers active to investigate issues, without causing further message build up in the queue.
Other Resources Management
Apache ActiveMQ Artemis allows to start and stop its remote resources (acceptors, diverts, bridges, etc.) so that a server can be taken off line for a given period of time without stopping it completely (e.g. if other management operations must be performed such as resolving heuristic transactions). These resources are:
-
Acceptors
They can be started or stopped using the
start()
or.stop()
method on theAcceptorControl
interface. The acceptors parameters can be retrieved using theAcceptorControl
attributes (see Understanding Acceptors) -
Diverts
They can be started or stopped using the
start()
orstop()
method on theDivertControl
interface. Diverts parameters can be retrieved using theDivertControl
attributes (see Diverting and Splitting Message Flows)) -
Bridges
They can be started or stopped using the
start()
(resp.stop()
) method on theBridgeControl
interface. Bridges parameters can be retrieved using theBridgeControl
attributes (see Core bridges) -
Broadcast groups
They can be started or stopped using the
start()
orstop()
method on theBroadcastGroupControl
interface. Broadcast groups parameters can be retrieved using theBroadcastGroupControl
attributes (see Clusters) -
Cluster connections
They can be started or stopped using the
start()
orstop()
method on theClusterConnectionControl
interface. Cluster connections parameters can be retrieved using theClusterConnectionControl
attributes (see Clusters)
Management Via JMX
Apache ActiveMQ Artemis can be managed using JMX.
The management API is exposed by Apache ActiveMQ Artemis using MBeans. By
default, Apache ActiveMQ Artemis registers its resources with the domain
org.apache.activemq.artemis
. For example, the ObjectName
to manage the
anycast queue exampleQueue
on the address exampleAddress
is:
org.apache.activemq.artemis:broker=<brokerName>,component=addresses,address="exampleAddress",subcomponent=queues,routing-type="anycast",queue="exampleQueue"
and the MBean is:
org.apache.activemq.artemis.api.core.management.QueueControl
The MBean's ObjectName
is built using the helper class
org.apache.activemq.artemis.api.core.management.ObjectNameBuilder
. Example
usage of the ObjectNameBuilder
to obtain ActiveMQServerControl
's name:
brokerName = "0.0.0.0"; // configured e.g. in broker.xml <broker-name> element
objectNameBuilder = ObjectNameBuilder.create(ArtemisResolver.DEFAULT_DOMAIN, brokerName, true);
serverObjectName = objectNameBuilder.getActiveMQServerObjectName()
Managing Apache ActiveMQ Artemis using JMX is identical to management of any Java Applications using JMX. It can be done by reflection or by creating proxies of the MBeans.
Configuring JMX
By default, JMX is enabled to manage Apache ActiveMQ Artemis. It can be
disabled by setting jmx-management-enabled
to false
in broker.xml
:
<jmx-management-enabled>false</jmx-management-enabled>
Role Based Authorisation for JMX
Although by default Artemis uses the Java Virtual Machine's Platform MBeanServer
this is guarded using role based authorisation that leverages
the broker's JAAS plugin support. This is configured via the authorisation
element in the management.xml
configuration file and can be used to restrict
access to attributes and methods on MBeans.
There are 3 elements within the authorisation
element, allowlist
,
default-access
and role-access
. Lets discuss each in turn.
Allowlist contains a list of MBeans that will bypass the authorisation, this is typically used for any MBeans that are needed by the console to run etc. The default configuration is:
<allowlist>
<entry domain="hawtio"/>
</allowlist>
This means that any MBean with the domain hawtio
will be allowed access
without authorisation. for instance hawtio:plugin=artemis
. You can also use
wildcards for the MBean properties so the following would also match.
<allowlist>
<entry domain="hawtio" key="type=*"/>
</allowlist>
Note:
The allowlist element has replaced the whitelist element which is now deprecated
The role-access
defines how roles are mapped to particular MBeans and its
attributes and methods, the default configuration looks like:
<role-access>
<match domain="org.apache.activemq.artemis">
<access method="list*" roles="view,update,amq"/>
<access method="get*" roles="view,update,amq"/>
<access method="is*" roles="view,update,amq"/>
<access method="set*" roles="update,amq"/>
<access method="*" roles="amq"/>
</match>
</role-access>
This contains 1 match and will be applied to any MBean that has the domain
org.apache.activemq.artemis
. Any access to any MBeans that have this domain
are controlled by the access
elements which contain a method and a set of
roles. The method being invoked will be used to pick the closest matching
method and the roles for this will be applied for access. For instance if you
try the invoke a method called listMessages
on an MBean with the
org.apache.activemq.artemis
domain then this would match the access
with
the method of list*
. You could also explicitly configure this by using the
full method name, like so:
<access method="listMessages" roles="view,update,amq"/>
You can also match specific MBeans within a domain by adding a key attribute that is used to match one of the properties on the MBean, like:
<match domain="org.apache.activemq.artemis" key="subcomponent=queues">
<access method="list*" roles="view,update,amq"/>
<access method="get*" roles="view,update,amq"/>
<access method="is*" roles="view,update,amq"/>
<access method="set*" roles="update,amq"/>
<access method="*" roles="amq"/>
</match>
You could also match a specific queue for instance:
org.apache.activemq.artemis:broker=<brokerName>,component=addresses,address="exampleAddress",subcomponent=queues,routing-type="anycast",queue="exampleQueue"
by configuring:
<match domain="org.apache.activemq.artemis" key="queue=exampleQueue">
<access method="list*" roles="view,update,amq"/>
<access method="get*" roles="view,update,amq"/>
<access method="is*" roles="view,update,amq"/>
<access method="set*" roles="update,amq"/>
<access method="*" roles="amq"/>
</match>
You can also use wildcards for the MBean properties so the following would also match, allowing prefix match for the MBean properties.
<match domain="org.apache.activemq.artemis" key="queue=example*">
<access method="list*" roles="view,update,amq"/>
<access method="get*" roles="view,update,amq"/>
<access method="is*" roles="view,update,amq"/>
<access method="set*" roles="update,amq"/>
<access method="*" roles="amq"/>
</match>
In case of multiple matches, the exact matches have higher priority than the wildcard matches and the longer wildcard matches have higher priority than the shorter wildcard matches.
Access to JMX MBean attributes are converted to method calls so these are
controlled via the set*
, get*
and is*
. The *
access is the catch all
for everything other method that isn't specifically matched.
The default-access
element is basically the catch all for every method call
that isn't handled via the role-access
configuration. This has the same
semantics as a match
element.
Local JMX Access with JConsole
Due to the authorisation which is enabled by default Apache ActiveMQ Artemis
can not be managed locally using JConsole when connecting as a local
process. This is because JConsole does not pass any authentication information
when connecting this way which means the user cannot therefore be authorised
for any management operations. In order to use JConsole the user will either
have to disable authorisation by completely removing the authorisation
element
from management.xml
or by enabling remote access and providing the proper
username and password credentials (discussed next).
Remote JMX Access
By default remote JMX access to Artemis is disabled for security reasons.
Artemis has a JMX agent which allows access to JMX MBeans remotely. This is
configured via the connector
element in the management.xml
configuration
file. To enable this you simply add the following xml:
<connector connector-port="1099"/>
This exposes the agent remotely on the port 1099
. If you were connecting via
JConsole you would connect as a remote process using the service url:
service:jmx:rmi:///jndi/rmi://localhost:1099/jmxrmi
You'd be able to supply an appropriate user name and password in this case as well.
You can also configure the connector using the following:
-
connector-host
The host to expose the agent on.
-
connector-port
The port to expose the agent on.
-
rmi-registry-port
The port that the RMI registry binds to. If not set, the port is always random. Set to avoid problems with remote JMX connections tunnelled through firewall.
-
jmx-realm
The jmx realm to use for authentication, defaults to
activemq
to match the JAAS configuration. -
object-name
The object name to expose the remote connector on; default is
connector:name=rmi
. -
secured
Whether the connector is secured using SSL.
-
key-store-path
The location of the keystore.
-
key-store-password
The keystore password. This can be masked.
-
key-store-provider
The provider;
JKS
by default. -
trust-store-path
The location of the truststore.
-
trust-store-password
The trustore password. This can be masked.
-
trust-store-provider
The provider;
JKS
by default. -
password-codec
The fully qualified class name of the password codec to use. See the password masking documentation for more details on how this works.
Note:
It is important to note that the rmi registry will pick an ip address to bind to, If you have a multi IP addresses/NICs present on the system then you can choose the ip address to use by adding the following to artemis.profile
-Djava.rmi.server.hostname=localhost
Note:
Remote connections using the default JVM Agent not enabled by default as Artemis exposes the MBean Server via its own configuration. This is so Artemis can leverage the JAAS authentication layer via JMX. If you want to expose this then you will need to disable both the connector and the authorisation by removing them from the
management.xml
configuration. Please refer to Java Management guide to configure the server for remote management (system properties must be set inartemis.profile
).
By default, Apache ActiveMQ Artemis server uses the JMX domain
"org.apache.activemq.artemis". To manage several Apache ActiveMQ Artemis
servers from the same MBeanServer, the JMX domain can be configured for each
individual Apache ActiveMQ Artemis server by setting jmx-domain
in
broker.xml
:
<!-- use a specific JMX domain for ActiveMQ Artemis MBeans -->
<jmx-domain>my.org.apache.activemq</jmx-domain>
Example
See the JMX Management Example which shows how to use a remote connection to JMX and MBean proxies to manage Apache ActiveMQ Artemis.
Exposing JMX using Jolokia
The default Broker configuration ships with the Jolokia
HTTP agent deployed as a web application. Jolokia is a remote JMX-over-HTTP
bridge that exposes MBeans. For a full guide as to how to use it refer to
Jolokia Documentation, however a
simple example to query the broker's version would be to use a curl
command
like this:
curl -v -H "Origin: http://localhost" -u myUser:myPass http://localhost:8161/console/jolokia/read/org.apache.activemq.artemis:broker=\"0.0.0.0\"/Active
By default it's necessary to pass the Origin
header due to the CORS checking
which is configured in etc/jolokia-access.xml
.
Such a curl
command would give you back something like the following (after
formatting):
{
"request": {
"mbean": "org.apache.activemq.artemis:broker=\"0.0.0.0\"",
"attribute": "Version",
"type": "read"
},
"value": "2.24.0",
"timestamp": 1663086398,
"status": 200
}
JMX and the Web Console
The web console that ships with Artemis uses Jolokia under the covers which in
turn uses JMX. This will use the authentication configuration in the
management.xml
file as described in the previous section. This means that
when MBeans are accessed via the console the credentials used to log into the
console and the roles associated with them. By default access to the console is
only allow via users with the amq
role. This is configured in the
artemis.profile
via the system property -Dhawtio.role=amq
. You can
configure multiple roles by changing this to -Dhawtio.roles=amq,view,update
.
If a user doesn't have the correct role to invoke a specific operation then this will display an authorisation exception in the console.
Using Management Message API
The management message API in ActiveMQ Artemis is accessed by sending Core Client messages to a special address, the management address.
Management messages are regular Core Client messages with well-known properties that the server needs to understand to interact with the management API:
-
The name of the managed resource
-
The name of the management operation
-
The parameters of the management operation
When such a management message is sent to the management address, Apache
ActiveMQ Artemis server will handle it, extract the information, invoke the
operation on the managed resources and send a management reply to the
management message's reply-to address (specified by
ClientMessageImpl.REPLYTO_HEADER_NAME
).
A ClientConsumer
can be used to consume the management reply and retrieve the
result of the operation (if any) stored in the reply's body. For portability,
results are returned as a JSON String rather than Java
Serialization (the
org.apache.activemq.artemis.api.core.management.ManagementHelper
can be used
to convert the JSON string to Java objects).
These steps can be simplified to make it easier to invoke management operations using Core messages:
-
Create a
ClientRequestor
to send messages to the management address and receive replies -
Create a
ClientMessage
-
Use the helper class
org.apache.activemq.artemis.api.core.management.ManagementHelper
to fill the message with the management properties -
Send the message using the
ClientRequestor
-
Use the helper class
org.apache.activemq.artemis.api.core.management.ManagementHelper
to retrieve the operation result from the management reply.
For example, to find out the number of messages in the queue exampleQueue
:
ClientSession session = ...
ClientRequestor requestor = new ClientRequestor(session, "activemq.management");
ClientMessage message = session.createMessage(false);
ManagementHelper.putAttribute(message, "queue.exampleQueue", "messageCount");
session.start();
ClientMessage reply = requestor.request(m);
int count = (Integer) ManagementHelper.getResult(reply);
System.out.println("There are " + count + " messages in exampleQueue");
Management operation name and parameters must conform to the Java interfaces
defined in the management
packages.
Names of the resources are built using the helper class
org.apache.activemq.artemis.api.core.management.ResourceNames
and are
straightforward (e.g. queue.exampleQueue
for QueueControl
of the Queue
exampleQueue
, or broker
for the ActiveMQServerControl
).
Note:
The
ManagementHelper
class can be used only with Core JMS messages. When called with a message from a different JMS library, an exception will be thrown.
Configuring Management
The management address to send management messages is configured in
broker.xml
:
<management-address>activemq.management</management-address>
By default, the address is activemq.management
.
The management address requires a special user permission manage
to be able
to receive and handle management messages. This is also configured in
broker.xml:
<!-- users with the admin role will be allowed to manage -->
<!-- Apache ActiveMQ Artemis using management messages -->
<security-setting match="activemq.management">
<permission type="manage" roles="admin" />
</security-setting>
Example
See the Management Example which shows how to use JMS messages to manage the Apache ActiveMQ Artemis server.
Management Notifications
Apache ActiveMQ Artemis emits notifications to inform listeners of potentially interesting events (creation of new resources, security violation, etc.).
These notifications can be received by two different ways:
-
JMX notifications
-
Notification messages
JMX Notifications
If JMX is enabled (see Configuring JMX section), JMX notifications can be
received by subscribing to
org.apache.activemq.artemis:type=Broker,brokerName=<broker name>,module=Core,serviceType=Server
for notifications on resources.
Notification Messages
Apache ActiveMQ Artemis defines a special management notification address. Queues can be bound to this address so that clients will receive management notifications as messages.
A client which wants to receive management notifications must create a queue bound to the management notification address. It can then receive the notifications from its queue.
Notifications messages are regular messages with additional properties corresponding to the notification (its type, when it occurred, the resources which were concerned, etc.).
Since notifications are regular messages, it is possible to use message selectors to filter out notifications and receives only a subset of all the notifications emitted by the server.
Configuring The Management Notification Address
The management notification address to receive management notifications is
configured in broker.xml
:
<management-notification-address>activemq.notifications</management-notification-address>
By default, the address is activemq.notifications
.
Suppressing Session Notifications
Some messaging patterns can generate a lot of SESSION_CREATED
and
SESSION_CLOSED
notifications. In a clustered environment this will come with
some computational overhead. If these notifications are not otherwise used they
can be disabled through:
<suppress-session-notifications>true</suppress-session-notifications>
The only time these notifications are required is in a cluster with MQTT
clients where unique client ID utilization needs to be enforced. Default value
is false
Receiving Notification Messages
Apache ActiveMQ Artemis's Core JMS Client can be used to receive notifications:
Topic notificationsTopic = ActiveMQJMSClient.createTopic("activemq.notifications");
Session session = ...
MessageConsumer notificationConsumer = session.createConsumer(notificationsTopic);
notificationConsumer.setMessageListener(new MessageListener() {
public void onMessage(Message notif) {
System.out.println("------------------------");
System.out.println("Received notification:");
try {
Enumeration propertyNames = notif.getPropertyNames();
while (propertyNames.hasMoreElements()) {
String propertyName = (String)propertyNames.nextElement();
System.out.format(" %s: %s\n", propertyName, notif.getObjectProperty(propertyName));
}
} catch (JMSException e) {
}
System.out.println("------------------------");
}
});
Example
See the Management Notification Example
which shows how to use a JMS MessageListener
to receive management
notifications from ActiveMQ Artemis server.
Notification Types and Headers
Below is a list of all the different kinds of notifications as well as which
headers are on the messages. Every notification has a _AMQ_NotifType
(value
noted in parentheses) and _AMQ_NotifTimestamp
header. The timestamp is the
un-formatted result of a call to java.lang.System.currentTimeMillis()
.
-
BINDING_ADDED
(0)_AMQ_Binding_Type
,_AMQ_Address
,_AMQ_ClusterName
,_AMQ_RoutingName
,_AMQ_Binding_ID
,_AMQ_Distance
,_AMQ_FilterString
-
BINDING_REMOVED
(1)_AMQ_Address
,_AMQ_ClusterName
,_AMQ_RoutingName
,_AMQ_Binding_ID
,_AMQ_Distance
,_AMQ_FilterString
-
CONSUMER_CREATED
(2)_AMQ_Address
,_AMQ_ClusterName
,_AMQ_RoutingName
,_AMQ_Distance
,_AMQ_ConsumerCount
,_AMQ_User
,_AMQ_ValidatedUser
,_AMQ_RemoteAddress
,_AMQ_SessionName
,_AMQ_FilterString
,_AMQ_CertSubjectDN
-
CONSUMER_CLOSED
(3)_AMQ_Address
,_AMQ_ClusterName
,_AMQ_RoutingName
,_AMQ_Distance
,_AMQ_ConsumerCount
,_AMQ_User
,_AMQ_RemoteAddress
,_AMQ_SessionName
,_AMQ_FilterString
-
SECURITY_AUTHENTICATION_VIOLATION
(6)_AMQ_User
,_AMQ_CertSubjectDN
,_AMQ_RemoteAddress
-
SECURITY_PERMISSION_VIOLATION
(7)_AMQ_Address
,_AMQ_CheckType
,_AMQ_User
-
DISCOVERY_GROUP_STARTED
(8)name
-
DISCOVERY_GROUP_STOPPED
(9)name
-
BROADCAST_GROUP_STARTED
(10)name
-
BROADCAST_GROUP_STOPPED
(11)name
-
BRIDGE_STARTED
(12)name
-
BRIDGE_STOPPED
(13)name
-
CLUSTER_CONNECTION_STARTED
(14)name
-
CLUSTER_CONNECTION_STOPPED
(15)name
-
ACCEPTOR_STARTED
(16)factory
,id
-
ACCEPTOR_STOPPED
(17)factory
,id
-
PROPOSAL
(18)_JBM_ProposalGroupId
,_JBM_ProposalValue
,_AMQ_Binding_Type
,_AMQ_Address
,_AMQ_Distance
-
PROPOSAL_RESPONSE
(19)_JBM_ProposalGroupId
,_JBM_ProposalValue
,_JBM_ProposalAltValue
,_AMQ_Binding_Type
,_AMQ_Address
,_AMQ_Distance
-
CONSUMER_SLOW
(21)_AMQ_Address
,_AMQ_ConsumerCount
,_AMQ_RemoteAddress
,_AMQ_ConnectionName
,_AMQ_ConsumerName
,_AMQ_SessionName
-
ADDRESS_ADDED
(22)_AMQ_Address
,_AMQ_Routing_Type
-
ADDRESS_REMOVED
(23)_AMQ_Address
,_AMQ_Routing_Type
-
CONNECTION_CREATED
(24)_AMQ_ConnectionName
,_AMQ_RemoteAddress
-
CONNECTION_DESTROYED
(25)_AMQ_ConnectionName
,_AMQ_RemoteAddress
-
SESSION_CREATED
(26)_AMQ_ConnectionName
,_AMQ_User
,_AMQ_SessionName
-
SESSION_CLOSED
(27)_AMQ_ConnectionName
,_AMQ_User
,_AMQ_SessionName
-
MESSAGE_DELIVERED
(28)_AMQ_Address
,_AMQ_Routing_Type
,_AMQ_RoutingName
,_AMQ_ConsumerName
,_AMQ_Message_ID
-
MESSAGE_EXPIRED
(29)_AMQ_Address
,_AMQ_Routing_Type
,_AMQ_RoutingName
,_AMQ_ConsumerName
,_AMQ_Message_ID
Message Counters
Message counters can be used to obtain information on queues over time as Apache ActiveMQ Artemis keeps a history on queue metrics.
They can be used to show trends on queues. For example, using the management API, it would be possible to query the number of messages in a queue at regular interval. However, this would not be enough to know if the queue is used: the number of messages can remain constant because nobody is sending or receiving messages from the queue or because there are as many messages sent to the queue than messages consumed from it. The number of messages in the queue remains the same in both cases but its use is widely different.
Message counters give additional information about the queues:
-
count
The total number of messages added to the queue since the server was started
-
countDelta
the number of messages added to the queue since the last message counter update
-
messageCount
The current number of messages in the queue
-
messageCountDelta
The overall number of messages added/removed from the queue since the last message counter update. For example, if
messageCountDelta
is equal to-10
this means that overall 10 messages have been removed from the queue (e.g. 2 messages were added and 12 were removed) -
lastAddTimestamp
The timestamp of the last time a message was added to the queue
-
lastAckTimestamp
The timestamp of the last time a message from the queue was acknowledged
-
updateTimestamp
The timestamp of the last message counter update
These attributes can be used to determine other meaningful data as well. For example, to know specifically how many messages were consumed from the queue since the last update simply subtract the
messageCountDelta
fromcountDelta
.
Configuring Message Counters
By default, message counters are disabled as it might have a small negative effect on memory.
To enable message counters, you can set it to true
in broker.xml
:
<message-counter-enabled>true</message-counter-enabled>
Message counters keep a history of the queue metrics (10 days by default) and
sample all the queues at regular interval (10 seconds by default). If message
counters are enabled, these values should be configured to suit your messaging
use case in broker.xml
:
<!-- keep history for a week -->
<message-counter-max-day-history>7</message-counter-max-day-history>
<!-- sample the queues every minute (60000ms) -->
<message-counter-sample-period>60000</message-counter-sample-period>
Message counters can be retrieved using the Management API. For example, to retrieve message counters on a queue using JMX:
// retrieve a connection to Apache ActiveMQ Artemis's MBeanServer
MBeanServerConnection mbsc = ...
QueueControlMBean queueControl = (QueueControl)MBeanServerInvocationHandler.newProxyInstance(mbsc,
on,
QueueControl.class,
false);
// message counters are retrieved as a JSON String
String counters = queueControl.listMessageCounter();
// use the MessageCounterInfo helper class to manipulate message counters more easily
MessageCounterInfo messageCounter = MessageCounterInfo.fromJSON(counters);
System.out.format("%s message(s) in the queue (since last sample: %s)\n",
messageCounter.getMessageCount(),
messageCounter.getMessageCountDelta());
Example
See the Message Counter Example which shows how to use message counters to retrieve information on a queue.