探索Rabbus:NodeJS中的高效消息总线抽象库
在NodeJS的世界里,Rabbus是一个高度主观的、轻量级的消息总线抽象库,它建立在强大的RabbitMQ之上,并使用rabbot作为与RabbitMQ交互的主要库。
关于Rabbus
Rabbus提供了一些最常见模式的基本实现:
- 发送/接收
- 发布/订阅
- 请求/响应
这些模式中的左侧对象是“生产者”,它们产生消息由RabbitMQ进行路由和处理。右侧的对象是“消费者”,从RabbitMQ队列中消费消息。
生产者和消费者都继承自同名的基础类,提供了通用功能,使得所有生产者和消费者都能被扩展(例如,通过中间件)。
安装Rabbus
只需简单的NPM命令即可安装:
npm install --save rabbot rabbus
请注意,Rabbus的package.json文件中没有明确列出rabbot作为依赖项,这是故意为之,以防止库版本冲突。
升级Rabbus
如果你正在升级到Rabbus的新版本,请确保阅读升级指南。
Rabbus演示
在demos目录下有几个示例展示了Rabbus的基本用法,包括:
- 发送/接收
- 发布/订阅
- 请求/响应
务必查看demo文档,了解如何运行这些示例。
Rabbus文档
详细的Rabbus文档存储在docs目录下,每个主要方面都有单独的文件:
核心文档
其他文档
配置RabbitMQ连接
有关配置RabbitMQ连接的信息,请参阅rabbot的文档。
消息传递模式
Rabbus提供了三种模式对来配合使用。每一种都打算与它的配对一起使用。虽然直接使用这些对象是可能的,但鼓励你根据需要继承这些对象,以便封装特定用途的配置,从而更容易进行测试和维护。
所有的消息消费者在消费消息时都会收到一组常见的参数:
<obj>.<consumerMethod>(function(message, properties, actions, next){
});
这些参数为你提供了特定信息或可调用函数,以便继续处理或完成进程。
关于这些参数的定义,请参见中间件文档。
基本API和中间件
Rabbus使用了基础消息生产者和消费者对象来提供所有消息生产者和消费者的通用功能。这为所有对象提供了一致的API,并使创建自己的模式和扩展Rabbus的功能集变得容易。
拓扑
除了模式对象之外,Rabbus还包括了一个拓扑对象和在其对象中使用的中间件。这些对象类型允许在需要的时候提供更大的自由度和灵活性。
拓扑对象允许您预定义并构建所需的RabbitMQ拓扑结构。您也可以利用现有拓扑构造(如交换机、队列和绑定),防止Rabbus尝试重新创建它们。
请参考拓扑文档获取更多信息。
发送自定义消息属性
RabbitMQ允许您指定任意数量的自定义头和其他属性,而rabbot则允许您按需操作这些属性。
使用Rabbus,你可以在发送消息时传递任何自定义的属性或头信息。通过以下几种方式之一来实现:
- 中间件 - 参见下面的文档
- 在发送消息时提供一个键值列表
例如:
sender.send(someMessage, {
expiresAfter: 1000,
headers: {
foo: "bar"
}
});
这样会发送一条具有1秒TTL(1000毫秒)的消息,并带有foo: bar
的头。
发送消息后的回调
如果你希望在消息发送后指定回调方法,可以在属性对象中设置onComplete
属性:
sender.send(someMessage, {
expiresAfter: 1000,
onComplete: function(){
console.log("the message has been sent!");
}
});
如果不指定对象字面量,你可以直接将回调函数作为第二个参数。
sender.send(someMessage, function(){
console.log("the message has been sent!");
});
限制消息处理
如果需要限制特定消息处理器处理的消息数量,你可以在配置中指定一个limit
:
function SomeSubscriber(){
Rabbus.Subscriber.call(this, rabbot, {
// ...
queue: {
// ...
limit: 1
}
});
}
这将限制你的SomeSubscriber
只处理一次消息。当你的处理代码调用done
时,将会处理下一个消息。
NoBatch:确认/拒绝单个消息
rabbot默认的行为是批量处理消息的ack
和nack
调用。这可以提高高达400%的小规模处理性能。但在长时间运行的过程导致消息未被及时确认的情况下,可能会出现问题。
为了避免批量ack/nack的问题,rabbot和Rabbus提供了noBatch
选项用于队列定义。
var Subscriber = new Rabbus.Subscriber({
// ...
queue: {
//...
noBatch: true
}
});
以下Rabbus对象提供了noBatch
特性:
- Rabbus.Receiver
- Rabbus.Subscriber
- Rabbus.Responder
messageType属性
Rabbus基于rabbot库构建,而rabbot使用messageType
属性作为消息的一个重要组成部分。messageType
属性的行为使rabbot和Rabbus在某些方面表现得与RabbitMQ/AMQP本身不同。
内部上,rabbot使用名为Postal.js的内存消息库来协助消息交付给消费者函数。messageType
属性被postal用作其自身的路由密钥形式。
因此,你可以让两个消费者接收到来自同一队列的一条消息的副本...或者,让来自不同队列的消息出现在单个订阅者那里。
c1 = new Rabbus.Subscriber({
// ...
exchange: "foo",
routingKey: "foo",
queue: "foo",
messageType: "foo" // <= 注意消息类型
});
c2 = new Rabbus.Subscriber({
// ...
exchange: "bar",
routingKey: "bar",
queue: "bar",
messageType: "foo" // <= 同样的消息类型
});
c1.subscribe(function(msg, props, actions){
console.log("c1 got it!");
actions.ack();
});
c2.subscribe(function(msg, props, actions){
console.log("c2 got it!");
actions.ack();
});
在这个例子中,当为c1发布消息进行消费时,很可能你会在控制台看到“c1 got it!”和“c2 got it!”两条信息。这是因为messageType
相同,rabbot内部使用messageType
来决定c1和c2的处理方法都应该收到消息。
如果省略messageType
,rabbot将使用路由键作为向处理器交付消息的方式。只要你的路由键是唯一的,通常你应该保留messageType
为空。
但这并不意味着rabbot所做的没有价值。这只是与标准的RabbitMQ/AMQP有所不同。
法律条款
Rabbus版权 ©2016 Muted Solutions, LLC。所有权利保留。
Rabbus根据MIT许可分发。