节点.js控制台错误管道到另一个程序(使其异步)



来自 Expressjs 文档:

为了使您的应用保持纯粹异步,您仍然需要管道 console.err() 到另一个程序

问:

  1. 使用 stdout 和 stderr 重定向运行我的节点应用程序是否足以不阻塞事件循环?像这样:node app 2>&1 | tee logFile
  2. 如果 ad.1 的答案是正确的,那么在使用 Winston 或 Banyan 时如何实现非阻塞日志记录?他们有一些内置机制来实现这一点,或者他们只是将数据保存到特定文件中,浪费当前 Node .js进程的 CPU 时间?或者,也许为了实现真正的异步日志记录,他们应该将数据管道传输到执行"保存到文件"的子进程(它仍然是性能积极的吗?如果我的思维方式是错误的,谁能解释或纠正我?

  3. 编辑部分:我可以假设来自过程 A、B、...对于这个特定的进程(A,B,...),处理L的etc比将其写入文件(或通过网络发送)便宜。 切中要害: 我正在为使用 nodejs 集群的应用程序设计记录器。 简而言之 - 其中一个进程 (L) 将处理来自其他进程 (A、B、...) 的数据流。 进程 L 将消息排队(例如逐行或其他一些特殊分隔符),并将其逐个记录到文件、db 或其他任何地方。 这种方法的优点是减少了流程的负载,这些流程可以将更多时间花在完成其工作上。 还有一件事 - 假设是简化此库的使用,因此用户将仅包含此记录器,而无需通过 shell 进行任何其他交互(流重定向)。你认为这个解决方案有意义吗?也许您知道一个已经在这样做的图书馆?

让我们先设置一些地面...

写入终端屏幕(console.log()等)、写入文件(fs.writeFile()fs.writeFileSync()等)或将数据发送到流process.stdout.write(data)等)将始终"阻塞事件循环"。为什么?因为这些函数的某些部分总是用JavaScript编写的。这些函数所需的最少工作量是获取输入并将其移交给一些本机代码,但某些 JS 将始终被执行。

而且由于涉及JS,它将不可避免地"阻塞"事件循环,因为无论如何JavaScript代码总是在单个线程上执行。

这是一件坏事吗...?

不。处理某些日志数据并将其发送到文件或流所需的时间非常短,并且不会对性能产生重大影响。

那么,这什么时候会是一件坏事呢?

您可以通过执行通常称为"同步"I/O 操作的操作来损害您的应用程序 - 即写入文件,并且在写入完成之前实际上不执行任何其他 JavaScript 代码。当你这样做时,你把所有数据交给底层的原生代码,虽然理论上能够继续在JS空间中做其他工作,但你有意决定等到原生代码用结果回复你。这将"阻塞"您的事件循环,因为这些 I/O 操作可能比执行常规代码花费更长的时间(磁盘/网络往往是计算机中最慢的部分)。

现在,让我们回到写信给stdout/stderr

来自 Node.js' 文档:

process.stdout 和 process.stderr 与其他 Node.js 流的重要区别:

  1. 它们分别由 console.log() 和 console.error() 在内部使用。
  2. 它们不能被关闭(end() 将抛出)。
  3. 它们永远不会发出"完成"事件。
  4. 写入可能是同步的,具体取决于流连接到的内容以及系统是 Windows 还是POSIX:
    • 文件:在 Windows 和 POSIX 上同步
    • TTY(终端):在Windows上异步,在POSIX上同步
    • 管道(和套接字):在Windows上同步,在POSIX上异步

我假设我们正在使用下面的POSIX系统。

实际上,这意味着当您的 Node.js 输出流未通过管道传输并直接发送到 TTY 时,将某些内容写入控制台将阻止事件循环,直到整个数据块发送到屏幕。但是,如果我们现在在将某些内容写入控制台 Node 时将输出流重定向到其他内容(进程、文件等.js将不会等待操作完成并在将数据写入该输出流时继续执行其他 JavaScript 代码。

在实践中,我们可以在同一时间段内执行更多的JavaScript

有了这些信息,您现在应该能够自己回答所有问题:

  1. 如果您不向控制台写入任何内容,则无需重定向 Node.js 进程的stdout/stderr,或者如果您不向另一个流写入任何内容,则只能重定向其中一个流。无论如何,您都可以重定向它们,但是如果您不使用它们,您将不会获得任何性能优势。
  2. 如果将记录器配置为将日志数据写入流,则它不会过多地阻塞事件循环(除非涉及一些繁重的处理)。

如果您非常关心应用程序的性能,请不要使用 Winston 或 Bunyan进行日志记录 - 它们非常慢。改用皮诺 - 请参阅自述文件中的基准测试。

要回答 (1),我们可以深入了解 Express 文档,您将看到指向控制台的 Node.js 文档的链接,该文档链接到有关进程 I/O 的 Node 文档。它描述了process.stdout和process.stderr的行为方式:

process.stdout 和 process.stderr 与其他 Node.js 流的重要区别:

  1. 它们分别由 console.log() 和 console.error() 在内部使用。
  2. 它们不能被关闭(end() 将抛出)。
  3. 它们永远不会发出"完成"事件。
  4. 写入可能是同步的,具体取决于流连接到的内容以及系统是 Windows 还是 POSIX:
    • 文件:在Windows和POSIX上同步
    • TTY(终端):在Windows上异步,在POSIX上同步
    • 管道(和套接字):在Windows上同步,在POSIX上异步

有了这个,我们可以尝试了解node app 2>&1 | tee logFile会发生什么:

  • Stdout 和 stderr 通过管道传输到进程tee
  • tee写入终端和文件日志文件。

这里重要的部分是stdout 和 stderr 通过管道传输到进程,这意味着它应该是异步的。

关于(2)这取决于您如何配置Bunyan或Winston:

  • Winston具有传输的概念,它基本上允许您配置日志的去向。如果需要异步日志,则应使用控制台传输以外的任何记录器。使用文件传输应该没问题,因为它应该为此创建一个文件流对象,并且是异步的,并且不会阻止 Node 进程。

  • Bunyan有一个类似的配置选项:流。根据他们的文档,它可以接受任何流接口。只要你避免在这里使用 process.stdout 和 process.stderr 流,你应该没问题。

最新更新