赞
踩
与消息队列类似的是阻塞队列(Blocking Queue),它是一个生产者消费者模型 (是在一个进程内部进行的)。
而所谓的消息队列(Message Queue),就是把阻塞队列这样的数据结构,单独提取成了一个程序,进行独立部署 -> 生产者消费模型 (进程和进程之间 / 服务和服务之间);一般是部署在分布式系统上的,就是说整个服务器程序,不是一个单一的程序了,而是由一组服务器构成的集群。
生产者消费者模型作用:
市面上一些知名的消息队列
一个生产者,一个消费者
N 个生产者,N 个消费者
Broker server 内部也涉及一些关键概念(是为了如何进出队列)
RabbitMQ 就是按照这些概念来组织的(AMQP协议),而项目的实现也是参照 RabbitMq 的。
消息队列服务器(Broker Server),要提供的核心 API 有下面几个
销毁队列(queueDelete)
创建交换机(exchangeDeclare)
销毁交换机(exchageDelete)
创建绑定(queueBind)
解除绑定(queueUnbind)
发布消息(basicPublish)
订阅消息(basicConsume)
确认消息(basicAck)
RabbitMQ 提供了 肯定(已读已回) 和 否定的 (已读未回)确认,此处我们项目就只有 肯定确认。
在这里的项目中,并没有搞一个 API 叫 “消费消息”,即让消费者通过这个 API 从服务器上取走消息。
对于 MQ 和 消费者之间的工作模式有两种,一是 Push(推),就是 Broker 把收到的数据,主动的发送给订阅的消费者,RabbitMQ 只支持 推 的方式;二是 Pull (拉),就是消费者主动调用 Broker 的 API 取数据,Kafka 就能支持 拉。
交换机在转发消息的时候,是有一套转发规则的
提供了几种不同的 交换机类型 (ExchangType)来描述这里不同的转发规则
RabbitMQ 主要实现了四种交换机类型(也是由 AMQP 协议定义的)
项目中实现了前三种
如果当前 bindingKey 和 routingKey 对上了,就可以把消息转发到对应的队列
package com.example.mq.mqserver.core; public enum ExchangeType { DIRECT(0), FANOUT(1), TOPIC(2); private final int type; private ExchangeType(int type) { this.type = type; } public int getType() { return type; } }
上述 虚拟机、交换机、队列、绑定、消息,需要存储起来。此时内存和硬盘各存储一份,内存为主,硬盘为辅。
在内存中存储的原因:
对于 MQ 来说,能够高效的转发处理数据,是非常关键的指标! 因此对于使用内存来组织数据,得到的效率,就比放硬盘要高很多。
在硬盘中存储原因:
为了防止内存中数据随着进程重启 / 主机重启而丢失。
其他的服务器(生产者 / 消费者)通过网络,是要和 Broker Server 进行交互的。
此处设定,使用 TCP + 自定义的应用层协议 实现 生产者 / 消费者 和 BrokerServer 之间的交互工作
应用层协议主要工作:就是让客户端可以通过网络,调用 brokerserver 提供的编程接口
因此,客户端这边也要提供上述 API,只有服务器是真正干实事的;客户端只是发送 / 接受响应
客户端的本地方法调用,实际上就好像调用了一个远端服务器的方法一样 (远程过程调用 RPC,可以视为是编写客户端服务器程序,通信过程的一种设计思想)。
客户端除了提供上述 9 个和服务器方法对应的方法之外,还需要提供 4 个 额外的方法,支撑其他工作
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。