视频参考:https://www.bilibili.com/video/av55976700
1、为什么要引入MQ
1)、系统之间耦合比较严重
2)、面对大流量并发,容易被冲垮
3)、等待同步存在性能问题
2、应用场景
1)、异步通信
注册时的短信、邮件通知,减少响应时间;
2)、应用解耦
信息发送者和消息接受者无需耦合,比如调用第三方;
3)、流量削峰
例如秒杀系统
3、MQ的demo练习
开发基本步骤:
两种消费方式:
点对点消息传递特点:
(1)、点对点消息生产和消费
生产者:
import org.apache.activemq.ActiveMQConnectionFactory; import javax.jms.*; /** * Created by Administrator on 2020/2/10. */ public class JmsProduce { public static final String ACTIVE_MQ_URL = "tcp://127.0.0.1:61616"; public static final String QUEUE_NAME = "queue01"; public static void main(String[] args) throws JMSException { //1、创建连接工厂,按照给定的url地址,采用默认的用户名和密码 ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory(ACTIVE_MQ_URL); //2、通过连接工厂,获取连接的connection并启动访问 QueueConnection connection = connectionFactory.createQueueConnection(); connection.start(); //3创建会话session (事物、签收) Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); //4、创建目的地具体是主体还是队列 Queue queue = session.createQueue(QUEUE_NAME); // 5\创建消息的生产者 MessageProducer producer = session.createProducer(queue); for (int i =0; i<6;i++){ TextMessage textMessage = session.createTextMessage("message=" + i); producer.send(textMessage); } // 6、关闭资源 producer.close(); session.close(); connection.close(); System.out.println("消息发送到MQ完成"); } }
消费者:
import org.apache.activemq.ActiveMQConnectionFactory; import javax.jms.*; import java.io.IOException; /** * Created by Administrator on 2020/2/10. */ public class JmsConsumer { public static final String ACTIVE_MQ_URL = "tcp://127.0.0.1:61616"; public static final String QUEUE_NAME = "queue01"; public static void main(String[] args) throws JMSException, IOException { System.out.println("我是2号消费者"); //1、创建连接工厂,按照给定的url地址,采用默认的用户名和密码 ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory(ACTIVE_MQ_URL); //2、通过连接工厂,获取连接的connection并启动访问 QueueConnection connection = connectionFactory.createQueueConnection(); connection.start(); //3创建会话session (事物、签收) Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); //4、创建目的地具体是主体还是队列 Queue queue = session.createQueue(QUEUE_NAME); // 5\创建消息的消费者 MessageConsumer consumer = session.createConsumer(queue); // 方法一: /* // 同步阻塞方式,订阅者或接受者调用MessageConsumer的receive()方法来接收消息 // receive方法在能够接收消息之前(或超时之前)将一直阻塞 while(true){ TextMessage message = (TextMessage) consumer.receive(4000l); if(null != message){ System.out.println("消息者接收消息=" + message.getText()); }else{ break; } }*/ // 方法二 通过监听的方法来监听消息 // 异步非阻塞方式(监听器onMessage())订阅者或接收者通过MessageConsumer的setMessageListener(MessageListener messageListener) // 注册一个消息监听器,当消息到达之后,系统自动调用监听器的onMessage方法 consumer.setMessageListener(new MessageListener() { @Override public void onMessage(Message message) { if(null != message && message instanceof TextMessage){ TextMessage textMessage = (TextMessage) message; try { System.out.println("消息者接收消息=" + textMessage.getText()); } catch (JMSException e) { e.printStackTrace(); } } } }); System.in.read(); //先生产,先启动一号消费者、再启动二号消费者 1号可以消费、2号不可以 // 先启动2个消费者、在启动生产者生产6条消息, 2个消费者是一人一半 // 、关闭资源 consumer.close(); session.close(); connection.close(); } }
(2)、主题消息发布
先启动消费者,在启动生产者
消费者:
import org.apache.activemq.ActiveMQConnectionFactory; import javax.jms.*; import java.io.IOException; /** * Created by Administrator on 2020/2/10. */ public class JmsConsumerTopic { public static final String ACTIVE_MQ_URL = "tcp://127.0.0.1:61616"; public static final String TOPIC_NAME = "topic01"; public static void main(String[] args) throws JMSException, IOException { System.out.println("我是3号消费者"); //1、创建连接工厂,按照给定的url地址,采用默认的用户名和密码 ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory(ACTIVE_MQ_URL); //2、通过连接工厂,获取连接的connection并启动访问 QueueConnection connection = connectionFactory.createQueueConnection(); connection.start(); //3创建会话session (事物、签收) Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); //4、创建目的地具体是主題 Topic topic = session.createTopic(TOPIC_NAME); // 5\创建消息的消费者 MessageConsumer consumer = session.createConsumer(topic); // 通过监听的方法来监听消息 // 异步非阻塞方式(监听器onMessage())订阅者或接收者通过MessageConsumer的setMessageListener(MessageListener messageListener) // 注册一个消息监听器,当消息到达之后,系统自动调用监听器的onMessage方法 consumer.setMessageListener(message -> { if(null != message && message instanceof TextMessage){ TextMessage textMessage = (TextMessage) message; try { System.out.println("消息者接收Topic消息=" + textMessage.getText()); } catch (JMSException e) { e.printStackTrace(); } } }); System.in.read(); // 、关闭资源 consumer.close(); session.close(); connection.close(); } }
生产者:
import org.apache.activemq.ActiveMQConnectionFactory; import javax.jms.*; /** * Created by Administrator on 2020/2/10. */ public class JmsProduceTopic { public static final String ACTIVE_MQ_URL = "tcp://127.0.0.1:61616"; public static final String TOPIC_NAME = "topic01"; public static void main(String[] args) throws JMSException { //1、创建连接工厂,按照给定的url地址,采用默认的用户名和密码 ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory(ACTIVE_MQ_URL); //2、通过连接工厂,获取连接的connection并启动访问 QueueConnection connection = connectionFactory.createQueueConnection(); connection.start(); //3创建会话session (事物、签收) Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); //4、创建目的地具体是主題 Topic topic = session.createTopic(TOPIC_NAME); // 5\创建消息的生产者 MessageProducer producer = session.createProducer(topic); for (int i =0; i<3;i++){ TextMessage textMessage = session.createTextMessage("Topic-message=" + i); producer.send(textMessage); } // 6、关闭资源 producer.close(); session.close(); connection.close(); System.out.println("Topic消息发送到MQ完成"); } }
(3)、队列和主题的区别