我正在尝试扩展以下示例程序,该程序创建一个简单的JMS消息并同时将其推送到同一队列。目前,示例程序在单个四核主机上大约需要20秒。任何人都可以建议对以下内容进行一些更改以提高性能吗? 20秒测量仅适用于以下并行流处理线:
test.parallelStream().forEach(e -> sender.sendMessage(e));
我能想到的一种方法是将我的Collection(“test”)展开给几个主机,然后通过将每个线程配置为拥有自己的线程池,然后以块的形式同时处理集合。这样做的一个缺点是容错,并且必须放置适当的构造以确保每个线程池不处理相同的消息。
另一种方法是使用更高性能/并发的代理,如Kafka
请注意无论我采用什么异步线程方法,我都需要能够控制从这些线程向另一个应用程序发送的消息数量,因为它们只支持一定数量的并发消息。还有其他想法吗?
完整来源:
import java.util.ArrayList;
import java.util.List;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TextMessage;
import org.apache.activemq.ActiveMQConnection;
import org.apache.activemq.ActiveMQConnectionFactory;
public class Sender {
private static ConnectionFactory factory = null;
private static Connection connection = null;
private static Session session = null;
private static Destination destination = null;
private static MessageProducer producer = null;
public Sender() {}
public void sendMessage(String test) {
try {
TextMessage message = session.createTextMessage();
message.setText(test);
producer.send(message);
} catch (JMSException e) {
e.printStackTrace();
}
}
public static void main(String[] args) throws JMSException {
factory = new ActiveMQConnectionFactory(ActiveMQConnection.DEFAULT_BROKER_URL);
((ActiveMQConnectionFactory)factory).setUseAsyncSend(true);
((ActiveMQConnectionFactory)factory).setOptimizeAcknowledge(true);
connection = factory.createConnection();
connection.start();
session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
destination = session.createQueue("SAMPLEQUEUE");
producer = session.createProducer(destination);
producer.setDeliveryMode(DeliveryMode.PERSISTENT);
List<String> test = new ArrayList<String>();
for (int i = 0; i <= 100000; i++) {
test.add(Integer.toString(i));
}
Sender sender = new Sender();
test.parallelStream().forEach(e -> sender.sendMessage(e));
}
}
答案 0 :(得分:1)
正如所指出的,MessagProducer不保证是线程安全的,但也不是Session。
无论如何,关于这一点:
ExecutorService executor = Executors.newFixedThreadPool(2); for (String msg: msgs) { executor.execute(() -> send(msg)); }
当然,你不应该一起使用所有这些方法,只需使用常识来适应另一种方法。
答案 1 :(得分:1)
除了上面所说的内容之外,我还将专注于您如何使用消息。如果您的接收端应用程序可以同时处理有限数量的消息,那么您同时发送的消息数量并不重要,因为它们将在队列中等待,直到您的接收应用程序准备好消耗它们。所以,说你的接收应用程序可以同时处理10个请求。我会在你的队列中设置10个消费者,每个消费者只有在处理了之前处理过的请求之后才从队列中读取传入的请求。这样,传入消息的速度并不重要(除了担心队列溢出)。而且您的应用程序将始终同时处理不超过10个请求。