我正在使用Play Framework 2.2.2,我正在使用JavaAkka(Akka Actor System)实现RabbitMQ使用者应用程序。因此,当Play应用程序使用Global.OnStart函数启动时,我有一个MainActor。 MainActor创建RabbitMQ通道,然后从队列开始使用。该队列中的每条消息都是另一个队列的名称,该队列必须分配给另一个必须从消息中提到的队列开始消耗的子actor或子actor。基本上,我有一个订阅了一个RabbitMQ队列的MainActor和几个由Main actor创建的子actor,每个子actor都订阅了自己的RabbitMQ队列。问题是我出于某种原因无法培养超过7名儿童演员。我怀疑它是等待来自RabbitMQ的消息的子actor中的while(true)构造。这是我的实施:
主要演员:
import play.Logger;
import com.typesafe.config.ConfigFactory;
import java.io.IOException;
import akka.actor.Props;
import akka.actor.UntypedActor;
import akka.actor.ActorRef;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.QueueingConsumer;
import play.libs.Akka;
import util.RabbitMQConnection;
public class MainActor extends UntypedActor {
@Override
public void onReceive(Object msg) throws Exception {
try{
Connection connection = RabbitMQConnection.getConnection();
Channel channel = connection.createChannel();
String main_queue_name = ConfigFactory.load().getString("rabbitmq.default_queue");
channel.queueDeclare(main_queue_name, false, false, false, null);
QueueingConsumer consumer = new QueueingConsumer(channel);
channel.basicConsume(main_queue_name, true, consumer);
while (true) {
QueueingConsumer.Delivery delivery = consumer.nextDelivery();
String message = new String(delivery.getBody());
System.out.println(" [x] Received '" + message + "'");
ActorRef childActor = getContext().actorOf(Props.create(childActor.class));
childActor.tell(message, getSelf());
}
}catch (Exception e){
System.out.println(e.toString());
}
}
}
儿童演员:
import play.Logger;
import com.typesafe.config.ConfigFactory;
import java.io.IOException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectWriter;
import play.libs.Akka;
import play.libs.Json;
import akka.actor.UntypedActor;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.QueueingConsumer;
import util.RabbitMQConnection;
public class childActor extends UntypedActor {
@Override
public void onReceive(Object msg) throws Exception {
ObjectWriter ow = new ObjectMapper().writer().withDefaultPrettyPrinter();
String queue_name = ow.writeValueAsString(msg);
try{
Connection connection = RabbitMQConnection.getConnection();
Channel channel = connection.createChannel();
channel.queueDeclare(queue_name, false, false, false, null);
QueueingConsumer consumer = new QueueingConsumer(channel);
channel.basicConsume(queue_name, true, consumer);
while (true) {
QueueingConsumer.Delivery delivery = consumer.nextDelivery();
String message = new String(delivery.getBody());
JsonNode jsonMsg = Json.parse(message);
// Call some function to process the message
}
}catch (Exception e){
System.out.println(e.toString());
}
}
}
答案 0 :(得分:1)
我认为在这种情况下你没有正确使用Actor。在我看来,对于给定的actor,你不应该在receive
方法中有一段时间(真实)。另外,QueueingConsumer
已被弃用,而且rabbitmq的人建议使用界面Consumer
或默认的无操作实现DefaultConsumer
来实现消费者。
我这样做的方式是:
这里的一些代码:( 警告:未编译或测试)
自定义rabbitmq消费者:
public class MyCustomRabbitMQConsumer extends DefaultConsumer {
private ActorRef destinationActor;
public MyCustomRabbitMQConsumer(ActorRef destinationActor) {
this.destinationActor = destinationActor;
}
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) {
destinationActor.tell(new String(body));
}
}
主要演员:
import play.Logger;
import com.typesafe.config.ConfigFactory;
import java.io.IOException;
import akka.actor.Props;
import akka.actor.UntypedActor;
import akka.actor.ActorRef;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.QueueingConsumer;
import play.libs.Akka;
import util.RabbitMQConnection;
public class MainActor extends UntypedActor {
private MyCustomRabbitMQConsumer rabbitConsumer;
@Override
public void preStart() {
Connection connection = RabbitMQConnection.getConnection();
Channel channel = connection.createChannel();
String main_queue_name = ConfigFactory.load().getString("rabbitmq.default_queue");
channel.queueDeclare(main_queue_name, false, false, false, null);
rabbitConsumer = new MyCustomRabbitMQConsumer(getSelf());
channel.basicConsume(main_queue_name, true, rabbitConsumer);
}
@Override
public void onReceive(Object msg) throws Exception {
if(msg instanceOf String) {
String queueName = (String) msg;
System.out.println(" [x] Received '" + queueName + "'");
getContext().actorOf(Props.create(childActor.class, queueName));
}
}
}
ChildActor:
import akka.actor.UntypedActor;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.QueueingConsumer;
import util.RabbitMQConnection;
public class ChildActor extends UntypedActor {
private MyCustomRabbitMQConsumer rabbitConsumer;
private String queueName;
public ChildActor(String queueName) {
this.queueName = queueName;
}
@Override
public void preStart() {
Connection connection = RabbitMQConnection.getConnection();
Channel channel = connection.createChannel();
String main_queue_name = ConfigFactory.load().getString("rabbitmq.default_queue");
channel.queueDeclare(queueName, false, false, false, null);
rabbitConsumer = new MyCustomRabbitMQConsumer(getSelf());
channel.basicConsume(queueName, true, rabbitConsumer);
}
@Override
public void onReceive(Object msg) throws Exception {
if(msg instanceOf String) {
String strMsg = (String) msg;
JsonNode jsonMsg = Json.parse(message);
// Call some function to process the message
}
}
}
这适用于n个演员。