今天突然遇到一個需求,就是要求我的ActiveMQ隊列消息需要多個線程消費者去消費,但是每個消費者,雖然MQ支持多個消費者但是,每個消費者消費的數量可能不同,有的線程跑的快的,就肯定會多消費一些,但是現在的需求是要每個線程消費的數量一樣,這就需要用到MQ分組了,
首先是在消息生產的時候就就對每個消息進行分組
生產者工具類
@Component
public class ActiveMqUtils {
/**
* 注入JMS
*/
@Autowired
private JmsTemplate jmsTemplate;
public <T> String sendNorMolMessageById(Destination destination, String text,String GroupId) {
// 連接工廠
ConnectionFactory connectionFactory = jmsTemplate.getConnectionFactory();
Connection connection = null;
Session session = null;
MessageProducer producer = null;
try {
// 創建鏈接
connection = connectionFactory.createConnection();
connection.start();
// 創建session,開啓事物
session = connection.createSession(Boolean.TRUE, Session.AUTO_ACKNOWLEDGE);
// 創建生產者
producer = session.createProducer(destination);
// 設置持久化
producer.setDeliveryMode(DeliveryMode.PERSISTENT);
// 設置過期時間
//producer.setTimeToLive(time);
TextMessage message = session.createTextMessage(text);
message.setStringProperty("JMSGroupID",GroupId);
producer.send(message);
// 提交
session.commit();
return message.getJMSMessageID();
} catch (JMSException e) {
throw new RuntimeException(e);
} finally {
// 關閉連接
close(producer, session, connection, connectionFactory);
}
}
TextMessage message = session.createTextMessage(text);
message.setStringProperty("JMSGroupID",GroupId);
然後用工具生產,
/**
* 產生點對點的消息隊列
*/
@Override
public Result<String> createMq(String quenName,String text) {
Destination destination = new ActiveMQQueue(quenName);
String JMSMessageId = null;
for (int i = 0; i < 10; i++) {
/*Stu stu = stuMapper.selectByPrimaryKey(1);
String stuStr = new String();
if (stu!=null) {
stuStr = FastJsonUtils.getBeanToJson(stu);
}else {
stuStr = text;
}*/
JMSMessageId = utils.sendNorMolMessageById(destination, text, "GroupIdA");
JMSMessageId = utils.sendNorMolMessageById(destination, text, "GroupIdB");
//延時6秒後再次發送
//utils.sendDelayMessage(destination, text, 6*1000,6*1000,3);
}
return new Result<String>("消息已經產生:"+JMSMessageId,true);
}
分別命名爲GroupIdA,GroupIdB兩個分組,
最後對消息進行監聽
@Component
public class ActiveMqListenConfig {
private Logger logger = LoggerFactory.getLogger(this.getClass());
@JmsListener(destination="queueSend",selector="JMSGroupID='GroupIdA'")
public void recieveTaskMq(String message) {
logger.info("消費者1監聽到的消息是:" + message + ",並且這條消息已經被消費了");
}
@JmsListener(destination="queueSend" ,selector="JMSGroupID='GroupIdB'")
public void recieveTaskMq2(String message) {
logger.info("消費者2監聽到的消息是:" + message + ",並且這條消息已經被消費了");
}
}
這裏值得注意一下的就是selector="JMSGroupID='GroupIdA'",這是@JmsListener裏面的,是可以根據條件來對消息進行監聽的
在啓動項目後調用接口
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------以上是我將兩個消費者分到了不同的組所以它會將它所監聽到的隊列消息全部消費完,
當我讓兩個消費者全部監聽GroupIdA時,兩個消費者加起來肯定只會消息10跳消息,隊列中肯定還會剩下10條都是GroupIdB的
@Component
public class ActiveMqListenConfig {
private Logger logger = LoggerFactory.getLogger(this.getClass());
@JmsListener(destination="queueSend",selector="JMSGroupID='GroupIdA'")
public void recieveTaskMq(String message) {
logger.info("消費者1監聽到的消息是:" + message + ",並且這條消息已經被消費了");
}
@JmsListener(destination="queueSend" ,selector="JMSGroupID='GroupIdA'")
public void recieveTaskMq2(String message) {
logger.info("消費者2監聽到的消息是:" + message + ",並且這條消息已經被消費了");
}
}
重啓啓動項目,跑起來
看下控制檯,只有10條被消費了
再看下隊列消息,
也只被消費了10條,驗證成功