RabbitMq的安装和三种常用方式(direct,fanout,topic)

RabbitMq原理 请参考这篇文档和Springboot整合RabbitMq

1.Rabbit安装

1.安装Erlang
由于RabbitMQ依赖Erlang, 所以需要先安装Erlang。
        从EPEL源安装(这种方式安装的Erlang版本可能不是最新的,有时候不能满足RabbitMQ需要的最低版本)

 # 启动EPEL源
 $ sudo yum install epel-release 
 # 安装erlang
 $ sudo yum install erlang

2.完成后安装RabbitMQ

先下载rpm:

wget http://www.rabbitmq.com/releases/rabbitmq-server/v3.6.6/rabbitmq-server-3.6.6-1.el7.noarch.rpm

下载完成后安装:

yum install rabbitmq-server-3.6.6-1.el7.noarch.rpm 

3.关于RabbitMQ的一些基本操作
sudo chkconfig rabbitmq-server on # 添加开机启动RabbitMQ服务
sudo /sbin/service rabbitmq-server start # 启动服务
sudo /sbin/service rabbitmq-server status # 查看服务状态
sudo /sbin/service rabbitmq-server stop # 停止服务
sudo /sbin/service rabbitmq-server restart # 重启服务

# 查看当前所有用户
 sudo rabbitmqctl list_users

# 查看默认guest用户的权限
sudo rabbitmqctl list_user_permissions guest

# 由于RabbitMQ默认的账号用户名和密码都是guest。
 sudo rabbitmqctl delete_user guest

# 添加新用户
 sudo rabbitmqctl add_user username password

# 设置用户tag
 sudo rabbitmqctl set_user_tags username administrator

# 赋予用户默认vhost的全部操作权限
 sudo rabbitmqctl set_permissions -p / username ".*" ".*" ".*"

# 查看用户的权限
sudo rabbitmqctl list_user_permissions username

4.开启web管理接口
如果只从命令行操作RabbitMQ,多少有点不方便。幸好RabbitMQ自带了web管理界面,只需要启动插件便可以使用。

 sudo rabbitmq-plugins enable rabbitmq_management

然后通过浏览器访问

http://localhost:15672

输入用户名和密码访问web管理界面了。
4. 开启用户远程访问
默认情况下,RabbitMQ的默认的guest用户只允许本机访问, 如果想让guest用户能够远程访问的话,只需要将配置文件中的loopback_users列表置为空即可,/etc/rabbitmq/rabbitmq.config默认是没有,只需要创建即可,然后加入配置,.一定不要忽略,然后执行重启命令

[
  {rabbit, [
      {loopback_users, []}
    ]
  }
].
sudo /sbin/service rabbitmq-server restart

然后就可以远程连接上rabbitmq了

2. 常用模式

通用RabbitMq连接代码

   <dependencies>
        <dependency>
            <groupId>com.rabbitmq</groupId>
            <artifactId>amqp-client</artifactId>
            <version>3.6.5</version>
        </dependency>
    </dependencies>
public class ConnectionUtils {
    private static String virtualHost = "/";

    public static Connection newConnection() throws IOException, TimeoutException {
        // 1.创建连接工厂
        ConnectionFactory connectionFactory = new ConnectionFactory();
        // 2.虚拟服务器
        connectionFactory.setVirtualHost(virtualHost);
        // 3.连接用户名
        connectionFactory.setUsername("guest");
        // 4.连接密码
        connectionFactory.setPassword("guest");
        // 5.连接地址
        connectionFactory.setHost("127.0.0.1");
        // 6.连接端口
        connectionFactory.setPort(5672);
        Connection connection = connectionFactory.newConnection();

        return connection;
    }
}
1.Direct模式

生产者

public class DirectProducer {

    private static String EXCHANGE = "direct";

    public static void main(String[] args) throws IOException, TimeoutException {
        //1.创建连接
        Connection connection = ConnectionUtils.newConnection();
        // 2.创建通道
        Channel channel = connection.createChannel();
        //3.绑定的交换机 参数1交互机名称 参数2 exchange类型
        channel.exchangeDeclare(EXCHANGE, "direct");
        String msg = "Direct模式生产消息";
        System.out.println("生产者生产消息:" + msg);
        String routingKey = "info";
        // 4.生产消息
        channel.basicPublish(EXCHANGE,routingKey ,null, msg.getBytes());
    }
}

消费者

public class DirectConsumer {
    private static String QUEUE_DIRECT = "direct";

    private static String EXCHANGE = "direct";

    public static void main(String[] args) throws IOException, TimeoutException, InterruptedException {
        System.out.println("Direct消费者");
        //1.创建连接
        Connection connection = ConnectionUtils.newConnection();
        // 2.创建通道
        final Channel channel = connection.createChannel();
        // 3.声明队列
        /**
         * String queue, boolean durable, boolean exclusive, boolean autoDelete, Map<String, Object> arguments
         * queue:这没什么好说的,队列名
         *
         * durable:是否持久化,那么问题来了,这是什么意思?持久化,指的是队列持久化到数据库中。在之前的博文中也说过,如果RabbitMQ服务挂了怎么办,队列丢失了自然是不希望发生的。持久化设置为true的话,即使服务崩溃也不会丢失队列
         * exclusive:是否排外,what? 这又是什么呢。设置了排外为true的队列只可以在本次的连接中被访问,也就是说在当前连接创建多少个channel访问都没有关系,但是如果是一个新的连接来访问,对不起,不可以,下面是我尝试访问了一个排外的queue报的错。还有一个需要说一下的是,排外的queue在当前连接被断开的时候会自动消失(清除)无论是否设置了持久化
         * autoDelete:这个就很简单了,是否自动删除。也就是说queue会清理自己。但是是在最后一个connection断开的时候
         * 设置队列的其他一些参数
         */
        channel.queueDeclare(QUEUE_DIRECT, false, false, false, null);
        /**
         * String queue, String exchange, String routingKey
         */
        channel.queueBind(QUEUE_DIRECT, EXCHANGE, "info");
        DefaultConsumer defaultConsumer = new DefaultConsumer(channel) {
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                String msgString = new String(body, "UTF-8");
                System.out.println("短信消费者获取消息:" + msgString);
            }
        };
        // 4.设置应答模式,true的时候为自动应答,false为手动应答,需要处理
        channel.basicConsume(QUEUE_DIRECT, true, defaultConsumer);
    }
}

在这里插入图片描述

2.Fanout模式

生产者

public class Producer {

    private static String EXCHANGE = "sms_email";

    public static void main(String[] args) throws IOException, TimeoutException {
        //1.创建连接
        Connection connection = ConnectionUtils.newConnection();
        // 2.创建通道
        Channel channel = connection.createChannel();
        //3.绑定的交换机 参数1交互机名称 参数2 exchange类型
        channel.exchangeDeclare(EXCHANGE, "fanout");
        String msg = "测试生产消息";
        try {
//            channel.txSelect();
            // 4.生产消息
            channel.basicPublish(EXCHANGE, "", null, msg.getBytes());
//            int i = 1 / 0;
            System.out.println("生产品生产消息:" + msg);
//            channel.txCommit();
        } catch (IOException e) {
            e.printStackTrace();
//            channel.txRollback();
        } finally {
            channel.close();
            connection.close();
        }
    }
}

短信消费者

/**
 * @author Administrator
 */
public class SmsConsumer {
    private static String QUEUE_SMS = "sms";

    private static String EXCHANGE = "sms_email";
    public static void main(String[] args) throws IOException, TimeoutException, InterruptedException {
        System.out.println("短信消费者");
        //1.创建连接
        Connection connection = ConnectionUtils.newConnection();
        // 2.创建通道
        final Channel channel = connection.createChannel();
        // 3.声明队列
        /**
         * String queue, boolean durable, boolean exclusive, boolean autoDelete, Map<String, Object> arguments
         * queue:这没什么好说的,队列名
         *
         * durable:是否持久化,那么问题来了,这是什么意思?持久化,指的是队列持久化到数据库中。在之前的博文中也说过,如果RabbitMQ服务挂了怎么办,队列丢失了自然是不希望发生的。持久化设置为true的话,即使服务崩溃也不会丢失队列
         * exclusive:是否排外,what? 这又是什么呢。设置了排外为true的队列只可以在本次的连接中被访问,也就是说在当前连接创建多少个channel访问都没有关系,但是如果是一个新的连接来访问,对不起,不可以,下面是我尝试访问了一个排外的queue报的错。还有一个需要说一下的是,排外的queue在当前连接被断开的时候会自动消失(清除)无论是否设置了持久化
         * autoDelete:这个就很简单了,是否自动删除。也就是说queue会清理自己。但是是在最后一个connection断开的时候
         * 设置队列的其他一些参数
         */
        channel.queueDeclare(QUEUE_SMS, false, false, false, null);
        /**
         * String queue, String exchange, String routingKey
         */
        channel.queueBind(QUEUE_SMS, EXCHANGE, "message");
        DefaultConsumer defaultConsumer = new DefaultConsumer(channel) {
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                String msgString = new String(body, "UTF-8");
                System.out.println("短信消费者获取消息:" + msgString);
            }
        };
        // 4.设置应答模式,true的时候为自动应答,false为手动应答,需要处理
        channel.basicConsume(QUEUE_SMS, true, defaultConsumer);
    }
}

在这里插入图片描述

邮件消费者

public class EmailConsumer {
    private static String QUEUE_EMAIL = "eamil";
    private static String EXCHANGE = "sms_email";

    public static void main(String[] args) throws IOException, TimeoutException, InterruptedException {
        System.out.println("邮件消费者");
        //1.创建连接
        Connection connection = ConnectionUtils.newConnection();
        // 2.创建通道
        final Channel channel = connection.createChannel();
        // 3.声明队列
        /**
         * String queue, boolean durable, boolean exclusive, boolean autoDelete, Map<String, Object> arguments
         * queue:这没什么好说的,队列名
         *
         * durable:是否持久化,那么问题来了,这是什么意思?持久化,指的是队列持久化到数据库中。在之前的博文中也说过,如果RabbitMQ服务挂了怎么办,队列丢失了自然是不希望发生的。持久化设置为true的话,即使服务崩溃也不会丢失队列
         * exclusive:是否排外,what? 这又是什么呢。设置了排外为true的队列只可以在本次的连接中被访问,也就是说在当前连接创建多少个channel访问都没有关系,但是如果是一个新的连接来访问,对不起,不可以,下面是我尝试访问了一个排外的queue报的错。还有一个需要说一下的是,排外的queue在当前连接被断开的时候会自动消失(清除)无论是否设置了持久化
         * autoDelete:这个就很简单了,是否自动删除。也就是说queue会清理自己。但是是在最后一个connection断开的时候
         * 设置队列的其他一些参数
         */
        channel.queueDeclare(QUEUE_EMAIL, false, false, false, null);
        channel.queueBind(QUEUE_EMAIL, EXCHANGE, "message");
//        channel.txSelect();
        try {
//            int i = 1/0;
            DefaultConsumer defaultConsumer = new DefaultConsumer(channel) {
                @Override
                public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                    String msgString = new String(body, "UTF-8");
                    System.out.println("邮件消费者获取消息:" + msgString);
                }
            };
            // 4.设置应答模式,true的时候为自动应答,false为手动应答,需要处理
            channel.basicConsume(QUEUE_EMAIL, true, defaultConsumer);
//            channel.txCommit();
        } catch (Exception e) {
//            channel.txRollback();
        }

    }
}

在这里插入图片描述

3.Topic模式

生产者

public class Producer {

    private static String TOPIC_EXCHANGE = "topic";

    public static void main(String[] args) throws IOException, TimeoutException {
        //1.创建连接
        Connection connection = ConnectionUtils.newConnection();
        // 2.创建通道
        Channel channel = connection.createChannel();
        //3.绑定的交换机 参数1交互机名称 参数2 exchange类型
        channel.exchangeDeclare(TOPIC_EXCHANGE, "topic");
        String msg = "Topic生产消息";
        String msg1 = "Topic1生产消息";
        String msg2 = "Topic2生产消息";
        // 4.生产消息
        channel.basicPublish(TOPIC_EXCHANGE, "topic.test", null, msg.getBytes());
        System.out.println("Topic生产消息:" + msg1);
        channel.basicPublish(TOPIC_EXCHANGE, "topic.test.test", null, msg1.getBytes());
        System.out.println("Topic生产消息:" + msg1);
        channel.basicPublish(TOPIC_EXCHANGE, "topic.test1", null, msg2.getBytes());
        System.out.println("Topic生产消息:" + msg2);
    }

在这里插入图片描述
短信消费者:topic.*,*代表匹配0个或多个单词

public class TopicSmsConsumer {
    private static String QUEUE_SMS = "sms";

    private static String EXCHANGE = "topic";
    public static void main(String[] args) throws IOException, TimeoutException, InterruptedException {
        System.out.println("短信消费者");
        //1.创建连接
        Connection connection = ConnectionUtils.newConnection();
        // 2.创建通道
        final Channel channel = connection.createChannel();
        // 3.声明队列
        /**
         * String queue, boolean durable, boolean exclusive, boolean autoDelete, Map<String, Object> arguments
         * queue:这没什么好说的,队列名
         *
         * durable:是否持久化,那么问题来了,这是什么意思?持久化,指的是队列持久化到数据库中。在之前的博文中也说过,如果RabbitMQ服务挂了怎么办,队列丢失了自然是不希望发生的。持久化设置为true的话,即使服务崩溃也不会丢失队列
         * exclusive:是否排外,what? 这又是什么呢。设置了排外为true的队列只可以在本次的连接中被访问,也就是说在当前连接创建多少个channel访问都没有关系,但是如果是一个新的连接来访问,对不起,不可以,下面是我尝试访问了一个排外的queue报的错。还有一个需要说一下的是,排外的queue在当前连接被断开的时候会自动消失(清除)无论是否设置了持久化
         * autoDelete:这个就很简单了,是否自动删除。也就是说queue会清理自己。但是是在最后一个connection断开的时候
         * 设置队列的其他一些参数
         */
        channel.queueDeclare(QUEUE_SMS, false, false, false, null);
        /**
         * String queue, String exchange, String routingKey
         */
        channel.queueBind(QUEUE_SMS, EXCHANGE, "topic.*");
        DefaultConsumer defaultConsumer = new DefaultConsumer(channel) {
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                String msgString = new String(body, "UTF-8");
                System.out.println("短信消费者获取消息:" + msgString);
            }
        };
        // 4.设置应答模式,true的时候为自动应答,false为手动应答,需要处理
        channel.basicConsume(QUEUE_SMS, true, defaultConsumer);
    }
}

在这里插入图片描述

邮件消费者,topic.#,#代表匹配一个

public class TopicEamilConsumer {
    private static String QUEUE_EMAIL = "eamil";
    private static String EXCHANGE = "topic";

    public static void main(String[] args) throws IOException, TimeoutException, InterruptedException {
        System.out.println("邮件消费者");
        //1.创建连接
        Connection connection = ConnectionUtils.newConnection();
        // 2.创建通道
        final Channel channel = connection.createChannel();
        // 3.声明队列
        /**
         * String queue, boolean durable, boolean exclusive, boolean autoDelete, Map<String, Object> arguments
         * queue:这没什么好说的,队列名
         *
         * durable:是否持久化,那么问题来了,这是什么意思?持久化,指的是队列持久化到数据库中。在之前的博文中也说过,如果RabbitMQ服务挂了怎么办,队列丢失了自然是不希望发生的。持久化设置为true的话,即使服务崩溃也不会丢失队列
         * exclusive:是否排外,what? 这又是什么呢。设置了排外为true的队列只可以在本次的连接中被访问,也就是说在当前连接创建多少个channel访问都没有关系,但是如果是一个新的连接来访问,对不起,不可以,下面是我尝试访问了一个排外的queue报的错。还有一个需要说一下的是,排外的queue在当前连接被断开的时候会自动消失(清除)无论是否设置了持久化
         * autoDelete:这个就很简单了,是否自动删除。也就是说queue会清理自己。但是是在最后一个connection断开的时候
         * 设置队列的其他一些参数
         */
        channel.queueDeclare(QUEUE_EMAIL, false, false, false, null);
        channel.queueBind(QUEUE_EMAIL, EXCHANGE, "topic.#");

        DefaultConsumer defaultConsumer = new DefaultConsumer(channel) {
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                String msgString = new String(body, "UTF-8");
                System.out.println("邮件消费者获取消息:" + msgString);
            }
        };
        // 4.设置应答模式,true的时候为自动应答,false为手动应答,需要处理
        channel.basicConsume(QUEUE_EMAIL, true, defaultConsumer);
    }
}

在这里插入图片描述

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值