我多久可以使用Socket.IO发送数据?

时间:2017-11-13 23:16:08

标签: javascript node.js sockets websocket socket.io

我正在创建一个Web应用程序,需要将少量数据(每个插槽3个整数值)从服务器发送到客户端非常频繁,我想看看是否有最大频率来更新客户端使用Socket.IO

我希望实现至少50个套接字连接,每秒发送20次更新。理想的数字是200个套接字连接,每秒发送50个更新。

问题:使用Socket.IO发送新数据的频率是否有限制?

注意:我认识到这也成为服务器 - 客户端连接的速度问题,因此我需要了解有关连接速度的任何信息。我计算出,如果发送的每个数据包大约是500字节,那么我将能够在1 MB / s连接上每秒发送20次更新到100个连接。

2 个答案:

答案 0 :(得分:5)

这是一个非常系统,网络和代码相关的问题。

这是一个小型的测试工具我曾经用于类似的普通socket.io测试之前,我已经插入了一些适合你的问题。

服务器

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))
    }
  }

})

客户端

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条消息转储到一个localhost客户端,其中4个整数作为2 GHz CPU上的有效负载(计数器+ 3个时间戳)。服务器和客户端node进程都使用95-100%的CPU核心。所以纯吞吐量看起来不错。

我可以在服务器进程的55%CPU使用率下,每秒向100个本地客户端发送100条消息。

在我的开发计算机上的单个node进程中,我无法每秒向130个客户端收到超过130-140条消息。

新的高频Intel Skylake CPU服务器可能会在本地拆除这些数字。添加一个可能是flakey的网络连接,它会将其恢复正常。除了本地网络延迟之外的任何其他内容都可能会破坏您认为将以如此高的消息速率获得的内容。任何较慢的延迟抖动都会对帧频率造成严重影响"客户端上的消息。可能需要为客户端添加时间戳消息并跟踪它们。

如果遇到问题,还有像ws这样的低级websocket库需要更多的实现,但是你可以更好地控制套接字连接,你可以从中获得更多的性能。 / p>

您拥有的连接越多,您将使用其余代码和套接字代码获得更多争用。您可能最终需要使用multiple nodes来保持平稳。 Cluster can split the app across multiple Node.js processes。您可能需要Redis,ZeroMQNanomsg之类的东西来管理IPC。节点9中的V8支持SharedArrayBufferAtomics,但在Node中没有多少用于与工作者一起使用。

答案 1 :(得分:3)

  

使用Socket.IO发送数据的频率是多少?

     

使用Socket.IO发送新数据的频率是否有限制?

没有编码限制。它只取决于您处理两端消息的能力以及提供它们的带宽。如果您真的想知道自己对自己运行的硬件,网络和操作系统的限制,那么您必须设计一个测试来发送代表性大小的快速火灾数据包并查看您可以发送的数量一秒钟,他们都到达目的地,两端都没有出现任何错误。

  

理想的数字是200个套接字连接,每秒发送50个更新。

您的服务器需要能够每秒发送10,000封邮件,并且每个客户端需要能够每秒处理50封传入邮件。理论上,只要有合适的硬件和正确的网络连接,这一切都是可能的。

但是,每秒50次更新听起来可能既不必要又效率低下。没有最终用户会每20毫秒感知到一些变化,这就是每秒50次更新。因此,将每个客户端的更新批处理为每秒10次更新会更有效率。

  

我计算出如果发送的每个数据包大约是500字节,那么我将能够在1 MB / s连接上每秒发送20次更新到100个连接。

这种类型的计算仅适用于发送大块数据。对于许多小消息,由于TCP数据包开销和许多小消息的webSocket / socket.io开销开始成为整体带宽消耗的可测量百分比,并且因为TCP是可靠的协议,所以存在许多低效率,还来回确认交付的ACK。如果数据包很小,你可能不会遇到整体带宽问题,处理大量小数据包的问题会更多,而且开销也会更多。

如果您可以将更新组合为每秒更少的更新,那么您将获得更好的可扩展性。