Quantcast
Channel: html5 – The Zinger
Viewing all articles
Browse latest Browse all 22

Adding Enterprise Features to a Socket.io Application with Kaazing WebSockets

0
0

As we discussed in my prior blog post Meeting WebSockets for real, WebSockets enable development of distributed event-driven applications, particularly ones that exchange messages.  Kaazing’s high-level client libraries substantially simplify this effort.  It is possible to add these capabilities to a new Web application in a matter of minutes.

However, what if you already have a NodeJS application and your application already exchanges messages using very popular Socket.io library?

Socket.io is a fantastic open source technology that is very easy to use and adopt. However, many critical requirements of enterprise applications may present some challenges when using socket.io.  Most enterprises require advanced security, enhanced scalability, fault tolerance, etc.

In addition, ‘out of the box’ socket.io does not have support for mobile clients that many enterprises mandate.  In these cases there is a need to transition to an enterprise-class platform and library for using Websocket.

In this article I want to discuss how easy it is to modify your existing code written with socket.io to work with Kaazing WebSockets using a publish/subscribe model.

 

Let’s First Start with a Working Socket.io App

Let’s start with my AngularJS implementation of the canonical TodoMVC application that uses socket.io.   I had a lot of fun building that app; you can find it here.  We are going to make the simple Todo application into a shared app so one user can see the changes of other users).  In addition we can add a NodeJS server component to store the current state of the items; so new users will receive an initial update.  And to prevent potential race conditions when items are being edited by a user, we will simply disable the updating of items by other users; other more sophisticated code can be added later.

Let’s look at several sections of my application’s main controller (complete source available on GitHub).


...

// Connect to pub-sub service
$scope.socket=io();

// Load initial data on connect
$scope.socket.on('connect', $scope.loadData);

// Setup receive callback
$scope.socket.on('todomvc-snd', $scope.processReceivedCommand);

...

The first thing is to connect to socket.io:


$scope.socket=io();

Once a connection is established, we send the request to the server to load any initial data .  We do this by sending the command “init” to “todomvc-rcv” socket together with the attached to the $scope client ID (server will send the reply to this command to all the clients – clients with different IDs will ignore it):

$scope.socket.on('connect', $scope.loadData);

…

$scope.loadData=function(){
        var msg={
                command:'init',
                client:$scope.client
        }
        $scope.socket.emit('todomvc-rcv', msg);
        $log.info("Sent initialization!");
}

Now, we need to setup the callback method to receive messages from the server:

$scope.socket.on('todomvc-snd', $scope.processReceivedCommand);

$scope.processReceivedCommand is straightforward and just responds to individual commands.

$scope.processReceivedCommand=function(cmd){
        $log.info("Received command "+cmd.command);
        if (cmd.command==='insert'){
        ...
        }
        else if (cmd.command==='remove'){
        ...
        }
        else if (cmd.command==='update'){
        ...
        }
        else if (cmd.command==='initdata'){
        ...
        }
}

Note, we are setting up callback on a todomvc-snd topic, while sending the messages to todomvc-rcv topic. I could not find the way to have socket.io send the data from one client to the others directly. To overcome this issue, the client will send the data to a server on the topic A and the server will retransmit the message to the other clients on the topic B.
Sending the data is pretty trivial. For example, to add the item:

var msg={
  command:'insert',
  item:newTodo
}
$scope.socket.emit('todomvc-rcv', msg);

That was the client side of the application.  Let’s now look at the server side NodeJS component.  Besides the code to process the received message and serve static pages it also contains the part that connects to socket.io:

io.on('connection', function(s){
      console.log('a user connected');
     socket=s;
      s.on('disconnect', function(){
          console.log('user disconnected');
      });
      s.on('todomvc-rcv', processMessage);
});

Function processMessage contains the code to store the items that also includes send message calls to retransmit.

function processMessage(cmd) {
        console.log('Command: '+ cmd);
        if (cmd.command === 'insert') {
        ...
        }
        else if (cmd.command === 'remove') {
        ...
        }
        else if (cmd.command === 'update') {
        ...
        }
        else if (cmd.command === 'init') {
        ...
        }
}

Similar to the client side code, sending messages is very simple.  If we want to send the message retCmd to everyone:

var retCmd = {
  command: "initdata",
  client: cmd.client,
  items: todos
}

socket.emit("todomvc-snd", retCmd);

If we want the message to be received to all the sockets except the one that sent it:

socket.broadcast.emit("todomvc-snd",cmd);

Now, we can run and test the application.  This page will give you detailed instructions.

Now… Adding the Socket.io Facade to Kaazing WebSockets

To make things easy, we are going to employ the Kaazing Gateway AMQP Edition since NodeJS has robust libraries for AMQP.  While the Kaazing Gateway comes pre-packaged with the Apache Qpid AMQP broker, it can easily be RabbitMQ or another AMQP-compliant broker.  Refer to https://github.com/kaazing/tutorials/tree/develop/todomvc for the instructions for the installation of the Gateway.

Modifying client code

We are going to use Kaazing Universal Client Library for AngularJS to communicate with WebSocket Gateway.  This client library provides a high-level messaging abstraction that is independent of the underlying AMQP or JMS implementations.
Here are the steps we need to take

  • Modify app.js to include the Kaazing Universal Client Library service and create connection parameters contstants (see https://github.com/kaazing/tutorials/blob/develop/todomvc/js/app.js )
    angular.module('todomvc', ['ngRoute', 'ngResource', 'KaazingClientService']).
        .config(function ($routeProvider) {
            ...
        })
        .constant('todoMvcWebSocketConfig', {
            URL: "ws://localhost:8001/amqp",
            TOPIC_PUB: 'todomvc',
            TOPIC_SUB: 'todomvc',
            username: 'guest',
            password: 'guest';
        });
    
  • In the main controller source code
    • Connect to Gateway and establish all callbacks (replace $scope.socket=io() and all $scope.socket.on calls)
      // Connect to WebSocket
      AngularUniversalClient.connect(
            'amqp, - use AMQP protocol
            todoMvcWebSocketConfig.URL,  // connect URL (default is ws://localhost:8001/amqp)
            todoMvcWebSocketConfig.username,// use guest account
            todoMvcWebSocketConfig.password,// use guest pswd
            todoMvcWebSocketConfig.TOPIC_PUB, // use 'todomvc' as publishing topic
            todoMvcWebSocketConfig.TOPIC_SUB, // use 'todomvc' as subscription topic
              true, // No Local flag set to true which prevents the client to receive messages that it sent
              $scope.processReceivedCommand, // function for processing received messages
                   function(e){alert(e);}, // function to process WebSockets errors
            $scope.logWebSocketMessage, // function to process WebSocket logging messages
            $scope.loadData // function that will be called when the connection is established
      );
      
      
    • Replace $scope.socket.emit with AngularUniversalClient.sendMessage
      var msg={
          command: 'insert',
          item:newTodo
      }
      AngularUniversalClient.sendMessage(msg);
      
      

Note that we no longer need to use different topics for publishing and subscription.  The Kaazing WebSocket Gateway will send published messages to all subscribed clients without the need to retransmit them in the server code!

Server code changes

To preserve our server side code we are going to use the Kaazing Socket.io wrapper located in the node subdirectory of the todomvc implementation.
https://github.com/kaazing/tutorials/blob/develop/todomvc/node/socketioalt.js
The wrapper hides the details of the use of AMQP protocol (which is used for communication with NodeJS) while exposing interface that mimics the one used in Socket.io.

With our socket.io wrapper, we only need to make two changes on the server:

  • Change both send and receive topics to “todomvc”
  • Remove the code that retransmits messages

Here is the final server code implementation.

Summary of Changes

If you were to run the diff:

  • app.js vs app-socketio.js:
    • Added declaration of the Kaazing Universal Client Service
    • Added constant for the connection parameters
  • todoCtrl.js vs todoCtrl-socketio.js
    • Added reference to Kaazing Universal Client Service
    • Added reference to the connection parameters constant
    • Replaced connection and callbacks for socket.io with a single call to initialize Kaazing Unviersal Client
    • Replaced Socket.io socket.emit functions with Kaazing Universal Client sendMessage cals
  • serverws.js vs serversocketio.js
    • Replaced declaration of io:
      var io = require('socket.io')(http);
      

      was changed to

      var io=require('./node/socketioalt.js')('amqp://localhost:5672');
      
    • Removed all retransmit calls socket.broadcast.emit(“todomvc-snd”,cmd);
    • Changed the topics “todomvc-snd” and “todomvc-rcv” to “todomvc

Conclusion

Its very easy to upgrade a socket.io application to use the enterprise-class Kaazing WebSocket Gateway.  There are barely any source changes in your existing code.  Not only do you now get high-performance, advanced security and scalability features, Kaazing technology will extend your former Socket.io applications to work with mobile clients and many B2B and inside-the-firewall applications.

It’s a huge win.



Viewing all articles
Browse latest Browse all 22

Latest Images

Trending Articles





Latest Images