不依赖于第三方组件,只和Broker通信
内置管理和性能采集协议
较合理的超时时间设置
批量发送和消费,消费者为拉模式
支持两阶段事务
支持业务ID顺序消费
支持机房部署,就近发送和消费
默认数据压缩,更快的性能
支持流量分流控制
<
dependency
>
<
groupId
>com.jd.jmq
groupId
>
<
artifactId
>jmq-client-spring
artifactId
>
<
version
>2.1.5-SNAPSHOT
version
>
dependency
>
<
dependency
>
<
groupId
>com.jd.ump
groupId
>
<
artifactId
>profiler
artifactId
>
<
version
>3.2.0
version
>
dependency
>
|
schema配置(2.1.5-SNAPSHOT版本)
<
beans
...
xmlns:jmq
=
"http://code.jd.com/schema/jmq"
xsi:schemaLocation="...
http://code.jd.com/schema/jmq
http://code.jd.com/schema/jmq/jmq-1.0.xsd">
|
schema配置(2.1.0以下版本,包括2.1.0)
<
beans
...
xmlns:jmq
=
"http://code.jd.com/schema/jmq"
xsi:schemaLocation="...
http://code.jd.com/schema/jmq
http://code.jd.com/schema/jmq/jmq-1.0.xsd">
|
schema配置(2.1.1以上版本,包括2.1.1,不包括 2.1.5-SNAPSHOT)
<
beans
...
xmlns:jmq
=
"http://code.jd.com/schema/jmq"
xsi:schemaLocation="...
http://code.jd.com/schema/jmq
http://code.jd.com/schema/jmq/jmq-1.1.xsd">
|
<
dependency
>
<
groupId
>com.jd.jmq
groupId
>
<
artifactId
>jmq-client-core
artifactId
>
<
version
>2.1.5-SNAPSHOT
version
>
dependency
>
<
dependency
>
<
groupId
>com.jd.jmq
groupId
>
<
artifactId
>jmq-client-ump
artifactId
>
<
version
>2.1.5-SNAPSHOT
version
>
dependency
>
<
dependency
>
<
groupId
>com.jd.ump
groupId
>
<
artifactId
>profiler
artifactId
>
<
version
>3.2.0
version
>
dependency
>
|
重要说明,在配置中或者应用代码中使用到的topic都不需要加任何前缀,填写申请时的主题代码即可
属性
|
说明
|
默认值
|
---|---|---|
address | 目录服务地址 | JMQ接入地址 |
user | 用户 |
|
password | 密码 |
|
app |
接入的应用(系统)代码,此属性必须填写,和user完全一样 | nullAPP不同的TOPIC不能共用transport |
sendTimeout | 发送超时(毫秒) | 5000测试环境请适度改大 |
epoll | 是否使用epoll模式,会根据系统环境自动设置 | true |
<
jmq:transport
address
=
"jmq-cluster.jd.local:80"
user
=
"${jmq.user}"
password
=
"${jmq.password}"
app
=
"${jmq.producer.app}"
/>
|
<
jmq:transport
address
=
"jmq-testcluster.jd.local:50088"
password
=
"${jmq.password}"
app
=
"${jmq.producer.app}"
/>
|
属性
|
说明
|
默认值
|
---|---|---|
transport | 连接通道 | jmq.transport |
retryTimes | 发送失败后的重试次数 | 2 |
<
jmq:producer
id
=
"producer"
retryTimes
=
"2"
transport
=
"jmq.transport"
/>
|
注:在jmq管理平台, 暂停消费只能用于紧急情况,如果长时间暂停会导致消息积压,服务端消息文件无法删除,磁盘会被写满
//获取实例
Producer producer= (Producer) context.getBean(
"producer"
);
//普通发送方式
Message message =
new
Message(
"topic"
,
"消息内容"
,
"业务ID"
);
//业务ID不要超过16个字节,不然归档会有问题, 超过100个字节重试会有问题
producer.send(message, timeout);
//批量发送方式
List
new
ArrayList
for
(
int
j =
0
; j < n; j++) {
Message message =
new
Message(
"topic"
,
"消息内容"
,
"业务ID"
);
messages.add(message);
}
producer.send(messages);
|
/**
* 事务的单条发送
*/
protected
void
sendTransaction(
int
i)
throws
JMQException {
Message message =
new
Message(topic, topic +
"_test_"
+ i, topic +
"_rid_"
+ i);
Boolean ret = producer.send(message,
new
LocalTransaction
@Override
public
Boolean execute()
throws
Exception {
System.out.println(
"execute local transaction ok!"
);
return
true
;
}
@Override
public
int
getTimeout() {
return
50000
;
}
});
System.out.println(
"local transaction ret value:"
+ ret);
}
|
重要说明:JMQ不再区分正常消息和重试消息,请不要再根据消息属性来判断是否是重试消息。
属性
|
说明
|
默认值
|
---|---|---|
transport | 连接工厂 | jmq.transport |
autoStart | 自动启动消费 | true,》=1.2.25以上版本支持,高级特性谨慎设置 |
pullTimeout | 长轮询超时时间(一般不需要配置) | 10000ms pullTimeout必须大于longPull时间,否则客户端会报"请求超时" |
longPull |
长轮询等待时间(一般不需要配置) | 5000ms |
maxConcurrent
|
连接单组broker最大并发数,客户端实际线程数为单组运行的线程数*broker数(一般不需要配置,默认等于对列数) |
topic索引分区数,管理端配置 》=1.3.1以上版本支持 |
minConcurrent |
连接单组broker最小并发数(一般不需要配置) |
0 自动调节》=1.3.1以上版本支持 |
属性
|
说明
|
默认值
|
---|---|---|
topic | 消费者topic串,必须注入 | null |
listener | 消息监听器是MessageListener接口的实现类所创建的对象,用于处理收到的消息 抛出异常将回滚重试消息,否则成功消费并删除消息,所以如果认为消息处理失败还需重试请抛出异常 |
null |
<
jmq:consumer
id
=
"consumer"
transport
=
"jmq.transport"
>
<
jmq:listener
topic
=
"${jmq.consumer.topic}"
listener
=
"messageListener"
/>
jmq:consumer
>
<
bean
id
=
"messageListener"
class
=
"com.jd.jmq.demo.DefaultMessageListener"
/>
|
拉取模式指用户在代码里主动调用pull方法,不需要在配置文件里面再配置
method: pull(String topic,MessageListener listener)
topic:指消费的主题名
listener:是一个回调对象,当pull拉取到消息后会主动调用listener.onMessage(),
与监听模式的区别是:监听模式由JMQ客户端守护线程去不停的拉取消息进行消费,拉取模式由用户控制拉取的频率,不主动调用就不会消费消息。但是都不需要主动对消息进行确认
messageConsumer.start();
for (;;){
//手动拉取消息
messageConsumer.pull(topic,messageListener);
}
|
/**
* 消费方法。注意: 消费不成功请抛出异常,JMQ会自动重试
*
* @param messages
* @throws Exception
*/
@Override
public
void
onMessage(List messages)
throws
Exception {
if
(messages ==
null
|| messages.isEmpty()) {
return
;
}
for
(Message message : messages) {
logger.info(String.format(
"收到一条消息,消息主题(队列名):%s,内容是:%s"
, message.getTopic(), message.getText()));
}
}