消息队列——RabbitMQ基本概念+容器化部署和简单工作模式程序

目录

基本概念

[MQ 的优势](#MQ 的优势)

1.应用解耦

2.异步提速

3.削峰填谷

[MQ 的劣势](#MQ 的劣势)

使用mq的条件

常见MQ产品

RabbitMQ简介

RabbitMQ的六种工作模式

JMS

RabbitMQ安装和配置。

RabbitMQ控制台使用。

RabbitMQ快速入门------生产者

需求:

RabbitMQ快速入门------消费者

小结


基本概念

多个系统之间的通信方式有两种,一是直接远程调用,二是通过第三方,mq就是这个第三方

MQ 的优势

1.应用解耦

一个好的系统肯定会要求高内聚低耦合。

像下面这个,订单系统发个订单到库存时,如果库存系统损坏了可能会连带影响订单系统。

有了mq之后,消息存放在mq里面,哪怕库存坏了几分钟,好了之后也可以从mq中接着拿消息出来。

还有一个时,如果要添加一个新的x系统,一般要修改订单系统的代码来兼容。

有了mq之后,订单系统会把所有消息都放到mq里面,新的系统的不管是什么都从mq里面拿东西就好了,就不需要改代码了

2.异步提速

同步下需要走完整个流程才能有反馈,所以很慢。

异步下,即使没有运行完整个流程,也会立刻返回消息,后面的系统会继续从mq中取出消息执行。这种属于是骗人

3.削峰填谷

瞬时请求太多致使服务器宕机了。

mq在这里只是缓存消息和发布消息,不负责业务逻辑处理,因此完全可以承载更多的请求。

如果一层mq解决不了,那就再加一层。

使用mq技术在项目里面之后这些优势可以作为项目亮点写在简历上。

MQ 的劣势

使用mq的条件

常见MQ产品

RabbitMQ简介

RabbitMQ支持AMQP协议,

在AMQP中,交换机分发消息,queue存储消息。分发通过Routes进行 。

RabbitMq里面RabbitMQ Server作为服务端,生产者和消费者都是作为客户端,通过tcp连接和服务端进行通信。如果每一次通信都建立tcp连接资源消耗极大,故这里Connection作为一个连接池,里面有许多管道,通过channel进行通信,这样可以节约资源。

RabbitMq中有很多虚拟机,每个虚拟机里面有很多Exchange和Queue,交换机可以绑定到不同的队列上,Binding就是交换价绑定到队列上的过程。

RabbitMQ的六种工作模式

生产消息和消费消息的工作方式

JMS

类比jdbc是java程序和数据库通信的接口,JMS就是java程序和消息队列通信的接口。

RabbitMQ安装和配置。

在云服务器上直接安装docker版本的就可以了。

Downloading and Installing RabbitMQ --- RabbitMQ

XML 复制代码
docker run -it --rm --name rabbitmq -p 5672:5672 -p 15672:15672 rabbitmq:3.12-management

运行如下所示

安装好后通过IP+端口访问管理界面。

管理界面端口是15672,tcp连接的端口是5672。

账号密码都是guest

RabbitMQ控制台使用。

在控制台可以看见有一个Overview概览,Connection连接,channels通道,Exchanges交换机,Queues,和Admin,Admin中可以管理用户和虚拟机等

这里新建了一个超级用户yhy和一个虚拟机itcast授权给yhy。

有了管理员权限就可以用新用户的账号密码登录了。

RabbitMQ快速入门------生产者

需求:

在idea中创建一个新的空工程,添加两个maven模块。

然后再在两个工程里面分别导入rabbitMQ的依赖和编译的版本插件。

XML 复制代码
 <dependencies>
         <!--rabbitmq的java客户端-->
         <dependency>
             <groupId>com.rabbitmq</groupId>
             <artifactId>amqp-client</artifactId>
             <version>5.6.0</version>
         </dependency>
     </dependencies>

    <build>
        <plugins>
            <!--编译插件-->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.0</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
        </plugins>
    </build>

有基本架构图和简单工作模式的图可得以下流程。因为简单模式中没有交换机,所以这里不涉及交换机的创建。

java 复制代码
//发送消息
public class producer {
    public static void main(String[] args) throws IOException, TimeoutException {
        //1.创建连接工厂
        ConnectionFactory factory=new ConnectionFactory();
        //2.设置参数
        factory.setHost("XXX.XX.XXX.XXX"); //设置ip地址。默认为127.0.0.1
        factory.setPort(5672);              //端口 默认值5672
        factory.setVirtualHost("/itcast");  //设置虚拟机 默认值/
        factory.setUsername("yhy");        //用户名,默认值guest
        factory.setPassword("XXXXXX");     //密码,默认值guest
        //3.创建连接Connection
        Connection connection = factory.newConnection();
        //4.创建Channel
        Channel channel = connection.createChannel();
        //5.创建队列Queue
        /*
        queueDeclare(String queue, boolean durable, boolean exclusive, boolean autoDelete, Map<String, Object> arguments)
        参数:
            1.queue:队列名称
            2.durable:是否持久化,当mq重启之后,还在
            3.exclusive:
                *是否独占。只能有一个消费者监听这队列
                *当Connection关闭时,是否删除队列
            4.autoDelete: 是否自动删除。当没有Consumer时,自动删除掉
            5.arguments:参数。
        */
        //如果没有一个名叫hello_yhy的队列,则会自动创建一个
        channel.queueDeclare("hello_yhy",true,false,false,null);
        //6.发送消息
        /*
        basicPublish(String exchange, String routingKey, AMQP.BasicProperties props, byte[] body)
        参数:
            1.exchange:交换机名称。简单模式下交换机会使用默认的""。
            2.routerKey:路由名称。
            3.props:配置信息
            4.body:发送消息数据
        */
        String body="hello rabbitmq!!!";
        channel.basicPublish("","hello_yhy",null,body.getBytes());
        //7.释放资源
        channel.close();
        connection.close();
    }
}

在控制台中可以看见现在没有一个队列。

运行完之后可以看见hello_yhy队列出现了。

但是没有新的Connection和channel出现,因为最后关闭了,如果代码最后不关闭就会出现。

然后程序不同就会显示一直running。

RabbitMQ快速入门------消费者

与生产者非常类似。

但是由上图可知,创建channel的参数虽然一样,但是是不同的channel.

在写生产者时已经有一个队列了,所以再创建一次也没有问题

目前队列中有两条消息。

java 复制代码
public class consumer {
    public static void main(String[] args) throws IOException, TimeoutException {
        //1.创建连接工厂
        ConnectionFactory factory=new ConnectionFactory();
        //2.设置参数
        factory.setHost("XXX.XX.XXX.XXX"); //设置ip地址。默认为127.0.0.1
        factory.setPort(5672);              //端口 默认值5672
        factory.setVirtualHost("/itcast");  //设置虚拟机 默认值/
        factory.setUsername("yhy");        //用户名,默认值guest
        factory.setPassword("XXXXXX");     //密码,默认值guest
        //3.创建连接Connection
        Connection connection = factory.newConnection();
        //4.创建Channel
        Channel channel = connection.createChannel();
        //5.创建队列Queue
        /*
        queueDeclare(String queue, boolean durable, boolean exclusive, boolean autoDelete, Map<String, Object> arguments)
        参数:
            1.queue:队列名称
            2.durable:是否持久化,当mq重启之后,还在
            3.exclusive:
                *是否独占。只能有一个消费者监听这队列
                *当Connection关闭时,是否删除队列
            4.autoDelete: 是否自动删除。当没有Consumer时,自动删除掉
            5.arguments:参数。
        */
        //如果没有一个名叫hello_yhy的队列,则会自动创建一个
        channel.queueDeclare("hello_yhy",true,false,false,null);

        /*
        * basicConsume(String queue, boolean autoAck, Consumer callback)
        * 参数:
        *   1.队列名称
        *   2.autoAck:是否自动确认
        *   3.callback:回调对象
        * */
        //6.接收消息
        Consumer consumer=new DefaultConsumer(channel){
            /*
            * 回调方法,当收到消息后,会自动执行该方法
            * 1.consumerTag:标识
            * 2.envelope :获取一些信息,交换机,路由key...
            * 3.properties: 配置信息
            * 4.body: 数据
            * */
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                System.out.println("consumerTag:"+consumerTag);
                System.out.println("Exchange:"+envelope.getExchange());
                System.out.println("RoutingKey:"+envelope.getRoutingKey());
                System.out.println("properties:"+properties);
                System.out.println("body:"+new String(body));
            }
        };
        channel.basicConsume("hello_yhy",true,consumer);

        //不需要关闭资源
    }
}

运行消费者代码之后

可以看见雀氏取出了两条消息。并且控制台看见已经没有消息了。

小结

相关推荐
Soari21 小时前
Ziggo-CaaS-Switch软件配置: undefined reference to pthread_create
java·开发语言·fpga开发·tsn·zynq·交换机配置
云烟成雨TD21 小时前
Spring AI Alibaba 1.x 系列【13】 检查点 (Checkpoint) 机制及各类持久化实现
java·人工智能·spring
其实是白羊21 小时前
我用 Vibe Coding 搓了一个 IDEA 插件,复制URI 再也不用手动拼了
后端·intellij idea
用户83562907805121 小时前
Python 操作 Word 文档节与页面设置
后端·python
酒後少女的夢21 小时前
设计模式教程
后端·架构
凌览21 小时前
别再手搓 Skill 了,用这个工具 5 分钟搞定
前端·后端
殷紫川21 小时前
深入拆解 Fork/Join 框架:核心原理、分治模型与参数调优实战
java
yaaakaaang21 小时前
十六、解释器模式
java·解释器模式
若阳安好21 小时前
【提效小工具】IN SQL、UPDATE SQL、INSERT SQL
java·数据库·sql
乐之者v21 小时前
20多个表,每个都有userId 和其他几个属性,要根据userId把他们全部汇总,如何处理?
java·mysql