Rabbitmq 高级消息队列中间件,实现了AMQP协议,由Erlang语言编写,天生支持分布式
docker安装、运行
docker search rabbitmq:management
docker pull rabbitmq:management
docker run -d --name rabbitmq --publish 5671:5671 --publish 5672:5672 --publish 4369:4369 --publish 25672:25672 --publish 15671:15671 --publish 15672:15672 rabbitmq:management
安装成功后可通过 ip地址+15672 端口访问, 使用 guest /guest 登录进入web管理控制台
Rabbitmq 核心组件
Channel 通道
channel是RabbitMq服务器与客户端数据交互流转的通道,基于TCP连接,每个线程独占一个channel,为何要基于channel而不直接基于tcp连接通信?原因是tcp建立与断开成本太大,系统整体可支撑的tcp连接数量是有限制的。rabbitmq这样设计极大的提高了系统的吞吐量
Queue 队列
Queue类似于邮箱的概念,消息最终会到达的地方,Consume直接消费Queue里面的消息
Exchange 交换机
exchange用于接收生产者发送的消息,然后根据路由规则将消息路由到Queue,exchange共有四种类型
direct 直达,路由规则与Queue一一对应
topic 主题,消费者可以按需订阅
fanout 广播,所有的消费者都会接收到
headers不常用
RoutingKey 路由规则,也叫绑定,定义了消息从交换机到Queue的规则
需要注意的是,rabbitmq的消息是有确认机制的,如果客户端没有确认或者没有设置为自动确认,rabbitmq会重新发或者发给另外一个Queue,rabbitmq持久化机制是需要 message,exchange,queue都需要设置为持久化才会进行持久化操作,持久化是写入硬盘的一个持久化日志文件,所以会性能有影响,采用SSD会提升性能
Java示例
maven依赖
<dependency>
<groupId>com.rabbitmq</groupId>
<artifactId>amqp-client</artifactId>
<version>5.1.2</version>
</dependency>
public class RabbitmqTest {
@Test
public void connectionTest() throws Exception {
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost("139.199.60.XX");
Connection connection = connectionFactory.newConnection();
Channel channel = connection.createChannel();
channel.queueDeclare("queu1", false, false, false, null);
String message = "SB大傻逼";
channel.basicPublish("", "queu1", null, message.getBytes("utf-8"));
channel.close();
connection.close();
}
@Test
public void recvTest() throws Exception {
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost("139.199.60.XX");
Connection connection = connectionFactory.newConnection();
Channel channel = connection.createChannel();
channel.queueDeclare("queu1", false, false, false, null);
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("消费消息【" + message + "】");
}
};
channel.basicConsume("queu1", true, consumer);
}
}