轮子项目--消息队列的实现(2)

关于消息队列的核心概念有以下几个:交换机(Exchange),队列(MSGqueue),绑定(Binding)以及消息(Message),由于客户端不关心上面这些,只是把当前的数据发送到Broker Server中,再由Broker Server去处理这些数据,具体如何处理,由Broker Server决定,所以上述这些放到Broker Server中。因此就需要在mqserver包中的core包创建相关的核心类。

交换机

交换机这个类中需要有那些参数呢?

       首先,在消息队列系统中,为了区分不同的交换机,可以使用name这个属性进行区分。每个交换机都有一个唯一的名称,这个名字是在声明(创建)交换机时指定的。通过这个名字,生产者可以选择将消息发送到哪个具体的交换机,消费者也可以根据需要绑定到特定的交换机上。从轮子项目--消息队列的实现(1)-优快云博客得知,交换机有四种类型,因此我们可以使用枚举类表示要创建的交换机类型

        针对交换机,队列,绑定,消息... 内存中也需要存储,执行效率高,硬盘存储为了持久化
有些交换机,队列,绑定,消息... 是需要持久化的,有些不需要持久化,用户使用时就可以通过开关(boolean)来决定是否持久化,因此可以增加boolean durable用来表示是否可以持久化。

        通过设置autoDelete来指代交换机的自动删除过程。具体来说,当一个生产者通过调用Broker服务器的API创建了一个交换机并设置其为autoDelete=true之后,如果在生产者完成消息发送后,该交换机不再有队列绑定,并且在一段时间内没有被使用,那么这个交换机会被系统自动删除。

        最终我们也可以使用Map<String,Object> arguments来表示创建一个交换机时所需要的额外参数,可以通过这些选项来开启交换机不同的功能。

消息队列

        与交换机有些相同的是,消息队列MSGQueue中也需要name来进行身份的标识,可以用boolean durable用来表示是否可以持久化,以及自动删除和额外参数的功能。为了增加系统的安全性,例如:只有创建该队列的连接可以访问它。或者是当一个队列为特定的应用程序或任务创建时,为了以保证这个队列不会被其他应用或任务干扰,可以设置队列的排他性,用参数boolean exclusive表示,exclusive=true:队列仅允许声明它的连接(Connection) 使用,其他连接访问会被拒绝。当声明队列的连接关闭时,队列自动删除(无论 durable 设置如何)。exclusive=false,队列可被任何有权限的连接访问.

绑定关系

       为了确定消息来源,每个绑定都需要指定一个目标交换机,因此需要参数ExchangeName,为了决定消息最终应路由至哪个队列进行存储和消费,需要QueueName参数。生产者发送消息到交换机,交换机根据类型绑定规则将消息路由到哪些队列。绑定是连接交换机和队列的纽带,而绑定键是绑定时的参数,用于确定哪些消息应该被路由到该队列,Binding Key 是绑定的核心参数之一。它的存在是为了实现消息路由的灵活性和精确性。

消息

        Message有两个部分

  • 属性部分:BasicProperties
  • 正文部分:byte[] (正文支持二进制,为了保证通用性不适用String)

        其中消息属性是消息的元数据,可以用来描述信息,如消息的类型,格式,可以控制消息的行为,如消息的优先级,过期时间,持久化等,可以传递上下文信息,如事务ID,可以支持消息路由,如Routing Key。因此属性类设置了String messageId用于表示消息的唯一id,int deliveryMode表示是否可以持久化,String routingKey和绑定中的Binding Key相互匹配,表示消息可以转发到哪些队列中去。

        消息如果持久化的话,最终是要存储到文件中去,使用文件而不使用数据库的原因是:1. 我们的消息并不需要强大的增删改查功能。2. 消息太多,频繁的进行增删改查会导致性能问题。但是一个文件存储许多消息,我们如何寻找到我们所需要的消息呢?可以下列的偏移量来找到某个消息,[offsetBeg, offsetEnd), offsetBeg表示消息数据的开头距离文件开头的偏移量(字节),offsetEnd表示消息数据的结尾距离文件开头的偏移量(字节).消息在文件中,可能被删除,这里使用逻辑删除,逻辑删除并不是真正的删除,而是被标记为无效,由于是在文件中使用,所以用byte类型的isValid表示文件是否被删除。

        为了快速的获取Message的属性,可以在Message类中加上一系列的set和get方法,就不需要在关系属性的参数构成了。由于Message对象属性比较多,创建Message对象比较麻烦,为了简单,可以让工厂方法帮我们封装一个创建Message对象的过程,这个对象创建的Message对象,会自动生成唯一的MessageId。方法传参需要RoutingKey与Binding Key相互匹配,以及Message的属性和正文部分,当属性部分有RoutingKey时,我们可以用外面的RoutingKey覆盖掉,为了区分ID,可以使用"M-"拼接上UUID保证是Message生成的唯一性ID。此处把body和basicProperties 先设置出来,它们是核心内容,而 offsetBeg 和 offsetEnd 则是消息持久化才会用到,在把消息写入文件之前在进行设定,此处只是在内存中创建Message对象。

        注意,此处的Message 对象,是需要在网络上传输,并且也需要能写入文件中.此时就需要针对Message 对象进行序列化和反序列化,此处使用 标准库自带的序列化和反序列化,不适json,json本质是文本格式里面放的是文本类型数据。而Message对象是二进制格式的。使用标准库的序列化和反序列化,需要在类上实现Serializable接口,这里并需要重新方法。offsetBegoffsetEnd不需要被序列化保存到文件中,此时消息一旦被写入文件后,所在的位置就固定了,并不需要单独存储。不被标准库序列化加上关键字transient。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值