===== Upgrades ===== ==== Implementation checklist ==== === P1 === 1) turn off stick sessions for chat. \\ Reconfigure haproxy to remove ACL which implements sticky sessions by directing chat requests to a specific app server 2) Test. 3) Test more. === P2 ==== ** Recent development : It has been observed that XHR calls to chat role are taking too long, still waiting for more data to take a decision on investigation. The out come might change this phase. ** * Downtime required * 0) Add one more CPU core to the server hosting chat role. 1) Spawn another node.js instance on port 8011. 2) Reconfigure Haprxoy to use this new chat role for LB. 3) Test. === P3 ==== 1) Replace current node.js instance with newer version. 2( Archive current app and deploy new Juggernaut app (which support 0.10) 3) Test === P4 === 1) Enable websockets on node.js (already enabled in P3). 2) Reconfigure timeouts in haproxy. 3) Reload haproxy and test. ==== Load balance Chat Role ==== Tested load balancing on DEV. \\ Encountered issues but bypassed using headers and TCP mode in LB. \\ Two separate instances of application, load balanced via haproxy for two separate unsticky node.js instances. ==== Upgrade Node ==== NPM + Websocket support. Faster. Security Patches. After some code changes, was able to execute Juggernaut over node.js 0.10.29. ==== Use WebSockets ==== ===== Original Implementation ===== Chat is implemented using the ruby Juggernaut library (https://github.com/maccman/juggernaut). Setting up the necessary components for chat Install Node.js wget http://nodejs.org/dist/node-v0.2.4.tar.gz tar -xzvf node-v0.2.4.tar.gz cd node-v0.2.4 ./configure make sudo make install Install Redis wget http://redis.googlecode.com/files/redis-2.0.3.tar.gz tar -xzvf redis-2.0.3.tar.gz cd redis-2.0.3 make make install Running Start Redis cd redis-2.0.3 ./redis-server redis.conf Download Juggernaut, and start the Juggernaut server: git clone git://github.com/maccman/juggernaut.git --recursive cd juggernaut node server.js Please note that node.js server and the redis server should be running for the chat to be working. In case , if you see any js errors on starting juggernut server , you can try updating the node to latest version. By default the server runs on port 8080. If you need to change the port then change the line in server.js (Juggernaut.listen();)file and pass the port number to the listen function. After this install the necessary gems (Only on application servers). From the application home directory run bundle install (Install the bundler gem first, if it's not installed: "sudo gem install bundler") ====== Open Issues ====== - The chat contents as well as window opened is not retained across different page requests. i.e. when the user navigates to another page the chat windows are lost. The chat window is now being retained across page requests, however the data is not being retained. - There is no tracking or user presence at present. The user list shows all the users in the system for now, even though the user may not really be online. This is being taken care now. As soon as some user comes online the chat user list get updated and similarly when a user goes offline the user gets removed from chat list. - The contents/history of chat is not stored anywhere. Chat history is now being maintained for a session. ====== Maintain Chat History ====== The immediate goal is to maintain the chat transcript across page request. The larger goal is to maintain the Chat History based on session and user. i.e. A user should be able to see a list of chat transcripts grouped by Session and within it grouped by user. In order to maintain the chat transcripts across page requests the message data will be stored in a cache. The data layout of the chat cache will looks as below. It is nothing but a hash (set of key/value pairs). Each user will have his own cache key. #user 1 and 2 are also part of a group called 5 #message data for user 1 "1" => { "2_User" => { #chat transcripts between user 1 and 2 :type => 'User', :messages => [ {:message_text => 'xxx', :type => 'received',:image => '/path/to/profile/image'}, {:message_text => 'yyyy', :type => 'sent',:image => '/path/to/profile/image'} ] }, "5_Group" => { #chat transcripts that user 1 has as part of messages sent and received to the group :type => 'Group', :messages => [ {:message_text => 'hello group', :type => 'sent',:image => '/path/to/profile/image'}, {:message_text => 'hi group', :type => 'received',:image => '/path/to/profile/image'} ] } }, #message data for user 2 "2" => { "1_User" => { :type => 'User', :messages => [ {:message_text => 'xxx', :type => 'sent',:image => '/path/to/profile/image'}, {:message_text => 'yyyy', :type => 'received',:image => '/path/to/profile/image'} ] }, "5_Group" => { :type => 'Group', :messages => [ {:message_text => 'hello group', :type => 'received',:image => '/path/to/profile/image'}, {:message_text => 'hi group', :type => 'received',:image => '/path/to/profile/image'} ] } } ====== Server side activities ====== * When a chat message is sent the "send_message" action of ChatsController is called. * When any message is sent (in the send_message action) we know have the information about the user who sent the message and the user/group who is going to receive the message. * The "Send_message" action will now update the chat history cache with the above information. Basically when a message is sent we update 2 hashes - 1) the hash corresponding the user who sent the message 2) The hash corresponding the the user who will receive the message. If the message is being sent to a group then the hash corresponding to all the online members of the group will be updated. * Clear the chat data from cache for the user when the user logs out. ====== Client Side activities ====== * When a chat window is closed we hide the chat window instead of removing the window from the DOM. This will ensure that data at client side is not lost when the user initiates the chat with the user who's window he had just closed. * When a new page is requested, we send the data corresponding the the current user from the chat cache in json format along with the response. * At present the UI of the chat windows that were open is being built across request, just the chat data does not get retained. Now the response will have the chat data in form of JSON will will be used to update the UI of chat window. At present the chat cache for a user gets cleared under following circumstances - When user clicks on Logout - A rufus tasks keeps running every 5 minutes which checks whether the users for whom the chat history is cached is currently online or not. If not, then clear it cache for the user. ===== Open Items ===== - Persist the Chat data to database just before the cache is cleared. ===== Upgrading chat server to latest version ===== We need to update socket.io to version 8+ to have some connection related issues fixed. So, for the entire chat setup to work fine, the following this need to be upgraded. 1) Remove the current nodejs setup. 2) Install latest juggernaut, nodejs and redis. (Base Reference - https://github.com/maccman/juggernaut) a) Upgrading python - (version - 2.7.3) http://toomuchdata.com/2012/06/25/how-to-install-python-2-7-3-on-centos-6-2/ **Note** - This can have some effects on system packages on gnome machines. Please make sure they do not break. b) Nodejs setup (install any version - 0.8.1 + ) Instructions - https://github.com/joyent/node/wiki/Installation Download page - http://nodejs.org/download/ (install from source code) c) Redis Download & Instructions - http://redis.io/download d) Juggernaut - npm install -g juggernaut **Testing** - Start the redis service as in the instructions above. - To srart juggernaut juggernat --port - Open http://localhost: you should see a page with message 'connected to chanel1'