簡介
慢消費者在非持久性主題上會出現問題,因爲它們會強制broker爲它們在內存保留舊消息。一旦填滿,就會導致broker放慢生產者的速度,導致快的消費者也會變慢。
目前,有一個策略可以讓你配置broker除了prefect bufer之外還將爲消費者保留的最大匹配的消息數。在達到此最大值後,當新消息進入時,舊消息將被丟棄。這將允許你在內存中保留當前消息並繼續向慢消費者發送消息,但會丟棄舊消息。
Pending Message Limit Strategy
你可以在Destination map配置PendingMessageLimitStrategy的實現類,以便不同topic有不用的策略來處理慢速消費者。例如,你可能希望將此策略引用於價格非常高的,但對於交易和訂單而言,你可能不希望丟棄舊的消息。
該策略計算消費者在內存中保留的最大待處理消息數(高於prefetch size)。值爲0意味着除了prefect size外不保留任何消息。大於0的值將保留該數量的消息,在新消息進入時丟棄舊的消息。值爲-1表示禁止丟棄消息。
目前有兩種不同的策略實現:
- ConstantPendingMessageLimitStrategy
- PrefetchRatePendingMessageLimitStrategy
ConstantPendingMessageLimitStrategy
此策略對所有使用者使用常量限制(高於其預取大小)。
示例:
<constantPendingMessageLimitStrategy limit="50"/>
PrefetchRatePendingMessageLimitStrategy
此種策略是將prefect size 乘以一個你配置的數來計算待處理消息的最大數量。比如,你可以爲每個消費者保留大約2.5倍的prefect size的消息。
示例:
<prefetchRatePendingMessageLimitStrategy multiplier="2.5"/>
使用Prefect策略來配置限制
在JMS客戶端,您可以爲持久性的和非持久性的queue和topic配置prefect策略。prefect策略還允許爲每個連接/消費者指定最大的預處理消息的數量。
prefect 策略參考:http://activemq.apache.org/what-is-the-prefetch-limit-for.html
配置驅逐策略
ActiveMQ有一個MessageEvictionStrategy,用於決定哪個消息應該在慢速消費者身上被驅逐。 默認實現是:
<oldestMessageEvictionStrategy/>
這表示丟棄最舊的消息。
你還可以根據JMS消息屬性來丟棄給定屬性的消息。
示例:
<uniquePropertyMessageEvictionStrategy propertyName="STOCK"/>
propertyName是爲特定的價格指定的JMS消息屬性。上面的示例表示移除有STOCK屬性且最舊的消息。
另外,還可以刪除最低優先級且最舊的消息。
<oldestMessageWithLowestPriorityEvictionStrategy/>
示例
下面的例子展示了ActiveMQ borker的配置文件。對於PRICES.>通配符範圍的topic,pendingMessageLimitStrategy屬性設置爲僅爲每個消費者保留除Prefetch size外,再保留10條消息。
<?xml version="1.0" encoding="utf-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:amq="http://activemq.apache.org/schema/core" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://activemq.apache.org/schema/core http://activemq.apache.org/schema/core/activemq-core.xsd">
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"/>
<broker xmlns="http://activemq.apache.org/schema/core" persistent="false" brokerName="${brokername}">
<!-- lets define the dispatch policy -->
<destinationPolicy>
<policyMap>
<policyEntries>
<policyEntry topic="FOO.>">
<!--消息分發策略:使用輪詢策略-->
<dispatchPolicy>
<roundRobinDispatchPolicy/>
</dispatchPolicy>
<!--恢復策略:只恢復最後1個消息-->
<subscriptionRecoveryPolicy>
<lastImageSubscriptionRecoveryPolicy/>
</subscriptionRecoveryPolicy>
</policyEntry>
<!--對於ORDERS.開頭的topic,消息分發策略爲:按順序分發-->
<policyEntry topic="ORDERS.>">
<dispatchPolicy>
<strictOrderDispatchPolicy/>
</dispatchPolicy>
<!-- 恢復最近1分鐘內的消息 -->
<subscriptionRecoveryPolicy>
<timedSubscriptionRecoveryPolicy recoverDuration="60000"/>
</subscriptionRecoveryPolicy>
</policyEntry>
<policyEntry topic="PRICES.>">
<!-- lets force old messages to be discarded for slow consumers -->
<pendingMessageLimitStrategy>
<constantPendingMessageLimitStrategy limit="10"/>
</pendingMessageLimitStrategy>
<!-- 10 seconds worth -->
<subscriptionRecoveryPolicy>
<timedSubscriptionRecoveryPolicy recoverDuration="10000"/>
</subscriptionRecoveryPolicy>
</policyEntry>
<policyEntry tempTopic="true" advisoryForConsumed="true"/>
<policyEntry tempQueue="true" advisoryForConsumed="true"/>
</policyEntries>
</policyMap>
</destinationPolicy>
</broker>
</beans>
使用技巧
如果你知道某個特定的消費者會變慢,那麼設置它的prefect size小於快速消費者的大小。
例如,如果您知道特定服務器速度很慢並且您的消息速率非常高並且您有一些非常快的消費者,那麼您可能希望啓用此功能並將慢速服務器上的預取設置爲略低於 快速服務器。
監測慢消費者的狀況
您還可以使用JMX控制檯查看活動訂閱的統計信息。 這允許您在TopicSubscriptionViewMBean上查看以下統計信息:
統計信息 | 說明 |
---|---|
discarded | 在成爲慢速消費者後,在訂閱的生命週期中丟棄了多少條消息 |
matched | 當前匹配的消息數量,只要預取緩衝區中有一些容量可用,就會立即發送到訂閱。因此,非零值意味着此訂閱的預取緩衝區已滿 |