一、顺序消息
此处只是简单的实现方式,只能支撑对性能和吞吐量不大的场景。
解决方式:
1、指定单一的address和queue,消息都放在一个queue中
2、在创建connection的时候,设置consumerWindowSize,保证consumer不进行消息缓存
<property name="consumerWindowSize" value="0"></property>
如此,消息创建后,将按照先后顺序进入queue,消费的时候,每次取一个消息进行消费。
说明:此时可以有多个producer,但是只能有一个consumer
二、Last-Value-Queue模式
Last Value Queue模式能够很好的解决一些只需要最新消息的场景,比如股价,只关心最新价格。
当producer每隔一段时间,就会发送一个消息(比如股价),相同股票代码的价格数据,在消费时,只关心最新的消息。
解决方式:
1、需要在创建queue时开启Last-Value-Queue模式
如果是auto-created的,则在指定destination时,加上参数即可:
<property name="defaultDestinationName" value="xx::dd.notice.hh?last-value=true"></property>
说明:对于LVQ有两种设置模式,一种是通过last-value=true启用,此时消息主键默认使用
org.apache.activemq.artemis.api.core.Message.HDR_LAST_VALUE_NAME
来设定;另一种是通过last-value-key来启用,直接指定key值(主键值)
说明2:如果queue已存在了,则需要删除重建,才能使LVQ模式生效
2、在发送消息的时候,通过设置message的属性值(key需要与步骤1中的一致),来进行消息的处理
message.setStringProperty(
String.valueOf(org.apache.activemq.artemis.api.core.Message.HDR_LAST_VALUE_NAME),
entity.getFundCode() + entity.getAsOfDate());
producer示例代码:
@RequestMapping("/sendJmsLVQ")
@ResponseBody
public String sendLvq() {
MqSettleNoticeEntity entity = new MqSettleNoticeEntity();
entity.setFundCode("SC001");
entity.setAsOfDate(20210101);
jmsTemplate.send(new MessageCreator() {
@Override
public Message createMessage(Session session) throws JMSException {
Message message = session.createObjectMessage(entity);
message.setStringProperty(
String.valueOf(org.apache.activemq.artemis.api.core.Message.HDR_LAST_VALUE_NAME),
entity.getFundCode() + entity.getAsOfDate());
return message;
}
});
return "hello LVQ";
}
三、消息类型
目前,JMS消息支持如下几种类型:
- TextMessage: 文本消息
- BytesMessage: 二进制消息
- MapMessage: K-V消息
- ObjectMessage: 直接序列化JAVA对象的消息
- StreamMessage:包含基本类型序列的消息
对于常规来说,一般都是使用TextMessage,尤其是系统间的消息。一般是JSON字符串,接收方自行进行解析。
如果对于系统内的消息,比如同一个系统不同模块,含有相同的java类,则可以考虑直接使用序列化的对象作为消息,此时使用ObjectMessage,可以通过定义messageConverter进行处理。
接收方可以自动转换成所需要的的JAVA对象。
如果是系统间的消息,由于一般没有相同的JAVA类,故一般不建议使用ObjectMessage