什么是rabbitmq
rabbitmq是一种消息队列,用于服务于服务之间信息传递,服务解耦。是一个由erlang开发的AMQP(Advanced Message Queue )的开源实现。
原理结构
包含要素
生产者、消费者、消息
生产者:消息的创建者,发送到rabbitmq;
消费者:连接到rabbitmq,订阅到队列上,消费消息,持续订阅(basicConsumer)和单条订阅(basicGet).
消息:包含有效载荷和标签,有效载荷指要传输的数据,标签描述了有效载荷,并且rabbitmq用它来决定谁获得消息,消费者只能拿到有效载荷,并不知道生产者是谁。
信道
信道,概念:信道是生产者和消费者与rabbit通信的渠道,生产者publish或是消费者subscribe一个队列都是通过信道来通信的。信道是建立在TCP连接上的虚拟连接,什么意思呢?就是说rabbitmq在一条TCP上建立成百上千个信道来达到多个线程处理,这个TCP被多个线程共享,每个线程对应一个信道,信道在rabbit都有唯一的ID ,保证了信道私有性,对应上唯一的线程使用。
交换器、队列、绑定、路由键
队列通过路由键(routing key,某种确定的规则)绑定到交换器,生产者将消息发布到交换器,交换器根据绑定的路由键将消息路由到特定队列,然后由订阅这个队列的消费者进行接收。
入门程序
依赖
<dependency>
<groupId>com.rabbitmq</groupId>
<artifactId>amqp-client</artifactId>
<version>5.0.0</version>
</dependency>
生产者
public class Pro {
//交换器名称
public final static String EXCHANGE_NAME = "direct_logs";
public static void main(String[] args) throws IOException, TimeoutException {
ConnectionFactory connectionFactory = new ConnectionFactory();
Connection connection = connectionFactory.newConnection("127.0.0.1");
//信道
Channel channel = connection.createChannel();
//创建交换器,BuiltinExchangeType.DIRECT为交换器类型
channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.DIRECT);
/*日志消息级别,作为路由键使用*/
String[] serverities = {"error", "info", "warning"};
for (int i = 0; i < 3; i++) {
//路由键
String severity = serverities[i % 3];
String msg = "Hellol,RabbitMq" + (i + 1);
//发送消息
channel.basicPublish(EXCHANGE_NAME, severity, null, msg.getBytes());
System.out.println("发送的消息是 = [" + msg + "]");
}
channel.close();
connection.close();
}
}
消费者
public class NolCum {
public static void main(String[] args) throws IOException, TimeoutException {
ConnectionFactory connectionFactory = new ConnectionFactory();
Connection connection = connectionFactory.newConnection("127.0.0.1");
//信道
Channel channel = connection.createChannel();
//交换器
channel.exchangeDeclare(Pro.EXCHANGE_NAME, BuiltinExchangeType.DIRECT);
//创建队列
String newQueue = "newQueue";
channel.queueDeclare(newQueue, false, false, false, null);
//根据路由键将队列和交换器进行绑定
String routekey = "info";/*表示只关注error级别的日志消息*/
channel.queueBind(newQueue, Pro.EXCHANGE_NAME, routekey);
//开始接受消息
final 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("Received[" + envelope.getRoutingKey()
+ "]" + message);
}
};
//消费者开始消费队列上的消息
channel.basicConsume(newQueue, true, consumer);
}
}