消息中间件 -RabbitMQ QoS预取模式 (二十五)

在确认消息被接收之前,消费者可以预先要求接收一定数量的消息,在处理完一定数量的消息后,批量进行确认。如果消费者应用程序在确认消息之前崩溃,则所有未确认的消息将被重新发送给其他消费者。所以这里存在着一定程度上的可靠性风险。

这种机制一方面可以实现限速(将消息暂存到RabbitMQ内存中)的作用,一方面可以保证消息确认质量(比如确认了但是处理有异常的情况)。

 注意:

消费确认模式必须是非自动ACK机制(这个是使用baseQos的前提条件,否则会Qos不生效),然后设置basicQos的值;另外,还可以基于consume和channel的粒度进行设置(global)。

basicQos方法参数详细解释:

prefetchSize:最多传输的内容的大小的限制,0为不限制,但据说prefetchSize参数,rabbitmq没有实现。

prefetchCount:会告诉RabbitMQ不要同时给一个消费者推送多于N个消息,即一旦有N个消息还没有ack,则该consumer将block掉,直到有消息ack

global:true\false 是否将上面设置应用于channel,简单点说,就是上面限制是channel级别的还是consumer级别。

如果同时设置channel和消费者,会怎么样?AMQP规范没有解释如果使用不同的全局值多次调用basic.qos会发生什么。 RabbitMQ将此解释为意味着两个预取限制应该彼此独立地强制执行; 消费者只有在未达到未确认消息限制时才会收到新消息。

channel.basicQos(10, false); // Per consumer limit

channel.basicQos(15, true);  // Per channel limit

channel.basicConsume("my-queue1", false, consumer1);

channel.basicConsume("my-queue2", false, consumer2);

也就是说,整个通道加起来最多允许15条未确认的消息,每个消费者则最多有10条消息。

代码实现:

普通消费者

public class QosConsumerMain {

    public static void main(String[] argv)
            throws IOException, TimeoutException {
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("127.0.0.1");

        // 打开连接和创建频道,与发送端一样
        Connection connection = factory.newConnection();
        final Channel channel = connection.createChannel();
        channel.exchangeDeclare(DirectProducer.EXCHANGE_NAME,
                "direct");

        /*声明一个队列*/
        String queueName = "focuserror";
        channel.queueDeclare(queueName,false,false,
                false,null);

        /*绑定,将队列和交换器通过路由键进行绑定*/
        String routekey = "error";/*表示只关注error级别的日志消息*/
        channel.queueBind(queueName,DirectProducer.EXCHANGE_NAME,routekey);

        System.out.println("waiting for message........");

        /*声明了一个消费者*/
        final Consumer consumer = new DefaultConsumer(channel){
            @Override
            public void handleDelivery(String consumerTag,
                                       Envelope envelope,
                                       AMQP.BasicProperties properties,
                                       byte[] body) throws IOException {
                String message = new String(body, "UTF-8");
                System.out.println("Received["+envelope.getRoutingKey()
                        +"]"+message);
                channel.basicAck(envelope.getDeliveryTag(),false);
            }
        };
        channel.basicQos(150,true);
        /*消费者正式开始在指定队列上消费消息*/
        BatchAckConsumer batchAckConsumer = new BatchAckConsumer(channel);
        channel.basicConsume(queueName,false,consumer);
        channel.basicConsume(queueName,false,batchAckConsumer);


    }

}

批量消费者

public class BatchAckConsumer extends DefaultConsumer {

    private int messasgeCount = 0;

    public BatchAckConsumer(Channel channel) {
        super(channel);
        System.out.println("批量消费者启动...");
    }

    @Override
    public void handleDelivery(String consumerTag, Envelope envelope,
                               AMQP.BasicProperties properties,
                               byte[] body) throws IOException {
        String message = new String(body, "UTF-8");
        System.out.println("批量消费者Received["+envelope.getRoutingKey()
                +"]"+message);
        messasgeCount++;
        if (messasgeCount % 50==0){
            this.getChannel().basicAck(envelope.getDeliveryTag(),
                    true);
            System.out.println("批量消费者进行消息的确认-------------");
        }
        if(message.equals("stop")){
            this.getChannel().basicAck(envelope.getDeliveryTag(),
                    true);
            System.out.println("批量消费者进行最后部分业务消息的确认-------------");
        }
    }
}

生产者:

public class QosProducer {

    public final static String EXCHANGE_NAME = "direct_logs";

    public static void main(String[] args) throws IOException, TimeoutException {
        /**
         * 创建连接连接到MabbitMQ
         */
        ConnectionFactory factory = new ConnectionFactory();
        // 设置MabbitMQ所在主机ip或者主机名
        factory.setHost("127.0.0.1");

        // 创建一个连接
        Connection connection = factory.newConnection();
        // 创建一个信道
        Channel channel = connection.createChannel();
        // 指定转发
        channel.exchangeDeclare(EXCHANGE_NAME, "direct");

        //发送210条消息,其中第210条消息表示本批次消息的结束
        for(int i=0;i<210;i++){
            // 发送的消息
            String message = "Hello World_"+(i+1);
            if(i==209){
                message = "stop";
            }
            //参数1:exchange name
            //参数2:routing key
            channel.basicPublish(EXCHANGE_NAME, "error",
                    null, message.getBytes());
            System.out.println(" [x] Sent 'error':'"
                    + message + "'");
        }
        // 关闭频道和连接
        channel.close();
        connection.close();
    }

}

运行结果:

waiting for message........
批量消费者启动...
Received[error]Hello World_1
批量消费者Received[error]Hello World_2
Received[error]Hello World_3
批量消费者Received[error]Hello World_4
Received[error]Hello World_5
批量消费者Received[error]Hello World_6
Received[error]Hello World_7
批量消费者Received[error]Hello World_8
Received[error]Hello World_9
批量消费者Received[error]Hello World_10
Received[error]Hello World_11
批量消费者Received[error]Hello World_12
Received[error]Hello World_13
批量消费者Received[error]Hello World_14
Received[error]Hello World_15
批量消费者Received[error]Hello World_16
Received[error]Hello World_17
批量消费者Received[error]Hello World_18
Received[error]Hello World_19
批量消费者Received[error]Hello World_20
Received[error]Hello World_21
批量消费者Received[error]Hello World_22
Received[error]Hello World_23
批量消费者Received[error]Hello World_24
Received[error]Hello World_25
批量消费者Received[error]Hello World_26
Received[error]Hello World_27
批量消费者Received[error]Hello World_28
Received[error]Hello World_29
批量消费者Received[error]Hello World_30
Received[error]Hello World_31
批量消费者Received[error]Hello World_32
Received[error]Hello World_33
批量消费者Received[error]Hello World_34
Received[error]Hello World_35
批量消费者Received[error]Hello World_36
Received[error]Hello World_37
批量消费者Received[error]Hello World_38
Received[error]Hello World_39
批量消费者Received[error]Hello World_40
Received[error]Hello World_41
批量消费者Received[error]Hello World_42
Received[error]Hello World_43
批量消费者Received[error]Hello World_44
Received[error]Hello World_45
批量消费者Received[error]Hello World_46
Received[error]Hello World_47
批量消费者Received[error]Hello World_48
Received[error]Hello World_49
批量消费者Received[error]Hello World_50
Received[error]Hello World_51
批量消费者Received[error]Hello World_52
Received[error]Hello World_53
批量消费者Received[error]Hello World_54
Received[error]Hello World_55
批量消费者Received[error]Hello World_56
Received[error]Hello World_57
批量消费者Received[error]Hello World_58
Received[error]Hello World_59
批量消费者Received[error]Hello World_60
Received[error]Hello World_61
批量消费者Received[error]Hello World_62
Received[error]Hello World_63
批量消费者Received[error]Hello World_64
Received[error]Hello World_65
批量消费者Received[error]Hello World_66
Received[error]Hello World_67
批量消费者Received[error]Hello World_68
Received[error]Hello World_69
批量消费者Received[error]Hello World_70
Received[error]Hello World_71
批量消费者Received[error]Hello World_72
Received[error]Hello World_73
批量消费者Received[error]Hello World_74
Received[error]Hello World_75
批量消费者Received[error]Hello World_76
Received[error]Hello World_77
批量消费者Received[error]Hello World_78
Received[error]Hello World_79
批量消费者Received[error]Hello World_80
Received[error]Hello World_81
批量消费者Received[error]Hello World_82
Received[error]Hello World_83
批量消费者Received[error]Hello World_84
Received[error]Hello World_85
批量消费者Received[error]Hello World_86
Received[error]Hello World_87
批量消费者Received[error]Hello World_88
Received[error]Hello World_89
批量消费者Received[error]Hello World_90
Received[error]Hello World_91
批量消费者Received[error]Hello World_92
Received[error]Hello World_93
批量消费者Received[error]Hello World_94
Received[error]Hello World_95
批量消费者Received[error]Hello World_96
Received[error]Hello World_97
批量消费者Received[error]Hello World_98
Received[error]Hello World_99
批量消费者Received[error]Hello World_100
批量消费者进行消息的确认-------------
Received[error]Hello World_101
批量消费者Received[error]Hello World_102
Received[error]Hello World_103
批量消费者Received[error]Hello World_104
Received[error]Hello World_105
批量消费者Received[error]Hello World_106
Received[error]Hello World_107
批量消费者Received[error]Hello World_108
Received[error]Hello World_109
批量消费者Received[error]Hello World_110
Received[error]Hello World_111
批量消费者Received[error]Hello World_112
Received[error]Hello World_113
批量消费者Received[error]Hello World_114
Received[error]Hello World_115
批量消费者Received[error]Hello World_116
Received[error]Hello World_117
批量消费者Received[error]Hello World_118
Received[error]Hello World_119
批量消费者Received[error]Hello World_120
Received[error]Hello World_121
批量消费者Received[error]Hello World_122
Received[error]Hello World_123
批量消费者Received[error]Hello World_124
Received[error]Hello World_125
批量消费者Received[error]Hello World_126
Received[error]Hello World_127
批量消费者Received[error]Hello World_128
Received[error]Hello World_129
批量消费者Received[error]Hello World_130
Received[error]Hello World_131
批量消费者Received[error]Hello World_132
Received[error]Hello World_133
批量消费者Received[error]Hello World_134
Received[error]Hello World_135
批量消费者Received[error]Hello World_136
Received[error]Hello World_137
批量消费者Received[error]Hello World_138
Received[error]Hello World_139
批量消费者Received[error]Hello World_140
Received[error]Hello World_141
批量消费者Received[error]Hello World_142
Received[error]Hello World_143
批量消费者Received[error]Hello World_144
Received[error]Hello World_145
批量消费者Received[error]Hello World_146
Received[error]Hello World_147
批量消费者Received[error]Hello World_148
Received[error]Hello World_149
批量消费者Received[error]Hello World_150
Received[error]Hello World_151
批量消费者Received[error]Hello World_152
Received[error]Hello World_153
批量消费者Received[error]Hello World_154
Received[error]Hello World_155
批量消费者Received[error]Hello World_156
Received[error]Hello World_157
批量消费者Received[error]Hello World_158
Received[error]Hello World_159
批量消费者Received[error]Hello World_160
Received[error]Hello World_161
批量消费者Received[error]Hello World_162
Received[error]Hello World_163
批量消费者Received[error]Hello World_164
Received[error]Hello World_165
批量消费者Received[error]Hello World_166
Received[error]Hello World_167
批量消费者Received[error]Hello World_168
Received[error]Hello World_169
批量消费者Received[error]Hello World_170
Received[error]Hello World_171
批量消费者Received[error]Hello World_172
Received[error]Hello World_173
批量消费者Received[error]Hello World_174
Received[error]Hello World_175
批量消费者Received[error]Hello World_176
Received[error]Hello World_177
批量消费者Received[error]Hello World_178
Received[error]Hello World_179
批量消费者Received[error]Hello World_180
Received[error]Hello World_181
批量消费者Received[error]Hello World_182
Received[error]Hello World_183
批量消费者Received[error]Hello World_184
Received[error]Hello World_185
批量消费者Received[error]Hello World_186
Received[error]Hello World_187
批量消费者Received[error]Hello World_188
Received[error]Hello World_189
批量消费者Received[error]Hello World_190
Received[error]Hello World_191
批量消费者Received[error]Hello World_192
Received[error]Hello World_193
批量消费者Received[error]Hello World_194
Received[error]Hello World_195
批量消费者Received[error]Hello World_196
Received[error]Hello World_197
批量消费者Received[error]Hello World_198
Received[error]Hello World_199
批量消费者Received[error]Hello World_200
批量消费者进行消息的确认-------------
Received[error]Hello World_201
批量消费者Received[error]Hello World_202
Received[error]Hello World_203
批量消费者Received[error]Hello World_204
Received[error]Hello World_205
批量消费者Received[error]Hello World_206
Received[error]Hello World_207
批量消费者Received[error]Hello World_208
Received[error]Hello World_209
批量消费者Received[error]stop
批量消费者进行最后部分业务消息的确认-------------
 

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值