裂腦是一種情況,當兩個不同的代理程式同時服務相同的訊息時會發生。當發生這種情況時,用戶端應用程式不是像應該的那樣都共享同一個代理程式,而是可能會被分為兩個裂腦代理程式。這是有問題的,因為它可能導致
-
重複訊息,例如,當同一個 JMS 佇列上的多個消費者在兩個代理程式之間分割並收到相同的訊息時
-
遺漏訊息,例如,當同一個 JMS 主題上的多個消費者在兩個代理程式之間分割,而生產者只將訊息發送到一個代理程式時
裂腦最常發生在 HA 複製配置中的一對代理程式失去連接它們的複製連線時。當此連線遺失時,備份會假設主要代理程式已死亡,因此會啟動。此時,網路上有兩個彼此隔離的代理程式,並且由於備份具有來自主要代理程式的所有訊息副本,因此它們各自服務相同的訊息。
共享儲存配置呢?
雖然在技術上,HA 共享儲存配置中的一對代理程式也可能發生裂腦,但這需要代理程式共享的儲存裝置的檔案鎖定機制發生故障。 使用共享儲存的好處之一是,儲存裝置本身充當仲裁者,以確保一致性並減輕裂腦。 |
從裂腦中恢復可能就像停止錯誤啟動的代理程式一樣簡單。但是,只有在沒有用戶端應用程式連接到它並執行訊息傳遞操作時,此解決方案才是可行的。允許用戶端應用程式與裂腦代理程式互動的時間越長,就越難理解和解決由此產生的問題。
您可以選擇幾種不同的配置,這將有助於減輕裂腦。
1. 可插拔鎖管理器
可插拔鎖管理器配置需要第三方在主要和備份代理程式之間建立共享鎖。共享鎖確保在任何給定時間點只有主要或備份代理程式處於活動狀態,類似於共享儲存用例中檔案鎖的功能。
外掛程式決定使用哪個第三方實現。它可以像支援鎖定的網路檔案系統(例如 NFS)上的共享檔案一樣簡單,也可以像 etcd 這樣更複雜的東西。
代理程式附帶一個基於 Apache ZooKeeper 的參考外掛程式實作,這是用於此類任務的常見實作。
可插拔鎖管理器的主要好處是它將建立可靠投票的責任從代理程式中釋放出來。這表示可以可靠地保護單個 HA 代理程式對,免於裂腦。
2. 多數決投票
多數決投票是一個流程,叢集中的一個節點可以確定叢集中的另一個節點是否處於活動狀態,而無需直接與該節點通信。然後,啟動投票的代理程式可以根據結果採取行動(例如,關閉自身以避免裂腦)。
多數決投票需要叢集中其他活動代理程式的參與。當然,這需要叢集中確實存在其他活動代理程式,這意味著多數決投票不能用於單個 HA 代理程式對。此外,它也不能用於僅有兩對 HA 代理程式,因為這仍然不足以構成合法的多數。必須至少有三對 HA 才能透過多數決投票建立適當的多數。
2.1. 投票機制
當主要代理程式和備份代理程式之間的複製連線遺失時,備份和/或主要代理程式可能會啟動投票。
為了使投票通過,需要多數肯定回應。例如,在 3 節點叢集中,投票將以 2 個肯定回應通過。對於 4 節點叢集,則需要 3 個肯定回應,依此類推。 |
2.1.1. 備份投票
預設情況下,如果備份失去與其主要代理程式的複製連線,它將自動啟動。但是,可以透過 vote-on-replication-failure
屬性進行配置,以啟動多數決投票,以決定是否啟動。如果這樣做,備份將繼續投票,直到它收到允許其啟動的投票,或偵測到主要代理程式仍然處於活動狀態。在後一種情況下,它將重新啟動為備份。
有關配置的更多詳細資訊,請參閱複製配置一節。
2.1.2. 主要投票
預設情況下,如果主要伺服器失去與備份的複製連線,它將繼續執行並等待備份重新連線並再次開始複製。但是,這可能表示主要伺服器即使在備份已啟動的情況下仍然處於活動狀態,因此可以透過 vote-on-replication-failure
屬性配置此行為。
有關配置的更多詳細資訊,請參閱複製配置一節。
3. 網路 Ping
您可以在 broker.xml
中設定一個或多個在伺服器生命週期內將被 ping 的位址。如果伺服器無法 ping 通列表中的一個或多個位址,它將停止自身。
如果您使用 --ping
引數執行 create
命令,您將建立一個可立即用於網路檢查的預設 XML。
$ ./artemis create /myDir/myServer --ping 10.0.0.1
此 XML 將新增至您的 broker.xml
<!--
You can verify the network health of a particular NIC by specifying the <network-check-NIC> element.
<network-check-NIC>theNicName</network-check-NIC>
-->
<!--
Use this to use an HTTP server to validate the network
<network-check-URL-list>http://www.apache.org</network-check-URL-list> -->
<network-check-period>10000</network-check-period>
<network-check-timeout>1000</network-check-timeout>
<!-- this is a comma separated list, no spaces, just DNS or IPs
it should accept IPV6
Warning: Make sure you understand your network topology as this is meant to check if your network is up.
Using IPs that could eventually disappear or be partially visible may defeat the purpose.
You can use a list of multiple IPs, any successful ping will make the server OK to continue running -->
<network-check-list>10.0.0.1</network-check-list>
<!-- use this to customize the ping used for ipv4 addresses -->
<network-check-ping-command>ping -c 1 -t %d %s</network-check-ping-command>
<!-- use this to customize the ping used for ipv6 addresses -->
<network-check-ping6-command>ping6 -c 1 %2$s</network-check-ping6-command>
一旦您遺失到指定範例中 10.0.0.1
的連線,代理程式將記錄類似以下內容
09:49:24,562 WARN [org.apache.activemq.artemis.core.server.NetworkHealthCheck] Ping Address /10.0.0.1 wasn't reacheable 09:49:36,577 INFO [org.apache.activemq.artemis.core.server.NetworkHealthCheck] Network is unhealthy, stopping service ActiveMQServerImpl::serverUUID=04fd5dd8-b18c-11e6-9efe-6a0001921ad0 09:49:36,625 INFO [org.apache.activemq.artemis.core.server] AMQ221002: Apache ActiveMQ Artemis Message Broker version 1.6.0 [04fd5dd8-b18c-11e6-9efe-6a0001921ad0] stopped, uptime 14.787 seconds 09:50:00,653 WARN [org.apache.activemq.artemis.core.server.NetworkHealthCheck] ping: sendto: No route to host 09:50:10,656 WARN [org.apache.activemq.artemis.core.server.NetworkHealthCheck] Host is down: java.net.ConnectException: Host is down at java.net.Inet6AddressImpl.isReachable0(Native Method) [rt.jar:1.8.0_73] at java.net.Inet6AddressImpl.isReachable(Inet6AddressImpl.java:77) [rt.jar:1.8.0_73] at java.net.InetAddress.isReachable(InetAddress.java:502) [rt.jar:1.8.0_73] at org.apache.activemq.artemis.core.server.NetworkHealthCheck.check(NetworkHealthCheck.java:295) [artemis-commons-1.6.0-SNAPSHOT.jar:1.6.0-SNAPSHOT] at org.apache.activemq.artemis.core.server.NetworkHealthCheck.check(NetworkHealthCheck.java:276) [artemis-commons-1.6.0-SNAPSHOT.jar:1.6.0-SNAPSHOT] at org.apache.activemq.artemis.core.server.NetworkHealthCheck.run(NetworkHealthCheck.java:244) [artemis-commons-1.6.0-SNAPSHOT.jar:1.6.0-SNAPSHOT] at org.apache.activemq.artemis.core.server.ActiveMQScheduledComponent$2.run(ActiveMQScheduledComponent.java:189) [artemis-commons-1.6.0-SNAPSHOT.jar:1.6.0-SNAPSHOT] at org.apache.activemq.artemis.core.server.ActiveMQScheduledComponent$3.run(ActiveMQScheduledComponent.java:199) [artemis-commons-1.6.0-SNAPSHOT.jar:1.6.0-SNAPSHOT] at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) [rt.jar:1.8.0_73] at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:308) [rt.jar:1.8.0_73] at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:180) [rt.jar:1.8.0_73] at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:294) [rt.jar:1.8.0_73] at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [rt.jar:1.8.0_73] at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [rt.jar:1.8.0_73] at java.lang.Thread.run(Thread.java:745) [rt.jar:1.8.0_73]
一旦您重新建立到已設定檢查清單的網路連線
09:53:23,461 INFO [org.apache.activemq.artemis.core.server.NetworkHealthCheck] Network is healthy, starting service ActiveMQServerImpl:: 09:53:23,462 INFO [org.apache.activemq.artemis.core.server] AMQ221000: primary Message Broker is starting with configuration Broker Configuration (clustered=false,journalDirectory=./data/journal,bindingsDirectory=./data/bindings,largeMessagesDirectory=./data/large-messages,pagingDirectory=./data/paging) 09:53:23,462 INFO [org.apache.activemq.artemis.core.server] AMQ221013: Using NIO Journal 09:53:23,462 INFO [org.apache.activemq.artemis.core.server] AMQ221043: Protocol module found: [artemis-server]. Adding protocol support for: CORE 09:53:23,463 INFO [org.apache.activemq.artemis.core.server] AMQ221043: Protocol module found: [artemis-amqp-protocol]. Adding protocol support for: AMQP 09:53:23,463 INFO [org.apache.activemq.artemis.core.server] AMQ221043: Protocol module found: [artemis-hornetq-protocol]. Adding protocol support for: HORNETQ 09:53:23,463 INFO [org.apache.activemq.artemis.core.server] AMQ221043: Protocol module found: [artemis-mqtt-protocol]. Adding protocol support for: MQTT 09:53:23,464 INFO [org.apache.activemq.artemis.core.server] AMQ221043: Protocol module found: [artemis-openwire-protocol]. Adding protocol support for: OPENWIRE 09:53:23,464 INFO [org.apache.activemq.artemis.core.server] AMQ221043: Protocol module found: [artemis-stomp-protocol]. Adding protocol support for: STOMP 09:53:23,541 INFO [org.apache.activemq.artemis.core.server] AMQ221003: Deploying queue jms.queue.DLQ 09:53:23,541 INFO [org.apache.activemq.artemis.core.server] AMQ221003: Deploying queue jms.queue.ExpiryQueue 09:53:23,549 INFO [org.apache.activemq.artemis.core.server] AMQ221020: Started Acceptor at 0.0.0.0:61616 for protocols [CORE,MQTT,AMQP,STOMP,HORNETQ,OPENWIRE] 09:53:23,550 INFO [org.apache.activemq.artemis.core.server] AMQ221020: Started Acceptor at 0.0.0.0:5445 for protocols [HORNETQ,STOMP] 09:53:23,554 INFO [org.apache.activemq.artemis.core.server] AMQ221020: Started Acceptor at 0.0.0.0:5672 for protocols [AMQP] 09:53:23,555 INFO [org.apache.activemq.artemis.core.server] AMQ221020: Started Acceptor at 0.0.0.0:1883 for protocols [MQTT] 09:53:23,556 INFO [org.apache.activemq.artemis.core.server] AMQ221020: Started Acceptor at 0.0.0.0:61613 for protocols [STOMP] 09:53:23,556 INFO [org.apache.activemq.artemis.core.server] AMQ221007: Server is now active 09:53:23,556 INFO [org.apache.activemq.artemis.core.server] AMQ221001: Apache ActiveMQ Artemis Message Broker version 1.6.0 [0.0.0.0, nodeID=04fd5dd8-b18c-11e6-9efe-6a0001921ad0]
請確保您了解您的網路拓撲,因為這是為了驗證您的網路。使用最終可能消失或部分可見的 IP 可能會適得其反。您可以使用多個 IP 的清單。任何成功的 ping 都將使伺服器可以繼續執行 |