消息中间件介绍

笔记

windows安装:https://www.cnblogs.com/vaiyanzi/p/9531607.html

RabbitMQ用户角色分类

RabbitMQ各类角色描述:
none
不能访问 management plugin


management
用户可以通过AMQP做的任何事外加:
列出自己可以通过AMQP登入的virtual hosts  
查看自己的virtual hosts中的queues, exchanges 和 bindings
查看和关闭自己的channels 和 connections
查看有关自己的virtual hosts的“全局”的统计信息,包含其他用户在这些virtual hosts中的活动。


policymaker
management可以做的任何事外加:
查看、创建和删除自己的virtual hosts所属的policies和parameters


monitoring  
management可以做的任何事外加:
列出所有virtual hosts,包括他们不能登录的virtual hosts
查看其他用户的connections和channels
查看节点级别的数据如clustering和memory使用情况
查看真正的关于所有virtual hosts的全局的统计信息


administrator   
policymaker和monitoring可以做的任何事外加:
创建和删除virtual hosts
查看、创建和删除users
查看创建和删除permissions
关闭其他用户的connections

 

 

不同的消息分发模式

1.简单模式

 

 1.导入依赖

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

 

2.消息生产者

public class Producer {
    public static void main(String[] args){
        // 所有的中间件技术都是基于Tcp/ip协议基础之上构建新型的协议规范
        // 只不过rabbitmq遵循的是amqp

        // 1.创建连接工程
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("localhost");
        factory.setPort(5672);
        factory.setUsername("guest");
        factory.setPassword("guest");
        factory.setVirtualHost("/");

        // 2.创建连接Connection
        Connection connection = null;
        Channel channel = null;
        try {
            connection = factory.newConnection("生产者");


            // 3.通过连接过去通道Channel
            channel = connection.createChannel();

            // 4.通过通道创建交换机,声明队列,绑定关系,路由key,发送消息和接收消息
            String queueName = "queue1";
            // 队列名称,是否持久化,是否有排他性,是否自动删除,
            channel.queueDeclare(queueName,false,false,false,null);
            // 5.准备消息内容
            String message = "你好,RabbitMQ";
            // 6.发送消息给队列
            channel.basicPublish("",queueName,null,message.getBytes());
            System.out.println("消息发送成功!");

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 7.关闭连接
            if (channel != null && channel.isOpen()){
                try {
                    channel.close();
                } catch (Exception e){
                    e.printStackTrace();
                }
            }
            // 8.关闭连接
            if (connection != null && connection.isOpen()){
                try {
                    connection.close();
                } catch (Exception e){
                    e.printStackTrace();
                }
            }
        }
    }
}

 

3.消息消费者

public class Consumer {
    public static void main(String[] args) {
        // 1.创建连接工程
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("localhost");
        factory.setPort(5672);
        factory.setUsername("guest");
        factory.setPassword("guest");
        factory.setVirtualHost("/");

        // 2.创建连接Connection
        Connection connection = null;
        Channel channel = null;

        try {
            connection = factory.newConnection("消费者");

            // 3.通过连接获取通道Channel
            channel = connection.createChannel();

            // 4.通过通道创建交换机,声明队列,绑定关系,路由key,发送消息和接收消息
            channel.basicConsume("queue1", true, new DeliverCallback() {
                @Override
                public void handle(String s, Delivery delivery) throws IOException {
                    System.out.println("收到的消息是:\n" + new String(delivery.getBody(), "UTF-8"));
                }
            },new CancelCallback(){
                @Override
                public void handle(String s) throws IOException {
                    System.out.println("接受消息失败");
                }
            });

            /*
            DeliverCallback deliverCallback = (consumerTag, delivery) -> {
                String message = new String(delivery.getBody(), "UTF-8");
                System.out.println(" [x] Received '" + message + "'");
            };
            channel.basicConsume("queue1", true, deliverCallback, consumerTag -> { });
            */
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 7.关闭连接
            if (channel != null && channel.isOpen()){
                try {
                    channel.close();
                } catch (Exception e){
                    e.printStackTrace();
                }
            }
            // 8.关闭连接
            if (connection != null && connection.isOpen()){
                try {
                    connection.close();
                } catch (Exception e){
                    e.printStackTrace();
                }
            }
        }
    }
}

 

2.fanout模式

 

 

发布订阅者模式,发布者发布消息,所有订阅的人都可以接收到消息
public class Producer {
    public static void main(String[] args){
        // 所有的中间件技术都是基于Tcp/ip协议基础之上构建新型的协议规范
        // 只不过rabbitmq遵循的是amqp

        // 1.创建连接工程
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("localhost");
        factory.setPort(5672);
        factory.setUsername("guest");
        factory.setPassword("guest");
        factory.setVirtualHost("/");

        // 2.创建连接Connection
        Connection connection = null;
        Channel channel = null;
        try {
            connection = factory.newConnection("生产者");
            // 3.通过连接过去通道Channel
            channel = connection.createChannel();
            // 4.准备消息内容
            String message = "fanout模式消息";
            // 5.准备交换机
            String exchangeName = "fanout-exchange";
            // 6.定义路由
            String routerKey = "";
            // 7.指定交换机的类型
            String type = "fanout";

            // 8.发送消息给消息中间件rabbitmq-server,没有定义路由
            channel.basicPublish(exchangeName,routerKey,null,message.getBytes());
            System.out.println("消息发送成功!");
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("消息发送异常");
        } finally {
            // 关闭连接
            if (channel != null && channel.isOpen()){
                try {
                    channel.close();
                } catch (Exception e){
                    e.printStackTrace();
                }
            }
            // 关闭连接
            if (connection != null && connection.isOpen()){
                try {
                    connection.close();
                } catch (Exception e){
                    e.printStackTrace();
                }
            }
        }
    }
}
===============================================================

// 线程开启三个队列接收消息
public class Consumer {
    public static void main(String[] args) {
//        Thread thread = new Thread(runnable,"queue1");
//        thread.start();
        new Thread(runnable,"queue1").start();
        new Thread(runnable,"queue2").start();
        new Thread(runnable,"queue3").start();
    }
    private static Runnable runnable = new Runnable() {
        @Override
        public void run() {
            // 1.创建连接工程
            ConnectionFactory factory = new ConnectionFactory();
            factory.setHost("localhost");
            factory.setPort(5672);
            factory.setUsername("guest");
            factory.setPassword("guest");
            factory.setVirtualHost("/");
            final String queueName = Thread.currentThread().getName();
            // 2.创建连接Connection
            Connection connection = null;
            Channel channel = null;
            try {
                connection = factory.newConnection("消费者");
                // 3.通过连接过去通道Channel
                channel = connection.createChannel();
                // 4.通过通道创建交换机,声明队列,绑定关系,路由key,发送消息和接收消息
                channel.basicConsume(queueName, true, new DeliverCallback() {
                    @Override
                    public void handle(String s, Delivery delivery) throws IOException {
                        System.out.println(queueName+"\n"+"收到的消息是:\n" + new String(delivery.getBody(), "UTF-8"));
                    }
                },new CancelCallback(){
                    @Override
                    public void handle(String s) throws IOException {
                        System.out.println("接受消息失败");
                    }
                });
                System.out.println("开始接收消息");
                System.in.read();

        /*    这是官网的原实现例子
        DeliverCallback deliverCallback = (consumerTag, delivery) -> {
            String message = new String(delivery.getBody(), "UTF-8");
            System.out.println(" [x] Received '" + message + "'");
        };
        channel.basicConsume("queue1", true, deliverCallback, consumerTag -> { });
        */
            } catch (Exception e) {
                e.printStackTrace();
                System.out.println("接收异常");
            } finally {
                // 关闭连接
                if (channel != null && channel.isOpen()){
                    try {
                        channel.close();
                    } catch (Exception e){
                        e.printStackTrace();
                    }
                }
                // 关闭连接
                if (connection != null && connection.isOpen()){
                    try {
                        connection.close();
                    } catch (Exception e){
                        e.printStackTrace();
                    }
                }
            }
        }
    };
}

 

3.Direct模式

 

 

在fanout模式基础上添加路由过滤
 
public class Producer {
    public static void main(String[] args){
        // 所有的中间件技术都是基于Tcp/ip协议基础之上构建新型的协议规范
        // 只不过rabbitmq遵循的是amqp
        // 1.创建连接工程
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("localhost");
        factory.setPort(5672);
        factory.setUsername("guest");
        factory.setPassword("guest");
        factory.setVirtualHost("/");
        // 2.创建连接Connection
        Connection connection = null;
        Channel channel = null;
        try {
            connection = factory.newConnection("生产者");
            // 3.通过连接过去通道Channel
            channel = connection.createChannel();
            // 4.准备消息内容
            String message = "routing模式";
            // 5.准备交换机
            String exchangeName = "direct_exchange";
            // 6.定义路由    只有routerKey是email的订阅者才可以接收到消息
            String routerKey = "email";
            // 7.指定交换机的类型
            String type = "direct";
            // 8.发送消息给消息中间件rabbitmq-server
            channel.basicPublish(exchangeName,routerKey,null,message.getBytes());
            System.out.println("消息发送成功!");
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("消息发送异常");
        } finally {
            // 关闭连接
            if (channel != null && channel.isOpen()){
                try {
                    channel.close();
                } catch (Exception e){
                    e.printStackTrace();
                }
            }
            // 关闭连接
            if (connection != null && connection.isOpen()){
                try {
                    connection.close();
                } catch (Exception e){
                    e.printStackTrace();
                }
            }
        }
    }
}

=============
接收方的实现与fanout相同

 

4.Topic模式

 

 

在Direct模式基础上添加匹配类型
 * 代表至少有1个等级
 # 代表可以有0个或多个等级
public class Producer {
    public static void main(String[] args){
        // 所有的中间件技术都是基于Tcp/ip协议基础之上构建新型的协议规范
        // 只不过rabbitmq遵循的是amqp
        // 1.创建连接工程
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("localhost");
        factory.setPort(5672);
        factory.setUsername("guest");
        factory.setPassword("guest");
        factory.setVirtualHost("/");
        // 2.创建连接Connection
        Connection connection = null;
        Channel channel = null;
        try {
            connection = factory.newConnection("生产者");
            // 3.通过连接过去通道Channel
            channel = connection.createChannel();
            // 4.准备消息内容
            String message = "topic模式";
            // 5.准备交换机
            String exchangeName = "topic_exchange";
            // 6.定义路由        topic匹配模式,匹配com.#  *.course.* #.order.#
            String routerKey = "com.course.order";
            // 7.指定交换机的类型
            String type = "topic";
            // 8.发送消息给消息中间件rabbitmq-server
            channel.basicPublish(exchangeName,routerKey,null,message.getBytes());
            System.out.println("消息发送成功!");
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("消息发送异常");
        } finally {
            // 关闭连接
            if (channel != null && channel.isOpen()){
                try {
                    channel.close();
                } catch (Exception e){
                    e.printStackTrace();
                }
            }
            // 关闭连接
            if (connection != null && connection.isOpen()){
                try {
                    connection.close();
                } catch (Exception e){
                    e.printStackTrace();
                }
            }
        }
    }
}

 

5.Headers模式
添加参数条件匹配
 
用代码声明交换机和队列并绑定
String exchangeName = "direct_message_exchange";
// 定义路由
String routerKey = "56test";
// 指定交换机的类型
String type = "direct";


// 声明交换机:exchangeDeclare(交换机名称,交换机模式,是否持久化)
channel.exchangeDeclare(exchangeName,type,true);
// 声明队列:queueDeclare(队列名称,是否持久化,是否具有排他性,是否自动删除,参数)
channel.queueDeclare("queue5",true,false,false,null);
channel.queueDeclare("queue6",true,false,false,null);
channel.queueDeclare("queue7",true,false,false,null);


// 绑定队列和交换机的关系
channel.queueBind("queue5",exchangeName,"56test");
channel.queueBind("queue6",exchangeName,"56test");
channel.queueBind("queue7",exchangeName,"nothing");


// 8.发送消息给消息中间件rabbitmq-server
channel.basicPublish(exchangeName,routerKey,null,message.getBytes());

 

Work模式
 

 

 

 
1.轮询模式(均分)
不会因为服务器性能影响消费的数
 
一个消息分发者
public class Producer {
    public static void main(String[] args){
        // 所有的中间件技术都是基于Tcp/ip协议基础之上构建新型的协议规范
        // 只不过rabbitmq遵循的是amqp

        // 1.创建连接工程
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("localhost");
        factory.setPort(5672);
        factory.setUsername("guest");
        factory.setPassword("guest");
        factory.setVirtualHost("/");
        // 2.创建连接Connection
        Connection connection = null;
        Channel channel = null;
        try {
            connection = factory.newConnection("生产者");
            // 3.通过连接过去通道Channel
            channel = connection.createChannel();


            for (int i = 0; i <= 20; i++) {
                String message = "work_lunXun"+i;
                // 8.发送消息给消息中间件rabbitmq-server
                channel.basicPublish("","queue1",null,message.getBytes());
            }
            System.out.println("消息发送成功!");
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("消息发送异常");
        } finally {
            // 关闭连接
            if (channel != null && channel.isOpen()){
                try {
                    channel.close();
                } catch (Exception e){
                    e.printStackTrace();
                }
            }
            // 关闭连接
            if (connection != null && connection.isOpen()){
                try {
                    connection.close();
                } catch (Exception e){
                    e.printStackTrace();
                }
            }
        }


    }
}

 

两个消息接收者

public class Work1 {
    public static void main(String[] args) {
// 1.创建连接工程
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("localhost");
        factory.setPort(5672);
        factory.setUsername("guest");
        factory.setPassword("guest");
        factory.setVirtualHost("/");

        // 2.创建连接Connection
        Connection connection = null;
        Channel channel = null;

        try {
            connection = factory.newConnection("消费者-work1");
            // 3.通过连接过去通道Channel
            channel = connection.createChannel();

            // 4.通过通道创建交换机,声明队列,绑定关系,路由key,发送消息和接收消息
//            channel.basicQos(1);
            channel.basicConsume("queue1", true, new DeliverCallback() {
                @Override
                public void handle(String s, Delivery delivery) throws IOException {
                    System.out.println("Work1-收到的消息是:\n" + new String(delivery.getBody(), "UTF-8"));
                    try {
                        // 为什么要延时?
                        Thread.sleep(2000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            },new CancelCallback(){
                @Override
                public void handle(String s) throws IOException {
                    System.out.println("接受消息失败");
                }
            });


            System.out.println("Work1-开始接收消息");
            System.in.read();
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("接收异常");
        } finally {
            // 关闭连接
            if (channel != null && channel.isOpen()){
                try {
                    channel.close();
                } catch (Exception e){
                    e.printStackTrace();
                }
            }
            // 关闭连接
            if (connection != null && connection.isOpen()){
                try {
                    connection.close();
                } catch (Exception e){
                    e.printStackTrace();
                }
            }
        }
    }
}


public class Work2 {

    public static void main(String[] args) {
// 1.创建连接工程
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("localhost");
        factory.setPort(5672);
        factory.setUsername("guest");
        factory.setPassword("guest");
        factory.setVirtualHost("/");

        // 2.创建连接Connection
        Connection connection = null;
        Channel channel = null;

        try {
            connection = factory.newConnection("消费者-work2");
            // 3.通过连接过去通道Channel
            channel = connection.createChannel();

            // 4.通过通道创建交换机,声明队列,绑定关系,路由key,发送消息和接收消息
//            channel.basicQos(1);
            channel.basicConsume("queue1", true, new DeliverCallback() {
                @Override
                public void handle(String s, Delivery delivery) throws IOException {
                    System.out.println("Work2-收到的消息是:\n" + new String(delivery.getBody(), "UTF-8"));
                    try {
                        // 为什么要延时?
                        Thread.sleep(200);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            },new CancelCallback(){
                @Override
                public void handle(String s) throws IOException {
                    System.out.println("接受消息失败");
                }
            });
            System.out.println("Work2-开始接收消息");
            System.in.read();
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("接收异常");
        } finally {
            // 关闭连接
            if (channel != null && channel.isOpen()){
                try {
                    channel.close();
                } catch (Exception e){
                    e.printStackTrace();
                }
            }
            // 关闭连接
            if (connection != null && connection.isOpen()){
                try {
                    connection.close();
                } catch (Exception e){
                    e.printStackTrace();
                }
            }
        }
    }
}

 

2.公平分发
 
服务器性能好的会偷任务执行
public class Producer {
    public static void main(String[] args){
        // 所有的中间件技术都是基于Tcp/ip协议基础之上构建新型的协议规范
        // 只不过rabbitmq遵循的是amqp

        // 1.创建连接工程
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("localhost");
        factory.setPort(5672);
        factory.setUsername("guest");
        factory.setPassword("guest");
        factory.setVirtualHost("/");

        // 2.创建连接Connection
        Connection connection = null;
        Channel channel = null;
        try {
            connection = factory.newConnection("生产者");
            // 3.通过连接过去通道Channel
            channel = connection.createChannel();


            for (int i = 0; i <= 20; i++) {
                String message = "work_lunXun"+i;
                // 8.发送消息给消息中间件rabbitmq-server
                channel.basicPublish("","queue1",null,message.getBytes());
            }
            System.out.println("消息发送成功!");
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("消息发送异常");
        } finally {
            // 关闭连接
            if (channel != null && channel.isOpen()){
                try {
                    channel.close();
                } catch (Exception e){
                    e.printStackTrace();
                }
            }
            // 关闭连接
            if (connection != null && connection.isOpen()){
                try {
                    connection.close();
                } catch (Exception e){
                    e.printStackTrace();
                }
            }
        }


    }
}

================================================

public class Work1 {
    public static void main(String[] args) {
// 1.创建连接工程
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("localhost");
        factory.setPort(5672);
        factory.setUsername("guest");
        factory.setPassword("guest");
        factory.setVirtualHost("/");
        // 2.创建连接Connection
        Connection connection = null;
        Channel channel = null;
        try {
            connection = factory.newConnection("消费者-work2");
            // 3.通过连接过去通道Channel
            channel = connection.createChannel();
            // 4.通过通道创建交换机,声明队列,绑定关系,路由key,发送消息和接收消息
            channel.basicQos(2);
            Channel finalChannel = channel;
            /* 需要改成channel.basicConsume("queue1", false, new DeliverCallback() {
             *  原来:   channel.basicConsume("queue1", true, new DeliverCallback() {
             * */
            channel.basicConsume("queue1", false, new DeliverCallback() {
                @Override
                public void handle(String s, Delivery delivery) throws IOException {
                    System.out.println("Work2-收到的消息是:\n" + new String(delivery.getBody(), "UTF-8"));
                    try {
                        // 为什么要延时?比较不同性能是否影响消费数量
                        Thread.sleep(5000);
                        finalChannel.basicAck(delivery.getEnvelope().getDeliveryTag(),false);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            },new CancelCallback(){
                @Override
                public void handle(String s) throws IOException {
                    System.out.println("接受消息失败");
                }
            });
            System.out.println("Work2-开始接收消息");
            System.in.read();
        /*
        DeliverCallback deliverCallback = (consumerTag, delivery) -> {
            String message = new String(delivery.getBody(), "UTF-8");
            System.out.println(" [x] Received '" + message + "'");
        };
        channel.basicConsume("queue1", true, deliverCallback, consumerTag -> { });
        */
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("接收异常");
        } finally {
            // 关闭连接
            if (channel != null && channel.isOpen()){
                try {
                    channel.close();
                } catch (Exception e){
                    e.printStackTrace();
                }
            }
            // 关闭连接
            if (connection != null && connection.isOpen()){
                try {
                    connection.close();
                } catch (Exception e){
                    e.printStackTrace();
                }
            }
        }
    }
}

============================
public class Work2 {
    public static void main(String[] args) {
// 1.创建连接工程
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("localhost");
        factory.setPort(5672);
        factory.setUsername("guest");
        factory.setPassword("guest");
        factory.setVirtualHost("/");

        // 2.创建连接Connection
        Connection connection = null;
        Channel channel = null;

        try {
            connection = factory.newConnection("消费者-work2");
            // 3.通过连接过去通道Channel
            channel = connection.createChannel();


            // 4.通过通道创建交换机,声明队列,绑定关系,路由key,发送消息和接收消息
            channel.basicQos(2);
            // 下面内部类中也用到了channel,所以需要中间变量防止冲突
            Channel finalChannel = channel;
            /* 需要改成channel.basicConsume("queue1", false, new DeliverCallback() {
            *  原来:   channel.basicConsume("queue1", true, new DeliverCallback() {
            * */
            channel.basicConsume("queue1", false, new DeliverCallback() {
                @Override
                public void handle(String s, Delivery delivery) throws IOException {
                    System.out.println("Work2-收到的消息是:\n" + new String(delivery.getBody(), "UTF-8"));
                    try {
                        // 为什么要延时?比较不同性能是否影响消费数量
                        Thread.sleep(2000);
                        finalChannel.basicAck(delivery.getEnvelope().getDeliveryTag(),false);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            },new CancelCallback(){
                @Override
                public void handle(String s) throws IOException {
                    System.out.println("接受消息失败");
                }
            });
            System.out.println("Work2-开始接收消息");
            System.in.read();
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("接收异常");
        } finally {
            // 关闭连接
            if (channel != null && channel.isOpen()){
                try {
                    channel.close();
                } catch (Exception e){
                    e.printStackTrace();
                }
            }
            // 关闭连接
            if (connection != null && connection.isOpen()){
                try {
                    connection.close();
                } catch (Exception e){
                    e.printStackTrace();
                }
            }
        }
    }
}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

posted @ 2021-04-27 19:07  G-G  阅读(95)  评论(0)    收藏  举报