Scaling WebRTC based applications

WebRTC is a free, open project that provides browsers and mobile applications with Real-Time Communications (RTC) capabilities via simple APIs. The WebRTC components have been optimized to best serve this purpose.

WebRTC is supported by Chrome, Firefox, Opera, Android, and iOS.

First attempt

In the simplest form, there are peers (WebRTC clients) and a signaling server. At the beginning, peers don’t know each other, and they don’t know the necessary network information to make direct connection possible. Before establishing a direct connection, peers should exchange necessary data using a signaling server. This is a middle point that is known to each peer. So each peer can connect to the signaling server, and then one peer can call another one—by asking the signaling server to exchange specific data with another peer and make peers know each other. Both clients exchange the necessary data (including network details) and then establish direct peer-to-peer connection. After the connection is established, peers don’t use the server anymore.

webrtc-peers

A message service for signaling needs to be bidirectional: client to server and server to client. In this case, we can use WebSocket which is designed for full duplex client–server communication. To support highly concurrent users, our WebRTC app needs signaling servers able to handle considerable load. In this case, we can do vertical scaling by adding multiple signaling servers behind a load balancer. There is a problem with this when 2 peers about to make a call but connecting to different servers. So, how these 2 servers talk to each other ? The solution is to use a message queue such as ZeroMQ, Redis,… Each signaling server needs to create 2 clients connecting to the message queue: 1 for publishing message to the queue and the other for subscribing the queue.  When a server gets a request to route a message to a client which is not in the local connections dictionary, it will publish a message to the queue server, which will tell all the sub-scriber servers to look for this client and issue the message if it’s connected to that server.

webrtc-lb.png

Using TURN servers

In some cases, when clients use NAT and firewalls, it is impossible to establish a peer connection using STUN. This situation often appears when a client is located in a corporative network with a strict policy. In such a case, the only way to establish the connection is to use the TURN server. The TURN server works as a proxy—all the data between peers (including audio, video, and service data) goes through the TURN server.

webrtc-turn.png

The TURN server has to support authentication and prohibit anonymous access. When using a TURN service, all the traffic from one peer to another goes through the TURN server.

We may also need to do vertical scaling for TURN servers by adding a load balancer.

Combining the best of both worlds

We can config TURN server as a fallback when a peer connection can’t be established when using STUN. That way we can combine the best of both worlds.

webrtc-lb-turn.png

When we create a peer connection object


var pc = RTCPeerConnection(configuration);

Here, configuration is an entity that contains different options to create a peer connection object. To utilize your TURN server, we use something like the following:


var configuration = {
'iceServers': [
{
'url': 'stun:stun.l.google.com:19302'
},
{
'url': 'turn:turn1.myserver.com:3478?transport=udp',
},
{
'url': 'turn:turn2.myserver.com:3478?transport=tcp',
'credential': 'xxxxx',
'username': 'superxxxxxxxx'
}
]
}

Here, we will ask the WebRTC API to use one of three ways when establishing a peer connection:

  • Public STUN server provided by Google.
  • TURN server with anonymous access.
  • TURN server with authentication.

But how clients know the turn servers’ urls and credential ? After the user gets authenticated, he will be redirected to the private area where the WebRTC interactive page is placed. The interactive page that a user gets from the web server should contain correct credentials for accessing the TURN server. These credentials are calculated by the web server and are then sent to the authorized client.