消息队列——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);

        //不需要关闭资源
    }
}

运行消费者代码之后

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

小结

相关推荐
也无晴也无风雨1 小时前
深入剖析输入URL按下回车,浏览器做了什么
前端·后端·计算机网络
憨子周1 小时前
2M的带宽怎么怎么设置tcp滑动窗口以及连接池
java·网络·网络协议·tcp/ip
霖雨2 小时前
使用Visual Studio Code 快速新建Net项目
java·ide·windows·vscode·编辑器
SRY122404193 小时前
javaSE面试题
java·开发语言·面试
Fiercezm3 小时前
JUC学习
java
无尽的大道3 小时前
Java 泛型详解:参数化类型的强大之处
java·开发语言
ZIM学编程3 小时前
Java基础Day-Sixteen
java·开发语言·windows
我不是星海3 小时前
1.集合体系补充(1)
java·数据结构
P.H. Infinity3 小时前
【RabbitMQ】07-业务幂等处理
java·rabbitmq·java-rabbitmq
爱吃土豆的程序员4 小时前
java XMLStreamConstants.CDATA 无法识别 <![CDATA[]]>
xml·java·cdata