RabbitMQ使用简述
RabbitMQ基于AMQP协议。
AMQP:是一个高级抽象层消息通信协议,RabbitMQ是AMQP协议的实现
RabbitMQ使用:Exchange(交换机)根据routing-key(路由选择键)匹配相应的queue(队列)
Exchange有4中类型:
direct:exchange在和queue进行binding时会设置routingkey,进行消息发送时,只有设置相同的routingkey,交换机才会路由到相应的队列。
topic:和direct差不多,只是topic允许routingkey使用通配符'*','#'.来匹配到相应的queue
fanout:直接将消息路由到所有绑定的队列中
header:和以上三个都不一样,其路由的规则是根据header来判断,其中的header就是以下方法的arguments参数
参考:https://www.cnblogs.com/julyluo/p/6265775.html,https://www.jianshu.com/p/d5675b1c8112
Routing Key:在Consumer在binding exchange和queue时指定;在Producer在发送消息时指定。
demo:
引入jar包:
<!-- RabbitMQ -->
<dependency>
<groupId>com.rabbitmq</groupId>
<artifactId>amqp-client</artifactId>
<version>5.0.0</version>
</dependency>
<dependency>
<groupId>org.springframework.amqp</groupId>
<artifactId>spring-rabbit</artifactId>
<version>2.0.0.RELEASE</version>
</dependency>
增加RabbitMQ配置
<!-- rabbitMQ配置 -->
<bean id="rabbitConnectionFactory"
class="org.springframework.amqp.rabbit.connection.CachingConnectionFactory">
<constructor-arg value="172.16.1.15"/>
<property name="username" value="admin"/>
<property name="password" value="admin"/>
<property name="channelCacheSize" value="8"/>
<property name="port" value="5672"></property>
</bean>
<rabbit:admin connection-factory="rabbitConnectionFactory"/>
<!--邮件相关队列-->
<rabbit:queue name="test_email_queue" durable="true"/>
<!--短信相关队列-->
<rabbit:queue name="test_sms_queue" durable="true"/>
<!--将队列和交换器通过路由键绑定-->
<rabbit:direct-exchange name="TEST_MQ"
xmlns="http://www.springframework.org/schema/rabbit"
durable="true">
<rabbit:bindings>
<rabbit:binding queue="test_email_queue" key="email" ></rabbit:binding>
<rabbit:binding queue="test_sms_queue" key="sms" ></rabbit:binding>
</rabbit:bindings>
</rabbit:direct-exchange>
<!-- 创建rabbitTemplate 消息模板类 -->
<bean id="rabbitTemplate" class="org.springframework.amqp.rabbit.core.RabbitTemplate">
<constructor-arg ref="rabbitConnectionFactory"></constructor-arg>
</bean>
<rabbit:listener-container connection-factory="rabbitConnectionFactory">
<rabbit:listener queues="test_email_queue" ref="processUserEmail"
method="onMessage"/>
<rabbit:listener queues="test_sms_queue" ref="processUserSms"
method="onMessage"/>
</rabbit:listener-container>
实现类:(生产者写入MQ)
package com.study.demo.service.impl; import com.study.demo.service.IUserReg; import com.study.demo.service.busi.SaveUser; import com.study.demo.vo.User; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.amqp.AmqpException; import org.springframework.amqp.core.Message; import org.springframework.amqp.core.MessageProperties; import org.springframework.amqp.rabbit.core.RabbitTemplate; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Service; /** * * @Description: RabbitMQ实现的异步用户注册 * @author leeSmall * @date 2018年9月18日 * */ @Service @Qualifier("async") public class AsyncProcess implements IUserReg{ private Logger logger = LoggerFactory.getLogger(AsyncProcess.class); @Autowired private RabbitTemplate rabbitTemplate; @Autowired private SaveUser saveUser; public boolean userRegister(User user) { try { saveUser.saveUser(user); rabbitTemplate.send("TEST_MQ","email", new Message(user.getEmail().getBytes(),new MessageProperties())); rabbitTemplate.send("TEST_MQ","sms", new Message(user.getEmail().getBytes(),new MessageProperties())); } catch (AmqpException e) { logger.error(e.toString()); return false; } return true; } }
消费者(监听调用该方法)
package com.study.demo.service.mq; import com.study.demo.service.busi.SendEmail; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.amqp.core.Message; import org.springframework.amqp.core.MessageListener; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; /** * * @Description: RabbitMQ消息消费端监听邮件消息类 * @author leeSmall * @date 2018年9月18日 * */ @Component public class ProcessUserEmail implements MessageListener { private Logger logger = LoggerFactory.getLogger(ProcessUserEmail.class); @Autowired private SendEmail sendEmail; public void onMessage(Message message) { logger.info("accept message,ready process......"); sendEmail.sendEmail(new String(message.getBody())); } }
package com.study.demo.service.mq; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.amqp.core.Message; import org.springframework.amqp.core.MessageListener; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import com.study.demo.service.busi.SendSms; /** * * @Description: RabbitMQ消息消费端监听sms消息类 * @author leeSmall * @date 2018年9月18日 * */ @Component public class ProcessUserSms implements MessageListener { private Logger logger = LoggerFactory.getLogger(ProcessUserSms.class); @Autowired private SendSms sendSms; public void onMessage(Message message) { logger.info("accept message,ready process......"); sendSms.sendSms(new String(message.getBody())); } }
使用目的:解耦,加快上文响应时间
使用场景:下单时关于库存的扣减、邮件、短信、消息的推送等需要异步处理的地方
如何使用的:
库存的扣减:
用户下单后,订单系统需要通知库存系统。传统的做法是,订单系统调用库存系统的接口。如下图:
传统模式的缺点:假如库存系统无法访问,则订单减库存将失败,从而导致订单失败,订单系统与库存系统耦合
应用消息队列后的方案:
订单系统:用户下单后,订单系统完成持久化处理,将消息写入消息队列,返回用户订单下单成功
库存系统:订阅下单的消息,采用拉/推的方式,获取下单信息,库存系统根据下单信息,进行库存操作
假如:在下单时库存系统不能正常使用。也不影响正常下单,因为下单后,订单系统写入消息队列就不再关心其他的后续操作了。实现订单系统与库存系统的应用解耦
库存系统:订阅下单的消息,采用拉/推的方式,获取下单信息,库存系统根据下单信息,进行库存操作
假如:在下单时库存系统不能正常使用。也不影响正常下单,因为下单后,订单系统写入消息队列就不再关心其他的后续操作了。实现订单系统与库存系统的应用解耦
邮件、短信的发送:
串行方式:
并行方式(异步):
消息队列方式(解耦):

浙公网安备 33010602011771号