Apache ActiveMQ Artemis 有一個廣泛的管理 API,允許使用者修改伺服器組態、建立新的資源(例如位址和佇列)、檢查這些資源(例如,佇列中目前保存多少訊息)並與之互動(例如,從佇列中移除訊息)。Apache ActiveMQ Artemis 也允許用戶端訂閱管理通知。

有多種方式可以存取 Apache ActiveMQ Artemis 管理 API

  • 使用 JMX — JMX 是管理 Java 應用程式的標準方式

  • 使用 Jolokia — Jolokia 通過 HTTP 介面公開應用程式的 JMX API

  • 使用核心用戶端 — 管理操作使用核心用戶端訊息傳送到 Apache ActiveMQ Artemis 伺服器

  • 使用任何 JMS 用戶端 — 管理操作使用 JMS 用戶端訊息傳送到 Apache ActiveMQ Artemis 伺服器

  • Web 主控台 — 一個提供管理 API 圖形介面的 Web 應用程式。

雖然有四種不同的方式來管理 Apache ActiveMQ Artemis,但每個 API 都支援相同的功能。如果可以使用 JMX 管理資源,也可以使用核心訊息實現相同的結果。

除了這四個管理介面外,ActiveMQ Artemis 的管理員還可以使用 Web 主控台和命令列管理工具

選擇取決於您的需求、您的應用程式設定和您的環境,以決定哪種方式最適合您。

1. 管理 API

無論您調用管理操作的方式為何,管理 API 都是相同的。

對於每個受管理資源,都有一個 Java 介面描述可以為此類資源調用哪些操作。

要了解可用的管理操作,請參閱這些介面的 Javadoc。它們位於 org.apache.activemq.artemis.api.core.management 套件中,並且名稱以 Control 結尾。

1.1. 伺服器管理

ActiveMQServerControl 介面是代理程式管理的進入點。

  • 列出、建立、部署和銷毀佇列

    可以使用 getQueueNames() 方法檢索已部署佇列的列表。

    可以使用管理操作 createQueue()deployQueue()destroyQueue() 建立或銷毀佇列。

    如果佇列已存在,createQueue 將會失敗,而 deployQueue 將不會執行任何操作。

  • 列出和關閉遠端連線

    可以使用 listRemoteAddresses() 檢索用戶端的遠端位址。也可以使用 closeConnectionsForAddress() 方法關閉與遠端位址相關的連線。

    或者,可以使用 listConnectionIDs() 列出連線 ID,並且可以使用 listSessions() 列出給定連線 ID 的所有會話。

  • 交易啟發式操作

    如果伺服器當機,當伺服器重新啟動時,可能有一些交易需要人工介入。listPreparedTransactions() 方法會列出處於準備狀態的交易(交易表示為不透明的 Base64 字串)。若要提交或回滾給定的已準備交易,可以使用 commitPreparedTransaction()rollbackPreparedTransaction() 方法來解決啟發式交易。可以使用 listHeuristicCommittedTransactions()listHeuristicRolledBackTransactions 方法列出啟發式完成的交易。

  • 啟用和重設訊息計數器

    可以使用 enableMessageCounters()disableMessageCounters() 方法啟用或停用訊息計數器。若要重設訊息計數器,可以調用 resetAllMessageCounters()resetAllMessageCounterHistories() 方法。

  • 檢索伺服器組態和屬性

    ActiveMQServerControl 通過其所有屬性公開 Apache ActiveMQ Artemis 伺服器組態(例如,使用 getVersion() 方法檢索伺服器的版本等)。

  • 列出、建立和銷毀核心橋接器和轉移

    可以使用 getBridgeNames()(對應 getDivertNames())方法檢索已部署的核心橋接器(對應轉移)的列表。

    可以使用管理操作 createBridge()destroyBridge()(對應 createDivert()destroyDivert())建立或銷毀核心橋接器(對應轉移)。

    可以使用管理操作 updateDivert() 更新轉移。

  • 可以停止伺服器並強制故障轉移到目前已附加的任何用戶端。

    若要執行此操作,請使用 forceFailover() 操作。

    由於此方法實際上會停止伺服器,因此您可能會收到一些錯誤,具體取決於您使用哪個管理服務來調用它。

1.2. 位址管理

可以使用 AddressControl 介面管理個別位址。

  • 修改位址的角色和權限

    您可以使用 addRole()removeRole() 方法新增或移除與佇列相關的角色。您可以使用 getRoles() 方法列出與佇列相關的所有角色

  • 暫停和恢復位址

    AddressControl 可以暫停和恢復位址以及繫結到該位址的所有佇列。新新增的佇列也將被暫停,直到該位址被恢復。因此,所有傳送到該位址的訊息都將被接收,但不會被傳遞。當它恢復時,將再次發生傳遞。

  • 封鎖和解除封鎖位址

    AddressControl 可以封鎖和解除封鎖位址。被封鎖的位址將不再向現有的生產者發出任何信用。新生產者將不會被授予任何信用。當位址被解除封鎖時,信用授予將會恢復。通過這種方式,可以耗盡與位址相關聯的所有佇列,以便以受管理的方式使代理程式靜止。

1.3. 佇列管理

大部分的管理 API 處理佇列。QueueControl 介面定義佇列管理操作。

佇列上的大多數管理操作都採用單個訊息 ID(例如,移除單個訊息)或篩選器(例如,使具有給定屬性的所有訊息過期)。

filter 參數中傳遞 null 或空字串表示管理操作將在佇列中的所有訊息上執行。

  • 使訊息過期、傳送到死信位址和移動訊息

    可以使用 expireMessages() 方法使佇列中的訊息過期。如果定義了過期位址,訊息將被傳送到該位址,否則它們將被丟棄。

    也可以使用 sendMessagesToDeadLetterAddress() 方法將訊息傳送到死信位址。它會傳回傳送到死信位址的訊息數量。如果未定義死信位址,則會從佇列中移除並丟棄訊息。

    也可以使用 moveMessages() 方法將訊息從一個佇列移動到另一個佇列。

  • 列出和移除訊息

    可以使用 listMessages() 方法從佇列中列出訊息,該方法傳回一個 Map 陣列,每個訊息對應一個 Map

    也可以使用 removeMessages() 方法從佇列中移除訊息,該方法針對單個訊息 ID 變體傳回一個 boolean,或者針對篩選器變體傳回已移除訊息的數量。removeMessages() 方法接受一個 filter 引數,以僅移除篩選的訊息。將篩選器設定為空字串實際上將移除所有訊息。

  • 計算訊息

    佇列中的訊息數量由 getMessageCount() 方法傳回。或者,countMessages() 將傳回佇列中符合給定篩選器的訊息數量。

  • 變更訊息優先權

    可以使用 changeMessagesPriority() 方法變更訊息優先權,該方法針對單個訊息 ID 變體傳回一個 boolean,或者針對篩選器變體傳回已更新訊息的數量。

  • 訊息計數器

    可以使用 listMessageCounter()listMessageCounterHistory() 方法列出佇列的訊息計數器(請參閱訊息計數器部分)。也可以使用 resetMessageCounter() 方法重設單個佇列的訊息計數器。

  • 檢索佇列屬性

    QueueControl 通過其屬性公開佇列設定(例如,如果佇列是用一個篩選器建立的,則使用 getFilter() 檢索佇列的篩選器,使用 isDurable() 了解佇列是否持久等)。

  • 暫停和恢復佇列

    QueueControl 可以暫停和恢復底層佇列。當佇列暫停時,它將接收訊息,但不會傳遞訊息。當它恢復時,它將開始傳遞已排隊的訊息(如果有的話)。

  • 停用和啟用佇列

    QueueControl 可以停用和啟用底層佇列。當佇列被停用時,將不再有訊息路由到它。當它被啟用時,它將再次開始路由訊息到它。

    如果您可能需要停用訊息路由到佇列,但希望保持用戶端活動以調查問題,而不會導致佇列中進一步累積訊息,則這非常有用。

1.4. 其他資源管理

Apache ActiveMQ Artemis 允許啟動和停止其遠端資源(接受器、轉移、橋接器等),以便在一段時間內使伺服器離線,而無需完全停止伺服器(例如,如果必須執行其他管理操作,例如解決啟發式交易)。這些資源是

  • 接受器

    可以使用 AcceptorControl 介面上的 start()stop() 方法啟動或停止它們。可以使用 AcceptorControl 屬性檢索接受器參數(請參閱 了解接受器

  • 轉移

    可以使用 DivertControl 介面上的 start()stop() 方法啟動或停止它們。可以使用 DivertControl 屬性檢索轉移參數(請參閱 轉移和分割訊息流

  • 橋接器

    可以使用 BridgeControl 介面上的 start() (或 stop()) 方法來啟動或停止橋接器。橋接器的參數可以使用 BridgeControl 的屬性來擷取 (請參閱 核心橋接器)。

  • 廣播群組

    可以使用 BroadcastGroupControl 介面上的 start()stop() 方法來啟動或停止廣播群組。廣播群組的參數可以使用 BroadcastGroupControl 的屬性來擷取 (請參閱 叢集)。

  • 叢集連線

    可以使用 ClusterConnectionControl 介面上的 start()stop() 方法來啟動或停止叢集連線。叢集連線的參數可以使用 ClusterConnectionControl 的屬性來擷取 (請參閱 叢集)。

2. 透過 JMX 管理

可以使用 JMX 來管理 Apache ActiveMQ Artemis。

管理 API 是由 Apache ActiveMQ Artemis 使用 MBean 公開。預設情況下,Apache ActiveMQ Artemis 會將其資源註冊到網域 org.apache.activemq.artemis。例如,要管理位址 exampleAddress 上名為 exampleQueue 的任何廣播佇列,其 ObjectName 為:

org.apache.activemq.artemis:broker=<brokerName>,component=addresses,address="exampleAddress",subcomponent=queues,routing-type="anycast",queue="exampleQueue"

而其 MBean 為:

org.apache.activemq.artemis.api.core.management.QueueControl

MBean 的 ObjectName 是使用輔助類別 org.apache.activemq.artemis.api.core.management.ObjectNameBuilder 建構的。以下範例說明如何使用 ObjectNameBuilder 來取得 ActiveMQServerControl 的名稱:

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()

使用 JMX 管理 Apache ActiveMQ Artemis 與使用 JMX 管理任何 Java 應用程式相同。可以透過反射或建立 MBean 的代理來完成。

2.1. 設定 JMX

預設情況下,JMX 已啟用來管理 Apache ActiveMQ Artemis。可以透過在 broker.xml 中將 jmx-management-enabled 設定為 false 來停用。

<jmx-management-enabled>false</jmx-management-enabled>

2.1.1. JMX 的角色型授權

Artemis 預設使用 Java 虛擬機器 (JVM) 的 Platform MBeanServer。這使用角色型授權來保護,該授權利用 Broker 的 JAAS 外掛程式支援。

用於限制對 MBean 及其操作存取的 RBAC 可以透過兩種方式之**一**來設定。透過 broker.xml 中的 security-settings,如 broker.xml 中的 JMX 授權 中所述,或透過下方描述的 management.xml 中的 authorization 元素。

JMX 授權在 management.xml 中

authorization 元素中有 3 個元素,allowlistdefault-accessrole-access。讓我們依次討論它們。

Allowlist 包含將繞過授權的 MBean 列表,這通常用於主控台執行等所需的任何 MBean。預設設定為:

<allowlist>
   <entry domain="hawtio"/>
</allowlist>

這表示任何網域為 hawtio 的 MBean 都將允許在沒有授權的情況下存取。例如 hawtio:plugin=artemis。您也可以為 MBean 屬性使用萬用字元,因此以下內容也將符合。

<allowlist>
   <entry domain="hawtio" key="type=*"/>
</allowlist>

allowlist 元素已取代現在已棄用的 whitelist 元素

role-access 定義角色如何對應到特定的 MBean 及其屬性和方法。預設設定如下:

<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>

這包含一個相符項,將應用於任何網域為 org.apache.activemq.artemis 的 MBean。任何對具有此網域的 MBean 的存取都由 access 元素控制,這些元素包含一個方法和一組角色。被調用的方法將用於選擇最接近的相符方法,並且將應用此方法的角色進行存取。例如,如果您嘗試在具有 org.apache.activemq.artemis 網域的 MBean 上調用名為 listMessages 的方法,則這將與方法為 list*access 相符。您也可以透過使用完整的方法名稱來明確設定,如下所示:

<access method="listMessages" roles="view,update,amq"/>

您也可以在網域中透過新增用於符合 MBean 屬性之一的索引鍵屬性來符合特定的 MBean,例如:

<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>

例如,您也可以符合特定的佇列:

org.apache.activemq.artemis:broker=<brokerName>,component=addresses,address="exampleAddress",subcomponent=queues,routing-type="anycast",queue="exampleQueue"

透過設定:

<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>

您也可以為 MBean 屬性使用萬用字元,因此以下內容也將符合,允許 MBean 屬性的首碼符合。

<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>

如果有多個相符項,則精確相符項的優先順序高於萬用字元相符項,而較長的萬用字元相符項的優先順序高於較短的萬用字元相符項。

對 JMX MBean 屬性的存取會轉換為方法呼叫,因此這些屬性會透過 set*get*is* 控制。* 存取是對所有未明確相符的其他方法的捕獲。

default-access 元素基本上是對所有未透過 role-access 設定處理的方法呼叫的捕獲。這與 match 元素具有相同的語意。

2.1.2. broker.xml 中的 JMX 授權

可以使用 broker.xml 中現有的 security-settings 進行 JMX RBAC。

使用 security-settings 中相符項的 viewedit 權限,可以替代 management.xml 中的授權區段。使用基於位址的單一安全性模型,以及可重新載入的設定,可以簡化操作。

必須使用 JVM 系統屬性設定委派給 Broker 安全管理員的 MBeanServer 攔截器,以便將其新增至 JVM 中的所有 MBeanServer。

這是透過系統屬性設定的,如下所示:

 java -Djavax.management.builder.initial=org.apache.activemq.artemis.core.server.management.ArtemisRbacMBeanServerBuilder
當提供此屬性時,必須省略/移除 management.xml 的授權區段,因為該區段取決於替代的 MBeanServer 攔截器和建構器。

用於 JMX RBAC 的 security-settings 相符位址使用 mops. (管理操作的縮寫) 首碼

MBeanServer 保護會將 JMX MBean ObjectName 對應到一般格式的階層式位址:

mops<.jmx domain><.type><.component><.name>[.operation]
對於 Broker 網域,網域會省略。

例如,要賦予 admin 角色所有 MBean 的 viewedit 權限,請使用以下 security-setting:

<security-setting match="mops.#">
   <permission type="view" roles="admin"/>
   <permission type="edit" roles="admin"/>
</security-setting>

若要僅將 managerRole 角色的 view 權限授予 activemq.management 位址,請以名稱 activemq.management 為目標,並使用 .* 來包含所有操作。

<security-setting match="mops.address.activemq.management.*">
   <permission type="view" roles="managerRole"/>
</security-setting>

若要確保沒有使用者有權限使用 Broker (伺服器控制) MBean 強制故障轉移,請使用以下內容來定義 Broker 元件上特定變動操作的空角色集:

<security-setting match="mops.broker.forceFailover">
   <permission type="edit" roles=""/>
</security-setting>

2.1.3. 使用 JConsole 的本機 JMX 存取

由於預設啟用的授權,當以「本機處理程序」連線時,Apache ActiveMQ Artemis「無法」使用 JConsole 在本機管理。這是因為 JConsole 在以這種方式連線時不會傳遞任何驗證資訊,這表示無法授權使用者執行任何管理操作。為了使用 JConsole,使用者必須完全從 management.xml 中移除 authorisation 元素來停用授權,或者啟用遠端存取並提供正確的使用者名稱和密碼認證 (接下來討論)。

2.1.4. 遠端 JMX 存取

預設情況下,為了安全性考量,Artemis 的遠端 JMX 存取已停用。

Artemis 有一個 JMX 代理程式,允許遠端存取 JMX MBean。這是透過 management.xml 設定檔中的 connector 元素設定的。若要啟用此功能,您只需新增以下 XML:

<connector connector-port="1099"/>

這會遠端將代理程式公開在埠 1099 上。如果您是透過 JConsole 連線,則您將使用服務 URL 以遠端處理程序連線:

service:jmx:rmi:///jndi/rmi://127.0.0.1:1099/jmxrmi

在這種情況下,您也可以提供適當的使用者名稱和密碼。

您也可以使用以下內容來設定連接器:

connector-host

要公開代理程式的主機。

connector-port

要公開代理程式的埠。

rmi-registry-port

RMI 登錄繫結的埠。如果未設定,則埠始終是隨機的。設定以避免通過防火牆通道傳輸的遠端 JMX 連線出現問題。

jmx-realm

用於驗證的 jmx 領域,預設為 activemq 以符合 JAAS 設定。

object-name

用於公開遠端連接器的物件名稱;預設值為 connector:name=rmi

secured

連接器是否使用 SSL 保護。

key-store-path

金鑰儲存區的位置。

key-store-password

金鑰儲存區密碼。這可以遮罩

key-store-provider

提供者;預設為 JKS

trust-store-path

信任儲存區的位置。

trust-store-password

信任儲存區密碼。這可以遮罩

trust-store-provider

提供者;預設為 JKS

password-codec

要使用的密碼編碼器的完整類別名稱。請參閱密碼遮罩文件,以取得有關此工作方式的更多詳細資訊。

請務必注意,rmi 登錄將選擇一個 IP 位址來繫結。如果系統上存在多個 IP 位址/NIC,您可以透過將以下內容新增至 artemis.profile 來選擇要使用的 IP 位址:-Djava.rmi.server.hostname=localhost

預設情況下,由於 Artemis 通過其自己的設定公開 MBean Server,因此預設未啟用使用預設 JVM 代理程式的遠端連線。這是為了讓 Artemis 可以透過 JMX 利用 JAAS 驗證層。如果您想要公開此內容,則需要透過從 management.xml 設定中移除連接器和授權來停用這兩者。請參閱Java 管理指南以設定伺服器進行遠端管理 (必須在 artemis.profile 中設定系統屬性)。

預設情況下,Apache ActiveMQ Artemis 伺服器使用 JMX 網域 "org.apache.activemq.artemis"。若要從「相同」的 MBeanServer 管理多個 Apache ActiveMQ Artemis 伺服器,可以透過在 broker.xml 中設定 jmx-domain 來設定每個個別的 Apache ActiveMQ Artemis 伺服器的 JMX 網域

<!-- use a specific JMX domain for ActiveMQ Artemis MBeans -->
<jmx-domain>my.org.apache.activemq</jmx-domain>

2.2. 範例

請參閱 JMX 管理範例,其中說明如何使用與 JMX 和 MBean 代理的遠端連線來管理 Apache ActiveMQ Artemis。

2.3. 使用 Jolokia 公開 JMX

預設 Broker 設定隨附作為 Web 應用程式部署的 Jolokia HTTP 代理程式。Jolokia 是透過 HTTP 的遠端 JMX 橋接器,會公開 MBean。有關如何使用它的完整指南,請參閱Jolokia 文件

2.3.1. 讀取屬性

一個簡單的範例來檢查代理程式是否運作中,可以使用像這樣的 curl 命令:

$ curl -s -H "Origin: https://127.0.0.1" -u myUser:myPass https://127.0.0.1:8161/console/jolokia/read/org.apache.activemq.artemis:broker=\"0.0.0.0\"/Active

或者,您可以發送 JSON 格式的 POST 請求,而不是使用 URL。

$ curl -s -H "Origin: https://127.0.0.1" -u myUser:myPass --header "Content-type: application/json" --request POST --data '{"attribute": "Active", "mbean": "org.apache.activemq.artemis:broker=\"0.0.0.0\"", "type": "read"}' https://127.0.0.1:8161/console/jolokia

預設情況下,由於在 etc/jolokia-access.xml 中配置的 CORS 檢查,因此必須傳遞 Origin 標頭。

這樣的 curl 命令會返回類似以下內容(格式化後):

{
  "request": {
    "mbean": "org.apache.activemq.artemis:broker=\"0.0.0.0\"",
    "attribute": "Version",
    "type": "read"
  },
  "value": "true",
  "timestamp": 1663086398,
  "status": 200
}

屬性的值包含在 value 中(即 true)。您可以使用像 jq 這樣的工具輕鬆解析此 JSON 資料,該工具在大多數 Linux 發行版中都可用,例如:

$ curl -s -H "Origin: https://127.0.0.1" -u myUser:myPass --header "Content-type: application/json" --request POST --data '{"attribute": "Active", "mbean": "org.apache.activemq.artemis:broker=\"0.0.0.0\"", "type": "read"}' https://127.0.0.1:8161/console/jolokia | jq -r '.value'

此命令會簡單地返回

true

請參閱 Jolokia 文件中關於 Jolokia 的 read 功能的更多詳細資訊。

2.3.2. 執行操作

除了讀取屬性之外,下一個最常見的任務是執行操作。例如,您可以使用 curl 列出與代理程式的連線,並使用 jq 解析輸出,如下所示:

$ curl -s -H "Origin: https://127.0.0.1" -u myUser:myPass "https://127.0.0.1:8161/console/jolokia/exec/org.apache.activemq.artemis:broker=\"0.0.0.0\"/listConnections/\"\"/-1/-1" | jq '.value | fromjson'

或者,您可以發送 JSON 格式的 POST 請求,而不是使用 URL。

$ curl -s -H "Origin: https://127.0.0.1" -u myUser:myPass --header "Content-type: application/json" --request POST --data '{"operation": "listConnections", "mbean": "org.apache.activemq.artemis:broker=\"0.0.0.0\"", "type": "exec", "arguments": [ "", -1, -1 ] }' https://127.0.0.1:8161/console/jolokia | jq '.value | fromjson'

這樣的命令會返回類似以下內容(格式化後):

{
  "data": [
    {
      "connectionID": "bd8d4635",
      "remoteAddress": "127.0.0.1:55754",
      "users": "",
      "creationTime": "Wed Jan 1 12:00:00 CDT 2020",
      "implementation": "RemotingConnectionImpl",
      "protocol": "CORE",
      "clientID": "",
      "localAddress": "tcp:///127.0.0.1:61616",
      "sessionCount": 2
    },
    {
      "connectionID": "2a7ac661",
      "remoteAddress": "127.0.0.1:54394",
      "users": "",
      "creationTime": "Wed Jan 1 12:00:00 CDT 2020",
      "implementation": "OpenWireConnection",
      "protocol": "OPENWIRE",
      "clientID": "ID:myMachine-34439-1727292626395-0:1",
      "localAddress": "tcp:///127.0.0.1:61616",
      "sessionCount": 3
    }
  ],
  "count": 2
}

您也可以利用管理方法選項語法來取得更精確的結果。

$ curl -s -H "Origin: https://127.0.0.1" -u myUser:myPass "https://127.0.0.1:8161/console/jolokia/exec/org.apache.activemq.artemis:broker=\"0.0.0.0\"/listConnections/\{\"field\":\"protocol\",\"operation\":\"EQUALS\",\"value\":\"OPENWIRE\"\}/-1/-1" | jq '.value | fromjson'

或者,您可以發送 JSON 格式的 POST 請求,而不是使用 URL。

$ curl -s -H "Origin: https://127.0.0.1" -u myUser:myPass --header "Content-type: application/json" --request POST --data '{"operation": "listConnections", "mbean": "org.apache.activemq.artemis:broker=\"0.0.0.0\"", "type": "exec", "arguments": [ "{\"field\":\"protocol\",\"operation\":\"EQUALS\",\"value\":\"OPENWIRE\"}", -1, -1 ] }' https://127.0.0.1:8161/console/jolokia | jq '.value | fromjson'

這樣的命令會返回類似以下內容(格式化後):

{
  "data": [
    {
      "connectionID": "2a7ac661",
      "remoteAddress": "127.0.0.1:54394",
      "users": "",
      "creationTime": "Wed Jan 1 12:00:00 CDT 2020",
      "implementation": "OpenWireConnection",
      "protocol": "OPENWIRE",
      "clientID": "ID:myMachine-34439-1727292626395-0:1",
      "localAddress": "tcp:///127.0.0.1:61616",
      "sessionCount": 3
    }
  ],
  "count": 1
}

請參閱 Jolokia 文件中關於 Jolokia 的 exec 功能的更多詳細資訊。

2.4. 管理方法選項語法

當有很多這些資源需要管理時,有時很難找到特定的資源。例如,如果與代理程式有 1,000 個連線,而您只想管理使用特定客戶端 ID 的一個特定連線。少數管理操作支援特殊的 JSON 語法,以根據以下輸入篩選結果:

  • field(請參閱下方每個管理操作的欄位清單)

  • operation

    • CONTAINS

    • NOT_CONTAINS

    • EQUALS

    • NOT_EQUALS

    • GREATER_THAN

    • LESS_THAN

  • value

  • sortField(選用)

  • sortOrder(選用)

    • asc

    • desc

以下是支援此語法的方法以及可用的欄位:

listConnections
  • connectionID

  • clientID

  • users

  • protocol

  • sessionCount

  • remoteAddress

  • localAddress

  • sessionID

  • creationTime

  • implementation

  • 範例

    {
      "field": "protocol",
      "operation": "EQUALS",
      "value": "OPENWIRE"
    }
listSessions
  • id

  • connectionID

  • consumerCount

  • producerCount

  • user

  • validatedUser

  • protocol

  • clientID

  • localAddress

  • remoteAddress

  • creationTime

  • 範例

    {
      "field": "remoteAddress",
      "operation": "CONTAINS",
      "value": "127.0.0.1"
    }
listAddresses
  • id

  • name

  • routingTypes

  • producerId

  • queueCount

  • internal

  • 範例

    {
      "field": "name",
      "operation": "CONTAINS",
      "value": "shipping"
    }
listQueues
  • id

  • name

  • consumerID

  • address

  • maxConsumers

  • filter

  • messageCount

  • consumerCount

  • deliveringCount

  • messagesAdded

  • messagesAcked

  • messagesExpired

  • routingType

  • user

  • autoCreated

  • durable

  • paused

  • temporary

  • purgeOnNoConsumers

  • messagesKilled

  • directDeliver

  • lastValue

  • exclusive

  • scheduledCount

  • lastValueKey

  • groupRebalance

  • groupRebalancePauseDispatch

  • groupBuckets

  • groupFirstKey

  • enabled

  • ringSize

  • consumersBeforeDispatch

  • delayBeforeDispatch

  • autoDelete

  • internalQueue

  • 範例

    {
      "field": "consumerCount",
      "operation": "GREATER_THAN",
      "value": "7"
    }
listConsumers
  • idconsumerID

  • sequentialIdsequentialId

  • sessionsessionID

  • connectionconnectionID

  • queuequeueName

  • filter

  • address

  • user

  • validatedUser

  • protocol

  • clientID

  • localAddress

  • remoteAddress

  • queueType

  • browseOnly

  • creationTime

  • messagesInTransitdeliveringCount

  • messagesInTransitSize

  • messagesDelivered

  • messagesDeliveredSize

  • messagesAcknowledged

  • messagesAcknowledgedAwaitingCommit

  • lastDeliveredTime

  • lastAcknowledgedTime

  • status

  • 範例

    {
      "field": "messagesAcknowledged",
      "operation": "LESS_THAN",
      "value": "10"
    }
listProducers
  • id

  • name

  • sessionsessionID

  • connectionID

  • addressdestination

  • user

  • validatedUser

  • protocol

  • clientID

  • localAddress

  • remoteAddress

  • creationTime

  • msgSent

  • msgSizeSent

  • lastProducedMessageID

  • 範例

    {
      "field": "validatedUser",
      "operation": "EQUALS",
      "value": "bob"
    }

2.4.1. 排序

結果可以按照任何欄位以遞增 (asc) 或遞減 (desc) 順序排序。例如,在呼叫 listConnections 時使用類似這樣的語法,可以取得所有 AMQP 連線,並將最新的連線放在最前面。

{
  "field": "protocol",
  "operation": "EQUALS",
  "value": "AMQP",
  "sortField": "creationTime",
  "sortOrder": "desc"
}

2.4.2. 分頁

這些方法也支援分頁。換句話說,結果可以分為多個群組,然後逐頁瀏覽。第二個參數是「頁碼」(即要檢查哪一頁),第三個參數是「頁面大小」(即每頁要返回多少個結果)。例如,這就是 Web 主控台顯示分頁結果的方式。

若要停用分頁,請為頁碼或頁面大小(或兩者)傳遞 -1

2.5. JMX 和 Web 主控台

Artemis 附帶的 Web 主控台在底層使用 Jolokia,而 Jolokia 又使用 JMX。這將使用JMX 的基於角色的授權章節中描述的驗證配置。這表示當透過主控台存取 MBean 時,會使用登入主控台所用的認證以及與之相關聯的角色。預設情況下,只有具有 amq 角色的使用者才能存取主控台。這是在 artemis.profile 中透過系統屬性 -Dhawtio.role=amq 配置的。您可以將此變更為 -Dhawtio.roles=amq,view,update 來配置多個角色。

如果使用者沒有正確的角色來調用特定操作,則這會在主控台中顯示授權例外。

2.5.1. ArtemisRbacMBeanServerBuilder 和 ArtemisRbacInvocationHandler

ArtemisRbacMBeanServerBuilder 類別配置為系統屬性 javax.management.builder.initial 的值時,會導致在 JVM 中的每個 JMX MBeanServer 上安裝 ArtemisRbacInvocationHandlerArtemisRbacInvocationHandler 會攔截 MBeanServer 上的所有操作,並選擇保護這些操作的子集。

對於受保護的操作,需要 viewedit 權限才能進行調用。如果目前已驗證的主題沒有所需的角色來授予這些權限,則會擲回安全性例外。

對於 MBeanServer 上的查詢操作,查詢的結果僅限於具有所需 view 權限的項目。

3. 使用管理訊息 API

ActiveMQ Artemis 中的管理訊息 API 是透過將核心客戶端訊息傳送到一個特殊位址(即管理位址)來存取的。

管理訊息是具有伺服器需要理解的已知屬性的常規核心客戶端訊息,以便與管理 API 互動。

  • 受管理資源的名稱

  • 管理操作的名稱

  • 管理操作的參數

當此類管理訊息傳送到管理位址時,Apache ActiveMQ Artemis 伺服器會處理它、提取資訊、調用受管理資源上的操作,並將管理回覆傳送到管理訊息的回覆位址(由 ClientMessageImpl.REPLYTO_HEADER_NAME 指定)。

可以使用 ClientConsumer 來取用管理回覆,並從回覆的本文中檢索操作的結果(如果有的話)。為了可移植性,結果會以 JSON 字串而不是 Java 序列化傳回(可以使用 org.apache.activemq.artemis.api.core.management.ManagementHelper 將 JSON 字串轉換為 Java 物件)。

這些步驟可以簡化,以便更容易地使用核心訊息調用管理操作:

  1. 建立一個 ClientRequestor 以將訊息傳送到管理位址並接收回覆

  2. 建立一個 ClientMessage

  3. 使用輔助類別 org.apache.activemq.artemis.api.core.management.ManagementHelper 以使用管理屬性填入訊息

  4. 使用 ClientRequestor 傳送訊息

  5. 使用輔助類別 org.apache.activemq.artemis.api.core.management.ManagementHelper 從管理回覆中檢索操作結果。

例如,若要找出佇列 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 套件中定義的 Java 介面。

資源的名稱是使用輔助類別 org.apache.activemq.artemis.api.core.management.ResourceNames 建構的,而且很簡單(例如,佇列 exampleQueueQueueControlqueue.exampleQueue,或 ActiveMQServerControlbroker)。

ManagementHelper 類別只能與核心 JMS 訊息搭配使用。當使用來自不同 JMS 程式庫的訊息呼叫時,會擲回例外。

3.1. 配置管理

傳送管理訊息的管理位址是在 broker.xml 中配置的

<management-address>activemq.management</management-address>

預設情況下,位址為 activemq.management

管理位址需要一個特殊的使用者權限 manage,才能夠接收和處理管理訊息。這也會在 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>

3.2. 管理訊息的精細 RBAC

可以選擇在傳送到管理位址的管理訊息內容上使用 RBAC。透過將屬性 management-message-rbac 設定為 true 來啟用 RBAC。

需要 manage 權限才能透過訊息執行管理操作。viewedit 權限必須與 manage 權限結合使用。

啟用時,可以透過安全性設定配置對傳送到管理位址的管理訊息內容進行更精細的權限設定。

用於 RBAC 的安全性設定比對位址會遵循以下一般階層形式: management-rbac-prefix、元件類型、元件名稱、操作。其中值是從管理訊息標頭中提取的。

<management-rbac-prefix>.<resource type>.<resource name>.<operation>

不可變的操作和屬性存取將需要 view 權限,所有其他操作將需要 edit 權限。

在下列範例中,dataImport 角色只能存取佇列的 id 屬性,這是 資料匯入命令列工具所需的唯一管理操作。

<security-setting match="mops.queue.*.getID">
   <permission type="view" roles="dataImport" />
   <permission type="manage" roles="dataImport" />
</security-setting>

如果您想要讓 admin 角色擁有完整存取權,請在 management-rbac-prefix 之後使用萬用字元,並同時授與 viewedit 權限

<security-setting match="mops.#">
   <permission type="view" roles="admin" />
   <permission type="update" roles="admin" />
   <permission type="manage" roles="admin" />
</security-setting>

3.3. 管理範例

請參閱管理範例,其中說明如何使用 JMS 訊息管理 Apache ActiveMQ Artemis 伺服器。

4. 管理通知

Apache ActiveMQ Artemis 會發出通知,以告知接聽者可能感興趣的事件(新資源的建立、安全性違規等等)。

這些通知可以透過兩種不同的方式接收:

  • JMX 通知

  • 通知訊息

4.1. JMX 通知

如果啟用 JMX(請參閱配置 JMX 章節),則可以透過訂閱 org.apache.activemq.artemis:type=Broker,brokerName=<broker name>,module=Core,serviceType=Server 來接收關於資源的 JMX 通知。

4.2. 通知訊息

Apache ActiveMQ Artemis 定義了一個特殊的管理通知位址。佇列可以綁定到這個位址,以便客戶端能夠接收到以訊息形式呈現的管理通知。

想要接收管理通知的客戶端必須建立一個綁定到管理通知位址的佇列。然後,它就可以從其佇列接收通知。

通知訊息是具有額外屬性的常規訊息,這些屬性對應於通知(其類型、發生時間、相關資源等)。

由於通知是常規訊息,因此可以使用訊息選擇器來篩選通知,並且只接收伺服器發出的所有通知的子集。

4.2.1. 設定管理通知位址

用於接收管理通知的管理通知位址在 broker.xml 中設定。

<management-notification-address>activemq.notifications</management-notification-address>

預設情況下,該位址為 activemq.notifications

4.2.2. 抑制會話通知

某些訊息傳遞模式會產生大量的 SESSION_CREATEDSESSION_CLOSED 通知。在叢集環境中,這會帶來一些計算開銷。如果這些通知沒有其他用途,則可以透過以下方式停用它們:

<suppress-session-notifications>true</suppress-session-notifications>

唯一需要這些通知的情況是在具有 MQTT 客戶端的叢集中,其中需要強制執行唯一的客戶端 ID 使用。預設值為 false

4.2.3. 接收通知訊息

可以使用 Apache ActiveMQ Artemis 的核心 JMS 客戶端來接收通知。

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("------------------------");
   }
});

4.3. 範例

請參閱管理通知範例,該範例示範如何使用 JMS MessageListener 從 ActiveMQ Artemis 伺服器接收管理通知。

4.4. 通知類型和標頭

以下是所有不同類型的通知以及訊息上的標頭的列表。每個通知都有一個 _AMQ_NotifType(括號中註明的值)和 _AMQ_NotifTimestamp 標頭。時間戳記是對 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)

factoryid

ACCEPTOR_STOPPED (17)

factoryid

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

5. 訊息計數器

訊息計數器可用於獲取佇列的隨時間資訊,因為 Apache ActiveMQ Artemis 會保留佇列指標的歷史記錄。

它們可用於顯示佇列的趨勢。例如,使用管理 API,可以定期查詢佇列中的訊息數。但是,這不足以了解佇列是否正在使用:訊息數量可能保持不變,因為沒有人從佇列傳送或接收訊息,或者因為傳送到佇列的訊息與從佇列消耗的訊息一樣多。在這兩種情況下,佇列中的訊息數量保持相同,但其使用方式差異很大。

訊息計數器提供有關佇列的其他資訊。

count

自伺服器啟動以來新增到佇列的訊息總數

countDelta

自上次訊息計數器更新以來新增到佇列的訊息數

messageCount

佇列中訊息的目前數量

messageCountDelta

自上次訊息計數器更新以來新增/從佇列移除的訊息的總體數量。例如,如果 messageCountDelta 等於 -10,則表示總共有 10 個訊息已從佇列中移除(例如,新增了 2 個訊息,移除了 12 個)。

lastAddTimestamp

上次將訊息新增到佇列的時間戳記

lastAckTimestamp

上次確認佇列中訊息的時間戳記

updateTimestamp

上次訊息計數器更新的時間戳記

這些屬性也可用於確定其他有意義的資料。例如,要具體了解自上次更新以來從佇列中消耗了多少訊息,只需從 countDelta 中減去 messageCountDelta 即可。

5.1. 設定訊息計數器

預設情況下,訊息計數器已停用,因為它可能會對記憶體產生輕微的負面影響。

要啟用訊息計數器,您可以在 broker.xml 中將其設定為 true

<message-counter-enabled>true</message-counter-enabled>

訊息計數器會保留佇列指標的歷史記錄(預設為 10 天),並定期(預設為 10 秒)對所有佇列進行採樣。如果啟用訊息計數器,則應在 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>

可以使用管理 API 檢索訊息計數器。例如,要使用 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());

5.2. 範例

請參閱訊息計數器範例,該範例示範如何使用訊息計數器來檢索佇列上的資訊。