转自 首夜盲毒预言家
参考资料:https://www.rabbitmq.com/maxlength.html
RabbitMQ 有两种方式限制队列长度,第一种是对队列中消息总数进行限制:
gordon.study.rabbitmq.features.TestQueueLengthLimit.java
<span style="color:#333333"><code><span style="color:#0000ff">public</span> <span style="color:#0000ff">class</span> <span style="color:#a31515">TestQueueLengthLimit</span> {
<span style="color:#0000ff">private</span> <span style="color:#0000ff">static</span> <span style="color:#0000ff">final</span> String QUEUE_NAME = <span style="color:#a31515">"queueLengthLimit"</span>;
<span style="color:#0000ff">public</span> <span style="color:#0000ff">static</span> <span style="color:#0000ff">void</span> <span style="color:#a31515">main</span>(String[] argv) <span style="color:#0000ff">throws</span> Exception {
ConnectionFactory factory = <span style="color:#0000ff">new</span> ConnectionFactory();
factory.setHost(<span style="color:#a31515">"localhost"</span>);
Connection connection = factory.newConnection();
Channel senderChannel = connection.createChannel();
Channel consumerChannel = connection.createChannel();
<span style="color:green">// 设置队列最大消息数量为5</span>
Map<String, Object> args = <span style="color:#0000ff">new</span> HashMap<String, Object>();
args.put(<span style="color:#a31515">"x-max-length"</span>, 5);
senderChannel.queueDeclare(QUEUE_NAME, <span style="color:#0000ff">false</span>, <span style="color:#0000ff">false</span>, <span style="color:#0000ff">true</span>, args);
<span style="color:green">// 发布6个消息</span>
<span style="color:#0000ff">for</span> (<span style="color:#0000ff">int</span> i = 0; i < 6;) {
String message = <span style="color:#a31515">"NO. "</span> + ++i;
senderChannel.basicPublish(<span style="color:#a31515">""</span>, QUEUE_NAME, <span style="color:#0000ff">null</span>, message.getBytes(<span style="color:#a31515">"UTF-8"</span>));
}
<span style="color:green">// 获取的消息为 NO. 2,说明队列头部第一条消息被抛弃</span>
Thread.sleep(100);
GetResponse resp = consumerChannel.basicGet(QUEUE_NAME, <span style="color:#0000ff">false</span>);
String message = <span style="color:#0000ff">new</span> String(resp.getBody(), <span style="color:#a31515">"UTF-8"</span>);
System.out.printf(<span style="color:#a31515">"consume: %s\n"</span>, message);
System.out.printf(<span style="color:#a31515">"queue size: %d\n"</span>, resp.getMessageCount());
<span style="color:green">// 现在队列中有4个 Ready消息,1个 Unacked消息。此时再发布两条消息,应该只有 NO. 3 被抛弃。</span>
senderChannel.basicPublish(<span style="color:#a31515">""</span>, QUEUE_NAME, <span style="color:#0000ff">null</span>, <span style="color:#a31515">"NO. 7"</span>.getBytes(<span style="color:#a31515">"UTF-8"</span>));
senderChannel.basicPublish(<span style="color:#a31515">""</span>, QUEUE_NAME, <span style="color:#0000ff">null</span>, <span style="color:#a31515">"NO. 8"</span>.getBytes(<span style="color:#a31515">"UTF-8"</span>));
Thread.sleep(100);
GetResponse resp2 = consumerChannel.basicGet(QUEUE_NAME, <span style="color:#0000ff">false</span>);
message = <span style="color:#0000ff">new</span> String(resp2.getBody(), <span style="color:#a31515">"UTF-8"</span>);
System.out.printf(<span style="color:#a31515">"consume: %s\n\n"</span>, message);
<span style="color:green">// 现在队列中有4个 Ready消息,2个 Unacked消息。</span>
<span style="color:green">// 此时Nack,消息2、4取消退回队列头导致队列消息数量超过设定值,谁能留下?</span>
consumerChannel.basicNack(resp2.getEnvelope().getDeliveryTag(), <span style="color:#0000ff">true</span>, <span style="color:#0000ff">true</span>);
Thread.sleep(100);
<span style="color:#0000ff">while</span> (<span style="color:#0000ff">true</span>) {
resp = consumerChannel.basicGet(QUEUE_NAME, <span style="color:#0000ff">true</span>);
<span style="color:#0000ff">if</span> (resp == <span style="color:#0000ff">null</span>) {
<span style="color:#0000ff">break</span>;
} <span style="color:#0000ff">else</span> {
message = <span style="color:#0000ff">new</span> String(resp.getBody(), <span style="color:#a31515">"UTF-8"</span>);
System.out.printf(<span style="color:#a31515">"consume: %s\n"</span>, message);
}
}
}
}</code></span>
顾名思义,x-max-length 参数限制了一个队列的消息总数,当消息总数达到限定值时,队列头的消息会被抛弃。
此外,处于 Unacked 状态的消息不纳入消息总数计算。但是,当 Unacked 消息被 reject 并重新入队时,就会受 x-max-length 参数限制,可能回不了队列。
第二种是对队列中消息体总字节数进行限制:
Map<String, Object> args = new HashMap<String, Object>();
args.put("x-max-length-bytes ", 1000);
senderChannel.queueDeclare(QUEUE_NAME, false, false, true, args);
只计算消息体的字节数,不算消息头、消息属性等字节数。