繁体   English   中英

Node.js 中面向行的流

[英]Line-oriented streams in Node.js

我正在使用 Node.js 开发一个多进程应用程序。 在这个应用程序中,父进程将产生一个子进程并使用基于 JSON 的消息协议通过管道与它通信。 我发现大型 JSON 消息可能会被“截断”,因此发送到管道上的数据侦听器的单个“块”不包含完整的 JSON 消息。 此外,小的 JSON 消息可以分组在同一块中。 每条 JSON 消息都由换行符分隔,所以我想知道是否已经有一个实用程序可以缓冲管道读取流,以便它一次发出一行(因此,对于我的应用程序,一个 JSON 文档一次)。 这似乎是一个非常常见的用例,所以我想知道它是否已经完成。

我很感激任何人都可以提供的任何指导。 谢谢。

也许佩德罗的承运人可以帮助你?

Carrier 帮助您在 node.js 上实现换行终止协议。

客户可以向您发送大量线路,运营商只会在每条完成的线路上通知您。

我对这个问题的解决方案是发送 JSON 消息,每个消息都以一些特殊的 unicode 字符结尾。 一个通常不会出现在 JSON 字符串中的字符。 称之为术语。

所以发件人只是执行“JSON.stringify(message) + TERM;” 并写下来。 然后接收者在 TERM 上拆分传入数据并使用 JSON.parse() 解析这些部分,这非常快。 诀窍是最后一条消息可能无法解析,因此我们只需保存该片段并在下一条消息到来时将其添加到下一条消息的开头。 接收代码是这样的:

        s.on("data", function (data) {
        var info = data.toString().split(TERM);
        info[0] = fragment + info[0];
        fragment = '';

        for ( var index = 0; index < info.length; index++) {
            if (info[index]) {
                try {
                    var message = JSON.parse(info[index]);
                    self.emit('message', message);
                } catch (error) {
                    fragment = info[index];
                    continue;
                }
            }
        }
    });

其中“片段”是在某个地方定义的,它将在数据块之间持续存在。

但什么是 TERM? 我使用了 unicode 替换字符 '\�'。 还可以使用 twitter 使用的技术,其中消息由 '\\r\\n' 分隔,推文使用 '\\n' 作为新行并且从不包含 '\\r\\n'

我发现这比搞乱包括长度等要简单得多。

最简单的解决方案是在每条消息之前发送 json 数据的长度作为固定长度的前缀(4 个字节?),并有一个简单的非成帧解析器来缓冲小块或拆分大块。

您可以尝试使用node-binary来避免手动编写解析器。 查看scan(key, buffer)文档示例 - 它完全逐行读取。

只要换行符(或您使用的任何分隔符)只会分隔 JSON 消息而不嵌入其中,您就可以使用以下模式:

let buf = ''
s.on('data', data => {
  buf += data.toString()
  const idx = buf.indexOf('\n')
  if (idx < 0) { return } // No '\n', no full message
  let lines = buf.split('\n')
  buf = lines.pop() // if ends in '\n' then buf will be empty
  for (let line of lines) {
    // Handle the line
  }
})

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM