i have one Job Distributor
who publishes messages on different Channels
.
Further, i want to have two (and more in the future) Consumers
who work on different tasks and run on different machines. (Currently i have only one and need to scale it)
Let's name these tasks (just examples):
FIBONACCI
(generates fibonacci numbers)RANDOMBOOKS
(generates random sentences to write a book)
Those tasks run up to 2-3 hours and should be divided equally to each Consumer
.
Every Consumer can have x
parallel threads for working on these tasks.
So i say: (those numbers are just examples and will be replaced by variables)
- Machine 1 can consume 3 parallel jobs for
FIBONACCI
and 5 parallel jobs forRANDOMBOOKS
- Machine 2 can consume 7 parallel jobs for
FIBONACCI
and 3 parallel jobs forRANDOMBOOKS
How can i achieve this?
Do i have to start x
Threads for each Channel
to listen on on each Consumer
?
When do i have to ack that?
My current approach for only one Consumer
is: Start x
Threads for each Task - each Thread is a Defaultconsumer implementing Runnable
. In the handleDelivery
method, i call basicAck(deliveryTag,false)
and then do the work.
Further: I want to send some tasks to a special consumer. How can i achieve that in combination with the fair distribution as mentioned above?
This is my Code for publishing
String QUEUE_NAME = "FIBONACCI";
Channel channel = this.clientManager.getRabbitMQConnection().createChannel();
channel.queueDeclare(QUEUE_NAME, true, false, false, null);
channel.basicPublish("", QUEUE_NAME,
MessageProperties.BASIC,
Control.getBytes(this.getArgument()));
channel.close();
This is my code for the Consumer
public final class Worker extends DefaultConsumer implements Runnable {
@Override
public void run() {
try {
this.getChannel().queueDeclare(this.jobType.toString(), true, false, false, null);
this.getChannel().basicConsume(this.jobType.toString(), this);
this.getChannel().basicQos(1);
} catch (IOException e) {
// catch something
}
while (true) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Control.getLogger().error("Exception!", e);
}
}
}
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] bytes) throws IOException {
String routingKey = envelope.getRoutingKey();
String contentType = properties.getContentType();
this.getChannel().basicAck(deliveryTag, false); // Is this right?
// Start new Thread for this task with my own ExecutorService
}
}
The class Worker
is started twice in this case: Once for FIBUNACCI
and once for RANDOMBOOKS
UPDATE
As the answers stated, RabbitMQ would not be the best solution for this, but a Couchbase or MongoDB pull approach would be best. I'm new to those systems, is there anybody that could explain to me, how this would be achieved?