Java 每分钟发送35000条jms消息
我们有一个spring引导应用程序,用于在另一个组件上执行负载测试。我们需要每分钟最多发送35000条JMS消息,因此我使用调度器每分钟运行一次任务 问题是,当我保持低强度时,它会设法在指定的时间间隔(一分钟)内发送消息。但是,当强度较高时,发送这段消息需要1分钟以上的时间。对以下实施有何建议 调度程序类Java 每分钟发送35000条jms消息,java,scheduled-tasks,spring-jms,scheduledexecutorservice,Java,Scheduled Tasks,Spring Jms,Scheduledexecutorservice,我们有一个spring引导应用程序,用于在另一个组件上执行负载测试。我们需要每分钟最多发送35000条JMS消息,因此我使用调度器每分钟运行一次任务 问题是,当我保持低强度时,它会设法在指定的时间间隔(一分钟)内发送消息。但是,当强度较高时,发送这段消息需要1分钟以上的时间。对以下实施有何建议 调度程序类 @Component public class MessageScheduler { private final Logger log = LoggerFactory.getLogger(g
@Component
public class MessageScheduler {
private final Logger log = LoggerFactory.getLogger(getClass());
private static ScheduledExecutorService executorService = Executors.newScheduledThreadPool(16);
private final static int TIME_PERIOD = ConfigFactory.getConfig().getInt("messages.period").orElse(60000);
@Autowired
JmsSender sender;
public void startScheduler() {
Runnable runnableTask = sender::sendMessagesChunk;
executorService.scheduleAtFixedRate(runnableTask, 0, TIME_PERIOD,
TimeUnit.MILLISECONDS);
}
}
@Component
public class JmsSender {
@Autowired
TrackingManager manager;
private final Logger log = LoggerFactory.getLogger(getClass());
private final static int TOTAL_MESSAGES = ConfigFactory.getConfig().getInt("total.tracking.messages").orElse(10);
private final static int TIME_PERIOD = ConfigFactory.getConfig().getInt("messages.period").orElse(60000);
private static int failedPerPeriod=0;
private static int totalFailed=0;
private static int totalMessageCounter=0;
public void sendMessagesChunk() {
log.info("Started at: {}", Instant.now());
log.info("Sending messages with intensity {} messages/minute", TOTAL_MESSAGES);
for (int i=0; i<TOTAL_MESSAGES; i++) {
try {
long start = System.currentTimeMillis();
MessageDTO msg = manager.createMessage();
send(msg);
long stop = System.currentTimeMillis();
if (timeOfDelay(stop-start)>=0L) {
Thread.sleep(timeOfDelay(stop-start));
}
} catch (Exception e) {
log.info("Error : " + e.getMessage());
failedPerPeriod++;
}
}
totalMessageCounter += TOTAL_MESSAGES;
totalFailed += failedPerPeriod;
log.info("Finished at: {}", Instant.now());
log.info("Success rate(of last minute): {} %, Succeeded: {}, Failed: {}, Success rate(in total): {} %, Succeeded: {}, Failed: {}"
,getSuccessRatePerPeriod(), getSuccededPerPeriod(), failedPerPeriod,
getTotalSuccessRate(), getTotalSucceded(), totalFailed);
failedPerPeriod =0;
}
private long timeOfDelay(Long elapsedTime){
return (TIME_PERIOD / TOTAL_MESSAGES) - elapsedTime;
}
private int getSuccededPerPeriod(){
return TOTAL_MESSAGES - failedPerPeriod;
}
private int getTotalSucceded(){
return totalMessageCounter - totalFailed;
}
private double getSuccessRatePerPeriod(){
return getSuccededPerPeriod()*100D / TOTAL_MESSAGES;
}
private double getTotalSuccessRate(){
return getTotalSucceded()*100D / totalMessageCounter;
}
private void send(MessageDTO messageDTO) throws Exception {
requestContextInitializator();
JmsClient client = JmsClientBuilder.newClient(UriScheme.JmsType.AMQ);
client.target(new URI("activemq:queue:" + messageDTO.getDestination()))
.msgTypeVersion(messageDTO.getMsgType(), messageDTO.getVersion())
.header(Header.MSG_VERSION, messageDTO.getVersion())
.header(Header.MSG_TYPE, messageDTO.getMsgType())
.header(Header.TRACKING_ID, UUID.randomUUID().toString())
.header(Header.CLIENT_ID, "TrackingJmsClient")
.post(messageDTO.getPayload());
}
用于发送消息的类
@Component
public class MessageScheduler {
private final Logger log = LoggerFactory.getLogger(getClass());
private static ScheduledExecutorService executorService = Executors.newScheduledThreadPool(16);
private final static int TIME_PERIOD = ConfigFactory.getConfig().getInt("messages.period").orElse(60000);
@Autowired
JmsSender sender;
public void startScheduler() {
Runnable runnableTask = sender::sendMessagesChunk;
executorService.scheduleAtFixedRate(runnableTask, 0, TIME_PERIOD,
TimeUnit.MILLISECONDS);
}
}
@Component
public class JmsSender {
@Autowired
TrackingManager manager;
private final Logger log = LoggerFactory.getLogger(getClass());
private final static int TOTAL_MESSAGES = ConfigFactory.getConfig().getInt("total.tracking.messages").orElse(10);
private final static int TIME_PERIOD = ConfigFactory.getConfig().getInt("messages.period").orElse(60000);
private static int failedPerPeriod=0;
private static int totalFailed=0;
private static int totalMessageCounter=0;
public void sendMessagesChunk() {
log.info("Started at: {}", Instant.now());
log.info("Sending messages with intensity {} messages/minute", TOTAL_MESSAGES);
for (int i=0; i<TOTAL_MESSAGES; i++) {
try {
long start = System.currentTimeMillis();
MessageDTO msg = manager.createMessage();
send(msg);
long stop = System.currentTimeMillis();
if (timeOfDelay(stop-start)>=0L) {
Thread.sleep(timeOfDelay(stop-start));
}
} catch (Exception e) {
log.info("Error : " + e.getMessage());
failedPerPeriod++;
}
}
totalMessageCounter += TOTAL_MESSAGES;
totalFailed += failedPerPeriod;
log.info("Finished at: {}", Instant.now());
log.info("Success rate(of last minute): {} %, Succeeded: {}, Failed: {}, Success rate(in total): {} %, Succeeded: {}, Failed: {}"
,getSuccessRatePerPeriod(), getSuccededPerPeriod(), failedPerPeriod,
getTotalSuccessRate(), getTotalSucceded(), totalFailed);
failedPerPeriod =0;
}
private long timeOfDelay(Long elapsedTime){
return (TIME_PERIOD / TOTAL_MESSAGES) - elapsedTime;
}
private int getSuccededPerPeriod(){
return TOTAL_MESSAGES - failedPerPeriod;
}
private int getTotalSucceded(){
return totalMessageCounter - totalFailed;
}
private double getSuccessRatePerPeriod(){
return getSuccededPerPeriod()*100D / TOTAL_MESSAGES;
}
private double getTotalSuccessRate(){
return getTotalSucceded()*100D / totalMessageCounter;
}
private void send(MessageDTO messageDTO) throws Exception {
requestContextInitializator();
JmsClient client = JmsClientBuilder.newClient(UriScheme.JmsType.AMQ);
client.target(new URI("activemq:queue:" + messageDTO.getDestination()))
.msgTypeVersion(messageDTO.getMsgType(), messageDTO.getVersion())
.header(Header.MSG_VERSION, messageDTO.getVersion())
.header(Header.MSG_TYPE, messageDTO.getMsgType())
.header(Header.TRACKING_ID, UUID.randomUUID().toString())
.header(Header.CLIENT_ID, "TrackingJmsClient")
.post(messageDTO.getPayload());
}
@组件
公共类JmsSender{
@自动连线
跟踪经理;
私有最终记录器log=LoggerFactory.getLogger(getClass());
private final static int TOTAL_MESSAGES=ConfigFactory.getConfig().getInt(“TOTAL.tracking.MESSAGES”).orElse(10);
private final static int TIME_PERIOD=ConfigFactory.getConfig().getInt(“messages.PERIOD”).orElse(60000);
私有静态int failedperperperperperperperiod=0;
私有静态int totalFailed=0;
私有静态int totalMessageCounter=0;
public void sendMessagesChunk(){
log.info(“开始于:{}”,Instant.now());
log.info(“发送强度为{}条消息/分钟的消息”,消息总数);
用于(int i=0;i=0L){
休眠(延迟时间(停止-启动));
}
}捕获(例外e){
log.info(“错误:+e.getMessage());
失败的perperperiod++;
}
}
totalMessageCounter+=消息总数;
totalFailed+=每个周期的失败次数;
log.info(“完成于:{}”,Instant.now());
log.info(“成功率(最后一分钟):{}%,成功:{},失败:{},成功率(总计):{}%,成功:{},失败:{}”
,GetSuccessRatePerPerPerPerPerPerPeriod(),GetSuccessedPerPerPerPerPerPeriod(),FailedPerPerPerPeriod,
getTotalSuccessRate()、GetTotalSuccessed()、totalFailed);
failedperperperperiod=0;
}
私人长延时(长延时){
返回(时间段/总消息)-elapsedTime;
}
private int getSucceedPerPerPerPerPerPerPeriod()函数{
返回总_消息-每个周期失败;
}
private int getTotalSuccedd(){
返回totalMessageCounter-totalFailed;
}
私有双GetSuccessRatePerPerPerPerPerPerPerPerPerPerPerPeriod(){
返回GetSucceedPerPerperiod()*100D/总消息数;
}
私有双getTotalSuccessRate(){
返回GetTotalSuccedd()*100D/totalMessageCounter;
}
私有void发送(MessageDTO MessageDTO)引发异常{
requestContextInitializator();
jmsclientclient=JmsClientBuilder.newClient(UriScheme.JmsType.AMQ);
target(新URI(“activemq:queue:+messageDTO.getDestination()))
.msgTypeVersion(messageDTO.getMsgType(),messageDTO.getVersion())
.header(header.MSG_VERSION,messageDTO.getVersion())
.header(header.MSG_TYPE,messageDTO.getMsgType())
.header(header.TRACKING\u ID,UUID.randomUUID().toString())
.header(header.CLIENT_ID,“TrackingJmsClient”)
.post(messageDTO.getPayload());
}
您应该解决两个问题:
send
方法太慢,将超过最大时间
发送消息的更快方法是使用某种批量操作。如果你的MQ API不支持批量操作,你就不能使用它!由于第二个限制(“一致”)
您可以异步发送消息,但如果您的MQ API为此创建线程而不是“非阻塞”异步,则可能会出现内存问题
使用javax.jms.MessageProducer.send
可以异步发送消息,但会为每个消息创建一个新的线程(将创建大量内存和服务器线程)
另一个加速可能是只创建一个JMS客户机(您的send
方法)
要实现第二个要求,您应该修复timeOfDelay
函数,它是错误的。实际上,您应该考虑send
函数的概率分布来估计适当的值,但是,您可以简单地执行以下操作:
long acktime=0L;
对于(int i=0;iIDK关于Spring的任何内容,但似乎在send方法中不断创建JmsClient可能会导致性能问题?感谢您的评论!我肯定只需要实例化一次jms客户端…感谢您的回复!不幸的是,我的MQ API不支持批量操作。现在我在timeOfDelay方法中看到了错误..我不会请尝试执行您的建议并再次检查。我有一个问题。我想如果accTime>TIME\u PERIOD在这段时间内我应该停止发送更多消息…对吗?@DimitrisBaltas批量操作并不重要。停止发送取决于什么更重要,发送所有消息或不使用更多时间。