RabbitMQ的环境安装
推荐两个写的比较好的地址
mq安装教程
https://blog.csdn.net/qq_38931949/article/details/95513014
mq插件安装教程
https://www.cnblogs.com/isunsine/p/11572457.html
这是什么鬼?
以管理员身份运行cmd后正常
以后只要是目录异常的情况,就用管理员身份运行cmd
3.8的延迟队列 https://download.csdn.net/download/a513142804/12504685
——————
Docker中安装
——————
创建容器
docker run -d --hostname my-rabbit --name rabbit -p 15672:15672 -p 5672:5672 rabbitmq:management
拷贝宿主文件到容器内
docker cp 本地文件路径 counterID全称:容器路径
docker cp rabbitmq_delayed_message_exchange-20171201-3.7.x.ez 982b190bf852:/plugins(这是我的,你需要修改文件路径和counterID)
启用插件
rabbitmq-plugins enable rabbitmq_delayed_message_exchange
RabbitMQ 入门
实践是检验真理的唯一标准,是学习的第一方法。接下来直接上代码
消费者
public class MyConsumer {
private final static String EXCHANGE_NAME = "SIMPLE_EXCHANGE";
private final static String QUEUE_NAME = "SIMPLE_QUEUE";
public static void main(String[] args) throws IOException, TimeoutException {
ConnectionFactory factory = new ConnectionFactory();
// 连接IP
factory.setHost("127.0.0.1");
// 连接端口
factory.setPort(5672);
// 虚拟机
factory.setVirtualHost("/");
// 用户
factory.setUsername("guest");
factory.setPassword("guest");
// 建立连接
Connection conn = factory.newConnection();
// 创建消息通道
Channel channel = conn.createChannel();
// 声明交换机 durable(持久化),autoDelete(自动删除)
// String exchange, String type, boolean durable, boolean autoDelete, Map<String Object> arguments
channel.exchangeDeclare(EXCHANGE_NAME,"direct", false, false, null);
// 声明队列 exclusive(排他性,只对同一个队列中可见)
// String queue, boolean durable, boolean exclusive, boolean autoDelete, Map<String, Object> arguments
channel.queueDeclare(QUEUE_NAME, false, false, false,null);
System.out.println("Waiting for message...");
// 绑定队列和交换机
channel.queueBind(QUEUE_NAME, EXCHANGE_NAME, "panghai.best");
// 创建消费者
Consumer consumer = new DefaultConsumer(channel){
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
String msg = new String(body, "UTF-8");
System.out.println("Received message: " + msg);
System.out.println("consumerTag: " + consumerTag);
System.out.println("deliveryTag: " + envelope.getDeliveryTag());
}
};
// String queue, boolean autoAck, Consumer callback
channel.basicConsume(QUEUE_NAME, true, consumer);
}
}
生产者
public class MyProducer {
private final static String EXCHANGE_NAME = "SIMPLE_EXCHANGE";
public static void main(String[] args) throws IOException, TimeoutException {
ConnectionFactory factory = new ConnectionFactory();
// 连接IP
factory.setHost("127.0.0.1");
// 连接端口
factory.setPort(5672);
// 虚拟机
factory.setVirtualHost("/");
// 用户
factory.setUsername("guest");
factory.setPassword("guest");
// 建立连接
Connection conn = factory.newConnection();
// 创建消息通道
Channel channel = conn.createChannel();
//发送消息
String msg = "Hello world, Rabbit MQ";
channel.basicPublish(EXCHANGE_NAME,"panghai.best", null, msg.getBytes());
channel.close();
conn.close();
}
}
额,劈里啪啦一通写,解释一下
Exchange中有个 Virtual Hosts 的概念,可以进行数据隔离
每一个 Virtual Hosts 都可以设置自己的用户名密码,消息发送可以保持隔离性
Exchange 和 QUEUE 进行绑定, 绑定关系是 routing-key
routing-key 的作用是什么? routing-key == bingding-key
生产者发送消息的时候需要指定往哪里发,发送信息有个标识。标识此数据属于哪一类消息,需要由那个类型的消费者进行消费。exchange就是通过这个标识routing-key来路由找到绑定在exchange上的queue,将消息入队。消费者根据binding-key找到自己要消费的消息队列,进行数据消费。
是不是很简单。
Springboot集成
@Configuration
public class RabbitConfig {
// 定义三个交换机
@Bean
public DirectExchange directExchange(){
return new DirectExchange("DIRECT_EXCHANGE");
}
@Bean
public TopicExchange topicExchange(){
return new TopicExchange("TOPIC_EXCHANGE");
}
@Bean
public FanoutExchange fanoutExchange(){
return new FanoutExchange("FANOUT_EXCHANGE");
}
// 定义四个队列
@Bean
public Queue firstQueue(){
return new Queue("FIRST_QUEUE");
}
@Bean
public Queue secondQueue(){
return new Queue("SECOND_QUEUE");
}
@Bean
public Queue thirdQueue(){
return new Queue("THIRD_QUEUE");
}
@Bean
public Queue fourthQueue(){
return new Queue("FOURTH_QUEUE");
}
// 定义四个绑定关系
@Bean
public Binding bindFirst(@Qualifier("firstQueue") Queue queue,@Qualifier("directExchange") DirectExchange exchange){
return BindingBuilder.bind(queue).to(exchange).with("panghai.best");
}
@Bean
public Binding bindSecond(@Qualifier("secondQueue") Queue queue,@Qualifier("topicExchange") TopicExchange exchange){
return BindingBuilder.bind(queue).to(exchange).with("*.panghai.*");
}
@Bean
public Binding bindThird(@Qualifier("thirdQueue") Queue queue,@Qualifier("fanoutExchange") FanoutExchange exchange){
return BindingBuilder.bind(queue).to(exchange);
}
@Bean
public Binding bindFourth(@Qualifier("fourthQueue") Queue queue,@Qualifier("fanoutExchange") FanoutExchange exchange){
return BindingBuilder.bind(queue).to(exchange);
}
}
@Component
@RabbitListener(queues = "FIRST_QUEUE")
public class FirstConsumer {
@RabbitHandler
public void process(String msg){
System.out.println("first queue received msg : " + msg);
}
}
@Component
public class MyProducer {
@Autowired
RabbitTemplate rabbitTemplate;
public void send(){
rabbitTemplate.convertAndSend("DIRECT_EXCHANGE", "panghai.best", "a direct msg");
rabbitTemplate.convertAndSend("TOPIC_EXCHANGE", "shanghai.panghai.teacher", "a topic msg shanghai");
rabbitTemplate.convertAndSend("TOPIC_EXCHANGE", "changsha.panghai.student", "a topic msg changsha");
rabbitTemplate.convertAndSend("FANOUT_EXCHANGE", "", "a fanout msg");
}
}
创建了3个Exchange,4个queue,4个消费者
每个消费者监听一个queue
queue绑定对应的exchange