我通过websocket传入数据。它以20ms的块发送二进制数据。我需要连接这些块中的每一个,以便后端进程可以在连续流中读取数据。
//Create the file and append binary as it comes in
tmp.file({postfix: '.raw' },function (err, path, fd, cleanup) {
if (err) throw err;
newPath = path
fs.appendFile(newPath, new Buffer(binary), (err) => {
if (err) throw err;
})
})
//Read the file as it is written
fs.createReadStream(newPath).pipe(recStream);
现在我只在createReadStream
上有一个简单的半秒延迟,以确保文件中有数据。
这当然感觉不正确并且无法正常工作。什么是正确的方法?
答案 0 :(得分:2)
在这种情况下,最好的办法是告诉服务器您接收数据暂停,直到您准备好处理更多(drain
)。假设不适合你:
首先将传入数据写入目标流。如果write(chunk)
返回false
,则表示流的内部缓冲区已满;是时候开始将后续数据缓冲到磁盘了。 (您刚写入的chunk
导致false
返回值缓冲;不要将其写入磁盘 - false
并不意味着写入失败,它只是一个信号,表明缓冲区的数据多于highWaterMark
。)
在临时文件夹中,创建一个新文件( A )写入流,并将下一个传入数据块写入其中。这样做直到您的目标流发出drain
事件。
目的地drain
时:
pipe()
方法,因为它会在您到达临时文件的末尾时发出数据结束信号,这不是我们想要的,因为它不是所有的实际结束传入的数据。 (Look at what pipe()
does并自行实施,减去调用end()
。)end
时,请删除文件 A 。然后返回步骤1并使用文件 B 再次开始该过程。 (如果在此期间没有数据写入文件 B ,请返回无缓冲操作,将传入数据直接写入目标流。)一旦服务器发出信号表示已完成发送数据和,所有数据都已从您的临时文件中write(null)
读入目标流,以表示没有更多数据。一切都完成了!
通过在临时缓冲区文件之间交换并在处理完数据后删除它们,您不必担心在将数据写入文件时读取数据。另外,您不必将整个传入数据流缓冲在磁盘上。
当然,这确实假设您的存储介质可以保证比通过网络接收数据更快地接受写入。这可能是安全的,但如果这个假设不正确,事情可能会崩溃。使用生产系统测试 - 什么是峰值传入数据速率以及您在prod系统上写入磁盘的速度有多快?