分布式架构之rabbitMQ使用

一、基于docker安装(Centos下)

1、查询一下镜像库

docker search rabbitmq:management

   

2、拉取镜像,并查看本地是否存在

docker pull rabbitmq:management

    

3、启动rabbitmq,这里开启两个端口映射,5672是rabbitmq默认的客户端连接端口,15672是web管理界面的端口。-d 是后台运行,--name 是给容器取别名便于后面查找,最后是镜像id。启动后查看运行状态

docker run -d -p 5672:5672 -p 15672:15672 --name rabbitmq db322a6c3b84

  

  

二、rabbitMQ管理

1、正确安装之后,访问管理界面,地址是ip:15672,会出现该界面,默认用guest/guest可以登录

  

  

三、代码连接(为了方便测试,生产消费端都写在一个文件,这样不好,真正使用请自行分离。)

调试过程中遇到一个问题(received 'fanout' but current is 'direct'。。。。。),由于我是用的docker部署的rabbitmq,解决方法如下:

#进入该容器
docker exec -it f6ccd6482b3a /bin/bash
#查看队列
rabbitmqctl list_queues
#停止
rabbitmqctl stop_app
#清除数据
rabbitmqctl reset
#启动
rabbitmqctl start_app

1、单发送单队列单接收(simple 简单模式),一个发送一个接收

public class RabbitmqSimple {
    private static final String IP = "192.168.1.60";
    private static final int PORT = 5672;
    private static final String USERNAME = "guest";
    private static final String PASSWORD = "guest";
    private static final String QUEUE_NAME = "queue_name";

    public static void main(String[] args) throws Exception{
        producer();
        consumer();
    }
    //生产者
    public static void producer() throws Exception{
        Connection connection = getConnection();
        Channel channel = connection.createChannel();
        //创建持久化、非自动删除的队列
        channel.queueDeclare(QUEUE_NAME,true,false,false,null);
        String message = "project_start";
        System.out.println("发送消息");
        //发送消息
        channel.basicPublish(
                "",
                QUEUE_NAME,
                MessageProperties.PERSISTENT_TEXT_PLAIN,
                message.getBytes()
        );
        channel.close();
        connection.close();
    }
    //消费者
    public static void consumer() throws Exception{
        Connection connection = getConnection();
        Channel channel = connection.createChannel();
        //客户端最多接受未被ack的消息个数
        channel.basicQos(50);
        Consumer defaultConsumer = new DefaultConsumer(channel) {
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                System.out.println(new String(body));
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                //表示该消息已经被消费
                channel.basicAck(envelope.getDeliveryTag(), false);
            }
        };
        channel.basicConsume(QUEUE_NAME,false,defaultConsumer);//手动模式,消费者成功消费后服务端不会自动标记为成功消费,需要将状态传回服务端手动更新
//      channel.basicConsume(QUEUE_NAME,true,defaultConsumer);//自动模式,消费者获取消息后服务端自动标记为成功消费
        TimeUnit.SECONDS.sleep(5);
        channel.close();
        connection.close();
        /**另一种方式获取,但方法已经不推荐**/
//        QueueingConsumer consumer = new QueueingConsumer(channel);
//        channel.basicConsume(QUEUE_NAME,consumer);
//        while (true){
//            QueueingConsumer.Delivery delivery = consumer.nextDelivery();
//            System.out.println(new String(delivery.getBody()));
//        }
        /**另一种方式获取,但方法已经不推荐**/
    }

    public static Connection getConnection() throws Exception{
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost(IP);
        factory.setPort(PORT);
        factory.setUsername(USERNAME);
        factory.setPassword(PASSWORD);
        Connection connection = factory.newConnection();
        return connection;
    }
}

    

2、单发送单队列多接收(work,工作模式),一个发送多个端一起处理消息

public class RabbitmqWork {
    private static final String IP = "192.168.1.60";
    private static final int PORT = 5672;
    private static final String USERNAME = "guest";
    private static final String PASSWORD = "guest";
    private static final String QUEUE_NAME = "queue_name";
    public static void main(String[] args) throws Exception{
        producer();
        consumer(1);
        consumer(2);
    }
    //生产者
    public static void producer() throws Exception{
        Connection connection = getConnection();
        Channel channel = connection.createChannel();
        //创建持久化、非自动删除的队列
        channel.queueDeclare(QUEUE_NAME,true,false,false,null);
        System.out.println("发送消息");
        for(int i=0;i<10;i++){
            //发送消息
            String message = "project_start:" + i;
            channel.basicPublish(
                    "",
                    QUEUE_NAME,
                    MessageProperties.PERSISTENT_TEXT_PLAIN,
                    message.getBytes()
            );
        }
        channel.close();
        connection.close();
    }
    //消费者
    public static void consumer(int cons) throws Exception{
        Connection connection = getConnection();
        Channel channel = connection.createChannel();
        //客户端最多接受未被ack的消息个数,现在设置1,同一时刻只接收一个,处理完返回成功再继续接收
        channel.basicQos(1);
        Consumer defaultConsumer = new DefaultConsumer(channel) {
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                System.out.println(cons + "消费者:"+ new String(body));
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                //表示该消息已经被消费
                channel.basicAck(envelope.getDeliveryTag(), false);
            }
        };
        channel.basicConsume(QUEUE_NAME,false,defaultConsumer);//手动模式,消费者成功消费后服务端不会自动标记为成功消费,需要将状态传回服务端手动更新
        TimeUnit.SECONDS.sleep(5);
    }

    public static Connection getConnection() throws Exception{
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost(IP);
        factory.setPort(PORT);
        factory.setUsername(USERNAME);
        factory.setPassword(PASSWORD);
        Connection connection = factory.newConnection();
        return connection;
    }
}

    

3、单发送多队列多接收(Publish/Subscribe 发布、订阅模式),假如每个消费者一个队列则可实现收到相同信息(广播)

public class RabbitmqPublish {
    private static final String IP = "192.168.1.60";
    private static final int PORT = 5672;
    private static final String USERNAME = "guest";
    private static final String PASSWORD = "guest";
    private static final String TYPE = "fanout";
    private static final String EXCHANGE_NAME = "exchange_name";
    private static final String QUEUE_NAME = "queue_name";
    private static final String QUEUE_NAME2 = "queue_name2";
    public static void main(String[] args) throws Exception{
        producer();
        consumer(QUEUE_NAME);
        consumer(QUEUE_NAME2);
    }
    //生产者
    public static void producer() throws Exception{
        Connection connection = getConnection();
        Channel channel = connection.createChannel();
        //创建持久化、非自动删除的交换器,Exchange有4种类型:direct(默认),fanout,topic,和headers,这里用fanout 广播消息,不需要使用queue
        channel.exchangeDeclare(EXCHANGE_NAME,TYPE);
        String message = "project_start";
        System.out.println("发送消息");
        //发送消息
        channel.basicPublish(
                EXCHANGE_NAME,
                "",
                MessageProperties.PERSISTENT_TEXT_PLAIN,
                message.getBytes()
        );
        channel.close();
        connection.close();
    }
    //消费者
    public static void consumer(String queue) throws Exception{
        Connection connection = getConnection();
        Channel channel = connection.createChannel();
        //交换机
        channel.exchangeDeclare(EXCHANGE_NAME,TYPE);
        //创建持久化、非自动删除的队列
        channel.queueDeclare(queue,true,false,false,null);
        //交换器和队列进行绑定,注意这里不同消费者交换器名字一样,但队列不同
        channel.queueBind(queue,EXCHANGE_NAME,"");
        channel.basicQos(1);
        Consumer defaultConsumer = new DefaultConsumer(channel) {
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                System.out.println(queue + ":" + new String(body));
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                //表示该消息已经被消费
                channel.basicAck(envelope.getDeliveryTag(), false);
            }
        };
        channel.basicConsume(queue,false,defaultConsumer);//手动模式,消费者成功消费后服务端不会自动标记为成功消费,需要将状态传回服务端手动更新
    }

    public static Connection getConnection() throws Exception{
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost(IP);
        factory.setPort(PORT);
        factory.setUsername(USERNAME);
        factory.setPassword(PASSWORD);
        Connection connection = factory.newConnection();
        return connection;
    }
}

   

4、消费者根据不同路由key(Routing 路由模式),在第三点的基础上把type改成direct,发送消息加了routing key

public class RabbitmqRouting {
    private static final String IP = "192.168.1.60";
    private static final int PORT = 5672;
    private static final String USERNAME = "guest";
    private static final String PASSWORD = "guest";
    private static final String TYPE = "direct";
    private static final String EXCHANGE_NAME = "exchange_name";
    private static final String QUEUE_NAME = "queue_name";
    private static final String QUEUE_NAME2 = "queue_name2";
    private static final String ROUTING_KEY = "routing_key";
    private static final String ROUTING_KEY2 = "routing_key2";
    public static void main(String[] args) throws Exception{
        producer();
        consumer(QUEUE_NAME,ROUTING_KEY);
        consumer(QUEUE_NAME2,ROUTING_KEY2);
    }
    //生产者
    public static void producer() throws Exception{
        Connection connection = getConnection();
        Channel channel = connection.createChannel();
        //创建持久化、非自动删除的交换器,Exchange有4种类型:direct(默认),fanout,topic,和headers,这里用fanout 广播消息,不需要使用queue
        channel.exchangeDeclare(EXCHANGE_NAME,TYPE);
        String message = "project_start";
        System.out.println("发送消息");
        //发送消息
        channel.basicPublish(
                EXCHANGE_NAME,
                ROUTING_KEY,
                MessageProperties.PERSISTENT_TEXT_PLAIN,
                message.getBytes()
        );
        //另一个路由
        String message2 = "project_start2";
        channel.basicPublish(
                EXCHANGE_NAME,
                ROUTING_KEY2,
                MessageProperties.PERSISTENT_TEXT_PLAIN,
                message2.getBytes()
        );
        channel.close();
        connection.close();
    }
    //消费者
    public static void consumer(String queue,String routing) throws Exception{
        Connection connection = getConnection();
        Channel channel = connection.createChannel();
        //交换机
        channel.exchangeDeclare(EXCHANGE_NAME,TYPE);
        //创建持久化、非自动删除的队列
        channel.queueDeclare(queue,true,false,false,null);
        //交换器和队列进行绑定,注意这里不同消费者交换器名字一样,但队列不同和路由key不一样
        channel.queueBind(queue,EXCHANGE_NAME,routing);
        channel.basicQos(1);
        Consumer defaultConsumer = new DefaultConsumer(channel) {
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                System.out.println(queue + ":" + new String(body));
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                //表示该消息已经被消费
                channel.basicAck(envelope.getDeliveryTag(), false);
            }
        };
        channel.basicConsume(queue,false,defaultConsumer);//手动模式,消费者成功消费后服务端不会自动标记为成功消费,需要将状态传回服务端手动更新
    }

    public static Connection getConnection() throws Exception{
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost(IP);
        factory.setPort(PORT);
        factory.setUsername(USERNAME);
        factory.setPassword(PASSWORD);
        Connection connection = factory.newConnection();
        return connection;
    }
}

   

5、两端都按通配符匹配(Topics 主题模式),在第三点的基础上把type改成topic,发送消息的routing key去匹配binding key,比如 routing.* 这种规则,也可以用 # ,* 是匹配一个单词,# 是匹配多个单词

public class RabbitmqTopic {
    private static final String IP = "192.168.1.60";
    private static final int PORT = 5672;
    private static final String USERNAME = "guest";
    private static final String PASSWORD = "guest";
    private static final String TYPE = "topic";
    private static final String EXCHANGE_NAME = "exchange_name";
    private static final String QUEUE_NAME = "queue_name";
    private static final String QUEUE_NAME2 = "queue_name2";
    private static final String ROUTING_KEY = "routing.key";
    private static final String ROUTING_KEY2 = "routing.key2";
    private static final String BINDING_KEY_COMMON = "routing.*";
    public static void main(String[] args) throws Exception{
        producer();
        consumer(QUEUE_NAME);
        consumer(QUEUE_NAME2);
    }
    //生产者
    public static void producer() throws Exception{
        Connection connection = getConnection();
        Channel channel = connection.createChannel();
        //创建持久化、非自动删除的交换器,Exchange有4种类型:direct(默认),fanout,topic,和headers,这里用fanout 广播消息,不需要使用queue
        channel.exchangeDeclare(EXCHANGE_NAME,TYPE);
        System.out.println("发送消息");
        //发送消息
        String message = "project_start";
        channel.basicPublish(
                EXCHANGE_NAME,
                ROUTING_KEY,
                MessageProperties.PERSISTENT_TEXT_PLAIN,
                message.getBytes()
        );
        //另一个路由
        String message2 = "project_start2";
        channel.basicPublish(
                EXCHANGE_NAME,
                ROUTING_KEY2,
                MessageProperties.PERSISTENT_TEXT_PLAIN,
                message2.getBytes()
        );
        channel.close();
        connection.close();
    }
    //消费者
    public static void consumer(String queue) throws Exception{
        Connection connection = getConnection();
        Channel channel = connection.createChannel();
        //交换机
        channel.exchangeDeclare(EXCHANGE_NAME,TYPE);
        //创建持久化、非自动删除的队列
        channel.queueDeclare(queue,true,false,false,null);
        //交换器和队列进行绑定,注意这里不同消费者交换器名字一样,但队列不同,路由采用匹配方式
        channel.queueBind(queue,EXCHANGE_NAME,BINDING_KEY_COMMON);
        channel.basicQos(1);
        Consumer defaultConsumer = new DefaultConsumer(channel) {
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                System.out.println(queue + ":" + new String(body));
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                //表示该消息已经被消费
                channel.basicAck(envelope.getDeliveryTag(), false);
            }
        };
        channel.basicConsume(queue,false,defaultConsumer);//手动模式,消费者成功消费后服务端不会自动标记为成功消费,需要将状态传回服务端手动更新
    }

    public static Connection getConnection() throws Exception{
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost(IP);
        factory.setPort(PORT);
        factory.setUsername(USERNAME);
        factory.setPassword(PASSWORD);
        Connection connection = factory.newConnection();
        return connection;
    }
}

     

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,以下是一个基于Spring Cloud和RabbitMQ的示例,演示如何在分布式系统中使用RabbitMQ进行消息传递。 首先,你需要在pom.xml文件中添加以下依赖项: ```xml <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-stream-rabbit</artifactId> </dependency> ``` 接下来,你需要在你的应用程序中创建一个名为“Sink”的接口,该接口定义了一个输入通道,用于接收RabbitMQ发送的消息: ```java public interface Sink { String INPUT = "input"; @Input(Sink.INPUT) SubscribableChannel input(); } ``` 然后,你可以在你的应用程序中创建一个Bean来处理接收到的消息。例如,以下代码演示如何打印接收到的消息: ```java @Component public class MessageReceiver { @StreamListener(Sink.INPUT) public void receiveMessage(String message) { System.out.println("Received message: " + message); } } ``` 接下来,你需要配置RabbitMQ连接和队列信息。你可以在application.yml文件中添加以下配置: ```yaml spring: rabbitmq: host: localhost port: 5672 username: guest password: guest my: queue: name: my-queue ``` 最后,你需要在你的应用程序中启用RabbitMQ支持。你可以在你的Spring Boot应用程序上添加@EnableBinding注释,启用消息通道和消息绑定: ```java @SpringBootApplication @EnableBinding(Sink.class) public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } } ``` 现在,当你向名为“my-queue”的队列发送消息时,应用程序将接收到该消息,并输出到控制台。 希望这个示例能够帮助你在Spring Cloud应用程序中使用RabbitMQ进行消息传递。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值