快速入门中间件 RabbitMQ消息中间件

消息队列解决的问题:
异步处理
应用解耦
流量削峰
日志处理

AMQP:Advanced Message Queuing Protocol ,一个通过统一的消息服务的应用层标准高级消息队列协议,是应用层协议的一个开放标准,为面向消息的中间件设计
安装步骤
官网地址:https://www.rabbitmq.com/install-windows.html 下载对应版本,rabbitmq是用erlang开发的所以要装erlang开发环境,地址https://www.erlang.org/downloads,下载直接next就可以了,需要配置一下环境变量
做完之后,打开cmd 运行命令rabbitmq-plugins enable rabbitmq_management 开启web管理插件,通过浏览器访问http://localhost:15672 默认用户guest 密码一致
https://www.cnblogs.com/t-ae/p/10137449.html
我开始安装报错,不是内部文件,可以先管理员方式运行rabbitmq-start 进入sbin目录,在输入上面的命令,在关闭以管理员运行

Virtual hosts 管理

虚拟主机,每一个虚拟主机中包含所有的AMQP基本组件,用户、队里、交换器等都是在虚拟主机里面创建。典型的用法是,如果公司的多个产品只想用一个服务器,就可以把他们划分到不同的虚拟主机中,里面的任何信息都是独立存在,互不干扰。一般以 / 开头

队列模型

简单模型
simple 模式
在这里插入图片描述
点对点消息模型,开启mq服务,开启进程p输出在向mq写消息,进程消费者进行监听

java连接测试一下
依赖



<dependency>
    <groupId>com.rabbitmq</groupId>
    <artifactId>amqp-client</artifactId>
    <version>4.0.2</version>
</dependency>


public class ConnectionUtils {
	
	public static Connection getConnection() throws IOException, TimeoutException{
		ConnectionFactory connectionFactory = new ConnectionFactory();
		//设置服务地址
		connectionFactory.setHost("127.0.0.1");
		//AMQP
		connectionFactory.setPort(5672);
	    connectionFactory.setVirtualHost("/tan");
	    connectionFactory.setUsername("tan");
	    connectionFactory.setPassword("123");
	    return connectionFactory.newConnection();
	}

    Connection connection = ConnectionUtils.getConnection();
    Channel createChannel = connection.createChannel();
     createChannel.queueDeclare(QUEUE_NAME, false, false, false, null);
     String msg="Hello simple";
     createChannel.basicPublish("", QUEUE_NAME, null, msg.getBytes());
     createChannel.close();
     connection.close();
Connection connection = ConnectionUtils.getConnection();
  Channel createChannel = connection.createChannel();
  createChannel.queueDeclare("test_simple_queue",false,false,false,null);
        DefaultConsumer defaultConsumer = new DefaultConsumer(createChannel){
         @Override
         public void handleDelivery(String consumerTag, Envelope envelope, BasicProperties properties, byte[] body)
           throws IOException {
          String string = new String(body,"utf-8");
          System.out.println(string);
         }
        };
        createChannel.basicConsume("test_simple_queue", true,defaultConsumer);

不足
耦合性高。生成者和消费者一一对应

WordQueues
工作队列

在这里插入图片描述

出现工作队列原因:simple队列是一对一的,而且实际开发,生产者发送消息毫不费力,而消息者一般是和业务结合的,消费者接受到消息之后就需要处理,可能需要时间

一个生产者,多个消费者,每个消费者获取到的消息唯一,多个消费者只有一个队列
消费者1

Connection connection = ConnectionUtils.getConnection();
  Channel createChannel = connection.createChannel();
  createChannel.queueDeclare(QUEUE_NAME,false,false,false,null);
  
  DefaultConsumer defaultConsumer = new DefaultConsumer(createChannel){
   @Override
   public void handleDelivery(String consumerTag, Envelope envelope, BasicProperties properties, byte[] body)
     throws IOException {
    
    String msg=new String (body,"utf-8");
        System.out.println("消费者1"+msg); 
        try {
     Thread.sleep(2);
    }catch (InterruptedException e) {
     // TODO Auto-generated catch block
     e.printStackTrace();
    }
   }
  };
  boolean autoAck=true;
  createChannel.basicConsume(QUEUE_NAME, autoAck,defaultConsumer);
 }

消费者2


 public static void main(String[] args) throws IOException, TimeoutException {
  Connection connection = ConnectionUtils.getConnection();
  Channel createChannel = connection.createChannel();
  createChannel.queueDeclare(QUEUE_NAME,false,false,false,null);
  
  DefaultConsumer defaultConsumer = new DefaultConsumer(createChannel){
   @Override
   public void handleDelivery(String consumerTag, Envelope envelope, BasicProperties properties, byte[] body)
     throws IOException {
    
    String msg=new String (body,"utf-8");
        System.out.println("消费者2"+msg); 
        try {
     Thread.sleep(1);
    }catch (InterruptedException e) {
     // TODO Auto-generated catch block
     e.printStackTrace();
    }
   }
  };
  boolean autoAck=true;
  createChannel.basicConsume(QUEUE_NAME, autoAck,defaultConsumer);
 }

轮询分发

** 公平分发 **
必须改变自动应答 ack 改为手动

send 生产者 开启 createChannel.basicQos(1);
消费者 createChannel.basicAck 加createChannel.basicAck(envelope.getDeliveryTag(), false); 反馈

消息应答与消息持久化

boolean autoAck=false
channel.basicConsumer(QUEUE_NAME,autoACK,consumer)

当autoAck为true时,为自动确认模式开启,一旦rabbitmq把消息给到消费者,该消息会从内存中间删除,这种情况下,如果杀死正在执行的消费者,就会丢失正在处理的消息

autoack为false时为手动模式,如果有一个消费者挂掉,就会交付给其他消费者,rabbitmq 支持消息应答,消费者发送一个消息应答,告诉rabbitmq,这个消息已经处理完成可以删除
消息应答默认是打开的

如果rabbitmq 挂了,我们任务依然会丢
boolean durable=false
channel.queueDeclare(QUEUE_NAME,durable,false,false,null)
durable 就是持久化
队列一旦声明是不可以更改的

publish_subscribe 订阅模式
在这里插入图片描述

一个生产者多个消费者,每一个消费者都有自己的队列,生产者没有吧消息直接发送给队列,而是发送给了交换机,每一个队列都必须绑定到交换机上面,生产者发送的消息经过交换机,到达队列,就可以实现一个消息被多个消费者消费
代码

生产者

Connection connection = ConnectionUtils.getConnection();
     Channel createChannel = connection.createChannel();
     //声明交换机
     createChannel.exchangeDeclare(EXCHANG_NAME, "fanout"); //fanout 类型为分发
     
     String meg="hello";
     createChannel.basicPublish(EXCHANG_NAME, "", null, meg.getBytes());
     
     System.out.println("send"+meg);
     createChannel.close();
     connection.close();

交换机是没有存储能力的,在rabbitmq里面只有队列有存储能力

Connection connection = ConnectionUtils.getConnection();
        final Channel createChannel = connection.createChannel(); 
        createChannel.queueDeclare("test_queue_fanput_emai",false,false,false,null);
      //绑定到交换机
        createChannel.queueBind("test_queue_fanput_emai", "TEST_EXCHANG_FAN", "");
        createChannel.basicQos(1);
        DefaultConsumer defaultConsumer = new DefaultConsumer(createChannel){
         @Override
         public void handleDelivery(String consumerTag, Envelope envelope, BasicProperties properties, byte[] body)
           throws IOException {
          String string = new  String(body);
          
          System.out.println("消费者1"+string);
          try {
     Thread.sleep(1);
    } catch (InterruptedException e) {
     // TODO Auto-generated catch block
     e.printStackTrace();
    }finally{
     createChannel.basicAck(envelope.getDeliveryTag(),false);
    }
         }
        };
 createChannel.basicConsume("test_queue_fanput_emai", false,defaultConsumer);
 
 
 }

交换机又叫转发器,一方面是接受生产者的信息,一方面又是向队列推送消息
channel.basicPulish("",queue_name,null,msg)
写空字符串匿名转发,

fanout 不处理路由键
direct 处理路由键

路由模式
在这里插入图片描述

生产者

在这里插入代码片
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值