RabbitMQ(4)Java Client - Hello World-Work Queue

RabbitMQ(4)Java Client - Hello World-Work Queue

RabbitMQ is a message broker, accepts and forwards messages.

1. RabbitMQ jargon
Producing - A program that sends messages is a producer.
Queue - A queue is the name for a mailbox. It can store as many messages as you like.
Consuming - A consumer is a program that mostly waits to receive messages.

2. Simple Java "Hello World"
RabbitMQ speaks AMQP, which is an open, general-purpose protocol for messaging.

Test Producer
package com.sillycat.easytalker.rabbitmq.hello;
import java.io.IOException;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;

public class TestProducer {
private final static String QUEUE_NAME = "hello";
private final static String SERVER_HOST = "localhost";
public static void main(String[] args) throws IOException {
ConnectionFactory factory = new ConnectionFactory();
factory.setHost(SERVER_HOST);
Connection connection = factory.newConnection();
Channel channel = connection.createChannel();

channel.queueDeclare(QUEUE_NAME, false, false, false, null);
String message = "Hello World! Woo!2";
channel.basicPublish("", QUEUE_NAME, null, message.getBytes());
System.out.println(" [x] Sent '" + message + "'");
channel.close();
connection.close();
}
}

Test Consumer
package com.sillycat.easytalker.rabbitmq.hello;
import java.io.IOException;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.ConsumerCancelledException;
import com.rabbitmq.client.QueueingConsumer;
import com.rabbitmq.client.ShutdownSignalException;

public class TestConsumer {
private final static String QUEUE_NAME = "hello";
private final static String SERVER_HOST = "localhost";
public static void main(String[] args) throws IOException,
ShutdownSignalException, ConsumerCancelledException,
InterruptedException {
ConnectionFactory factory = new ConnectionFactory();
factory.setHost(SERVER_HOST);
Connection connection = factory.newConnection();
Channel channel = connection.createChannel();
channel.queueDeclare(QUEUE_NAME, false, false, false, null);
System.out.println("
  • Waiting for messages. To exit press CTRL+C");
  • QueueingConsumer consumer = new QueueingConsumer(channel);
    channel.basicConsume(QUEUE_NAME, true, consumer);
    while (true) {
    QueueingConsumer.Delivery delivery = consumer.nextDelivery();
    String message = new String(delivery.getBody());
    System.out.println(" [x] Received '" + message + "'");
    Thread.sleep(5000);
    }
    }
    }

    3. Simple Java Work Queues
    We will create a Work Queue that will be used to distribute time-consuming tasks among multiple workers.

    Work Queues(aka: Task Queues) is to avoid doing a resource-intensive task immediately and having to wait for it to complete.

    This concept is especially useful in web applications where it's impossible to handle a complex task during a short HTTP request window.

    My NewTask.java Class is mostly the same as before, but we send a lot of tasks this time.
    package com.sillycat.easytalker.rabbitmq.workqueue;

    import com.rabbitmq.client.Channel;
    import com.rabbitmq.client.Connection;
    import com.rabbitmq.client.ConnectionFactory;
    import com.rabbitmq.client.MessageProperties;

    public class NewTask {

    private static final String TASK_QUEUE_NAME = "task_queue";

    private final static String SERVER_HOST = "localhost";

    public static void main(String[] argv) throws Exception {
    ConnectionFactory factory = new ConnectionFactory();
    factory.setHost(SERVER_HOST);

    Connection connection = factory.newConnection();
    Channel channel = connection.createChannel();
    channel.queueDeclare(TASK_QUEUE_NAME, true, false, false, null);

    String message = "job";
    for(int i = 0;i<10;i++){
    message = "job" + i;
    channel.basicPublish("", TASK_QUEUE_NAME,
    MessageProperties.PERSISTENT_TEXT_PLAIN, message.getBytes());
    System.out.println(" [x] Sent '" + message + "'");
    }
    channel.close();
    connection.close();
    }
    }

    The worker.java class, we can run 2 instances of this class to see, the log messsage as follow:
  • Waiting for messages. To exit press CTRL+C
  • [x] Received 'job0'
    [x] Done
    [x] Received 'job2'
    [x] Done
    [x] Received 'job4'
    [x] Done
    [x] Received 'job6'
    [x] Done
    [x] Received 'job8'
    [x] Done

    Another Instance:
  • Waiting for messages. To exit press CTRL+C
  • [x] Received 'job1'
    [x] Done
    [x] Received 'job3'
    [x] Done
    [x] Received 'job5'
    [x] Done
    [x] Received 'job7'
    [x] Done
    [x] Received 'job9'
    [x] Done

    package com.sillycat.easytalker.rabbitmq.workqueue;
    import com.rabbitmq.client.Channel;
    import com.rabbitmq.client.Connection;
    import com.rabbitmq.client.ConnectionFactory;
    import com.rabbitmq.client.QueueingConsumer;
    public class Worker {
    private static final String TASK_QUEUE_NAME = "task_queue";
    private final static String SERVER_HOST = "localhost";
    public static void main(String[] argv) throws Exception {
    ConnectionFactory factory = new ConnectionFactory();
    factory.setHost(SERVER_HOST);

    Connection connection = factory.newConnection();
    Channel channel = connection.createChannel();
    channel.queueDeclare(TASK_QUEUE_NAME, true, false, false, null);

    System.out.println("
  • Waiting for messages. To exit press CTRL+C");

  • channel.basicQos(1);

    QueueingConsumer consumer = new QueueingConsumer(channel);
    channel.basicConsume(TASK_QUEUE_NAME, false, consumer);
    while (true) {
    QueueingConsumer.Delivery delivery = consumer.nextDelivery();
    String message = new String(delivery.getBody());
    System.out.println(" [x] Received '" + message + "'");
    doWork(message);
    System.out.println(" [x] Done");
    channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
    }
    }

    private static void doWork(String task) throws InterruptedException {
    for (char ch : task.toCharArray()) {
    if (ch == '.')
    Thread.sleep(5000);
    }
    }
    }

    Message Acknowledgment
    If a worker dies, we'd like the task to be delivered to another worker.
    RabbitMQ supports message acknowledgements. An ack is sent back from the consumer to tell RabbitMQ that a particular message has been received, processed and that RabbitMQ is free to delete it. (ack acknowledgement charactor)

    If a consumer dies without sending an ack, RabbitMQ will understand that a message wasn't processed fully and will redeliver it to another consumer.

    Message acknowledgments are turned on by default. autoAck=true flag will turned them off.
    boolean autoAck = false;
    channel.basicConsume(TASK_QUEUE_NAME, autoAck, consumer);

    Message Durability
    We have learned how to make sure that even if the consumer dies, the task isn't lost. But our tasks will still be lost if RabbitMQ server stops.

    When RabbitMQ quits or crashes it will forget the queues and messages unless you tell it not to. We need to mark both the queue and messages as durable.
    boolean durable = true;
    channel.queueDeclare("hello", durable, false, false, null);

    Set the message to persistent
    channel.basicPublish("", TASK_QUEUE_NAME,
    MessageProperties.PERSISTENT_TEXT_PLAIN, message.getBytes());
    The persistence guarantees aren't strong, but it's more than enough for our simple task queue. If you need a stronger guarantee you can wrap the publishing code in a transaction.

    Fair dispatch
    In order to defeat that we can use the basicQos method with the prefetchCount = 1 setting. This tells RabbitMQ not to give more than one message to a worker at a time. Or, in other words, don't dispatch a new message to a worker until it has processed and acknowledged the previous one. Instead, it will dispatch it to the next worker that is not still busy.

    int prefetchCount = 1;
    channel.basicQos(prefetchCount);

    references:
    http://www.rabbitmq.com/java-client.html
    https://github.com/rabbitmq/rabbitmq-tutorials/tree/master/java
    http://www.rabbitmq.com/api-guide.html
    http://www.rabbitmq.com/getstarted.html
    http://www.rabbitmq.com/tutorials/tutorial-two-java.html

    你可能感兴趣的:(Hello world)