Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Using MessagePack (binary frames) with SocketCluster #64

Closed
mirague opened this issue Sep 14, 2016 · 6 comments
Closed

Using MessagePack (binary frames) with SocketCluster #64

mirague opened this issue Sep 14, 2016 · 6 comments

Comments

@mirague
Copy link

mirague commented Sep 14, 2016

Currently the SocketCluster client uses a format of:

{"event":"someType","data":{"foo":"bar"},"cid":3}

The format has considerable overhead on the messaging structure and I was wondering how we could go about implementing a buffered-approach such as MessagePack. This could save us big on bandwidth as we're developing an application with a high rate of message throughput.

Right now I'm trying something like:

/**
 * Send a Message to Remote over WebSocket.
 * Note: This method is part of an abstracted Transport layer used by both Client and Server
 */
send(messageType, message, callback = null) {
  // this.socket = SocketCluster socket

  if (this.socket.getState() !== 'open') {
    return;
  }

  const encoded = msgpack.encode({event: messageType, data: message}); // returns Buffer

  // Get the SocketCluster Transport and send Binary frame
  if (this.socket.transport) { // SCClient Socket
    this.socket.transport.socket.send(encoded);
  } else { // SCServer Socket
    this.socket.socket.send(encoded);
  }

  // The original SocketCluster way which reproduces a "heavy" json string-payload
  this.socket.emit(messageType, message);
}

What do you think of supporting raw binary frames directly? And if there's no interest in official support, could you share your thoughts on this? Thanks!

@mirague mirague changed the title Changing out the messaging format Using MessagePack (binary frames) with SocketCluster Sep 14, 2016
@jondubois
Copy link
Member

jondubois commented Sep 14, 2016

@mirague I think the current format is nice because it's simple and extensible... But I agree with your point.

For compression, there is support for perMessageDeflate (good for large messages). This has been in SC for a long time but I just added documentation today: Search for perMessageDeflate here: http://socketcluster.io/#!/docs/api-socketcluster

perMessageDeflate is great for large JSON messages but not very useful for very short messages sent with high throughput. (which is your use case)

I believe the WebSockets standard might support other custom compression algorithms in addition to per-message deflate but I'm not sure if/how that is implemented in browsers.
If compression can be done at the WebSocket level then there wouldn't be much point changing our current event format. I will need to research this a bit more.

Either way, yes I think it would be nice to allow the user to inject their own compression/decompression functions on the client and server.

We could also consider changing the current format to something more lightweight but this would introduce new problems:

  • It wouldn't be as clear (not as good for debugging)
  • Old SC clients would no longer work (unless we add support for both the old and new format...)

I'm kind of leaning on allowing the user to inject their own custom compression/decompression functions.
What do you think?

@jondubois
Copy link
Member

jondubois commented Sep 22, 2016

We could introduce a new concept: custom Codecs - So users could specify a custom JavaScript module for coding and decoding packets - Right now, only https://github.com/SocketCluster/sc-formatter is supported but we could allow the user to swap it out with anything they like.

For games, the user could use their own Codec optimized for their specific game - It could format messages as raw binary.

If a codec is used on the client, the same codec module will need to be provided on the server-side. It would just have two methods: encode and decode.

The community could then share codecs - Each one being optimized for specific purposes.

@jondubois
Copy link
Member

@mirague I added a new custom codec feature. See https://github.com/SocketCluster/socketcluster#custom-codecs

@mirague
Copy link
Author

mirague commented Sep 23, 2016

@jondubois Excellent work! I will have a look at the changes coming week, thank you!

@ivopc
Copy link

ivopc commented Oct 13, 2016

If there's a lot of req by sec, consider using webRTC + socketCluster (if it is p2p task, of course).

@jondubois
Copy link
Member

jondubois commented Nov 25, 2016

@mirague In case you're interested, I've done some work on a minimal binary codec which you can easily plug into SC: https://github.com/SocketCluster/sc-codec-min-bin

Right now it just uses MessagePack to encode/decode messages between JSON <=> ArrayBuffer/Buffer (Binary) but in the future, it will also do some SC-specific compression to reduce the protocol overhead to almost nothing - Suggestions and PRs are welcome.

You may want to upgrade socketcluster to v5.1.0 and socketcluster-client to v5.1.0 for best effect. Earlier versions of SC and the client did not encode the ping and pong messages (this is a minor aesthetic issue though).

Also, we started adding some features to speed up pub/sub in SC so that should help with high-throughput workloads as well.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants