RabbitMQ入门到精通,作为RabbitMQ入门是一个很好的范例.
RabbitMQ是一个由erlang开发的AMQP(Advanced Message Queue )的开源实现,是一种应用程序对应用程序的通信方法.应用程序通过读写出入队列的消息(针对应用程序的数据)来通信,而无需专用连接来链接它们.目前类似于RabbitMQ的消息中间件有很多, RabbitMq、ActiveMq、ZeroMq、kafka都是可选择,RabbitMQ解决的问题
package producerAndconsume;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.TimeUnit;
import com.rabbitmq.client.AMQP;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.QueueingConsumer;
/**
* Hello world!
*
*/
public class DirectMQ
{
//交换器名称
public final static String EXCHANGE_NAME = "test.amq.direct";
//队列名称
public final static String QUEUE_NAME = "test.queue";
//RoutingKey
public final static String ROUTINGKEY = "test.routingkey";
public static ConnectionFactory factory;
public static SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
static {
/**
* 创建连接连接到MabbitMQ
*/
factory = new ConnectionFactory();
//设置MabbitMQ所在主机ip或者主机名
factory.setHost("localhost");
//指定用户 密码
factory.setUsername("zl");
factory.setPassword("123");
//指定端口
factory.setPort(AMQP.PROTOCOL.PORT);
}
public static void init() throws Exception{
//创建一个连接
Connection connection = factory.newConnection();
//创建一信道
Channel channel = connection.createChannel();
//指定一个队列
boolean durable = false; //设置消息持久化 RabbitMQ不允许使用不同的参数重新定义一个队列,所以已经存在的队列,我们无法修改其属性。
//申明一个exchange
channel.exchangeDeclare(EXCHANGE_NAME, "direct", durable);
/* queueDeclare(String queue, boolean durable, boolean exclusive, boolean autoDelete,Map arguments)
* queue:队列名称
* durable:持久化(重启不丢失消息)
* exclusive:排他性,指针对此connection可见
* autoDelete:不使用时自动删除
* arguments:其他参数
*/
channel.queueDeclare(QUEUE_NAME, durable, false, false, null);
channel.close();
connection.close();
}
public static void main(String[] argv) throws Exception {
init();
//生产者要比消费者先启动
new Thread(new Runnable() {
public void run() {
try {
comsume();
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
TimeUnit.SECONDS.sleep(1);
produce();
/*
* result print
* 2017-09-04 20:45:09 send message: hello world!
2017-09-04 20:45:09 Received Message:'hello world!'
*/
}
public static void comsume() throws Exception {
Connection connection = factory.newConnection();
Channel channel = connection.createChannel();
//绑定queue
channel.queueBind(QUEUE_NAME,EXCHANGE_NAME, ROUTINGKEY);
//创建队列消费者
QueueingConsumer consumer = new QueueingConsumer(channel);
//指定消费队列
boolean ack = false ; //打开应答机制
// 指定消费队列
channel.basicConsume(QUEUE_NAME, ack, consumer);
//设置最大服务转发消息数量 只有在消费者空闲的时候会发送下一条信息。 (即该消费者处理的最大吞吐量)
int prefetchCount = 10;
channel.basicQos(prefetchCount);
while (true)
{
QueueingConsumer.Delivery delivery = consumer.nextDelivery();
String message = new String(delivery.getBody());
System.out.println(sf.format(new Date())+" Received Message:'" + message + "'");
//发送应答
channel.basicAck(delivery.getEnvelope().getDeliveryTag(),true);
}
}
public static void produce() throws Exception{
Connection connection = factory.newConnection();
Channel channel = connection.createChannel();
//发送的消息
String message = "hello world!";
channel.basicPublish(EXCHANGE_NAME, ROUTINGKEY, null, message.getBytes());
System.out.println(sf.format(new Date())+" send message: "+ message);
//关闭连接与信道
channel.close();
connection.close();
}
}
package producerAndconsume;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.TimeUnit;
import com.rabbitmq.client.AMQP;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.QueueingConsumer;
/**
* Hello world!
*
*/
public class TopicMQ
{
//交换器名称
public final static String EXCHANGE_NAME = "test.amq.topic";
//队列名称 1
public final static String QUEUE_NAME = "test.queue";
//RoutingKey one
public final static String TOPIC_ROUTINGKEY_ONE = "test.routingkey.one";
//RoutingKey one
public final static String TOPIC_ROUTINGKEY_TWO = "test.routingkey.two";
public static SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
public static ConnectionFactory factory;
static {
/**
* 创建连接连接到MabbitMQ
*/
factory = new ConnectionFactory();
//设置MabbitMQ所在主机ip或者主机名
factory.setHost("localhost");
//指定用户 密码
factory.setUsername("zl");
factory.setPassword("123");
//指定端口
factory.setPort(AMQP.PROTOCOL.PORT);
}
public static void init() throws Exception{
//创建一个连接
Connection connection = factory.newConnection();
//创建一信道
Channel channel = connection.createChannel();
//指定一个队列
boolean durable = false; //设置消息持久化 RabbitMQ不允许使用不同的参数重新定义一个队列,所以已经存在的队列,我们无法修改其属性。
//申明一个exchange
channel.exchangeDeclare(EXCHANGE_NAME, "topic", durable);
/* queueDeclare(String queue, boolean durable, boolean exclusive, boolean autoDelete,Map arguments)
* queue:队列名称
* durable:持久化(重启不丢失消息)
* exclusive:排他性,指针对此connection可见
* autoDelete:不使用时自动删除
* arguments:其他参数
*/
channel.queueDeclare(QUEUE_NAME, durable, false, false, null);
channel.close();
connection.close();
}
public static void main(String[] argv) throws Exception {
init();
//生产者要比消费者先启动
new Thread(new Runnable() {
public void run() {
try {
comsume();
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
TimeUnit.SECONDS.sleep(1);
produce(TOPIC_ROUTINGKEY_ONE);
produce(TOPIC_ROUTINGKEY_TWO);
/*
result print
2017-09-04 20:46:52 send message: test.routingkey.one
2017-09-04 20:46:52 Received Message:'test.routingkey.one'
2017-09-04 20:46:52 send message: test.routingkey.two
2017-09-04 20:46:52 Received Message:'test.routingkey.two'
*
*/
}
public static void comsume() throws Exception {
Connection connection = factory.newConnection();
Channel channel = connection.createChannel();
/* routingkey匹配规则
*可以匹配一个标识符。
#可以匹配0个或多个标识符。*/
channel.queueBind(QUEUE_NAME,EXCHANGE_NAME, "test.routingkey.*");
//创建队列消费者
QueueingConsumer consumer = new QueueingConsumer(channel);
//指定消费队列
boolean ack = false ; //打开应答机制
// 指定消费队列
channel.basicConsume(QUEUE_NAME, ack, consumer);
//设置最大服务转发消息数量 只有在消费者空闲的时候会发送下一条信息。 (即该消费者处理的最大吞吐量)
int prefetchCount = 10;
channel.basicQos(prefetchCount);
while (true)
{
QueueingConsumer.Delivery delivery = consumer.nextDelivery();
String message = new String(delivery.getBody());
System.out.println(sf.format(new Date()) +" Received Message:'" + message + "'");
//发送应答
channel.basicAck(delivery.getEnvelope().getDeliveryTag(),true);
}
}
public static void produce(String routingkey) throws Exception{
Connection connection = factory.newConnection();
Channel channel = connection.createChannel();
//发送的消息
String message = routingkey;
channel.basicPublish(EXCHANGE_NAME, routingkey, null, message.getBytes());
System.out.println(sf.format(new Date()) +" send message: "+ message);
//关闭连接与信道
channel.close();
connection.close();
}
}
package producerAndconsume;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.TimeUnit;
import com.rabbitmq.client.AMQP;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.QueueingConsumer;
/**
* Hello world!
*
*/
public class FanoutMQ
{
//交换器名称
public final static String EXCHANGE_NAME = "test.amq.fanout";
public static ConnectionFactory factory;
public static SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
static {
/**
* 创建连接连接到MabbitMQ
*/
factory = new ConnectionFactory();
//设置MabbitMQ所在主机ip或者主机名
factory.setHost("localhost");
//指定用户 密码
factory.setUsername("zl");
factory.setPassword("123");
//指定端口
factory.setPort(AMQP.PROTOCOL.PORT);
}
public static void init() throws Exception{
//创建一个连接
Connection connection = factory.newConnection();
//创建一信道
Channel channel = connection.createChannel();
//指定一个队列
boolean durable = false; //设置消息持久化 RabbitMQ不允许使用不同的参数重新定义一个队列,所以已经存在的队列,我们无法修改其属性。
//申明一个exchange
channel.exchangeDeclare(EXCHANGE_NAME, "fanout", durable);
channel.close();
connection.close();
}
public static void main(String[] argv) throws Exception {
init();
//生产者要比消费者先启动
new Thread(new Runnable() {
public void run() {
try {
comsume();
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
TimeUnit.SECONDS.sleep(1);
produce();
/*
* result print
2017-09-04 21:03:16 send message: hello world!
2017-09-04 21:03:16 amq.gen-y1Apmus-2O0LGRUi8Du_NA Received Message:'hello world!'
*/
}
public static void comsume() throws Exception {
Connection connection = factory.newConnection();
Channel channel = connection.createChannel();
// 创建一个非持久的、唯一的且自动删除的队列
String queueName = channel.queueDeclare().getQueue();
channel.queueBind(queueName, EXCHANGE_NAME, "");
//创建队列消费者
QueueingConsumer consumer = new QueueingConsumer(channel);
//指定消费队列
boolean ack = false ; //打开应答机制
// 指定消费队列
channel.basicConsume(queueName, ack, consumer);
//设置最大服务转发消息数量 只有在消费者空闲的时候会发送下一条信息。 (即该消费者处理的最大吞吐量)
int prefetchCount = 10;
channel.basicQos(prefetchCount);
while (true)
{
QueueingConsumer.Delivery delivery = consumer.nextDelivery();
String message = new String(delivery.getBody());
System.out.println(sf.format(new Date())+" "+ queueName+" Received Message:'" + message + "'");
//发送应答
channel.basicAck(delivery.getEnvelope().getDeliveryTag(),true);
}
}
public static void produce() throws Exception{
Connection connection = factory.newConnection();
Channel channel = connection.createChannel();
//发送的消息
String message = "hello world!";
channel.basicPublish(EXCHANGE_NAME, "", null, message.getBytes());
System.out.println(sf.format(new Date())+" send message: "+ message);
//关闭连接与信道
channel.close();
connection.close();
}
}
package producerAndconsume;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.UUID;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import com.rabbitmq.client.AMQP;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.DefaultConsumer;
import com.rabbitmq.client.Envelope;
public class RpcMQ
{
private static final String RPC_QUEUE_NAME = "rpc_queue";
public static ConnectionFactory factory;
public static SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
static {
/**
* 创建连接连接到MabbitMQ
*/
factory = new ConnectionFactory();
//设置MabbitMQ所在主机ip或者主机名
factory.setHost("localhost");
//指定用户 密码
factory.setUsername("zl");
factory.setPassword("123");
//指定端口
factory.setPort(AMQP.PROTOCOL.PORT);
}
public static void main(String[] argv) throws Exception {
server();
for (int i = 0; i < 2; i++) {
RPCClient fibonacciRpc =new RpcMQ().new RPCClient();
System.out.println(" [x] Requesting check hello "+i);
String response = fibonacciRpc.call("hello "+i);
System.out.println(" [.] Got '" + response + "'");
fibonacciRpc.close();
}
/* result print
[x] Awaiting RPC requests
[x] Requesting check hello 0
[.] Got 'check 'hello 0' success'
[x] Requesting check hello 1
[.] Got 'check 'hello 1' success'
*/
}
public static void server() throws Exception{
Connection connection = factory.newConnection();
final Channel channel = connection.createChannel();
channel.queueDeclare(RPC_QUEUE_NAME, false, false, false, null);
//可以运行多个服务器进程。通过channel.basicQos设置prefetchCount属性可将负载平均分配到多台服务器上。
channel.basicQos(10);
DefaultConsumer consumer = new DefaultConsumer(channel) {
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
AMQP.BasicProperties replyProps = new AMQP.BasicProperties
.Builder()
.correlationId(properties.getCorrelationId())
.build();
String response = "";
try {
String message = new String(body,"UTF-8");
response += "check '"+message+"' success";
System.out.println(sf.format(new Date())+" get message " + message+" and return "+response);
}
catch (RuntimeException e){
System.out.println("get exception: " + e.toString());
}
finally {
channel.basicPublish( "", properties.getReplyTo(), replyProps, response.getBytes("UTF-8"));
channel.basicAck(envelope.getDeliveryTag(), false);
}
}
};
//打开应答机制autoAck=false
channel.basicConsume(RPC_QUEUE_NAME, false, consumer);
System.out.println(" [x] Awaiting RPC requests");
}
class RPCClient {
private Connection connection;
private Channel channel;
private String replyQueueName;
public RPCClient() throws Exception {
connection = factory.newConnection();
channel = connection.createChannel();
// 注册'回调'队列,这样就可以收到RPC响应
replyQueueName = channel.queueDeclare().getQueue();
}
// 发送RPC请求
public String call(String message) throws Exception {
final String corrId = UUID.randomUUID().toString();
AMQP.BasicProperties props = new AMQP.BasicProperties.Builder().correlationId(corrId).replyTo(replyQueueName).build();
channel.basicPublish("", RPC_QUEUE_NAME, props, message.getBytes("UTF-8"));
final BlockingQueue response = new ArrayBlockingQueue(1);
channel.basicConsume(replyQueueName, true, new DefaultConsumer(channel) {
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
if (properties.getCorrelationId().equals(corrId)) {
response.offer(new String(body, "UTF-8"));
}
}
});
return response.take();
}
public void close() throws Exception {
connection.close();
}
}
}