The Solace Web Streaming API supports the WebSocket Protocol as a preferred transport. I have been playing around with using the Solace streaming API in Node.js as well as on my laptop, iPad, and Android phone.

In each case, the initialization time for apps is visibly faster when using a browser that supports WebSocket. I wrote a simple javascript app to display the init time, the protocols used, as well as continuously monitor the round trip time for the connection. The plotting of the  round trip time (RTT) uses SmoothieCharts which I think has a nice look and feel.

Why is the init time faster?

The Solace javascript client library always tries the WS_BINARY WebSocket transport first before falling back to one of several other methods for providing streaming data (such as polling with XMLHttpRequest). WebSocket supports bi-directional sending and receiving of streaming binary data without having to encode it as text first. When running on a non-websocket transport the Solace client libraries have to figure out the capabilities of the underlying browser an network and pick the “best” transport and encoding method (HTTP_BINARY_STREAMING, HTTP_BINARY, or  HTTP_BASE64). This automatic protocol selection ensures that your app will work, even in Microsoft IE, with the best available method of transport, and will be portable without the need for any changes or conditional checking  in your code.

Solace Transport Protocols
  • HTTP_BASE64 – A COMET model that uses base64 payload encoding. HTTP responses have a defined Content-Length.
  • HTTP_BINARY – A COMET model that uses binary payload encoding. HTTP responses have a defined Content-Length.
  • HTTP_BINARY_STREAMING – A COMET model that uses binary payload encoding. HTTP responses use Chunked Transfer-Encoding to stream data from the appliance to the client without needing to terminate the HTTP response.
  • WS_BINARY – A WebSocket communication channel uses binary payload encoding and provides full-duplex communication between the client and the appliance over a single TCP connection.

Want more control?

You can always explicitly set the transport protocol you want if you know ahead of time which one is going to work for your target platform.

mySessionProperties.transportProtocol = solace.TransportProtocol.HTTP_BASE64;

You can also control the amount of time to wait before the session will abandon a connection attempt with the current transport protocol and try a downgraded transport. This can be used to either speed up or slow down the process of walking from the best (WS_BINARY) to lowest common denominator (HTTP_BASE64) transport protocol.

mySessionProperties.transportDowngradeTimeoutInMsecs = 1000; //default is 10000ms

Try for yourself

The code for this app is both listed below,   and available for download. The only external includes are the standard solclient.js web streaming library and the smoothie.js library. Everything else is inline with comments to make it more easily understood.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html >
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Solace Session Init Timer</title>
<script type="text/javascript" src="solclient.js"></script>
<script type="text/javascript" src="smoothie.js"></script>
<script type="text/javascript">
var generateUid = function (separator) {
/// <summary>
///    Creates a unique id for identification purposes.
/// </summary>
/// <param name="separator" type="String" optional="true">
/// The optional separator for grouping the generated segmants: default "-".
/// </param>

var delim = separator || "-";
function S4() {
return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
}
return (S4() + S4() + delim + S4() + delim + S4() + delim + S4() + delim + S4() + S4() + S4());
};

function init() {

// Initialize SmoothChart Canvas
var smoothie = new SmoothieChart({millisPerPixel:50,  grid:{millisPerLine:3000}});
smoothie.streamTo(document.getElementById("mycanvas"),  900);
var line1 = new TimeSeries();
smoothie.addTimeSeries(line1,  { strokeStyle:'rgb(0,  255,  0)',  lineWidth:3 });
//Initialize Text Display Canvas
var c=document.getElementById("inittime");
var tx=c.getContext("2d");
tx.font="20px Arial";
tx.fillStyle="#FF0000";

// Set some Solace session properties
var mySessionProperties = new solace.SessionProperties();
mySessionProperties.connectTimeoutInMsecs = 30000;
mySessionProperties.readTimeoutInMsecs = 30000;
mySessionProperties.keepAliveIntervalInMsecs = 3000;
mySessionProperties.keepAliveIntervalsLimit = 3;
mySessionProperties.vpnName = "demo";
mySessionProperties.userName = "demouser";
mySessionProperties.password = "password";
mySessionProperties.url = 'http://69.20.234.126:8134/solace/smf';

// Callback that handled session events
// Note that we wait for a "session up" notification before doing lots of stuff that requires a connection
var sessionEventCb = function(session,  event) {
if (event.sessionEventCode === solace.SessionEventCode.UP_NOTICE) {
console.log( 'Session up');
sp = session.getSessionProperties();
console.log('transport protocol in use is :' + sp.transportProtocolInUse );
// Display the session init time and protocol on the inittime canvas (in HTML <body> below)
now = new Date().getTime();
var it = now - start;
tx.clearRect ( 0 ,  0 , 800 ,  150 ); //clear canvas
tx.fillText( 'Init Time: ' + it + 'ms  Transport Protocol: ' + sp.transportProtocolInUse, 10, 50);
//make a guid so multiple instances work
uid = generateUid('-');
console.log('uid = ' + uid);
// subscribe to a unique topic
topic = solace.SolclientFactory.createTopic( uid );
try {
mySession.subscribe(topic,  true);
} catch (error) {
console.error("failed to subscribe: " + error.toString());
}

// create a heartbeat message every second
iv = setInterval(function() {
var msg = solace.SolclientFactory.createMessage();
msg.setDestination( topic );
t = new Date().getTime();
msg.setXmlContent( t.toString() );
// Publish message
try {
mySession.send(msg);
} catch (error) {
// failed to send,  therefore stop publishing and log the error thrown
console.error("Failed to send solace message '" + msg.toString() + "'");
console.error(error.toString() + error.Message);
}
},  1000);

} else if (event.sessionEventCode === solace.SessionEventCode.DISCONNECTED) {
//cleanup when the link goes down and then re-initialize again
console.log( 'Session disconnected');
if (typeof iv != 'undefined') {
clearInterval(iv);
}
mySession.dispose();
setTimeout(function() { init(); },  100);
}
}

//Callback that handles incoming messages
function messageEventCb (session,  message) {
// Message received
try {
d = message.getXmlContent();
now = new Date().getTime();
//calc RTT
rtt = now - d;
} catch ( e) {
console.error( 'Date Error: ' + e.toString());
}
line1.append( now,  rtt );
}

//Create the session and register the callbacks we defined
mySession = solace.SolclientFactory.createSession(mySessionProperties, 
new solace.MessageRxCBInfo( messageEventCb,  this), 
new solace.SessionEventCBInfo( sessionEventCb,  this));
try{
var start = new Date().getTime();
mySession.connect();
} catch (error) {
console.error(' Error connecting to mySession: ' + error);
}
}
</script>
</head>

<body onload="init()" style="background-color:#333333">
<FONT COLOR="00ff00"><h4>RTT (milliseconds)</h4></FONT>
<canvas id="mycanvas" width="800" height="250"></canvas>
<p>
<canvas id="inittime" width="800" height="150"></canvas>
</body>
</html>
Solace logo
Solace

Solace helps large enterprises become modern and real-time by giving them everything they need to make their business operations and customer interactions event-driven. With PubSub+, the market’s first and only event management platform, the company provides a comprehensive way to create, document, discover and stream events from where they are produced to where they need to be consumed – securely, reliably, quickly, and guaranteed.

Behind Solace technology is the world’s leading group of data movement experts, with nearly 20 years of experience helping global enterprises solve some of the most demanding challenges in a variety of industries – from capital markets, retail, and gaming to space, aviation, and automotive.

Established enterprises such as SAP, Barclays and the Royal Bank of Canada, multinational automobile manufacturers such as Renault and Groupe PSA, and industry disruptors such as Jio use Solace’s advanced event broker technologies to modernize legacy applications, deploy modern microservices, and build an event mesh to support their hybrid cloud, multi-cloud and IoT architectures.