Cloud Foundry Blog

Scaling Real-time Apps on Cloud Foundry Using Node.js and RabbitMQ

In the previous blog Scaling Real-time Apps on Cloud Foundry Using Node.js and Redis, we used Redis as a ‘session store’ and also as a ‘pub-sub’ service for chat messages. But in many enterprise grade real-time apps, you may want to use RabbitMQ instead of Redis to do pub-sub because of the reliability and features that comes out-of-the-box in RabbitMQ. This is especially true for financial or Bank apps like Stock Quote apps where it is critical to protect and deliver each-and-every message AND do it as quickly as possible.

So, in this blog, we will start from Scaling Real-time Apps on Cloud Foundry Using Node.js and Redis and simply replace Redis with RabbitMQ pubsub.

The app architecture (before):

The app architecture w/ RabbitMQ (after):


Introduction to RabbitMQ

The Node.js community may not be familiar with RabbitMQ. So here are some of the high-level intro of RabbitMQ.

RabbitMQ is a message broker. It simply accepts messages from one or more endpoints “Producers” and sends it to one or more endpoints “Consumers”.

RabbitMQ is more sophisticated and flexible than just that. Depending on the configuration, it can also figure out what needs to be done when a consumer crashes(store and re-deliver message), when consumer is slow (queue messages), when there are multiple consumers (distribute work load), or even when RabbitMQ itself crashes (durable). For more please see: RabbitMQ tutorials.

RabbitMQ is also very fast & efficient. It implements Advanced Message Queuing Protocol “AMQP” that was built by and for Wall Street firms like J.P. Morgan Chase, Goldman Sachs, etc. for trading stocks and related activities. RabbitMQ is an Erlang (also well-known for concurrency & speed) implementation of that protocol.

For more please go through RabbitMQ’s website.


Fundamental pieces of RabbitMQ

RabbitMQ has 4 pieces.

  1. Producer (“P”) – Sends messages to an exchange along with “Routing key” indicating how to route the message.
  2. Exchange (“X”) – Receives message and Routing key from Producers and figures out what to do with the message.
  3. Queues(“Q”) – A temporary place where the messages are stored based on Queue’s “binding key” until a consumer is ready to receive the message. Note: While a Queue physically resides inside RabbitMQ, a consumer (“C”) is the one that actually creates it by providing a “Binding Key”.
  4. Consumer(“C”) – Subscribes to a Queue to receive messages.

Routing Key, Binding Key and types of Exchanges

To allow various work-flows like pub-sub, work queues, topics, RPC etc., RabbitMQ allows us to independently configure the type of the Exchange, Routing Key and Binding Key.

Routing Key:

A string/constraint from Producer instructing Exchange how to route the message. A Routing key looks like: “logs”, “errors.logs”, “warnings.logs” “tweets” etc.

Binding Key:

Another string/constraint added by a Consumer to a queue to which it is binding/listening to. A Binding key looks like: “logs”, “*.logs”, “#.logs” etc.

Note: In RabbitMQ, Binding keys can have “patterns” (but not Routing keys).

Types of Exchange:

Exchanges can be of 4 types:

  1. Direct – Sends messages from producer to consumer if Routing Key and Binding key match exactly.
  2. Fanout – Sends any message from a producer to ALL consumers (i.e ignores both routing key & binding key)
  3. Topic – Sends a message from producer to consumer based on pattern-matching.
  4. Headers – If more complicated routing is required beyond simple Routing key string, you can use headers exchange.

In RabbitMQ the combination of the type of Exchange, Routing Key and Binding Key make it behave completely differently. For example: A fanout Exchange ignores Routing Key and Binding Key and sends messages to all queues. A Topic Exchange sends a copy of a message to zero, one or more consumers based on RabbitMQ patterns (#, *).

Going into more details is beyond the scope of this blog, but here is another good blog that goes into more details: AMQP 0-9-1 Model Explained


Using RabbitMQ to do pub-sub in our Node.js chat app.

Now that we know some of the basics of RabbitMQ, and all the 4 pieces, let’s see how to actually use it in our Chat app.

Chat App:

Connecting to RabbitMQ and creating an Exchange

For our chat application, we will create a fanout exchange called chatExchange. And we will be using node-amqp module to talk to RabbitMQ service.

//Connect to RabbitMQ and get reference to the connection.
var rabbitConn = amqp.createConnection({});

//Create an exchange with a name 'chatExchange' and of type 'fanout'
var chatExchange;
rabbitConn.on('ready', function () {
    chatExchange = rabbitConn.exchange('chatExchange', {'type': 'fanout'});
});

Creating Producers (So Users can send chat messages)

In our chat app, users are both producers(i.e. sends chat messages to others) and also consumers (i.e. receives messages from others). Let’s focus on users being ‘producers’.

When a user sends a chat message, publish it to chatExchange w/o a Routing Key (Routing Key doesn’t matter because chatExchange is a ‘fanout’).

/**
     * When a user sends a chat message, publish it to chatExchange w/o a Routing Key (Routing Key doesn't matter
     * because chatExchange is a 'fanout').
     *
     * Notice that we are getting user's name from session.
     */
    socket.on('chat', function (data) {
        var msg = JSON.parse(data);
        var reply = {action: 'message', user: session.user, msg: msg.msg };
        chatExchange.publish('', reply);
    });

Similarly, when a user joins, publish it to chatExchange w/o Routing key.

/**
     * When a user joins, publish it to chatExchange w/o Routing key (Routing doesn't matter
     * because chatExchange is a 'fanout').
     *
     * Note: that we are getting user's name from session.
     */
    socket.on('join', function () {
        var reply = {action: 'control', user: session.user, msg: ' joined the channel' };
        chatExchange.publish('', reply);
    });

Creating Consumers (So Users can receive chat messages)

Creating consumers involves 3 steps:

  1. Create a queue with some options.
  2. Bind queue to exchange using some “Binding Key”
  3. Create a subscriber (usually a callback function) to actually obtain messages sent to the queue.

For our chat app,

  1. Let’s create a queue w/o any name. This forces RabbitMQ to create new queue for every socket.io connection w/ a new random queue name. Let’s also set exclusive flag to ensure only this consumer can access the messages from this queue.
rabbitConn.queue('', {exclusive: true}, function (q) {
 ..
 }
  1. Then bind the queue to chatExchange with an empty ‘Binding key’ and listen to ALL messages.
q.bind('chatExchange', "");
  1. Lastly, create a consumer (via q.subscribe) that waits for messages from RabbitMQ. And when a message comes, send it to the browser.
q.subscribe(function (message) {
   //When a message comes, send it back to browser
   socket.emit('chat', JSON.stringify(message));
 });

Putting it all together.

sessionSockets.on('connection', function (err, socket, session) {
    /**
     * When a user sends a chat message, publish it to chatExchange w/o a Routing Key (Routing Key doesn't matter
     * because chatExchange is a 'fanout').
     *
     * Notice that we are getting user's name from session.
     */
    socket.on('chat', function (data) {
        var msg = JSON.parse(data);
        var reply = {action: 'message', user: session.user, msg: msg.msg };
        chatExchange.publish('', reply);
    });

   /**
     * When a user joins, publish it to chatExchange w/o Routing key (Routing doesn't matter
     * because chatExchange is a 'fanout').
     *
     * Note: that we are getting user's name from session.
     */
    socket.on('join', function () {
        var reply = {action: 'control', user: session.user, msg: ' joined the channel' };
        chatExchange.publish('', reply);
    });


   /**
     * Initialize subscriber queue.
     * 1. First create a queue w/o any name. This forces RabbitMQ to create new queue for every socket.io connection w/ a new random queue name.
     * 2. Then bind the queue to chatExchange  w/ "#" or "" 'Binding key' and listen to ALL messages
     * 3. Lastly, create a consumer (via .subscribe) that waits for messages from RabbitMQ. And when
     * a message comes, send it to the browser.
     *
     * Note: we are creating this w/in sessionSockets.on('connection'..) to create NEW queue for every connection
   */
    rabbitConn.queue('', {exclusive: true}, function (q) {
        //Bind to chatExchange w/ "#" or "" binding key to listen to all messages.
        q.bind('chatExchange', "");

   //Subscribe When a message comes, send it back to browser
        q.subscribe(function (message) {
            socket.emit('chat', JSON.stringify(message));
        });
    });
 });

Running / Testing it on Cloud Foundry

  • Clone this app to rabbitpubsub folder
  • cd rabbitpubsub
  • npm install & follow the below instructions to push the app to Cloud Foundry
[~/success/git/rabbitpubsub]
> vmc push rabbitpubsub
Instances> 4       <----- Run 4 instances of the server

1: node
2: other
Framework> node

1: node
2: node06
3: node08
4: other
Runtime> 3  <---- Choose Node.js 0.8v

1: 64M
2: 128M
3: 256M
4: 512M
Memory Limit> 64M

Creating rabbitpubsub... OK

1: rabbitpubsub.cloudfoundry.com
2: none
URL> rabbitpubsub.cloudfoundry.com  <--- URL of the app (choose something unique)

Updating rabbitpubsub... OK

Create services for application?> y

1: blob 0.51
2: mongodb 2.0
3: mysql 5.1
4: postgresql 9.0
5: rabbitmq 2.4
6: redis 2.6
7: redis 2.4
8: redis 2.2
What kind?> 5 <----- Select & Add RabbitMQ 2.4v service (for pub-sub)

Name?> rabbit-e1223 <-- This is just a random name for RabbitMQ service

Creating service rabbit-e1223... OK
Binding rabbit-e1223 to rabbitpubsub... OK

Create another service?> y

1: blob 0.51
2: mongodb 2.0
3: mysql 5.1
4: postgresql 9.0
5: rabbitmq 2.4
6: redis 2.6
7: redis 2.4
8: redis 2.2
What kind?> 6 <----- Select & Add Redis 2.6v service (for session store)

Name?> redis-e9771 <-- This is just a random name for Redis service

Creating service redis-e9771... OK
Binding redis-e9771 to rabbitpubsub... OK

Bind other services to application?> n

Save configuration?> n

Uploading rabbitpubsub... OK
Starting rabbitpubsub... OK
Checking rabbitpubsub... OK

  • Once the server is up, open up multiple browsers and go to <servername>.cloudfoundry.com
  • Start chatting.

Tests

Test 1

  • While chatting, refresh the browser.
  • You should automatically be logged in.

Test 2

  • Open up JS debugger (On Chrome, do cmd + alt +j )
  • Restart the server by doing vmc restart <appname>
  • Once the server restarts, Socket.io should automatically reconnect
  • You should be able to chat after the reconnection.

That’s it for now. Hopefully this blog helps you get started with using RabbitMQ. Look forward for more Node.js and RabbitMQ related blogs. The content of this blog has also been covered in a video. Feel free to get in touch with us for questions on the material.


General Notes

  • Get the code right away – Github location: https://github.com/rajaraodv/rabbitpubsub.
  • Deploy right away – if you don’t already have a Cloud Foundry account, sign up for it here.
  • Check out Cloud Foundry getting started here and install the vmc Ruby command line tool to push apps.
  • To install the latest alpha or beta vmc tool run: sudo gem install vmc --pre.
Facebook Twitter Linkedin Digg Delicious Reddit Stumbleupon Email

Scaling Real-time Apps on Cloud Foundry Using Node.js and Redis

Common applications being built on Node.js like social networking and chat require real-time scaling capabilities across multiple instances. Developers need to deal with sticky sessions, scale-up, scale-down, instance crash/restart, and more. Cloud Foundry PaaS provides a ready platform to achieve this quickly.

The following blog post will walk you through deploying and managing real-time applications on Cloud Foundry using common Node.js examples and Redis key-value store capabilities.


Chat App

The main objective here is to build a simple chat app while tackling the scale requirements. Specifically, we will be building a simple Express, Socket.io and Redis-based Chat app that meets the following objectives:

  1. Chat server should run with multiple instances.
  2. The user login should be saved in a session.
    • User should be logged back in upon browser refresh
    • Socket.io should get user information from the session before sending chat messages.
    • Socket.io should only connect if user is already logged in.
  3. If the server instance that the user is connected to gets restarted, goes down or is scaled down while the user is chatting, the user should be reconnected to an available instance and recover the session.

Chat app’s Login page:

Chat app’s Chat page:

We will also cover:

  1. How to use Socket.io and Sticky Sessions
  2. How to use Redis as a session store
  3. How to use Redis as a pubsub service
  4. How to use sessions.sockets.io to get session info (like user info) from Express sessions
  5. How to configure Socket.io client and server to properly reconnect after one or more server instances goes down (i.e. has been restarted, scaled down or crashed)

Socket.io & Sticky Sessions

Socket.io is one of the earliest and most popular Node.js modules to help build real-time apps like chat, social networking etc. (Note: SockJS is another popular library similar to Socket.io).

When you run such a server in a cloud that has a load-balancer, reverse proxy, routers etc., it has to be configured to work properly, especially when you scale the server to use multiple instances.

One of the constraints Socket.io, SockJS and similar libraries have is that they need to continuously talk to the same instance of the server. They work perfectly well when there is only 1 instance of the server.

When you scale your app in a cloud environment, the load balancer (Nginx in the case of Cloud Foundry) will take over, and the requests will be sent to different instances causing Socket.io to break.

For such situations, load balancers have a feature called ‘sticky sessions’, also known as ‘session affinity’. The idea is that if this property is set, all the requests following the first load-balanced request will go to the same server instance.

In Cloud Foundry, cookie-based sticky sessions are enabled for apps that set the cookie jsessionid. Note that jsessionid is the cookie name commonly used to track sessions in Java/Spring applications. Cloud Foundry is simply adopting it as the sticky session cookie for all frameworks.

To make socket.io work, the apps just need to set a cookie with the name jsessionid.

/**
* Use cookieParser and session middleware together.
* By default Express/Connect app creates a cookie by name 'connect.sid'. But to scale Socket.io app,
* make sure to use cookie name 'jsessionid' (instead of connect.sid) use Cloud Foundry's 'Sticky Session' feature.
* W/o this, Socket.io won't work when you have more than 1 instance.
* If you are NOT running on Cloud Foundry, having cookie name 'jsessionid' doesn't hurt - it's just a cookie name.
*/
app.use(cookieParser);
app.use(express.session({store:sessionStore, key:'jsessionid', secret:'your secret here'}));

In the above diagram, when you open the app,

  1. Express sets a session cookie with name jsessionid.
  2. When socket.io connects, it uses that same cookie and hits the load balancer
  3. The load balancer always routes it to the same server that the cookie was set in.

Sending session info to Socket.io

Let’s imagine that the user is logging in via Twitter or Facebook, or a regular login screen. We are storing this information in a session after the user has logged in.

app.post('/login', function (req, res) {
    //store user info in session after login.
    req.session.user = req.body.user;
    ...
    ...
});

Once the user has logged in, we connect via socket.io to allow chatting. However, socket.io doesn’t know who the user is and if he or she is actually logged in before sending chat messages to others.

That’s where the sessions.sockets.io library comes in. It’s a very simple library that’s a wrapper around socket.io. All it does is grab session information during the handshake and then pass it to socket.io’s connection function.

//With just Socket.io..
io.sockets.on('connection', function (socket) {
    //do pubsub here
    ...
})

//But with sessions.sockets.io, you'll get session info

/*
 Use SessionSockets so that we can exchange (set/get) user data b/w sockets and http sessions
 Pass 'jsessionid' (custom) cookie name that we are using to make use of Sticky sessions.
 */
var SessionSockets = require('session.socket.io');
var sessionSockets = new SessionSockets(io, sessionStore, cookieParser, 'jsessionid');

sessionSockets.on('connection', function (err, socket, session) {

    //get info from session
    var user = session.user;

    //Close socket if user is not logged in
    if (!user)
        socket.close();

    //do pubsub
    socket.emit('chat', {user: user, msg: 'logged in'});
    ...
});


Redis as a session store

So far so good, but Express stores these sessions in MemoryStore (by default). MemoryStore is simply a Javascript object – it will be in memory as long as the server is up. If the server goes down, all the session information of all users will be lost!

We need a place to store this outside of our server, but it should also be very fast to retrieve. That’s where Redis as a session store come in.

Let’s configure our app to use Redis as a session store as below.

/*
 Use Redis for Session Store. Redis will keep all Express sessions in it.
 */
var redis = require('redis');
var RedisStore = require('connect-redis')(express);
var rClient = redis.createClient();
var sessionStore = new RedisStore({client:rClient});


  //And pass sessionStore to Express's 'session' middleware's 'store' value.
     ...
     ...
app.use(express.session({store: sessionStore, key: 'jsessionid', secret: 'your secret here'}));
     ...

With the above configuration, sessions will now be stored in Redis. Also, if one of the server instances goes down, the session will still be available for other instances to pick up.

Socket.io as pub-sub server

So far our sessions are taken care of with the above setup, but if we are using socket.io’s default pub-sub mechanism, it will work only for 1 sever instance. i.e. if user1 and user2 are on server instance #1, they can both chat with each other. If they are on different server instances, they cannot do so.

sessionSockets.on('connection', function (err, socket, session) {
    socket.on('chat', function (data) {
        socket.emit('chat', data); //send back to browser
        socket.broadcast.emit('chat', data); // send to others
    });

    socket.on('join', function (data) {
        socket.emit('chat', {msg: 'user joined'});
        socket.broadcast.emit('chat', {msg: 'user joined'});
    });
}

Redis as a PubSub service

In order to send chat messages to users across servers we will update our server to use Redis as a PubSub service (along with session store). Redis natively supports pub-sub operations. All we need to do is to create a publisher, a subscriber, and a channel.

//We will use Redis to do pub-sub

/*
 Create two Redis connections. A 'pub' for publishing and a 'sub' for subscribing.
 Subscribe 'sub' connection to 'chat' channel.
 */
var sub = redis.createClient();
var pub = redis.createClient();
sub.subscribe('chat');


sessionSockets.on('connection', function (err, socket, session) {
    socket.on('chat', function (data) {
        pub.publish('chat', data);
   });

    socket.on('join', function (data) {
        pub.publish('chat', {msg: 'user joined'});
    });

    /*
     Use Redis' 'sub' (subscriber) client to listen to any message from Redis to server.
     When a message arrives, send it back to browser using socket.io
     */
    sub.on('message', function (channel, message) {
        socket.emit(channel, message);
    });
}

The app architecture will now look like this:


Handling server scale-down / crashes / restarts

The app will work fine as long as all the server instances are running. What happens if the server is restarted or scaled down or one of the instances crash? How do we handle that?

Let’s first understand what happens in that situation.

The code below simply connects a browser to server and listens to various socket.io events.

/*
  Connect to socket.io on the server (***BEFORE FIX***).
  */
 var host = window.location.host.split(':')[0];
 var socket = io.connect('http://' + host);

 socket.on('connect', function () {
     console.log('connected');
 });
 socket.on('connecting', function () {
     console.log('connecting');
 });
 socket.on('disconnect', function () {
     console.log('disconnect');
 });
 socket.on('connect_failed', function () {
     console.log('connect_failed');
 });
 socket.on('error', function (err) {
     console.log('error: ' + err);
 });
 socket.on('reconnect_failed', function () {
     console.log('reconnect_failed');
 });
 socket.on('reconnect', function () {
     console.log('reconnected ');
 });
 socket.on('reconnecting', function () {
     console.log('reconnecting');
 });

While the user is chatting, if we restart the app on localhost or on a single host, socket.io attempts to reconnect multiple times (based on configuration) to see if it can connect. If the server comes up with in that time, it will reconnect. So we see the below logs:

If we restart the server (say using vmc restart redispubsub) and the user is chatting on the same app that’s running on Cloud Foundry AND with multiple instances, we will see the following log:

You can see that in the above logs, after the server comes back up, socket.io client (running in the browser) isn’t able to connect to socket.io server (running on Node.js in the server).

This is because, once the server is restarted on Cloud Foundry, instances are brought up as if they are brand-new server instances with different IP addresses and different ports and so jsessionid is no-longer valid. That in turn causes the load balancer to load balance socket.io’s reconnection requests (i.e. they are sent to different server instances) causing the socket.io server not to properly handshake and consequently to throw client not handshaken errors!

OK, let’s fix that reconnection issue

First, we will disable socket.io’s default “reconnect” feature, and then implement our own reconnection feature.

In our custom reconnection function, when the server goes down, we’ll make a dummy HTTP-get call to index.html every 4-5 seconds. If the call succeeds, we know that the (Express) server has already set jsessionid in the response. So, then we’ll call socket.io’s reconnect function. This time because jsessionid is set, socket.io’s handshake will succeed and the user can continue to chat without interruption.

/*
 Connect to socket.io on the server (*** FIX ***).
 */
var host = window.location.host.split(':')[0];

//Disable Socket.io's default "reconnect" feature
var socket = io.connect('http://' + host, {reconnect: false, 'try multiple transports': false});
var intervalID;
var reconnectCount = 0;
...
...
socket.on('disconnect', function () {
    console.log('disconnect');

    //Retry reconnecting every 4 seconds
    intervalID = setInterval(tryReconnect, 4000);
});
...
...


/*
 Implement our own reconnection feature.
 When the server goes down we make a dummy HTTP-get call to index.html every 4-5 seconds.
 If the call succeeds, we know that (Express) server sets ***jsessionid*** , so only then we try socket.io reconnect.
 */
var tryReconnect = function () {
    ++reconnectCount;
    if (reconnectCount == 5) {
        clearInterval(intervalID);
    }
    console.log('Making a dummy http call to set jsessionid (before we do socket.io reconnect)');
    $.ajax('/')
        .success(function () {
            console.log("http request succeeded");
            //reconnect the socket AFTER we got jsessionid set
            socket.socket.reconnect();
            clearInterval(intervalID);
        }).error(function (err) {
            console.log("http request failed (probably server not up yet)");
        });
};

In addition, since the jsessionid is invalidated by the load balancer, we can’t create a session with the same jsessionid or else the sticky session will be ignored by the load balancer. So on the server, when the dummy HTTP request comes in, we will regenerate the session to remove the old session and sessionid and ensure everything is afresh before we serve the response.

//Instead of..
exports.index = function (req, res) {
    res.render('index', { title: 'RedisPubSubApp', user: req.session.user});
};

//Use this..
exports.index = function (req, res) {
    //Save user from previous session (if it exists)
    var user = req.session.user;

    //Regenerate new session & store user from previous session (if it exists)
    req.session.regenerate(function (err) {
        req.session.user = user;
        res.render('index', { title: 'RedisPubSubApp', user: req.session.user});
    });
};


Running / Testing it on Cloud Foundry

  • Clone the app to redispubsub folder
  • cd redispubsub
  • npm install and follow the below instructions to push the app to Cloud Foundry
[~/success/git/redispubsub]
> vmc push redispubsub
Instances> 4       <----- Run 4 instances of the server

1: node
2: other
Framework> node

1: node
2: node06
3: node08
4: other
Runtime> 3  <---- Choose Node.js 0.8v

1: 64M
2: 128M
3: 256M
4: 512M
Memory Limit> 64M

Creating redispubsub... OK

1: redispubsub.cloudfoundry.com
2: none
URL> redispubsub.cloudfoundry.com  <--- URL of the app (choose something unique)

Updating redispubsub... OK

Create services for application?> y

1: blob 0.51
2: mongodb 2.0
3: mysql 5.1
4: postgresql 9.0
5: rabbitmq 2.4
6: redis 2.6
7: redis 2.4
8: redis 2.2
What kind?> 6 <----- Select & Add Redis v2.6 service

Name?> redis-e9771 <-- This is just a random name for Redis service

Creating service redis-e9771... OK
Binding redis-e9771 to redispubsub... OK
Create another service?> n

Bind other services to application?> n

Save configuration?> n

Uploading redispubsub... OK
Starting redispubsub... OK
Checking redispubsub... OK

  • Once the server is up, open up multiple browsers and go to <appname>.cloudfoundry.com
  • Start chatting

Test 1

  • Refresh the browser
  • You should automatically be logged in

Test 2

  • Open up JS debugger (in Chrome, do cmd + alt +j)
  • Restart the server by running vmc restart <appname>
  • Once the server restarts, Socket.io should automatically reconnect
  • You should be able to chat after the reconnection

That’s it for this time. Stay tuned for my next blog where I will discuss how RabbitMQ can be leveraged in scalable apps built on Cloud Foundry. The content of this blog has also been covered in a video. Feel free to get in touch with us for questions on the material.

General Notes

  • Get the code right away – Github location: https://github.com/rajaraodv/redispubsub.
  • Deploy right away – if you don’t already have a Cloud Foundry account, sign up for it here.
  • Check out Cloud Foundry getting started here and install the vmc Ruby command line tool to push apps.

  • To install the latest alpha or beta vmc tool run: sudo gem install vmc --pre.

Credits

Front end UI: https://github.com/steffenwt/nodejs-pub-sub-chat-demo

Facebook Twitter Linkedin Digg Delicious Reddit Stumbleupon Email

Cloud Foundry Now Supports Rails Assets Pipeline

Rails version 3.1 introduced the assets pipeline as a way to properly organize and serve static assets. We are adding assets pipeline support for Rails applications deployed on  CloudFoundry.com.

Assets pipeline includes compression, ERB evaluation, Javascript and CSS processing using Rails 3.1 Sprockets library.

In development mode, assets precompilation is not required – Rails turns on live compilation if it can’t find precompiled assets. In production mode, live compilation is disabled by default.

One of the ways to make this work on Cloud Foundry is to bundle assets with your application before you push. Now CloudFoundry.com also provides assets precompilation as one of the steps of application pre-processing.

Bundle assets locally

Rails provides a rake task to compile and bundle assets with your app. You can prepare them locally for production by running:

RAILS_ENV=production bundle exec rake assets:precompile

This task discovers all the assets included in the application, pre-compiles them and saves compiled versions in public/assets directory by default as well as manifest.yml which contains the list of compiled assets with their digest.

Assets compilation on Cloud Foundry

In order to run this in CloudFoundry.com we had to implement some additional pre-processing when the application is staged. First, Cloud Foundry assumes that assets were compiled locally via an assets manifest. If the assets manifest is not found, Cloud Foundry runs the “assets:precompile” rake task during staging. Later, when the application is being run on the DEA (the container for Cloud Foundry apps) we have all the assets. These can be statically served with the digest and other magic that Rails adds to these files.

Live compilation

One potential problem can occur during application initialization. The precompile rake task runs a complete initialization of the Rails application. This might trigger some of the initialization procedures and require service connections and environment checks that are unavailable during staging. You can turn this off by adding a configuration option in application.rb:

config.assets.initialize_on_precompile = false

If the assets:precompile task fails, Cloud Foundry makes use of live compilation mode which is the alternative to assets precompilation. In this mode assets are compiled when they are loaded for the first time. This is done by injecting a plugin to Rails application that forces live compilation process.

Rails.application.config.assets.compile = true

Example

Let’s create a simple Rails application that makes use of CoffeeScript.

rails new coffee-app
cd coffee-app
rails generate controller Hello index

Let’s add some CoffeeScript to app/assets/javascripts/hello.js.coffee file:

name = "CoffeeScript"
alert "Hello from #{ name }!"

If we start our application with “rails server” and browse,

http://localhost:3000/hello/index

we would see “Hello from CoffeeScript!”. This works in development mode without the need for assets precompilation. In production, Rails serves only precompiled static assets and does not fall back to assets pipeline which is disabled in production.rb:

config.assets.compile = false

With the support of assets precompilation we can push this application to CloudFoundry.com without any modifications.

vmc push coffee-app

If we go to http://coffee-app.cloudfoundry.com we would see our popup message as expected.

By taking advantage of these features, your Rails 3.1+ applications will properly precompile all your SASS, Coffee Script and ERB assets as intended.

- Maria Shaldibina
The Cloud Foundry Team

Facebook Twitter Linkedin Digg Delicious Reddit Stumbleupon Email

Recent Changes in Node.js Modules Support

Since Cloud Foundry introduced npm support, we added several improvements that make deploying Node.js applications with dependencies easier, faster and more transparent to developers.

Easy development

When we introduced npm support in Node.js, in addition to generating “npm-shrinkwrap.json” file with locked down dependencies you were required to remove the “node_modules” folder. If this was too disruptive, you could create an “cloudfoundry.json” file with an “ignoreNodeModules” property set to ‘true’.

This wasn’t an obvious solution. So we decided to change it. Detection of native modules is now done automatically by analyzing module contents. To lock down module versions, you can simply use the “npm shrinkwrap” command and your application is ready to be pushed with or without bundled modules. With this change, we have deprecated ignoreNodeModules property.

If you want to store your application in a git repository without node modules, the next time someone clones it, he/she can just push it to CloudFoundry.com without any modifications.

Fast deployment

In addition to  npm, we also improved our cache system. There are two levels of caching now — fetched and compiled modules. All modules that have been fetched from the npm registry are cached locally and pulled from that cache from that point on. If a module contains native code, it gets compiled on Cloud Foundry and the compiled version gets cached as well.

Based on the information from npm-shrinkwrap.json, Cloud Foundry checks if the module has been provided with the application itself. If it is there, and contains native code, it rebuilds it as needed. If the module hasn’t been provided with the app, Cloud Foundry checks the local cache for the given module, and if it needs compilation, provides the cached version.

As module contents can be modified by users, we are using hash of module files as a cache key.

Local modules

There may be situations when you need to customize an existing node module or move a part of your application as a reusable module. In this case, you would want your local module to be used without any modifications and be rebuilt, should it contain native code.

With automatic detection of native code – such modules will be rebuilt on Cloud Foundry and cached, based on their contents for your next push.

More informative logging

In addition to these node improvements, you can now see a detailed log of what’s going on in log files. You can get log messages by running:

vmc logs application-name

We can see if npm support is enabled (npm-shrinkwrap.json was provided) and which node version we are using:

Installing dependencies. Node version 0.6.8

For each node module we can see its installation status:

Installing express@2.5.11 from local path

In case of a failure we can see an error message and/or npm error output.:

Failed installing bcrypt@0.5.0: Node version requirement >= 0.6.0 is not compatible with the current node version 0.4.12

Node-gyp

Modules using node-gyp for the installation process are now supported on CloudFoundry.com for node08 runtime. For node06 and node04 runtimes, Cloud Foundry falls back to node-waf if the module provides the wscript file.

Git URLs

Another recent improvement is that we also support git URLs in npm-shrinkwrap.json. They can be specified in “from” or “version” fields according to npm requirements and both methods are supported. We have a separate cache for git modules and they also get compiled on Cloud Foundry if they have native extensions.

Example

In the previous blog post on auto-reconfiguration we used a Node app, “calipso”,  and performed additional steps for npm support. Let’s see how pushing calipso works now.

First, we clone calipso source from github:

$ git clone git://github.com/cliftonc/calipso.git

Then, we install node modules and lock them down.

$ npm install
$ npm shrinkwrap

Now, we can push our application.

$ vmc push calipso-app --runtime=node08

As we push we add mongodb service and set memory to 256M.

Would you like to deploy from the current directory? [Yn]:
Detected a Node.js Application, is this correct? [Yn]:
Application Deployed URL [calipso-app.cloudfoundry.com]:
Memory reservation (128M, 256M, 512M, 1G, 2G) [64M]: 256M
How many instances? [1]:
Bind existing services to 'calipso-app'? [yN]:
Create services to bind to 'calipso-app'? [yN]: y
  1: blob
  2: mongodb
  3: mysql
  4: postgresql
  5: rabbitmq
  6: redis
What kind of service?: 2
Specify the name of the service [mongodb-62f4d]:
Create another? [yN]:
Would you like to save this configuration? [yN]:
Creating Application: OK
Creating Service [mongodb-62f4d]: OK
Binding Service [mongodb-62f4d]: OK
Uploading Application:
  Checking for available resources: OK
  Processing resources: OK
  Packing application: OK
  Uploading (82K): OK
Push Status: OK
Staging Application 'calipso-app': OK
Starting Application 'calipso-app': OK

That’s it! We didn’t need to configure our application at all. In addition,  notice that staging process was faster and the preparation was effortless. When we look at the logs we can see how everything went. Try it and see how easy it is to manage your dependencies in Node.js applications now.

- Maria Shaldibina
The Cloud Foundry Team

Facebook Twitter Linkedin Digg Delicious Reddit Stumbleupon Email

Deploying to vCloud Using Cloud Foundry BOSH

A new Cloud Provider Interface (CPI) to support deploying Cloud Foundry applications on vCloud infrastructures is available today.

Cloud Foundry was designed and built to support distributed applications that can be moved between multiple clouds running different infrastructures such as vSphere, vCloud, OpenStack and Amazon Web Services.

The key to supporting multiple clouds is Cloud Foundry BOSH, a cloud deployment and lifecycle management tool that was announced earlier this year.

The vCloud CPI is available in the Cloud Foundry BOSH github repository.

The vCloud Director BOSH CPI project joins other Cloud Foundry BOSH community contributions.  The vCloud CPI, like BOSH itself,  is an open source project under the Apache 2 license.

In addition to support from a VMware core engineering team, developer community contributions are welcome.

For more information please refer to the deploying to vCloud Director using BOSH documentation.

Join in on the updates and conversations in the Cloud Foundry BOSH user group.

Anupam Dalal, VMware vCloud engineering team

Facebook Twitter Linkedin Digg Delicious Reddit Stumbleupon Email

Designing Portable Applications With Cloud Foundry

In the cloud computing world, preserving a choice of clouds is critical. The risks of being locked into a single cloud are substantial. Cloud Foundry provides an abstraction layer for deploying and scaling applications and preserves the ability to move between clouds today and into the future.

In this guest blog, Mark Geene and Vineet Joshi, Co-Founders of Cloud Elements, a Cloud Foundry Core application developer, provide guidance on how to design cloud portable applications while not compromising performance or functionality.

Why Portability is Important

We often find that the cloud provider clients select when they first develop their application does not meet latency, uptime or redundancy requirements as their application scales.

We were struck by the experience of one customer who actually saw the incremental costs on their cloud infrastructure provider rapidly increase as their app began to grow due to the additional time, management effort, and expense in setting up servers, managing load balancers and network configuration, and continuously adjusting the application and infrastructure for high availability, redundancy and failover.

In order to change to a more suitable cloud provider this company invested over six months of development effort to unwind proprietary service integrations, including storage management, workflow, and identity management.

Developing your application using open technologies will not guarantee portability when you redeploy your application to another cloud provider. You also need to consider the interaction of these technologies within the infrastructure you select.

RDS and MySQL Interoperability Lessons

We saw this firsthand in working with a client who developed a mobile sales force automation application for the retail industry in India. During the prototyping phase they sought to minimize cost and designed their application using Amazon RDS (Relational Database Service).

As the prototype became a successful product, a number of large retail clients wanted to deploy the application in a private cloud. To their surprise, the MySQL implementation of RDS is proprietary, and migrating the application data wasn’t as simple as exporting data files from RDS and importing these into a private MySQL installation.

Some of the APIs offered by RDS were not available in the open source version of MySQL. In hindsight, they regretted choosing a proprietary service because the migration to a truly open-source version of MySQL cost them nearly two additional months of effort.

Designing Portable Applications – Stories From Customers

Based on experiences like this we’ve developed a process to guide clients in designing portable cloud applications:

  • Select a PaaS first
  • Make portability a key PaaS selection criteria
  • Use PaaS services to drive your cloud application architecture
  • Select value-add application services with portability in mind
  • Loosely couple selected services
  • Select a PaaS First

    Selecting the right PaaS has a significant impact on keeping an application portable. We urge our clients to select their PaaS before they select their IaaS provider — not the other way around. You wouldn’t select your hardware vendor and then the operating system, why would you take this approach in the cloud?

    PaaS is the equivalent of your operating system for cloud applications. It provides a set of capabilities such as application runtimes and database services that are more portable if used at the platform tier than the infrastructure tier. In fact, we’ve avoided the RDS migration issue described above by using a PaaS as the provider of the MySQL database instead of IaaS, even when deploying to AWS.

    Public/Private PaaS Portability

    When we make portability a design criteria for our application, we make it an evaluation criteria in selecting a PaaS.

    Criteria we use in evaluating PaaS portability:

  • Multiple IaaS providers provide public clouds utilizing the PaaS
  • Open-source is available for private and hybrid cloud deployments
  • It provides application management and monitoring capabilities independent of infrastructure management and monitoring
  • For example, we developed an application for a client using Cloud Foundry PaaS deployed on a private cloud. We had two choices 1) use a PaaS that provides the runtimes and services for the application or 2) install, configure and manage these services ourselves. The technology stack for this application included Apache, Java running in a Tomcat container, PostgreSQL for the database and an open source NoSQL database.

    Past experience without a PaaS told us it was two weeks of effort to setup the hardware/OS, install and configure Apache, Tomcat, Java and PostgreSQL before we could even deploy the application. This effort did not include tweaking network, software and hardware configurations in order to ensure the application ran smoothly.

    For this particular client, we chose to deploy the application using Cloud Foundry in a private cloud. The setup, installation, configuration of Cloud Foundry and the deployment of our application to the private cloud took less than a day. More importantly, adding new servers/nodes simply involved replicating virtual machines with this configuration, which took less than a minute.

    This vast saving of time and effort does not even include the countless hours developers spend architecting and fitting their applications to provide functions such as health checks, real-time application management via JMX and integrating the hardware and application monitoring consoles. We were able to achieve all of the above without writing a single extra line of code.

    A few months later, we migrated our client’s applications to a hybrid cloud, i.e., some of the applications continued run in the private cloud, while some were moved to a dedicated Cloud Foundry instance on Rackspace’s cloud infrastructure. The total migration effort was 24 hours based on the portability of our underlying PaaS, Cloud Foundry.

    Strict Separation Between IaaS and PaaS services

    We see clients interested in maximizing the services provided by their public IaaS provider, including some services that cross over into the PaaS tier including storage, data and queuing services. Our advice to these customers is to architect the system to have a strict separation between IaaS and PaaS services to keep these services portable in case they need to move the PaaS layer and application services to another infrastructure provider.

    For these clients we selected a PaaS layer using Cloud Foundry which we used to anchor the cloud application architecture model.

    Figure 1 – The PaaS Tier of Our Cloud Application Architecture Model

    The services provided by Cloud Foundry define the PaaS tier of our model:

    • Application runtime services including Java on Spring, Ruby on Rails and node.js
    • Application management services including application health monitoring and alerting, application resource management and application scaling and deployment management.
    • Data services including PostgreSQL, MySQL, MongoDB and Redis. By persisting application data within data services offered by the PaaS, you increase the portability of your application data vs. persisting data directly to the infrastructure level data service, e.g., Rackspace Cloudfiles or AWS relational Data Service (RDS).
    • Messaging & Queuing services including RabbitMQ. Multiple cloud applications deployed within the same environment often need to communicate with each other. The mechanism for communication between applications should leverage the PaaS Messaging and Queuing services, which again eliminates dependencies on the infrastructure. For example, multiple applications should never use environment variables to communicate with each other, as extra effort is required to migrate such configuration from one IaaS provider to another.

    Use these services at the PaaS level instead of at the Infrastructure level and each of these services will be portable. Every Cloud Foundry Core instance includes the same release version of these services. If you stick with “Core” services your application will be certain to have portability among all Cloud Foundry Core compatible providers.

    Figure 2 – The IaaS Tier Follows Our Selected PaaS Services

    Based on some prototyping and performance testing, we were able to convince one of our customers to leverage a PaaS for the data and storage services. This also served to validate our application architecture model. Within a year this client decided to migrate to a different public cloud infrastructure provider to lower their costs. This layered architecture saved this customer a substantial amount of money by maintaining the architectural separation between the PaaS and IaaS providers for the data and storage services. The only activity we had to perform with the client was to install Cloud Foundry and replicate the application data to the new IaaS provider. This allowed us to migrate the application, services, and data (using Cloud Foundry Tunneling) to the new cloud infrastructure provider in a matter of days, which otherwise could have taken months.

    Social Networking App on AWS Demonstrates Service Integration

    We recently designed a social networking application for a startup customer that required the following application layer services: Payments, SMS Messaging, Email and Facebook/Twitter Integration. The application was to be deployed using Cloud Foundry on Amazon EC2. For each of these services Amazon offered alternatives as did third party SaaS providers.

    We evaluated these application level services, regardless if they’re offered from the IaaS or PaaS provider, like we would services from any third party SaaS provider based on functionality, price, performance and integration capabilities. Consider the implications to portability on your application. Will it be more difficult to migrate from the IaaS vendor if you utilize their other application services versus 3rd party application services that work on any cloud? Consider portability implications across technical, business and contract considerations.

    Integrating SaaS Applications

    When integrating value-add SaaS services into your application ensure a loose coupling between the application and the third party SaaS providers to optimize release management, operational integrity and application portability. The most recommended mechanism to achieve a loose coupling is to ensure that third party providers support RESTful APIs for your application to use and that your application provides a RESTful API for your customers to use.

    For example, we helped one of our customers integrate their SaaS application with two 3rd party cloud services, ServiceNow and Jira. The application provided a bridge between these two services so that external customers could use ServiceNow and the engineering staff could use Jira as the defect tracking tool.

    Jira has a RESTful API and ServiceNow has a tightly coupled interface via a Java JAR. We recommended that our client separate the integration between the SaaS app and ServiceNow into a separate “broker” application. As a result, changes to the vendor’s JAR file did not require any changes to the main application. The broker application provided the main application with a consistent, RESTful API, isolating the application from directly having to consume the Java JAR.

    Summary

    By selecting an open PaaS you significantly increases the probability of developing a portable application. Using a layered, PaaS centric design approach you can increase the portability of your application by limiting the proprietary IaaS services on which your application depends.

    Facebook Twitter Linkedin Digg Delicious Reddit Stumbleupon Email

    Preserving Cloud Application Portability – Introducing Cloud Foundry Core

    The Cloud Foundry team is happy to announce Cloud Foundry Core  -  a program designed to preserve cloud application portability.

    In the cloud computing world, preserving a choice of clouds is critical. The risks of being locked into a single cloud are substantial. Pricing, reliability, geographic location and compliance can all vary between clouds. Business requirements will evolve over time, necessitating the ability to move between clouds, whether public to private, private to public or between public cloud providers.

    Cloud Foundry Core provides a baseline of common capabilities and an open mechanism to instantly validate application portability.

    Cloud Foundry Core defines specific versions for application services and runtimes and introduces a system of current, next, and deprecated to provide access to feature innovation, enhanced performance and greater stability as applications continue to evolve.

    AppFogTier 3Uhuru SoftwareMicro Cloud Foundry™ and CloudFoundry.com are now Core compatible as part of their commitment to preserving cloud portability.

    -Dekel Tankel
    The Cloud Foundry Team

    Facebook Twitter Linkedin Digg Delicious Reddit Stumbleupon Email

    Cloud Application Portability Made Easy – Introducing Cloud Foundry Core

    The Cloud Foundry community is happy to announce Cloud Foundry Core  -  a program designed to make cloud application portability easier than ever. Cloud Foundry Core provides a baseline of common capabilities and an open mechanism to instantly validate application portability. Today we announce five Cloud Foundry Core compatible instances. AppFog, Tier 3, Uhuru Software, Micro Cloud Foundry™ and CloudFoundry.com are now Core compatible as part of their commitment to preserving cloud portability.

    Test your Cloud Foundry Core provider here.

    In the cloud computing world, preserving a choice of clouds is critical. The risks of being locked into a single cloud are substantial. Pricing, reliability, geographic location and compliance can all vary between clouds. Business requirements will evolve over time, necessitating the ability to move between clouds, whether public to private, private to public or between public cloud providers.

    Cloud Foundry Core – the Vehicle for Cloud Portability

    Cloud Foundry Core provides both a baseline of common capabilities and an open mechanism that allows anyone to instantly validate and confirm those capabilities are present on any Cloud Foundry instance. The components of a PaaS offering that applications depend on (runtimes, application services for data access and messaging) form the baseline of common capabilities. Cloud Foundry Core defines specific versions for each of these capabilities. Cloud Foundry Core introduces a system of current, next, and deprecated versions to provide access to feature innovation, enhanced performance and greater stability as application services and runtimes continue to evolve.

    Why Preserving Cloud Portability is Critical

    Preserving cloud portability is imperative in the cloud era. Being locked into a single cloud restricts the ability to respond to changing needs now and in the future. Cloud portability allows movement between providers that better suit pricing needs or can offer better quality of service. It provides the flexibility to pick and choose where to deploy applications based on compliance requirements, data protection laws, and latency constraints.  A choice of public or private clouds is key to adding capacity for managing growth as well as dealing with “cloudbursting” scenarios for optimizing spending.

    Commitment to Cloud Portability

    Cloud Foundry is committed to preserving cloud portability, now and in the future. In this context, it provides an abstraction layer for running applications without the application being aware of where it is executing.  In Cloud Foundry, the components of a PaaS offering that applications depend on (e.g. runtimes, messaging, data access) are built using open development frameworks and technologies (Java, Ruby, Node.js, MongoDB, MySQL, PostgreSQL, RabbitMQ, Redis). Moving applications between Cloud Foundry instances is simple with the vmc command line tool.

    Cloud Foundry Core Providers

    Today we announce five Cloud Foundry Core compatible instances providing developers a choice of deployment destinations.

    Each of the partners below are committed to the Cloud Foundry Core program and preserving cloud application portability now and in the future.

    • AppFog – enables Enterprise and Start-up developers to deploy, manage and scale apps across public, private and hybrid infrastructures
    • CloudFoundry.com – a public instance of Cloud Foundry operated by VMware on vSphere infrastructure
    • Micro Cloud Foundry™ – a complete instance of Cloud Foundry on your own computer
    • Tier 3 – enterprise-grade IaaS and PaaS in one comprehensive platform, with support for global deployments
    • Uhuru Software – the Uhuru AppCloud brings the best of .NET and Open Source together.

    Ultimately Cloud Foundry Core is the focal point for a network of compatible Cloud Foundry instances and distributions to take shape and grow, preserving choice for the developers and consumers of applications.

    Summary

    Cloud Foundry remains as committed as ever to Open PaaS and we appreciate the tremendous support from our ecosystem of partners and strong open source contributions from the developer community. Through Cloud Foundry Core we will continue to deliver on our commitment to preserve cloud application portability.

    Facebook Twitter Linkedin Digg Delicious Reddit Stumbleupon Email

    New Release of Micro Cloud Foundry

    We are excited to announce a new version of Micro Cloud Foundry™ with a new set of features. Among those new features is a new process to streamline frequent updates so that we can maintain compatibility between Micro Cloud Foundry and any Cloud Foundry-based clouds, including CloudFoundry.com.

    If you don’t have a Cloud Foundry
    account yet, sign up here.

    Micro Cloud Foundry is a complete version of the Cloud Foundry open PaaS, but it runs in a single virtual machine on a developer’s computer. Micro Cloud Foundry exemplifies how a multi-cloud approach to PaaS can help developers easily develop and test their applications locally and deploy to any Cloud Foundry-based clouds with no code or configuration changes.

    Download the new Micro Cloud Foundry here.

    In this blog, we will review notable new features and focus on how we will be releasing Micro Cloud Foundry going forward.

    What’s New

    We have a new Micro Cloud Foundry for you to download. Since the release of the last version (1.2), there have been many new features that have been implemented for Cloud Foundry. Now these features have been made available on Micro Cloud Foundry. Let’s review some of them:

    • Standalone apps support: This feature enables a new class of apps including background apps such as Resque workers, apps with bring-your-own-container, and Spring background tasks.
    • Enhanced Ruby support: While Cloud Foundry always offered auto-reconfiguration for relational databases for Ruby apps, we’ve since extended it to all service types, enabling many more applications to deploy to Cloud Foundry without changing a single line of code. We now also offer improved support for Rails 3.1 and 3.2 apps, Rack as a supported framework, the ability to run JRuby apps, and apps that specify git URLs in their Gemfiles along with numerous small improvements to make a much wider range of applications work well in Cloud Foundry.
    • Enhanced Java support: Java 7 support, which enables applications such as vert.x and containers that need NIO such as Netty.
    • Enhanced Scala support: We now offer explicit support for Play 2.0. You can also deploy apps using a Scala framework such as Unfiltered that requires Jetty and Blue Eyes that additionally requires the NIO support in Java 7.
    • Enhanced Node support: We took a comprehensive look at our Node.js support and made a series of improvements to make Node.js apps shine. We now offer NPM support, bringing it up to par with the Gemfile support for Ruby apps including support for packages specified as git URLs. We also offer auto-reconfiguration of all services for node.js apps.

    Download the new Micro Cloud Foundry from the download site. While there, you may notice a few changes, especially the availability of multiple versions and curiously new version names. Let us explain what they mean.

    Going Forward

    One of the ways developers use Micro Cloud Foundry is to deploy applications during development, where Micro Cloud Foundry is used as proving ground. Rather than installing a web server (Tomcat, etc.), runtimes (Java, Ruby, etc.), and services (Postgres, MongoDB, etc.), you can do a single download of Micro Cloud Foundry, boot it up, and deploy your applications using ‘vmc push’. You can run Java and Node.js apps in debug mode, take advantage of JVM hotswap to obviate the need to restart apps after changes, use a shell to access applications and services in the Micro Cloud Foundry VM, and so on. And you could do all this without even being connected to the network thanks to the offline capability of Micro Cloud Foundry (allowing you to develop apps for the cloud while flying through the clouds!).  Once you have your app working, you can push it to CloudFoundry.com, your own in-house Cloud Foundry cloud, or one of Cloud Foundry’s multi-cloud partners.

    For all of this flow to really work, it is imperative that Micro Cloud Foundry has the same functionality as CloudFoundry.com. This means we must continually update Micro Cloud Foundry to keep up with all the new improvements in the core code. Our manual process of building and testing the Micro Cloud Foundry VM simply wouldn’t be up to the task. So we took a hard look at how to make this a better process, starting with this release.

    This is how we will proceed:

    • Frequent releases: We will now release Micro Cloud Foundry whenever a change is pushed to CloudFoundry.com (subject to passing automated testing). If you track the cf-release repository, you will see it tagged with a release version such as v116, v114, and so on. Micro Cloud Foundry versions will match the same tags (along with a timestamp) so you can tell if you need to update Micro Cloud Foundry in order to catch up with changes in CloudFoundry.com. Since the launch over a year ago, we have been updating CloudFoundry.com about twice a week so you can expect a new Micro Cloud Foundry release at the same frequency. Later, we will consider releasing even more frequently for those who want to stay on the bleeding edge.
    • Automated building and testing: In the earlier releases, while we had scripts that would build Micro Cloud Foundry, there was some manual process involved. We also had a QA team testing Micro Cloud Foundry. This was in part necessitated by the requirement to run on multiple platforms (Fusion or Workstation for Mac, Windows, and Linux). Given our desire to update Micro Cloud Foundry bits at the same frequency as CloudFoundry.com, automated building and testing becomes an obvious requirement. We have already automated building Micro Cloud Foundry and doing a basic verification. Over the coming months, we will automate most, if not all, aspects of building, testing, and distributing Micro Cloud Foundry. Of course, Micro Cloud Foundry like the rest of Cloud Foundry, is an open source project, so you can definitely pitch in.
    • Improved user interface: Automated testing requires that the tests be able to configure Micro Cloud Foundry. When we decided to automate building and testing, we realized that while there is a way to do this through the command interface (by directing terminal input and output), it is difficult to make this work in a robust manner. Independent of this, we have been pondering a web interface that will provide an experience similar to a home network router. In a few weeks, we will provide a REST interface to Micro Cloud Foundry along with a web interface replacing the terminal interaction.

    We hope you will like what Micro Cloud Foundry has in store. You can follow our frequent releases on the Micro Cloud Foundry site.

    -Ramnivas Laddad and Matt Boedicker
    The Cloud Foundry Team

    Facebook Twitter Linkedin Digg Delicious Reddit Stumbleupon Email

    Password Policy in Cloud Foundry

    It’s a well-known fact that most users choose weak passwords. Choosing a strong password is actually much harder than it might seem at first. Huge wordlists constructed from previously leaked password databases are readily availably online and we consistently pick passwords which are at or near the top of those lists.

    In a worst-case (but increasingly common) scenario, where the actual database of hashed passwords is stolen, a half-decent cracking program will be able to spit out these weak passwords almost instantly, leading to large numbers of accounts being compromised. This is especially true for simple unsalted password hashes, which companies have been found to be using in some of the recent scandals, despite it being acknowledged as very poor practice for many years. Cloud Foundry stores passwords using bcrypt, which is deliberately designed to hinder password-cracking, but even so, weak passwords are still vulnerable.

    So what can be done to help people choose stronger passwords which are not easily cracked? Some sites have complicated and annoying password policies which force you to include a combination of numbers, symbols and different-case letters in your password, despite the fact that this usually just makes your password hard to remember without actually making it stronger (as depicted in the famous XKCD “correct horse battery staple” cartoon).

    Most users are familiar with the use of password-strength meters. In Cloud Foundry we plan to use a meter not just as a guideline for choosing a good password, but also to define the system policy. So rather than saying “you must satisfy these X annoying rules”, we simply say “you must get this score or higher on the meter”.

    Obviously, the question then arises as to what makes a good “score”. The code we use is based on the calculations from Dan Wheeler’s zxcvbn project (https://github.com/lowe/zxcvbn), which uses a combination of common password dictionaries and checking for patterns such as dates, keyboard sequences (hence the project name) and other typical “bad” password choices. The dropbox tech blog about the project gives an excellent overview of the algorithms used and the rationale for choosing this approach. It’s not perfect – finding a weak password with a reasonable score isn’t too difficult, particularly if you consider languages other than English, but it’s definitely a good start and something we hope to improve on in future releases.

    The main difference is that while the original project is a browser-based Javascript library, we will be using a server-side implementation both to provide feedback and to actually enforce a particular policy. The port of the zxcvbn library, as well as a sample application (both in Scala), are available on github. The sample application is also running on Cloud Foundry at https://szxcvbn.cloudfoundry.com/password.html. You can either use the ajax-enabled UI or directly submit requests to it and get a JSON response. Here’s an example using curl

    $ curl -H "Accept: application/json" -d password=correcthorsebatterystaple https://szxcvbn.cloudfoundry.com/
    

    which returns

    {"score":8,"crack_time_s":2.0372004064749978E9,"match_sequence":[{"start":0,"end":6,"token":"correct","dictName":"english","matchedWord":"correct","rank":1525},{"start":7,"end":11,"token":"horse","dictName":"passwords","matchedWord":"horse","rank":494},{"start":12,"end":18,"token":"battery","dictName":"english","matchedWord":"battery","rank":3845},{"start":19,"end":24,"token":"staple","dictName":"english","matchedWord":"staple","rank":14066}],"crack_time":"63.38 years","entropy":45.21165314373938}
    

    In our production implementation, the interface will only return the score plus the server’s required score (to allow the UI to tell the user how close they are to providing a strong enough password). The sample application is more verbose, providing information on how it has analyzed the supplied password string.

    Facebook Twitter Linkedin Digg Delicious Reddit Stumbleupon Email