我想通过 websocket 将 PostgreSQL 查询的结果流式传输到客户端。
使用 pg-promise 和pg-query-stream从数据库中获取数据。要通过 websocket 流式传输数据,我使用socket.io-stream。
单独来看,所有组件的性能都非常好。虽然当我将 pg-query-stream 传输到 socket.io-stream 时,性能会急剧下降。
我开始了:
var QueryStream = require('pg-query-stream');
var ss = require('socket.io-stream');
// Query with a lot of results
var qs = new QueryStream('SELECT...');
db.stream(qs, s => {
var socketStream = ss.createStream({objectMode: true});
ss(socket).emit('data', socketStream);
s.pipe(socketStream);
})
.then(data => {
console.log('Total rows processed:', data.processed,
'Duration in milliseconds:', data.duration);
});
我曾尝试使用非对象流:
var socketStream = ss.createStream();
ss(socket).emit('data', socketStream);
s.pipe(JSONStream.stringify()).pipe(socketStream);
或者:
var socketStream = ss.createStream();
ss(socket).emit('data', socketStream);
s.pipe(JSONStream.stringify(false)).pipe(socketStream);
查询和传输所有解决方案的数据大约需要一分钟。
查询结果可以在一秒内写入文件:
s.pipe(fs.createWriteStream('temp.txt'));
并且该文件可以在一秒钟内传输:
var socketStream = ss.createStream();
fs.createReadStream('temp.txt').pipe(socketStream);
所以不知何故,这些流似乎并没有很好地结合起来。
作为一个愚蠢的实验,我尝试在两者之间放置一些东西:
var socketStream = ss.createStream();
ss(socket).emit('data', socketStream);
var zip = zlib.createGzip();
var unzip = zlib.createGunzip();
s.pipe(JSONStream.stringify(false)).pipe(zip).pipe(unzip).pipe(socketStream);
突然间数据可以在一秒钟内查询和传输......
不幸的是,这不会作为我的最终解决方案。它会浪费太多的CPU。是什么导致这种流组合的性能下降?如何解决这个问题?