RabbitMQ学习之HelloWorld模型

首先什么是消息队列

消息指的是两个应用间传递的数据。数据的类型有很多种形式,可能只包含文本字符串,也可能包含嵌入对象。

“消息队列(Message Queue)”是在消息的传输过程中保存消息的容器。在消息队列中,通常有生产者和消费者两个角色。生产者只负责发送数据到消息队列,谁从消息队列中取出数据处理,他不管。消费者只负责从消息队列中取出数据处理,他不管这是谁发送的数据。

消息队列的三个作用

解耦。如图所示。假设有系统B、C、D都需要系统A的数据,于是系统A调用三个方法发送数据到B、C、D。这时,系统D不需要了,那就需要在系统A把相关的代码删掉。假设这时有个新的系统E需要数据,这时系统A又要增加调用系统E的代码。为了降低这种强耦合,就可以使用MQ,系统A只需要把数据发送到MQ,其他系统如果需要数据,则从MQ中获取即可。

异步。如图所示。一个客户端请求发送进来,系统A会调用系统B、C、D三个系统,同步请求的话,响应时间就是系统A、B、C、D的总和,也就是800ms。如果使用MQ,系统A发送数据到MQ,然后就可以返回响应给客户端,不需要再等待系统B、C、D的响应,可以大大地提高性能。对于一些非必要的业务,比如发送短信,发送邮件等等,就可以采用MQ

削峰。如图所示。这其实是MQ一个很重要的应用。假设系统A在某一段时间请求数暴增,有5000个请求发送过来,系统A这时就会发送5000条SQL进入MySQL进行执行,MySQL对于如此庞大的请求当然处理不过来,MySQL就会崩溃,导致系统瘫痪。如果使用MQ,系统A不再是直接发送SQL到数据库,而是把数据发送到MQ,MQ短时间积压数据是可以接受的,然后由消费者每次拉取2000条进行处理,防止在请求峰值时期大量的请求直接发送到MySQL导致系统崩溃。

今天介绍的HelloWorld模型是最简单的模型,如下图

相关资料可以参考:https://www.rabbitmq.com/tutorials/tutorial-one-python.html

相关代码如下

生产者

package com.baizhi.HelloWorld;

import com.baizhi.Utils.rabbitmqUtils;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;

import java.io.IOException;

public class Provider {
    public static void main(String[] args) {
        Connection connection= rabbitmqUtils.getConnection();
        Channel channel= null;
        try {
            channel = connection.createChannel();
            channel.queueDeclare("hello",true,false,false,null);
            for(int i=0;i<10;i++) {
                channel.basicPublish("", "hello", null, (i+"hello work").getBytes());
            }
            rabbitmqUtils.closeChannlAndConnection(channel,connection);
        } catch (IOException e) {
            e.printStackTrace();
        }




    }
}

消费者 

package com.baizhi.HelloWorld;

import com.baizhi.Utils.rabbitmqUtils;
import com.rabbitmq.client.*;

import java.io.IOException;

public class Customer {
    public static void main(String[] args) {
        Connection connection= rabbitmqUtils.getConnection();
        Channel channel= null;
        try {
            channel=connection.createChannel();
            channel.queueDeclare("hello", true , false,false, null);
            channel.basicConsume("hello",true,new DefaultConsumer(channel){
                @Override
                public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                    System.out.println("接收到的消息是:"+new String(body));
                }
            });
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

}

函数参数说明:队列声明函数

channel.QueueDeclare(name, durable, autoDelete, exclusive, noWait, args)

name:队列名字

durable:是否持久化, 队列的声明默认是存放到内存中的,如果rabbitmq重启会丢失,如果想重启之后还存在就要使队列持久化,保存到Erlang自带的Mnesia数据库中,当rabbitmq重启之后会读取该数据库

autoDelete:是否自动删除队列,当最后一个消费者断开连接之后队列是否自动被删除,可以通过RabbitMQ Management,查看某个队列的消费者数量,当consumers = 0时队列就会自动删除

exclusive:是否排外的,有两个作用,一:当连接关闭时connection.close()该队列是否会自动删除;二:该队列是否是私有的private,如果不是排外的,可以使用两个消费者都访问同一个队列,没有任何问题,如果是排外的,会对当前队列加锁,其他通道channel是不能访问的,如果强制访问会报异常

noWait:是否等待服务器返回

args:相关参数,目前一般为null



channel.basicPublish(exchange, routingKey, props, body);

exchange交换机名称, routingKey队列名称, props传递消息额外设置一般为null, body消息的具体内容


			channel.basicConsume("work", true,new DefaultConsumer(channel) {
				//body就是消息队列取出的消息
				public void handleDelivery(String consumerTag,com.rabbitmq.client.Envelope envelope, com.rabbitmq.client.AMQP.BasicProperties properties, byte[] body) throws IOException {
					System.out.println(new String(body));
				};
			});

 第一个参数 队列名称

第二个参数自动确认,当自动应答等于true的时候,表示当消费者一收到消息就表示消费者收到了消息,消费者收到了消息就会立即从队列中删除

第三个参数回调函数,

回调函数 由调用函数自己传一个参数决定 被调用函数的方式当程序跑起来时,一般情况下,应用程序(application program)会时常通过API调用库里所预先备好的函数。 但是有些库函数(library function)却要求应用先传给它一个函数,好在合适的时候调用,以完成目标任务。这个被传入的、后又被调用的函数就称为回调函数(callback function)

执行结果

执行生产者程序:

执行消费者程序

猜你喜欢

转载自blog.csdn.net/weixin_41066584/article/details/109062769