这是一个非常依赖系统、网络和代码的问题。
这是我之前用于类似的普通 socket.io 测试的一个小测试工具,我插入了一些位来满足您的问题。
Server
const io = require('socket.io')(8082)
const connections = []
io.on('connection', function(socket){
connections.push(socket);
const slog = (msg, ...args) => console.log('%s %s '+msg, Date.now(), socket.id, ...args)
slog('Client connected. Total: %s', connections.length)
socket.on('disconnect', function(data){
connections.splice(connections.indexOf(socket), 1);
slog('Client disconnected. Total: %s', connections.length)
})
socket.on('single', function(data){
socket.emit('single',[ 0, now, now, now ])
})
socket.on('start', function(data = {}){
slog('Start stream', data)
sendBatch(1, data.count, data.delay)
})
socket.on('start dump', function(data = {}){
slog('Start dump', data)
sendBatch(1, data.count)
})
function sendBatch(i, max, delay){
if ( i > max ) return slog('Done batch %s %s', max, delay)
socket.emit('batch',[ i, now, now, now ])
if (delay) {
setTimeout(()=> sendBatch(i++, max, delay), delay)
} else {
setImmediate(()=> sendBatch(i++, max))
}
}
})
Client
const io = require('socket.io-client')
const socket = io('http://localhost:8082', {transports: ['websocket']})
socket.on('connect_error', err => console.error('Socket connect error:', err))
socket.on('connect_timeout', err => console.error('Socket connect timeout:', err))
socket.on('reconnect', err => console.error('Socket reconnect:', err))
socket.on('reconnect_attempt', err => console.error('Socket reconnect attempt:', err))
socket.on('reconnecting', err => console.error('Socket reconnecting', err))
socket.on('reconnect_error', err => console.error('Socket reconnect error:', err))
socket.on('reconnect_failed', err => console.error('Socket reconnect failed:', err))
function batch(n){
socket.on('batch', function(data){
if ( data[0] >= n ) {
let end = Date.now()
let persec = n / (( end - start ) / 1000)
console.log('Took %s ms for %s at %s/s', end - start, n, persec.toFixed(1))
return socket.close()
}
})
}
function startDump(count = 500000){
socket.emit('start dump', { count: count })
console.log('Start dump', count)
batch(count)
}
function startStream(count = 50, delay = 1000){
socket.emit('start', { count: count, delay: delay })
console.log('Start stream', count, delay)
batch(count)
}
function pingIt(i, max = 50){
socket.on('single', function(data){
console.log('Got a single with:', data)
if (i >= max) {
let end = Date.now()
let persec = i / (end - start) * 1000
console.log('Took %s ms %s/s', end - start, persec.toFixed(2))
return socket.close()
}
socket.emit('single', i+=1)
})
socket.emit('single', i)
}
let start = Date.now()
//console.log('args command: %s count: %s delay: %s',process.argv[2], process.argv[3], process.argv[4])
switch(process.argv[2]){
case 'ping': pingIt(0, process.argv[3]); break
case 'stream': startStream(process.argv[3], process.argv[4]); break
case 'dump': startDump(process.argv[3]); break
default: console.log('ping stream dump'); socket.close()
}
测试请求/响应往返
node socketio-client.js ping 4
要测试吞吐量,请以服务器最快的速度转储消息。
node socketio-client.js dump 100000
测试 1000 条消息的流,每条消息之间有 18 毫秒的延迟,即每秒大约 50 条消息。
node socketio-client.js stream 1000 18
在我的开发机器上,我可以每秒将大约 40000 条消息转储到单个本地主机客户端,并在 2 GHz CPU 上使用 4 个整数作为有效负载(计数器 + 3 个时间戳)。服务器和客户端都可以node
每个进程使用 95-100% 的 CPU 核心。所以纯粹的吞吐量看起来还可以。
我可以在服务器进程的 CPU 使用率为 55% 的情况下每秒向 100 个本地客户端发送 100 条消息。
我无法从单个客户端向 100 个客户端每秒发送超过 130-140 条消息node
我的开发机器上的进程。
新的高频 Intel Skylake CPU 服务器可能会在本地消除这些数字。添加一个可能不稳定的网络连接,它就会立即恢复正常。除了本地网络延迟之外的任何因素都可能会扰乱您认为通过如此高的消息速率获得的收益。任何较慢的延迟抖动都会对客户端消息的“帧速率”造成严重破坏。可能需要在客户端上对消息加时间戳并对其进行跟踪。
如果您确实遇到问题,还有较低级别的 websocket 库,例如ws https://github.com/websockets/ws这将需要您更多的实现,但会给您更多对套接字连接的控制,并且您可能会从中获得更多的性能。
连接越多,与其余代码和套接字代码的争用就越多。您可能最终需要使用多个节点 https://socket.io/docs/using-multiple-nodes/#让事情顺利进行。集群可以将应用程序拆分为多个 Node.js 进程 https://stackoverflow.com/q/18310635/1318694。你可能需要像Redis这样的东西,ZeroMQ http://zeromq.org/ or Nanomsg http://nanomsg.org/管理IPC。 Node 9 中的 V8 支持共享数组缓冲区 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SharedArrayBuffer and Atomics https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Atomics但 Node 上还没有多少东西可以与工人一起使用它们。