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

Pau*_*ick 8 javascript sockets websocket node.js socket.io

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

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

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

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

Mat*_*att 11

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

这是一个小型的测试工具,我曾经用于类似的普通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))
    }
  }

})
Run Code Online (Sandbox Code Playgroud)

客户

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()
}
Run Code Online (Sandbox Code Playgroud)

测试请求/响应往返

 node socketio-client.js ping 4
Run Code Online (Sandbox Code Playgroud)

要测试吞吐量,请像服务器一样快速地转储消息.

 node socketio-client.js dump 100000
Run Code Online (Sandbox Code Playgroud)

测试1000条消息流,每条消息之间的延迟为18毫秒,即每秒约50条消息.

 node socketio-client.js stream 1000 18
Run Code Online (Sandbox Code Playgroud)

在我的开发机器上,我可以将每秒大约40000条消息转储到单个localhost客户机,其中4个整数作为2 GHz CPU上的有效负载(计数器+ 3个时间戳).服务器和客户端node进程都使用95-100%的CPU核心.所以纯吞吐量看起来不错.

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

node在我的开发机器上的单个进程中,我无法每秒向130个客户端发送超过130-140条消息.

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

如果你遇到了问题,那么还有更低级别的websocket库ws需要更多的实现,但是你可以更好地控制套接字连接,你可以从中获得更多的性能.

您拥有的连接越多,您将使用其余代码和套接字代码获得更多争用.您可能最终需要使用多个节点来保持平稳.群集可以跨多个Node.js进程拆分应用程序.您可能需要像Redis,ZeroMQNanomsg这样的东西来管理IPC.Node 9中的V8支持SharedArrayBufferAtomics,但在Node中没有太多用于与工作者一起使用它们.


jfr*_*d00 6

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

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

没有编码限制。这仅取决于您在两端处理消息的能力以及传递消息的带宽。如果您真的想知道自己对运行的硬件,网络和操作系统的限制,则必须设计一个测试以发送具有代表性大小的快速发送数据包,并查看您可以在一秒钟内发送多少个快速发送数据包。全部到达目的地,并且在两端都看不到错误。

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

您的服务器需要每秒能够发送10,000条消息,并且每个客户端每秒必须能够处理50条传入消息。从理论上讲,使用正确的硬件和正确的网络连接都是可能的。

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

我计算出,如果每个要发送的数据包大约为500个字节,那么我将能够以每秒1 MB的速度发送20次更新到100个连接。

这种类型的计算仅适用于发送大数据块。对于许多小消息,由于许多小消息的TCP数据包开销和webSocket / socket.io开销开始占总带宽消耗的可测量百分比,因此效率很低,并且由于TCP是可靠的协议,因此存在还来回流动的ACK确认发送。如果数据包很小,那么您可能不会遇到整体带宽问题,这个问题将更多地在于处理大量小数据包以及这样做的开销。

如果您可以将更新合并为每秒更少的更新,则将获得更好的可伸缩性。