- Presentation
- Running the Web application
- Deploying the infrastructure
- Running the experiment scenario
- Our feedback
This project is two things:
- a modern web application built with state-of-the-art tools and practices
- a cloud-like infrastructure allowing updates without service interruption
A simple chat application built with Nodejs/Express, Angular, SockJS, Mocha, Chai, WebDriverJS, Redis... Bootstrapped from Yearofmoo's AngularJS Seed: A starter AngularJS repository for getting started with AngularJS.
Everything has been coded with several tests first, at least one test by "layer" concerned (server, client) and one end-to-end test. This process was a bit dumb (some things were tested several times) on purpose, to force us in using all tools we wanted to discover (namely: Grunt, Karma and Protractor).
### Cloud-like infrastructureThe goal is to allow deploying web application updates without service interruption (not yet fully achieved, see Note below).
The main components are:
- HAProxy: Front proxy allowing loadbalancing
- Our web application tchatter running on Nodejs
- Redis: a key-value store, with publish/subscribe capabilities, allowing several app instances to share messages
Each component is embedded in a Docker container. To run Docker containers, easily, and independently to the user computer, a Virtualbox VM is run with Vagrant, based on Ubuntu 14.04
As shown in the following architecture diagram, the HAProxy container is connected to N webapp containers, which are connected to a single redis container.
Being part of one of our bi-annual free sessions at Stormshield, we built it with a specific demonstration scenario in mind. Indeed, we populated our chat with "Reservoir Dogs" characters who automatically talked to each other (implemented with an ugly addition in the client part of the app, as time was running out).
We were in an extreme prototyping mood with direct feedback, therefore tests have clearly been left behind :)
## Running the Web application ### PrerequisitesInstall NodeJS/Npm Install Redis or use the Redis container provided by the infrastructure part
### Installationnpm install -g grunt-cli
npm install
grunt install
grunt dev
- Go to:
http://localhost:8080
grunt test
grunt autotest
Run tests automatically when files change
grunt test:client
grunt autotest:client
grunt test:server
grunt autotest:server
grunt test:e2e
grunt autotest:e2e
npm run package
Install:
- Vagrant
- Ansible
- Launch the production environment with
npm run deploy
-
Open 6 different browser windows. A browser window must be attributed a unique user among: Mr Pink, Mr Blue, Mr White, Mr Brown, Mr Orange and Mr Blonde. You may have to clear cookies and refresh the page.
-
Start the discussion by entering "begin" message in Mr Blue's window. The discussion should now go on between the 6 windows.
-
Modify the version of the application: lib/message.js line 3
-
Deploy the new tchatter web application version with rolling update
npm run deploy
-
You can monitor node health on http://localhost:8888/stats
-
You should see application version in browser window change from 1 to 2 (if you choose 2 as new version). The discussion still goes on, as service was not interrupted
Note: As previously mentioned, there is still a service interruption. On service restart, there is a disconnection/reconnection for each browser client (the websocket is recreated):
- the client displays that inadequate information because the disconnection event comes from the server, not the client
- all messages sent by other clients meanwhile are lost for the disconnected client. Upon reconnection, the client should ask for the missing messages.
Angular: Our web app is not complex enough to have a clear opinion. The double databinding is quite spectacular, but comes at a price: we lost control of the view part, which can be regained at an expensive cost (directives).
Protractor: Can launch many browsers, but only works for angular applications. Besides, it instruments the application, thus changing our tests to white box mode (for instance, it refuses to launch tests while there is a "setInterval" activity). Instead, we directly used WebDriverJS.
SockJS: cool stuff :)
Grunt: nice tool!
Docker: Remember, a container is a process, not a VM! For instance, it is of no use to "ssh" into a container.
Ansible: rolling updates mechanism is not applicable to docker containers. Ansible allows to loop on hosts, but containers are not regular hosts (because of the previous point). Our solution here.
Redis: simple pub/sub channels implementation. That said, in our case, we would need some mechanism to ensure no messages are lost if there is no consumer.