8

所以情况是我有各种各样的数据源,它们提供来自外部设备的消息流。有些在串行端口上发送消息,有些通过 UDP,有些通过 Telnet。我希望构建一个小型 Node.js从这些来源中的每一个接收消息的系统。大约有 20 个来源。

然后我想将这些消息中继到多个地方,并且我希望允许客户端通过 telnet 连接并接收这些消息。

我想您可以将其称为“服务总线”或“消息总线”。

目前我只是在思考如何构建它的想法,我不想要一个可以做所有事情的巨大 node.js 文件。

我希望每个“接收器”都位于我的主 node.js 文件的外部 .js 文件中。我的方法是否正常,我可以对我的方法进行任何改进。

主 Node.js 文件

拉入两个“接收器”..每个接收器都将处理来自数据源的传入消息

var sys = require("sys");

AVLReceiver = require("./avlreceiver.js").AVLReceiver();
PagerReceiver = require("./pagerreceiver.js").PagerReceiver();

pagerreceiver.js - 一个示例消息接收器

从串口接收消息..

var serialport = require("serialport");
var sys = require("sys");

var PagerReceiver = {};

PagerReceiver.initializePort = function () {
    this.serialport = new serialport.SerialPort("/dev/ttyS0", { 
        parser: serialport.parsers.readline("\n"), baudrate: 57600 
      });

    this.serialport.on("data", this.processMessage);
};

PagerReceiver.processMessage = function (data) {
  //deal with the message
};

PagerReceiver.initializePort();

exports.PagerReceiver = function() {
       return PagerReceiver;
};

这是否是分解 node.js 系统的合适方法?任何关于 javascript 的评论也很感激。还有任何关于我应该考虑在 node.js 中构建消息总线的任何其他架构方法的评论都将是超级的。

谢谢阅读,

邓肯。

4

2 回答 2

4

This post is over 8 years old and the problem would be well and truly solved; but I thought I'd drop in some ideas using modern Node and Typescript for anyone who comes by this way.

A message bus is a really good fit as you found out. This helps to not overwhelm your application when the devices start sending out large volumes of messages.

A clean way to approach this would be to use a dedicated service bus like @node-ts/bus that deals with all the technical complexities of retrying messages, subscribing to topics etc.

The next would be to build in an Anti-corruption layer for the messages generated by the devices. When each message is received by them, it's translated into a domain message that conforms to your standards. This will prevent each message handler from having to have multiple concerns around deciphering messages and actioning them.

于 2019-04-30T07:02:41.473 回答
3

这是一个较老的问题,因此您可能已经构建了您的解决方案,但我会添加我的看法,以防它对某人有用。

The idea of keeping your receiver-specific code isolated definitely seems right to me, it'll make it clear to the reader which code relates to the main workflow and which code relates to a specific stream.

I'd also be tempted to try;

  • If possible giving all your Receivers the same interface so that the main code is simple.
  • Maybe use EventEmitters to trigger events that can be caught by higher-level app code
  • Externalise config such as serial ports and baud rates to a per-app or per-environment config file. Node's module system automatically checks "~/node_modules" so you can put per-environment config in there to avoid overwriting when you deploy new code.
  • I'd be tempted to take a look at the way your module exports its functionality, see below.

Instantiation

I find the way you're tackling the object creation slightly misleading, as it makes exports.PagerReceiver() seem like a class constructor, which it isn't; in this case it's returning a singleton object. The module itself is already a singleton instance so this is a bit redundant and potentially misleading.

Below is an example of how multiple calls to require() actually reference the same private variable i.

counter.js

var i = 0;

exports.iterate = function(){
    return i++;
};

test.js

var counter1 = require('./counter');
var counter2 = require('./counter');
console.log(counter1.iterate());
console.log(counter2.iterate());
console.log(counter1.iterate());
console.log(counter2.iterate());

output:

0
1
2
3

The following code is simpler and functionally the same, aside from being called with require() instead of require().PagerReceiver():

var serialport = require("serialport");
var sys = require("sys");

exports.processMessage = function (data) {
    //deal with the message
};

var port = new serialport.SerialPort("/dev/ttyS0", { 
    parser: serialport.parsers.readline("\n"), baudrate: 57600 
});

port.on("data", exports.processMessage);
于 2011-05-22T12:41:52.990 回答