推广
RabbitMQ专题讲座
https://segmentfault.com/l/15...
CoolMQ开源项目
我们利用消息队列实现了分布式事务的最终一致性解决方案,请大家围观。可以参考源码:https://github.com/vvsuperman…,项目支持网站: http://rabbitmq.org.cn,最新文章或实现会更新在上面
前言
消息队列想必大家都有一定了解:用来解耦,上级模块不用关心下级模块是否执行成功,最常见的比如说日志,核心系统并不关心日志是否成功,日志什么时候记录。这种情形就可以用消息队列来解耦。
RabbitMQ作为消息队列的一个典型实践,完全实现了AMQ标准,与Kafka的快快快不同,它追求的稳定、可靠。下面就来几篇文章来详细介绍下,均翻译至RabbitMQ的官方文档。
RabbitMQ是一个消息的中介(用来接受以及转发消息),就像是一个非常可靠的邮局,当信件放到邮局时,信件就确保能到达,所以,RabbitMQ可以看成是邮箱、邮局、以及邮递员的合体
RabbitMQ的一些重要概念
produceing(生产者):生产数据
queue(队列):
类似于邮箱,存在于RabbitMQ服务器的内部,用来存储消息,并且消息只能存储在队列里面。队列的大小只受RabbitMQ主机内存和硬盘的影响。同一个队列不仅可以绑定多个生产者,而且能够发送消息到多个消费者。
Consuming(消费者):接受并消费消息。
Hello World
下面我们来写我们的第一个“Hello World”,我们会使用Java的API来编写一个生产者来生产消息,以及一个消费者来消费消息
P是我们的生产者,而C是我们的消费者。中间的box是我们的queue:作为消息缓冲,是RabbitMQ用来存储转发消息给消费者的。
Java客户端库
RabbitMQ支持多重协议,这里我们会用AMQP 0-9-1来说明,它是一个消息队列的通用协议。RabbitMQ同时也有多种语言的客户端,我们在这里用Java来做说明。
首先请下载Java客户端包以及它所依赖的SLF4J和SLF4J SIMPLE,将它们拷贝到自己的工作区。
引入RabbitMQ同样也可以使用Maven来做依赖管理, groupId是com.rabbitmq 以及artifactId amqp-client
发送请求
生产者会发送消息到MQ,然后退出
在Send.java中,首先我们import一些类
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.Channel;
设置我们的主类
public class Send {
private final static String QUEUE_NAME = "hello";
public static void main(String[] argv)
throws java.io.IOException {
...
}
}
创建Connection
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
Connection connection = factory.newConnection();
Channel channel = connection.createChannel();
这里我们连接的是本地,你当然也可以连接到另一个服务器上,只需要指明服务器的名称和ip地址。
下面我们要创建一个Channel,大家可以想象一些,消息的产生和发送都是通过这个Channel完成的。
当然,我们还需要顶一个一个Queue来接受消息
channel.queueDeclare(QUEUE_NAME, false, false, false, null);
String message = "Hello World!";
channel.basicPublish("", QUEUE_NAME, null, message.getBytes());
System.out.println(" [x] Sent '" + message + "'");
对于Queue的定义是冥等的,如果不存在才会创建,如果存在则不会再建新的。消息会被格式化成byte的数组,方便进行任意的转换。
最后,我们关闭通道
channel.close();
connection.close();
完整的代码可以看这个地方:send.java
接受请求
消费者会从RabbitMQ接收到请求,消息是被推到消费者,而且消费者会一直监听着消息队列,一旦有有新的消息就会打印出来。
Recv.java几乎于Send完全类似
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Consumer;
import com.rabbitmq.client.DefaultConsumer;
Defaultconsumer是一个继承了Consumer接口的类,方便我们来存储消息队列来的消息。建立消费者与我们建立生产者非常类似:
public class Recv {
private final static String QUEUE_NAME = "hello";
public static void main(String[] argv)
throws java.io.IOException,
java.lang.InterruptedException {
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
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");
...
}
}
你可以注意到我们在消费者定义了一个Queue,因此我们是需要在生产者之前启动消费者的,我们要确保我们在消费消息之前这个队列是已经存在的。
然后我们需要告诉mq服务可以推送消息给我们。因为这个推送是异步的,因此我们可以提供一个回调方法,DefaultConsumer会暂时存储这个消息,直到消费者以及准备好来处理接受到的消息了(消息会存储在消费者中直到消费者有能力来消费它,可以想象一下数据库等高IO操作)
Consumer consumer = new DefaultConsumer(channel) {
@Override
public void handleDelivery(String consumerTag, Envelope envelope,
AMQP.BasicProperties properties, byte[] body)
throws IOException {
String message = new String(body, "UTF-8");
System.out.println(" [x] Received '" + message + "'");
}
};
channel.basicConsume(QUEUE_NAME, true, consumer);
完整的Recv.java地址
跑起来
我们可以先用javac来编译程序
javac -cp amqp-client-4.0.2.jar Send.java Recv.java
而后来运行它,这需要我们在路径加上它的依赖包,我们首先启动的是消费者
java -cp .:amqp-client-4.0.2.jar:slf4j-api-1.7.21.jar:slf4j-simple-1.7.22.jar Recv
而后启动发送者
java -cp .:amqp-client-4.0.2.jar:slf4j-api-1.7.21.jar:slf4j-simple-1.7.22.jar Send
消费者会持续等待,并打印从生产者哪里来的消息,你可以用(Ctrl-C)来停止它。所以你要另外开启一个命令行窗口来运行生产者。
查看队列
也许你想知道RabbitMQ中到底有多少个消息,你可以使用rabbitmqctl工具:
sudo rabbitmqctl list_queues
在Windows中:
rabbitmqctl.bat list_queues
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。