-
RabbitMQ基本原理
MQ全称为Message Queue, 是一种分布式应用程序的的通信方法,它是消费-生产者模型的一个典型的代表,producer往消息队列中不断写入消息,而另一端consumer则可以读取或者订阅队列中的消息。RabbitMQ是MQ产品的典型代表,是一款基于AMQP协议可复用的企业消息系统。业务上,可以实现服务提供者和消费者之间的数据解耦,提供高可用性的消息传输机制,在实际生产中应用相当广泛。
-
概念说明:
Broker:它提供一种传输服务,它的角色就是维护一条从生产者到消费者的路线,保证数据能按照指定的方式进行传输。
Exchange:消息交换机,它指定消息按什么规则,路由到哪个队列。
Queue:消息的载体,每个消息都会被投到一个或多个队列。
Binding:绑定,它的作用就是把exchange和queue按照路由规则绑定起来。
Routing Key:路由关键字,exchange根据这个关键字进行消息投递。
vhost:虚拟主机,一个broker里可以有多个vhost,用作不同用户的权限分离。
Producer:消息生产者,就是投递消息的程序。
Consumer:消息消费者,就是接受消息的程序。
Channel:消息通道,在客户端的每个连接里,可建立多个channel。 -
Queue基本集成实现代码
pom文件包导入:
<!--Spring Boot jar -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- End -->
<!-- RabbitMQ -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
- 消息队列消息生产者端实现:
application.properties文件配置:
#RabbitMQ配置
#IP地址配置
spring.rabbitmq.host=${mq.address}
#端口配置
spring.rabbitmq.port=${mq.port}
#用户名配置
spring.rabbitmq.username=${mq.usernam}
#用户密码配置
spring.rabbitmq.password=${mq.password}
# 开启发送确认
spring.rabbitmq.publisher-confirms=true
# 开启发送失败退回
spring.rabbitmq.publisher-returns=true
# 开启ACK
spring.rabbitmq.listener.direct.acknowledge-mode=manual
spring.rabbitmq.listener.simple.acknowledge-mode=manual
- 消息发送代码实现:
QueueConfig代码:
/**
* 消息队列配置 (注意队列不能用下划线字符,会报错的)
* @author zhongyulin
*
*/
public class QueueConfig {
/**
* PCS消息队列
*/
public final static String QUEUE_SITE_NAME = "QUEUESITE";
/**
* PCS消息队列
*/
public final static String QUEUE_PCSONE_NAME = "QUEUEPCSONE";
/**
* BCMU消息队列
*/
public final static String QUEUE_BCMU_NAME = "QUEUEBCMU";
/**
* BSMU消息队列
*/
public final static String QUEUE_BSMU_NAME = "QUEUEBSMU";
/**
* POWERDEV消息队列
*/
public final static String QUEUE_POWERDEV_NAME = "QUEUEPOWERDEV";
/**
* ENERDEV消息队列
*/
public final static String QUEUE_ENERDEV_NAME = "QUEUEENERDEV";
/**
* THD消息队列
*/
public final static String QUEUE_THD_NAME = "QUEUETHD";
}
MqSenderConf 消息队列配置类
import org.springframework.amqp.core.Queue;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import cn.common.rabbitmq.QueueConfig;
/**
* 消息队列配置
* @author zhongyulin
*
*/
@Configuration
public class MqSenderConf {
@Bean
@Qualifier(QueueConfig.QUEUE_SITE_NAME)
public Queue siteQueue() {
return new Queue(QueueConfig.QUEUE_SITE_NAME);
}
@Bean
@Qualifier(QueueConfig.QUEUE_PCSONE_NAME)
public Queue pcsQueue() {
return new Queue(QueueConfig.QUEUE_PCSONE_NAME);
}
@Bean
@Qualifier(QueueConfig.QUEUE_BSMU_NAME)
public Queue bsmuQueue() {
return new Queue(QueueConfig.QUEUE_BSMU_NAME);
}
@Bean
@Qualifier(QueueConfig.QUEUE_BCMU_NAME)
public Queue bcmuQueue() {
return new Queue(QueueConfig.QUEUE_BCMU_NAME);
}
@Bean
@Qualifier(QueueConfig.QUEUE_POWERDEV_NAME)
public Queue powerdevQueue() {
return new Queue(QueueConfig.QUEUE_POWERDEV_NAME);
}
@Bean
@Qualifier(QueueConfig.QUEUE_ENERDEV_NAME)
public Queue enerdevQueue() {
return new Queue(QueueConfig.QUEUE_ENERDEV_NAME);
}
@Bean
@Qualifier(QueueConfig.QUEUE_THD_NAME)
public Queue thdQueue() {
return new Queue(QueueConfig.QUEUE_THD_NAME);
}
- 队列消息发送类:
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* 消息队列发送消息
* @author zhongyulin
*
*/
@Component
public class MsgQueueSend {
@Autowired
private AmqpTemplate rabbitTemplate;
/**
* 消息队列发送消息
* @param queueName 消息队列
* @param msg 消息
*/
public void msgSend(String queueName,byte[] bymsg)throws Exception {
try {
rabbitTemplate.convertAndSend(queueName,bymsg);
} catch (Exception e) {
throw e;
}
}
}
- 消费端代码实现:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.amqp.core.Message;
import com.rabbitmq.client.Channel;
import cn.common.rabbitmq.QueueConfig;
import cn.device.util.MsgToByteUtil;
/**
* MQ消费处理类
* @author zhongyulin
*
*/
@Component
@RabbitListener(queues=QueueConfig.QUEUE_SITE_NAME)
public class SiteMQConsoumer {
private static Logger logger=LoggerFactory.getLogger(SiteMQConsoumer.class);
/**
* 解析读取数据
* @param bymsg
* @param channel
* @param message
* @throws IOException
*/
@RabbitHandler
public void readqueuesitemsg(byte[] bymsg,Channel channel, Message message) throws IOException {
logger.info("消费解析站点数据报文开始");
try {
//解析数据开始
String content=MsgToByteUtil.getObjectFromBytes(bymsg).toString();
logger.info("队列消息报文:"+content);
//ACK确认消息已经消费成功
channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
} catch (Exception e) {
logger.error("消息解析异常:"+e);
//丢弃这条消息
channel.basicNack(message.getMessageProperties().getDeliveryTag(), false,false);
}
}
}