RabbitMQ3-RabbitMQ消息类型

11 篇文章 0 订阅

1.1 概述

http://www.rabbitmq.com/getstarted.html

1.2 simplest(简单队列)

1.2.1.概述

The simplest thing that does something
- 简单队列 生产消费一一对应,耦合性高.
- 生产消息快,消费消息慢.如果很多容易堵塞

simplest
P:消息生产者;红色的:队列;C:消费者.

1.2.2 示例

pom.xml

<dependencies>
    <dependency>
        <groupId>com.rabbitmq</groupId>
        <artifactId>amqp-client</artifactId>
        <version>4.0.2</version>
    </dependency>

    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
        <version>1.7.10</version>
    </dependency>

    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-log4j12</artifactId>
        <version>1.7.5</version>
    </dependency>

    <dependency>
        <groupId>log4j</groupId>
        <artifactId>log4j</artifactId>
        <version>1.2.17</version>
    </dependency>

    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.11</version>
    </dependency>

     <dependency>
        <groupId>org.springframework.amqp</groupId>
        <artifactId>spring-rabbit</artifactId>
        <version>1.7.5.RELEASE</version>
    </dependency>

</dependencies>
rabbitmq.util

public class ConnectionUtils {
    /**
     * 获取MQ的连接  
     * @return
     * @throws TimeoutException 
     * @throws IOException 
     */
    public static Connection  getConnection() throws IOException, TimeoutException{
        //定义一个连接工厂
        ConnectionFactory factory =new ConnectionFactory();

        //设置服务地址
        factory.setHost("127.0.0.1");

        //AMQP 5672
        factory.setPort(5672);

        //vhost 
        factory.setVirtualHost("/vhost_bobshute");

        //用户名 
        factory.setUsername("bobshute");

        //密码
        factory.setPassword("123456");
        return factory.newConnection();
    }

}
rabbitmq.simple

  public class Send {
    private static final String QUEUE_NAME="test_simple_queue";
    public static void main(String[] args) throws IOException, TimeoutException {

        //获取一个连接
        Connection connection = ConnectionUtils.getConnection();

        //从连接中获取一个通道
        Channel channel = connection.createChannel();
        //创建队列声明 
        channel.queueDeclare(QUEUE_NAME, false, false, false, null);
        String msg="hello simple !";

        channel.basicPublish("", QUEUE_NAME, null, msg.getBytes());

        System.out.println("--send msg:"+msg);

        channel.close();
        connection.close();
    }
}
public class Recv {

    private static final String QUEUE_NAME = "test_simple_queue";

    @SuppressWarnings("deprecation")
    public static void main(String[] args) throws IOException,
            TimeoutException, ShutdownSignalException,
            ConsumerCancelledException, InterruptedException {

        // 获取连接
        Connection connection = ConnectionUtils.getConnection();
        // 创建频道
        Channel channel = connection.createChannel();

        //队列声明  
        channel.queueDeclare(QUEUE_NAME, false, false, false, null);
        //定义消费者
        DefaultConsumer consumer = new DefaultConsumer(channel){
            //获取到达消息
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope,
                    BasicProperties properties, byte[] body) throws IOException {

                String msg=new String(body,"utf-8");
                System.out.println("new api recv:"+msg);
            }
        };

        //监听队列    
        channel.basicConsume(QUEUE_NAME, true,consumer);
    }

    private static void oldapiu() throws IOException, TimeoutException,
            InterruptedException {
        // 获取连接
        Connection connection = ConnectionUtils.getConnection();

        // 创建频道
        Channel channel = connection.createChannel();
        // 定义队列的消费者
        QueueingConsumer consumer = new QueueingConsumer(channel);
        // 监听队列
        channel.basicConsume(QUEUE_NAME, true, consumer);
        while (true) {
            Delivery delivery = consumer.nextDelivery();
            String msgString = new String(delivery.getBody());
            System.out.println("[recv] msg:" + msgString);
        }
    }
}

1.3 Work queues(工作队列)

1.3.1 概述

Work queues

生产消息快,消费消息慢. work queues支持多个消费者.

  • 公平分发. 手动返回结果 backQos 受到结果响应才下一条.

1.3.2 Work queues(轮询分发)

rabbitmq.work

public class Send {

    /*                  |---C1
     *   P-----Queue----|
     *  `               |---C2
     * 
     */

    private static final String  QUEUE_NAME="test_work_queue";

    public static void main(String[] args) throws IOException, TimeoutException, InterruptedException {
        //获取连接
        Connection connection = ConnectionUtils.getConnection();

        //获取channel
        Channel channel = connection.createChannel();

        //声明队列
        channel.queueDeclare(QUEUE_NAME, false, false, false, null);

        for (int i = 0; i <50; i++) {

            String msg="hello "+i;
            System.out.println("[WQ ]send:"+msg);
            channel.basicPublish("", QUEUE_NAME, null, msg.getBytes());

            Thread.sleep(i*20);
        }

        channel.close();
        connection.close();
    }

}



public class Recv1 {
    private static final String  QUEUE_NAME="test_work_queue";

    public static void main(String[] args) throws IOException, TimeoutException {

        //获取连接
        Connection connection = ConnectionUtils.getConnection();
        //获取channel
        Channel channel = connection.createChannel();
        //声明队列
        channel.queueDeclare(QUEUE_NAME, false, false, false, null);

        //定义一个消费者
        Consumer consumer=new DefaultConsumer(channel){
            //消息到达 触发这个方法
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope,
                    BasicProperties properties, byte[] body) throws IOException {

                String msg=new String(body,"utf-8");
                System.out.println("[1] Recv msg:"+msg);

                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }finally{
                    System.out.println("[1] done ");
                }
            }
        };

        boolean autoAck=true;
        channel.basicConsume(QUEUE_NAME,autoAck , consumer);
    }

}


public class Recv2 {
    private static final String  QUEUE_NAME="test_work_queue";

    public static void main(String[] args) throws IOException, TimeoutException {

        //获取连接
        Connection connection = ConnectionUtils.getConnection();
        //获取channel
        Channel channel = connection.createChannel();
        //声明队列
        channel.queueDeclare(QUEUE_NAME, false, false, false, null);

        //定义一个消费者
        Consumer consumer=new DefaultConsumer(channel){
            //消息到达 触发这个方法
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope,
                    BasicProperties properties, byte[] body) throws IOException {

                String msg=new String(body,"utf-8");
                System.out.println("[2] Recv msg:"+msg);

                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }finally{
                    System.out.println("[2] done ");
                }
            }
        };

        boolean autoAck=true;
        channel.basicConsume(QUEUE_NAME,autoAck , consumer);
    }

}

1.3.3 Work queues(轮询分发)总结

接受消息的逻辑是一样的,支持处理时间不一样,会发现这种模式不管消费的时间,每个消费端各接受一次.

这种方式叫Round-robin(轮询分发)

  • 消费者接受消息个数一样的,每个接受一次.如50条消息.2个消费,那就一个接受奇数,一个接受偶书. 如果3个消费者,那就模3,每个消费端接受个数一样多.

1.3.4 Fair dispatch(公平分发)

rabbitmq.workfair


public class Send {

    /*                  |---C1
     *   P-----Queue----|
     *  `               |---C2
     * 
     */

    private static final String  QUEUE_NAME="test_work_queue";

    public static void main(String[] args) throws IOException, TimeoutException, InterruptedException {
        //获取连接
        Connection connection = ConnectionUtils.getConnection();

        //获取channel
        Channel channel = connection.createChannel();

        //声明队列
        channel.queueDeclare(QUEUE_NAME, true, false, false, null);

        /**
         * 每个消费者 发送确认消息之前,消息队列不发送下一个消息到消费者,一次只处理一个消息
         * 
         * 限制发送给同一个消费者 不得超过一条消息
         */
        int prefetchCount=1;
        channel.basicQos(prefetchCount);        //Fair dispatch 注意点



        for (int i = 0; i <50; i++) {

            String msg="hello "+i;
            System.out.println("[WQ ]send:"+msg);
            channel.basicPublish("", QUEUE_NAME, null, msg.getBytes());

            Thread.sleep(i*5);
        }

        channel.close();
        connection.close();
    }

}



public class Recv1 {
    private static final String  QUEUE_NAME="test_work_queue";

    public static void main(String[] args) throws IOException, TimeoutException {

        //获取连接
        Connection connection = ConnectionUtils.getConnection();
        //获取channel
        final Channel channel = connection.createChannel();
        //声明队列
        channel.queueDeclare(QUEUE_NAME, false, false, false, null);

        channel.basicQos(1);//保证一次只分发一个     //Fair dispatch 注意点

        //定义一个消费者
        Consumer consumer=new DefaultConsumer(channel){
            //消息到达 触发这个方法
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope,
                    BasicProperties properties, byte[] body) throws IOException {

                String msg=new String(body,"utf-8");
                System.out.println("[1] Recv msg:"+msg);

                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }finally{
                    System.out.println("[1] done ");

                    channel.basicAck(envelope.getDeliveryTag(), false); //手动回执 Fair dispatch 注意点
                }
            }
        };

        boolean autoAck=false;//自动应答 false  //Fair dispatch 注意点
        channel.basicConsume(QUEUE_NAME,autoAck , consumer);
    }

}


public class Recv2 {
    private static final String  QUEUE_NAME="test_work_queue";

    public static void main(String[] args) throws IOException, TimeoutException {

        //获取连接
        Connection connection = ConnectionUtils.getConnection();
        //获取channel
        final Channel channel = connection.createChannel();
        //声明队列
        channel.queueDeclare(QUEUE_NAME, false, false, false, null);
        channel.basicQos(1);//保证一次只分发一个  //Fair dispatch 注意点


        //定义一个消费者
        Consumer consumer=new DefaultConsumer(channel){
            //消息到达 触发这个方法
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope,
                    BasicProperties properties, byte[] body) throws IOException {

                String msg=new String(body,"utf-8");
                System.out.println("[2] Recv msg:"+msg);

                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }finally{
                    System.out.println("[2] done ");

                    channel.basicAck(envelope.getDeliveryTag(), false); //手动回执 Fair dispatch 注意点
                }
            }
        };

        boolean autoAck=false;//Fair dispatch 注意点
        channel.basicConsume(QUEUE_NAME,autoAck , consumer);
    }

}

1.3.5 Fair dispatch(公平分发) 总结

  • 现象:处理快的接收消息多,处理慢的接受消息少
  • 原理:一次发送一条,不自动应答,自动应答,收到应答后就发送新消息
  • 代码区别处
//channel注意出,消费和接受都写
channel.basicQos(1);//保证一次只分发一个  //Fair dispatch 注意点

//消费端注意
channel.basicAck(envelope.getDeliveryTag(), false); // 手动回执 Fair dispatch 注意点

boolean autoAck=false;//自动应答 false  //Fair dispatch 注意点
channel.basicConsume(QUEUE_NAME,autoAck , consumer);

1.4 Publish/Subscribe

1.4.1 概述

PublishSubscribe

  • 生产者不是直接把消费发送到队列,而是发到了Exchange(交换机,转发器)
  • 生产者发送的消息,经过交换机,到达队列,然后实现一个队列被多个消费者消费.
  • 每一个消费者都有自己的队列
  • 每个队列都要绑到交换机上
  • 一个生产者,多个消费者消费同样的消息

  • 应用场景
    比如一个消息又要发到短信,又要发到邮件.

  • exchange type(exchange类型) : fanout(分发)

  • 启动时需要先启动消费端

1.4.2 示例

rabbitmq.ps

public class Send {

    private static final String  EXCHANGE_NAME="test_exchange_fanout";
    public static void main(String[] args) throws IOException, TimeoutException {

        Connection connection = ConnectionUtils.getConnection();

        Channel channel = connection.createChannel();

        //声明交换机
        channel.exchangeDeclare(EXCHANGE_NAME, "fanout");//分发

        //发送消息
        String msg="hello ps";

        channel.basicPublish(EXCHANGE_NAME, "", null, msg.getBytes());

        System.out.println("Send :"+msg);

        channel.close();
        connection.close();
    }
}



public class Recv1 {

    private static final String QUEUE_NAME="test_queue_fanout_email";
    private static final String  EXCHANGE_NAME="test_exchange_fanout";
    public static void main(String[] args) throws IOException, TimeoutException {
        Connection connection = ConnectionUtils.getConnection();
        final Channel channel = connection.createChannel();

        //队列声明
        channel.queueDeclare(QUEUE_NAME, false, false, false, null);

        //绑定队列到交换机 转发器
        channel.queueBind(QUEUE_NAME, EXCHANGE_NAME, "");


        channel.basicQos(1);//保证一次只分发一个  

        //定义一个消费者
        Consumer consumer=new DefaultConsumer(channel){
            //消息到达 触发这个方法
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope,
                    BasicProperties properties, byte[] body) throws IOException {

                String msg=new String(body,"utf-8");
                System.out.println("[1] Recv msg:"+msg);

                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }finally{
                    System.out.println("[1] done ");
                    channel.basicAck(envelope.getDeliveryTag(), false);
                }
            }
        };

        boolean autoAck=false;//自动应答 false
        channel.basicConsume(QUEUE_NAME,autoAck , consumer);
    }
}



public class Recv2 {

    private static final String QUEUE_NAME="test_queue_fanout_sms";
    private static final String  EXCHANGE_NAME="test_exchange_fanout";
    public static void main(String[] args) throws IOException, TimeoutException {
        Connection connection = ConnectionUtils.getConnection();
        final Channel channel = connection.createChannel();

        //队列声明
        channel.queueDeclare(QUEUE_NAME, false, false, false, null);

        //绑定队列到交换机 转发器
        channel.queueBind(QUEUE_NAME, EXCHANGE_NAME, "");
        channel.basicQos(1);//保证一次只分发一个  

        //定义一个消费者
        Consumer consumer=new DefaultConsumer(channel){
            //消息到达 触发这个方法
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope,
                    BasicProperties properties, byte[] body) throws IOException {

                String msg=new String(body,"utf-8");
                System.out.println("[2] Recv msg:"+msg);

                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }finally{
                    System.out.println("[2] done ");
                    channel.basicAck(envelope.getDeliveryTag(), false);
                }
            }
        };

        boolean autoAck=false;//自动应答 false
        channel.basicConsume(QUEUE_NAME,autoAck , consumer);
    }
}

1.5 Routing

1.5.1 概述

Routing

* 匹配1个
# 匹配一个或多个

1.5.2 示例

packagerabbitmq.routing;

import java.io.IOException;
import java.util.concurrent.TimeoutException;

import com.mmr.rabbitmq.util.ConnectionUtils;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;

public class Send {

    private static final String EXCHANGE_NAME="test_exchange_direct";

    public static void main(String[] args) throws IOException, TimeoutException {
        Connection connection = ConnectionUtils.getConnection();
        Channel channel = connection.createChannel();
        //exchange
        channel.exchangeDeclare(EXCHANGE_NAME, "direct");

        String  msg="hello direct!";

        String routingKey="info";
        channel.basicPublish(EXCHANGE_NAME, routingKey, null, msg.getBytes());

        System.out.println("send "+msg);
        channel.close();
        connection.close();
    }
}




public class Recv1 {
    private static final String EXCHANGE_NAME = "test_exchange_direct";
    private static final String QUEUE_NAME = "test_queue_direct_1";

    public static void main(String[] args) throws IOException, TimeoutException {

        Connection connection = ConnectionUtils.getConnection();
        final Channel channel = connection.createChannel();
        channel.queueDeclare(QUEUE_NAME, false, false, false, null);
        channel.queueBind(QUEUE_NAME, EXCHANGE_NAME, "error");
        channel.basicQos(1);

        //定义一个消费者
        Consumer consumer=new DefaultConsumer(channel){
            //消息到达 触发这个方法
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope,
                    BasicProperties properties, byte[] body) throws IOException {

                String msg=new String(body,"utf-8");
                System.out.println("[1] Recv msg:"+msg);

                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }finally{
                    System.out.println("[1] done ");
                    channel.basicAck(envelope.getDeliveryTag(), false);
                }
            }
        };

        boolean autoAck=false;//自动应答 false
        channel.basicConsume(QUEUE_NAME,autoAck , consumer);
    }
}




public class Recv2 {
    private static final String EXCHANGE_NAME = "test_exchange_direct";
    private static final String QUEUE_NAME = "test_queue_direct_2";

    public static void main(String[] args) throws IOException, TimeoutException {

        Connection connection = ConnectionUtils.getConnection();
        final Channel channel = connection.createChannel();

        channel.queueDeclare(QUEUE_NAME, false, false, false, null);

        channel.queueBind(QUEUE_NAME, EXCHANGE_NAME, "error");
        channel.queueBind(QUEUE_NAME, EXCHANGE_NAME, "info");
        channel.queueBind(QUEUE_NAME, EXCHANGE_NAME, "warning");

        channel.basicQos(1);

        //定义一个消费者
        Consumer consumer=new DefaultConsumer(channel){
            //消息到达 触发这个方法
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope,
                    BasicProperties properties, byte[] body) throws IOException {

                String msg=new String(body,"utf-8");
                System.out.println("[2] Recv msg:"+msg);

                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }finally{
                    System.out.println("[2] done ");
                    channel.basicAck(envelope.getDeliveryTag(), false);
                }
            }
        };
        boolean autoAck=false;//自动应答 false
        channel.basicConsume(QUEUE_NAME,autoAck , consumer);
    }
}


1.6 Topics

1.6.1 概述

Topics

1.6.2 示例

package rabbitmq.topic;

import java.io.IOException;
import java.util.concurrent.TimeoutException;

import com.mmr.rabbitmq.util.ConnectionUtils;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;

public class Send {
    private static final String EXCHANGE_NAME = "test_exchange_topic";

    public static void main(String[] args) throws IOException, TimeoutException {


        Connection connection = ConnectionUtils.getConnection();

        Channel channel = connection.createChannel();

        //exchange
        channel.exchangeDeclare(EXCHANGE_NAME, "topic");//topic注意

        String msgString="商品....";
        channel.basicPublish(EXCHANGE_NAME, "goods.delete", null, msgString.getBytes());
        System.out.println("---send "+msgString);

        channel.close();
        connection.close();
    }
}



public class Recv1 {
    private static final String EXCHANGE_NAME = "test_exchange_topic";
    private static final String QUEUE_NAME = "test_queue_topic_1";

    public static void main(String[] args) throws IOException, TimeoutException {

        Connection connection = ConnectionUtils.getConnection();
        final Channel channel = connection.createChannel();

        channel.queueDeclare(QUEUE_NAME, false, false, false, null);
        channel.queueBind(QUEUE_NAME, EXCHANGE_NAME, "goods.add"); //topic注意
        channel.queueBind(QUEUE_NAME, EXCHANGE_NAME, "goods.update");//topic注意

        channel.basicQos(1);

        //定义一个消费者
        Consumer consumer=new DefaultConsumer(channel){
            //消息到达 触发这个方法
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope,
                    BasicProperties properties, byte[] body) throws IOException {

                String msg=new String(body,"utf-8");
                System.out.println("[1] Recv msg:"+msg);

                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }finally{
                    System.out.println("[1] done ");
                    channel.basicAck(envelope.getDeliveryTag(), false);
                }
            }
        };

        boolean autoAck=false;//自动应答 false
        channel.basicConsume(QUEUE_NAME,autoAck , consumer);
    }

}



public class Recv2 {
    private static final String EXCHANGE_NAME = "test_exchange_topic";
    private static final String QUEUE_NAME = "test_queue_topic_2";

    public static void main(String[] args) throws IOException, TimeoutException {

        Connection connection = ConnectionUtils.getConnection();
        final Channel channel = connection.createChannel();

        channel.queueDeclare(QUEUE_NAME, false, false, false, null);
        channel.queueBind(QUEUE_NAME, EXCHANGE_NAME, "goods.#");//topic注意

        channel.basicQos(1);

        //定义一个消费者
        Consumer consumer=new DefaultConsumer(channel){
            //消息到达 触发这个方法
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope,
                    BasicProperties properties, byte[] body) throws IOException {

                String msg=new String(body,"utf-8");
                System.out.println("[2] Recv msg:"+msg);

                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }finally{
                    System.out.println("[2] done ");
                    channel.basicAck(envelope.getDeliveryTag(), false);
                }
            }
        };

        boolean autoAck=false;//自动应答 false
        channel.basicConsume(QUEUE_NAME,autoAck , consumer);
    }
}

1.7 RPC

RPC

1.8 重要源码分析

public class ConnectionFactory implements Cloneable {

     public Connection newConnection() throws IOException, TimeoutException {
        return newConnection(this.sharedExecutor, Collections.singletonList(new Address(getHost(), getPort())));
    }

}



public interface Channel extends ShutdownNotifier {

    Queue.DeclareOk queueDeclare(String queue, boolean durable, boolean exclusive, boolean autoDelete,
                                 Map<String, Object> arguments) throws IOException;


    void basicPublish(String exchange, String routingKey, BasicProperties props, byte[] body) throws IOException;        

    void basicQos(int prefetchCount) throws IOException;


    Exchange.DeclareOk exchangeDeclare(String exchange, String type) throws IOException;


}

1.9 常用API

1.9.1 autoAck及basicAck (自动应答及手工回执)

channel中

//自动应答 ture,如果消息分发给消费者就从内存中删除,这种如果杀死正在处理的消费者,那么数据就丢了,默认为true
boolean autoAck=true;                  
//自动应答 false,需要手动回执确认收到消息,如果没有收到回执,则会再发送给其它消费者
boolean autoAck=false;                 
channel.basicConsume(QUEUE_NAME,autoAck , consumer);//设置是否自动应答
//ack Message acknowledgment

//消费时
channel.basicAck(envelope.getDeliveryTag(), false); // 手动回执 

1.9.2 durable(消息持久化)

//申明队列是时 
Queue.DeclareOk queueDeclare(String queue, boolean durable, boolean exclusive, boolean autoDelete,
                                 Map<String, Object> arguments) throws IOException;

1.9.3 exchange type(exchange类型)

    • fanout 分发
      Routing-type-fanout

    不处理,直接转发.

    • direct 处理
      Routing-type-direct
    • topic 模糊匹配,归类
      Routing-type-topic

* 匹配1个
# 匹配一个或多个

1.9.4 tx(事务)

能够进行事务管理,但是由于是同步的, 会降低吞吐量.

package com.mmr.rabbitmq.tx;

import java.io.IOException;
import java.util.concurrent.TimeoutException;

import com.mmr.rabbitmq.util.ConnectionUtils;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;

public class TxSend {

    private static final String QUEUE_NAME="test_queue_tx";

    public static void main(String[] args) throws IOException, TimeoutException {

        Connection connection = ConnectionUtils.getConnection();
        Channel channel = connection.createChannel();
        channel.queueDeclare(QUEUE_NAME,false,false,false,null);
        String msgString="hello tx message!";

        try {
            channel.txSelect();     //事务注意
            channel.basicPublish("", QUEUE_NAME, null,msgString.getBytes());
            int xx=1/0;
            System.out.println("send "+msgString);
            channel.txCommit(); //事务注意
        } catch (Exception e) {
            channel.txRollback();//事务注意
            System.out.println(" send message txRollback");
        }

        channel.close();
        connection.close();
    }
}



public class TxRecv {

    private static final String QUEUE_NAME="test_queue_tx";


    public static void main(String[] args) throws IOException, TimeoutException {

        Connection connection = ConnectionUtils.getConnection();
        Channel channel = connection.createChannel();
        channel.queueDeclare(QUEUE_NAME,false,false,false,null);
        channel.basicConsume(QUEUE_NAME, true,new DefaultConsumer(channel){

            @Override
            public void handleDelivery(String consumerTag, Envelope envelope,
                    BasicProperties properties, byte[] body) throws IOException {
                System.out.println("recv[tx] msg:"+new String(body,"utf-8"));
            }
        });
    }

}

1.9.5 confirm(确认模式)

public class Recv {

    private static final String QUEUE_NAME="test_queue_confirm3";

    public static void main(String[] args) throws IOException, TimeoutException {
        Connection connection = ConnectionUtils.getConnection();
        Channel channel = connection.createChannel();
        channel.queueDeclare(QUEUE_NAME,false,false,false,null);
        channel.basicConsume(QUEUE_NAME, true,new DefaultConsumer(channel){
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope,
                    BasicProperties properties, byte[] body) throws IOException {
                System.out.println("recv[confirm] msg:"+new String(body,"utf-8"));
            }
        });
    }

}


/**
 *普通模式,发一条(同步)
 */
public class Send1 {
    private static final String QUEUE_NAME="test_queue_confirm1";
    public static void main(String[] args) throws IOException, TimeoutException, InterruptedException {

        Connection connection = ConnectionUtils.getConnection();
        Channel channel = connection.createChannel();
        channel.queueDeclare(QUEUE_NAME,false,false,false,null);

        //生产者调用confirmSelect 将channel设置为confirm模式 注意
        channel.confirmSelect();        //confirm注意

        String msgString="hello confirm message!";
        channel.basicPublish("", QUEUE_NAME, null,msgString.getBytes());

        if(!channel.waitForConfirms()){ //confirm注意
            System.out.println("message send failed");
        }else {
            System.out.println("message send ok");
        }

        channel.close();
        connection.close();
    }
}





/**
 *普通模式-发批量(同步)
 */
public class Send2 {
    private static final String QUEUE_NAME="test_queue_confirm1";

    public static void main(String[] args) throws IOException, TimeoutException, InterruptedException {

        Connection connection = ConnectionUtils.getConnection();
        Channel channel = connection.createChannel();
        channel.queueDeclare(QUEUE_NAME,false,false,false,null);

        //生产者调用confirmSelect 将channel设置为confirm模式 注意
        channel.confirmSelect(); //confirm注意

        String msgString="hello confirm message batch!";
        //批量发送
        for (int i = 0; i < 10; i++) {
            channel.basicPublish("", QUEUE_NAME, null,msgString.getBytes());
        }

        //确认
        if(!channel.waitForConfirms()){
            System.out.println("message send failed");
        }else {
            System.out.println("message send ok");
        }

        channel.close();
        connection.close();
    }
}




/**
 * 确认模式-异步模式
 */
public class Send3 {
    private static final String QUEUE_NAME="test_queue_confirm3";

    public static void main(String[] args) throws IOException, TimeoutException {
        Connection connection = ConnectionUtils.getConnection();
        Channel channel = connection.createChannel();
        channel.queueDeclare(QUEUE_NAME,false,false,false,null);

        //生产者调用confirmSelect 将channel设置为confirm模式 注意
        channel.confirmSelect();//confirm注意

        //未确认的消息标识 
        final SortedSet<Long> confirmSet=Collections.synchronizedSortedSet(new TreeSet<Long>());

        //通道添加监听
        channel.addConfirmListener(new ConfirmListener() {

            //没有问题的handleAck,成功的调这里.
            public void handleAck(long deliveryTag, boolean multiple)
                    throws IOException {
                if(multiple){//多条
                    System.out.println("----handleAck----multiple");
                    confirmSet.headSet(deliveryTag+1).clear();  //headSet是返回此有序集合中小于(deliveryTag+1)的所有元素,clear是并清除
                }else{//单条
                    System.out.println("----handleAck-----multiple false");
                    confirmSet.remove(deliveryTag);
                }
            }

            //handleNack,失败的调这里.
            public void handleNack(long deliveryTag, boolean multiple)
                    throws IOException {
                if(multiple){//多条
                    System.out.println("---handleNack------multiple");
                    confirmSet.headSet(deliveryTag+1).clear();//headSet是返回此有序集合中小于(deliveryTag+1)的所有元素,clear是并清除
                }else{//单条
                    System.out.println("--handleNack-------multiple false");
                    confirmSet.remove(deliveryTag);
                }
            }
        });

        String msgStr="ssssss";

        while(true){
            long seqNo = channel.getNextPublishSeqNo();//消息编号,序列
            channel.basicPublish("", QUEUE_NAME, null, msgStr.getBytes());
            confirmSet.add(seqNo);      //边发,边存.
        }

    }

}

1.10 注意

  • 已经申明过的队列,不能修改队列属性(rabbitmq不允许用不同参数重新定义的已存在的队列)

注:根据牧马人老王整理.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值