Chloe and the RTW      Trotter Cashion    Strange Loop 2011
For thoselooking only  at slides!
Co-Founder
@cashion
github.com/   trotter
Go Get It!http://github.com/mashion/chloe
Why?
Knockout!
simulchart.com
Knockout! Made me cry :-(
We can Haz? http://utterinsanity.files.wordpress.com/2008/09/funny-pictures-cat-drives-an-invisible-racecar.jpg%3Fw%3D497%...
We can Haz? http://utterinsanity.files.wordpress.com/2008/09/funny-pictures-cat-drives-an-invisible-racecar.jpg%3Fw%3D497%...
We can Haz? http://utterinsanity.files.wordpress.com/2008/09/funny-pictures-cat-drives-an-invisible-racecar.jpg%3Fw%3D497%...
Got me thinking...
ChloeA realtime web-server... that doesn’t suck.
Cool History, Right?  http://github.com/mashion/chloe
Usage...A Simple Chat Service
<html>  <head>    <script type="text/javascript" src="/jquery-1.6.4.min.js"></script>    <script type="text/javascript" sr...
<html>  <head>    <script type="text/javascript" src="/jquery-1.6.4.min.js"></script>    <script type="text/javascript" sr...
<html>  <head>    <script type="text/javascript" src="/jquery-1.6.4.min.js"></script>    <script type="text/javascript" sr...
$(function () {  var form = $(form),      container = $(#messages);      chloe = new Chloe({host: localhost, port: 8901});...
$(function () {  var form = $(form),      container = $(#messages);      chloe = new Chloe({host: localhost, port: 8901});...
$(function () {  var form = $(form),      container = $(#messages);      chloe = new Chloe({host: localhost, port: 8901});...
$(function () {  var form = $(form),      container = $(#messages);      chloe = new Chloe({host: localhost, port: 8901});...
$(function () {  var form = $(form),      container = $(#messages);      chloe = new Chloe({host: localhost, port: 8901});...
get / do  erubis :indexendpost /updates do  data = URI.decode_www_form(request.body.read)  params = Hash[data]  uri = URI....
get / do  erubis :indexendpost /updates html from earlier         Get the do  data = URI.decode_www_form(request.body.read...
get / do  erubis :indexend                     chloe.send(form.serialize());post /updates do  data = URI.decode_www_form(r...
get / do  erubis :indexendpost /updates do Ruby trick!  data = URI.decode_www_form(request.body.read)  params = Hash[data]...
get / do  erubis :indexendpost /updates do  data = URI.decode_www_form(request.body.read)  params = Hash[data]  uri = URI....
get / do  erubis :indexendpost /updates do  data = URI.decode_www_form(request.body.read)  params = Hash[data] data to Chl...
How It Works
Chrome
Chrome   Server
Chrome          Server *         *could be Java, Ruby, Scala, Clojure, Node...
Chrome          Server *                 Chloe         *could be Java, Ruby, Scala, Clojure, Node...
Chrome            Server *                 Chloe         GET /           *could be Java, Ruby, Scala, Clojure, Node...
Chrome                Server *               Chloe           GET /         index.html             *could be Java, Ruby, Sc...
Chrome                Server *                Chloe           GET /         index.html          /chloe.js              *co...
Chrome                Server *                Chloe           GET /         index.html          /chloe.js     “Hey Everyon...
Chrome                Server *                Chloe           GET /         index.html          /chloe.js     “Hey Everyon...
Chrome                Server *                Chloe           GET /         index.html          /chloe.js     “Hey Everyon...
Chrome                Server *                Chloe           GET /         index.html          /chloe.js     “Hey Everyon...
FallbacksWebsocketsLong polling (jsonp)Cross domain xhr - SOON!This seems to be enough for now...
Channels
chloe.connect(function () {  chloe.subscribe(chat-room-5, function (message) {    $("#messages").prepend("<li>" + message ...
Channel Namechloe.connect(function () {  chloe.subscribe(chat-room-5, function (message) {    $("#messages").prepend("<li>...
chloe.connect(function () {  chloe.subscribe(chat-room-5, function (message) {    $("#messages").prepend("<li>" + message ...
chloe.connect(function () {  chloe.subscribe(chat-room-5, function (message) {    $("#messages").prepend("<li>" + message ...
chloe.connect(function () {  chloe.subscribe(chat-room-5, function (message) {    $("#messages").prepend("<li>" + message ...
What’s left for Channels Bi-directionality Per Channel callbacks
Performance Difficult to determine...
50                                          50              40                                 33.5Memory (MB)            ...
Tune Your TCP Stack#   ulimit -n 65536#   ifconfig eth0 txqueuelen 8192#   /sbin/sysctl -w net.core.somaxconn=4096#   /sbi...
Tune Your TCP Stack#   ulimit -n 65536#   ifconfig eth0 txqueuelen 8192#   /sbin/sysctl -w net.core.somaxconn=4096#       ...
Tune Your TCP Stack#   ulimit -n 65536#   ifconfig eth0 txqueuelen 8192#   /sbin/sysctl -w net.core.somaxconn=4096#   /sbi...
Tune Your TCP Stack#   ulimit -n 65536#   ifconfig eth0 txqueuelen 8192#   /sbin/sysctl -w net.core.somaxconn=4096#   /sbi...
Tune Your TCP Stack#   ulimit -n 65536#   ifconfig eth0 txqueuelen 8192#   /sbin/sysctl -w net.core.somaxconn=4096#   /sbi...
Tune Your TCP Stack#   ulimit -n 65536#   ifconfig eth0 txqueuelen 8192#   /sbin/sysctl -w net.core.somaxconn=4096#   /sbi...
Tune Your TCP Stack#   ulimit -n 65536#   ifconfig eth0 txqueuelen 8192#   /sbin/sysctl -w net.core.somaxconn=4096#   /sbi...
Tune Your TCP Stack#   ulimit -n 65536#   ifconfig eth0 txqueuelen 8192#   /sbin/sysctl -w net.core.somaxconn=4096#   /sbi...
Tune Your TCP Stack#   ulimit -n 65536#   ifconfig eth0 txqueuelen 8192#   /sbin/sysctl -w net.core.somaxconn=4096#   /sbi...
How much Overhead?
How much Overhead?       ?
Up and Running
Binaries AvailableMac, Ubuntu 32bit, Ubuntu 64bitFully self-contained (Erlang included).deb and .rpm will be coming soon...
It’s Easy!#   wget http://bit.ly/oqyQfL#   tar xzvf chloe-0.0.3-osx.tgz#   cd chloe-0.0.3#   ./bin/chloe start#   ./bin/ch...
It’s Easy!#   wget http://bit.ly/oqyQfL#   tar xzvf chloe-0.0.3-osx.tgz#   cd chloe-0.0.3#   ./bin/chloe start#   ./bin/ch...
It’s Easy!#   wget http://bit.ly/oqyQfL#   tar xzvf chloe-0.0.3-osx.tgz#   cd chloe-0.0.3#   ./bin/chloe start#   ./bin/ch...
It’s Easy!#   wget http://bit.ly/oqyQfL#   tar xzvf chloe-0.0.3-osx.tgz#   cd chloe-0.0.3#   ./bin/chloe start#   ./bin/ch...
It’s Easy!#   wget http://bit.ly/oqyQfL#   tar xzvf chloe-0.0.3-osx.tgz#   cd chloe-0.0.3#   ./bin/chloe start#   ./bin/ch...
./etc/app.config{chloe,  [     {application_server, "http://localhost:4567"},     {application_server_url, "http://localho...
./etc/app.config{chloe,                For XHR  [     {application_server, "http://localhost:4567"},     {application_serv...
./etc/app.config{chloe,  [        Callback url on your application     {application_server, "http://localhost:4567"},     ...
./etc/app.config{chloe,  [                  Chloe port     {application_server, "http://localhost:4567"},     {application...
./etc/app.config{chloe,  [                          Where Chloe’s JavaScript Lives     {application_server, "http://localh...
./etc/app.config{chloe,  [     {application_server, "http://localhost:4567"},                            Directory for Log...
./etc/app.config{chloe,  [     {application_server, "http://localhost:4567"},     {application_server_url, "http://localho...
Signing RequestsSECRET = "SEKRET PASSFRASE”post /updates do  data = URI.decode_www_form(request.body.read)  message = Hash...
Signing RequestsSECRET = "SEKRET PASSFRASE”post /updates do  data = URI.decode_www_form(request.body.read)  message = Hash...
Signing RequestsSECRET = "SEKRET PASSFRASE”post /updates do             From ./etc/app.config  data = URI.decode_www_form(...
Signing RequestsSECRET = "SEKRET PASSFRASE”post /updates do                   Concat t wo strings  data = URI.decode_www_f...
Signing RequestsSECRET = "SEKRET PASSFRASE”post /updates do                      Hash them  data = URI.decode_www_form(req...
Signing RequestsSECRET = "SEKRET PASSFRASE”post /updates do  data = URI.decode_www_form(request.body.read)  message = Hash...
If `secret` is in yourconfig, all requests to`/send` must be signed
Coming SoonImproved PerformanceBi-directional channelsPer-channel callback urlsRuntime configurationSSL Support
Coming LaterImproved monitoringExplore switch to mochiweb internallyClient side authentication
InternalsErlang Nerdery Time!
Session Manager       TransportsYaws        Callback                    Sessions                    Channel Store
Session Manager       TransportsYaws        Callback                    Sessions                    Channel Store
Session Manager       TransportsYaws        Callback                    Sessions                    Channel Store
Session Manager       TransportsYaws        Callback                    Sessions                    Channel Store
Session Manager       TransportsYaws        Callback                    Sessions                    Channel Store
SessionYaws   Websocket                   Manager   Session
Session     Yaws   Websocket                        Manager   SessionBrowser
Session     Yaws      Websocket                           Manager   SessionBrowser          New Conn
Session     Yaws      Websocket                            Manager   SessionBrowser          New Conn                     ...
Session     Yaws      Websocket                             Manager   SessionBrowser          New Conn                    ...
Session     Yaws      Websocket                             Manager   SessionBrowser          New Conn                    ...
Session     Yaws      Websocket                             Manager   SessionBrowser          New Conn                    ...
ChannelYaws    Store    Session   Websocket
Channel     Yaws    Store    Session   WebsocketServer
Channel     Yaws        Store    Session   WebsocketServer         Sessions?
Channel     Yaws         Store    Session   WebsocketServer         Sessions?         Session Pid
Channel     Yaws         Store    Session   WebsocketServer         Sessions?         Session Pid                Message!
Channel     Yaws         Store    Session    WebsocketServer         Sessions?         Session Pid                Message!...
Channel     Yaws         Store    Session    WebsocketServer         Sessions?         Session Pid                Message!...
Message Structure{ data,  version,  type,  channel,  id,  sessionId}
Message Structure{ data,  version,  type,The message itself  channel,  id,  sessionId}
Message Structure{ data,  version,  type,        Version of the message protocol  channel,  id,  sessionId}
Message Structure{ data,  version,  type,  channel,        Four types: connect, message,  id,               channel-subscr...
Message Structure{ data,  version,  type,  channel,  id,  sessionId the message is going        Where}
Message Structure{ data,  version,  type,  channel,  id,  sessionId}       No Idea...
Message Structure{ data,  version,  type,  channel,  id,  sessionId}       Session id for connection
Please Go Play With It http://github.com/mashion/chloe http://mashion.net http://trottercashion.com @cashion
Moved to Mountain View        Be my friend?
Thank You! Good luck w/ Chloe
Chloe and the Realtime Web
Upcoming SlideShare
Loading in...5
×

Chloe and the Realtime Web

1,239

Published on

This is my Chloe talk

Published in: Technology, Design
0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
1,239
On Slideshare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
8
Comments
0
Likes
1
Embeds 0
No embeds

No notes for slide

Chloe and the Realtime Web

  1. 1. Chloe and the RTW Trotter Cashion Strange Loop 2011
  2. 2. For thoselooking only at slides!
  3. 3. Co-Founder
  4. 4. @cashion
  5. 5. github.com/ trotter
  6. 6. Go Get It!http://github.com/mashion/chloe
  7. 7. Why?
  8. 8. Knockout!
  9. 9. simulchart.com
  10. 10. Knockout! Made me cry :-(
  11. 11. We can Haz? http://utterinsanity.files.wordpress.com/2008/09/funny-pictures-cat-drives-an-invisible-racecar.jpg%3Fw%3D497%26h%3D318
  12. 12. We can Haz? http://utterinsanity.files.wordpress.com/2008/09/funny-pictures-cat-drives-an-invisible-racecar.jpg%3Fw%3D497%26h%3D318
  13. 13. We can Haz? http://utterinsanity.files.wordpress.com/2008/09/funny-pictures-cat-drives-an-invisible-racecar.jpg%3Fw%3D497%26h%3D318
  14. 14. Got me thinking...
  15. 15. ChloeA realtime web-server... that doesn’t suck.
  16. 16. Cool History, Right? http://github.com/mashion/chloe
  17. 17. Usage...A Simple Chat Service
  18. 18. <html>  <head>    <script type="text/javascript" src="/jquery-1.6.4.min.js"></script>  <script type="text/javascript" src="http://localhost:8901/chloe.js"> </script>    <script type="text/javascript" src="/chat.js"></script>    <title>Ajax Chat</title>  </head>  <body>    <form>      <input name="message" id="message" type="text"/>      <input name="submit" type="submit" value="Send"/>    </form>    <ul id="messages"></ul>  </body></html>
  19. 19. <html>  <head>    <script type="text/javascript" src="/jquery-1.6.4.min.js"></script>  <script type="text/javascript" src="http://localhost:8901/chloe.js"> </script>    <script type="text/javascript" src="/chat.js"></script>    <title>Ajax Chat</title>  </head> Include Chloe JS  <body>    <form>      <input name="message" id="message" type="text"/>      <input name="submit" type="submit" value="Send"/>    </form>    <ul id="messages"></ul>  </body></html>
  20. 20. <html>  <head>    <script type="text/javascript" src="/jquery-1.6.4.min.js"></script>  <script type="text/javascript" src="http://localhost:8901/chloe.js"> </script>    <script type="text/javascript" src="/chat.js"></script>    <title>Ajax Chat</title>  </head>  <body>    <form> Include Your JS      <input name="message" id="message" type="text"/>      <input name="submit" type="submit" value="Send"/>    </form>    <ul id="messages"></ul>  </body></html>
  21. 21. $(function () {  var form = $(form),      container = $(#messages);      chloe = new Chloe({host: localhost, port: 8901});  chloe.connect(function () {    form.submit(function () {      chloe.send(form.serialize());      $(#message).val();      return false;    });    chloe.onmessage(function (message) {      container.prepend("<li>" + message + "</li>");    });  });});
  22. 22. $(function () {  var form = $(form),      container = $(#messages);      chloe = new Chloe({host: localhost, port: 8901});  chloe.connect(function () {    form.submit(function Instantiate () { Chloe      chloe.send(form.serialize());      $(#message).val();      return false;    });    chloe.onmessage(function (message) {      container.prepend("<li>" + message + "</li>");    });  });});
  23. 23. $(function () {  var form = $(form),      container = $(#messages);      chloe = new Chloe({host: localhost, port: 8901});  chloe.connect(function () {    form.submit(function () {      chloe.send(form.serialize());      $(#message).val(); Server Connect to the      return false;    });    chloe.onmessage(function (message) {      container.prepend("<li>" + message + "</li>");    });  });});
  24. 24. $(function () {  var form = $(form),      container = $(#messages);      chloe = new Chloe({host: localhost, port: 8901});  chloe.connect(function () {    form.submit(function () {      chloe.send(form.serialize());      $(#message).val();      return false;    }); Send data to the server    chloe.onmessage(function (message) {      container.prepend("<li>" + message + "</li>");    });  });});
  25. 25. $(function () {  var form = $(form),      container = $(#messages);      chloe = new Chloe({host: localhost, port: 8901});  chloe.connect(function () {    form.submit(function () {      chloe.send(form.serialize());      $(#message).val();      return false; this function when Run a message arrives    });    chloe.onmessage(function (message) {      container.prepend("<li>" + message + "</li>");    });  });});
  26. 26. get / do  erubis :indexendpost /updates do  data = URI.decode_www_form(request.body.read) params = Hash[data] uri = URI.parse("http://localhost:8901/send")  Net::HTTP.post_form(uri,                {"data" => params["message"]})  okend
  27. 27. get / do  erubis :indexendpost /updates html from earlier Get the do  data = URI.decode_www_form(request.body.read) params = Hash[data] uri = URI.parse("http://localhost:8901/send")  Net::HTTP.post_form(uri,                {"data" => params["message"]})  okend
  28. 28. get / do  erubis :indexend chloe.send(form.serialize());post /updates do  data = URI.decode_www_form(request.body.read) params = Hash[data] uri = URI.parse("http://localhost:8901/send")  Net::HTTP.post_form(uri,                {"data" => params["message"]})  okend
  29. 29. get / do  erubis :indexendpost /updates do Ruby trick!  data = URI.decode_www_form(request.body.read) params = Hash[data] uri = URI.parse("http://localhost:8901/send")  Net::HTTP.post_form(uri,                {"data" => params["message"]})  okend
  30. 30. get / do  erubis :indexendpost /updates do  data = URI.decode_www_form(request.body.read) params = Hash[data] uri = URI.parse("http://localhost:8901/send")  Net::HTTP.post_form(uri,                {"data" => params["message"]}) Chloe broadcast/multicast url  okend
  31. 31. get / do  erubis :indexendpost /updates do  data = URI.decode_www_form(request.body.read) params = Hash[data] data to Chloe Send the uri = URI.parse("http://localhost:8901/send")  Net::HTTP.post_form(uri,                {"data" => params["message"]})  okend
  32. 32. How It Works
  33. 33. Chrome
  34. 34. Chrome Server
  35. 35. Chrome Server * *could be Java, Ruby, Scala, Clojure, Node...
  36. 36. Chrome Server * Chloe *could be Java, Ruby, Scala, Clojure, Node...
  37. 37. Chrome Server * Chloe GET / *could be Java, Ruby, Scala, Clojure, Node...
  38. 38. Chrome Server * Chloe GET / index.html *could be Java, Ruby, Scala, Clojure, Node...
  39. 39. Chrome Server * Chloe GET / index.html /chloe.js *could be Java, Ruby, Scala, Clojure, Node...
  40. 40. Chrome Server * Chloe GET / index.html /chloe.js “Hey Everyone” *could be Java, Ruby, Scala, Clojure, Node...
  41. 41. Chrome Server * Chloe GET / index.html /chloe.js “Hey Everyone” POST /updates “Hey Everyone” *could be Java, Ruby, Scala, Clojure, Node...
  42. 42. Chrome Server * Chloe GET / index.html /chloe.js “Hey Everyone” POST /updates “Hey Everyone” POST /send “Hey Everyone” *could be Java, Ruby, Scala, Clojure, Node...
  43. 43. Chrome Server * Chloe GET / index.html /chloe.js “Hey Everyone” POST /updates “Hey Everyone” POST /send “Hey Everyone” “Hey Everyone” *could be Java, Ruby, Scala, Clojure, Node...
  44. 44. FallbacksWebsocketsLong polling (jsonp)Cross domain xhr - SOON!This seems to be enough for now...
  45. 45. Channels
  46. 46. chloe.connect(function () {  chloe.subscribe(chat-room-5, function (message) {    $("#messages").prepend("<li>" + message + "</li>")  });});post /updates do  uri = URI.parse("http://localhost:8901/send")  Net::HTTP.post_form(uri,       { "data" => "Hello room!", "channel" => "chat-room-5"})  "ok"end
  47. 47. Channel Namechloe.connect(function () {  chloe.subscribe(chat-room-5, function (message) {    $("#messages").prepend("<li>" + message + "</li>")  });});post /updates do  uri = URI.parse("http://localhost:8901/send")  Net::HTTP.post_form(uri,       { "data" => "Hello room!", "channel" => "chat-room-5"})  "ok"end
  48. 48. chloe.connect(function () {  chloe.subscribe(chat-room-5, function (message) {    $("#messages").prepend("<li>" + message + "</li>")  });}); Called when message arrivespost /updates do  uri = URI.parse("http://localhost:8901/send")  Net::HTTP.post_form(uri,       { "data" => "Hello room!", "channel" => "chat-room-5"})  "ok"end
  49. 49. chloe.connect(function () {  chloe.subscribe(chat-room-5, function (message) {    $("#messages").prepend("<li>" + message + "</li>")  });});post /updates do  uri = URI.parse("http://localhost:8901/send")  Net::HTTP.post_form(uri,       { "data" => "Hello room!", "channel" => "chat-room-5"})  "ok"end
  50. 50. chloe.connect(function () {  chloe.subscribe(chat-room-5, function (message) {    $("#messages").prepend("<li>" + message + "</li>")  });});post /updates do  uri = URI.parse("http://localhost:8901/send")  Net::HTTP.post_form(uri,       { "data" => "Hello room!", "channel" => "chat-room-5"})  "ok"end Channel for broadcast
  51. 51. What’s left for Channels Bi-directionality Per Channel callbacks
  52. 52. Performance Difficult to determine...
  53. 53. 50 50 40 33.5Memory (MB) 30 20 17 10 0 0 500 1000 Sessions
  54. 54. Tune Your TCP Stack# ulimit -n 65536# ifconfig eth0 txqueuelen 8192# /sbin/sysctl -w net.core.somaxconn=4096# /sbin/sysctl -w net.core.netdev_max_backlog=16384# /sbin/sysctl -w net.core.rmem_max=16777216# /sbin/sysctl -w net.core.wmem_max=16777216# /sbin/sysctl -w net.ipv4.tcp_max_syn_backlog=8192# /sbin/sysctl -w net.ipv4.tcp_syncookies=1 From cometd: http://cometd.org/documentation/2.x/howtos/loadtesting
  55. 55. Tune Your TCP Stack# ulimit -n 65536# ifconfig eth0 txqueuelen 8192# /sbin/sysctl -w net.core.somaxconn=4096# Increase number of file descriptors /sbin/sysctl -w net.core.netdev_max_backlog=16384# /sbin/sysctl -w net.core.rmem_max=16777216# /sbin/sysctl -w net.core.wmem_max=16777216# /sbin/sysctl -w net.ipv4.tcp_max_syn_backlog=8192# /sbin/sysctl -w net.ipv4.tcp_syncookies=1 From cometd: http://cometd.org/documentation/2.x/howtos/loadtesting
  56. 56. Tune Your TCP Stack# ulimit -n 65536# ifconfig eth0 txqueuelen 8192# /sbin/sysctl -w net.core.somaxconn=4096# /sbin/sysctl -w net.core.netdev_max_backlog=16384# Increase transaction queue length /sbin/sysctl -w net.core.rmem_max=16777216# /sbin/sysctl -w net.core.wmem_max=16777216# /sbin/sysctl -w net.ipv4.tcp_max_syn_backlog=8192# /sbin/sysctl -w net.ipv4.tcp_syncookies=1 From cometd: http://cometd.org/documentation/2.x/howtos/loadtesting
  57. 57. Tune Your TCP Stack# ulimit -n 65536# ifconfig eth0 txqueuelen 8192# /sbin/sysctl -w net.core.somaxconn=4096# /sbin/sysctl -w net.core.netdev_max_backlog=16384# /sbin/sysctl -w net.core.rmem_max=16777216# Increase size of listen queue /sbin/sysctl -w net.core.wmem_max=16777216# /sbin/sysctl -w net.ipv4.tcp_max_syn_backlog=8192# /sbin/sysctl -w net.ipv4.tcp_syncookies=1 From cometd: http://cometd.org/documentation/2.x/howtos/loadtesting
  58. 58. Tune Your TCP Stack# ulimit -n 65536# ifconfig eth0 txqueuelen 8192# /sbin/sysctl -w net.core.somaxconn=4096# /sbin/sysctl -w net.core.netdev_max_backlog=16384# /sbin/sysctl -w net.core.rmem_max=16777216# /sbin/sysctl -w net.core.wmem_max=16777216# Increase incoming packet queue /sbin/sysctl -w net.ipv4.tcp_max_syn_backlog=8192# /sbin/sysctl -w net.ipv4.tcp_syncookies=1 From cometd: http://cometd.org/documentation/2.x/howtos/loadtesting
  59. 59. Tune Your TCP Stack# ulimit -n 65536# ifconfig eth0 txqueuelen 8192# /sbin/sysctl -w net.core.somaxconn=4096# /sbin/sysctl -w net.core.netdev_max_backlog=16384# /sbin/sysctl -w net.core.rmem_max=16777216# /sbin/sysctl -w net.core.wmem_max=16777216# /sbin/sysctl -w net.ipv4.tcp_max_syn_backlog=8192# /sbin/sysctl Increase maximum receive window -w net.ipv4.tcp_syncookies=1 From cometd: http://cometd.org/documentation/2.x/howtos/loadtesting
  60. 60. Tune Your TCP Stack# ulimit -n 65536# ifconfig eth0 txqueuelen 8192# /sbin/sysctl -w net.core.somaxconn=4096# /sbin/sysctl -w net.core.netdev_max_backlog=16384# /sbin/sysctl -w net.core.rmem_max=16777216# /sbin/sysctl -w net.core.wmem_max=16777216# /sbin/sysctl -w net.ipv4.tcp_max_syn_backlog=8192# /sbin/sysctl -w net.ipv4.tcp_syncookies=1 Increase send window From cometd: http://cometd.org/documentation/2.x/howtos/loadtesting
  61. 61. Tune Your TCP Stack# ulimit -n 65536# ifconfig eth0 txqueuelen 8192# /sbin/sysctl -w net.core.somaxconn=4096# /sbin/sysctl -w net.core.netdev_max_backlog=16384# /sbin/sysctl -w net.core.rmem_max=16777216# /sbin/sysctl -w net.core.wmem_max=16777216# /sbin/sysctl -w net.ipv4.tcp_max_syn_backlog=8192# /sbin/sysctl -w net.ipv4.tcp_syncookies=1 How many SYN requests to keep in memory From cometd: http://cometd.org/documentation/2.x/howtos/loadtesting
  62. 62. Tune Your TCP Stack# ulimit -n 65536# ifconfig eth0 txqueuelen 8192# /sbin/sysctl -w net.core.somaxconn=4096# /sbin/sysctl -w net.core.netdev_max_backlog=16384# /sbin/sysctl -w net.core.rmem_max=16777216# /sbin/sysctl -w net.core.wmem_max=16777216# /sbin/sysctl -w net.ipv4.tcp_max_syn_backlog=8192# /sbin/sysctl -w net.ipv4.tcp_syncookies=1 Makes tcp_max_syn_backlog work From cometd: http://cometd.org/documentation/2.x/howtos/loadtesting
  63. 63. How much Overhead?
  64. 64. How much Overhead? ?
  65. 65. Up and Running
  66. 66. Binaries AvailableMac, Ubuntu 32bit, Ubuntu 64bitFully self-contained (Erlang included).deb and .rpm will be coming soon...
  67. 67. It’s Easy!# wget http://bit.ly/oqyQfL# tar xzvf chloe-0.0.3-osx.tgz# cd chloe-0.0.3# ./bin/chloe start# ./bin/chloe stop
  68. 68. It’s Easy!# wget http://bit.ly/oqyQfL# tar xzvf chloe-0.0.3-osx.tgz# cd chloe-0.0.3# ./bin/chloe start# ./bin/chloe stop
  69. 69. It’s Easy!# wget http://bit.ly/oqyQfL# tar xzvf chloe-0.0.3-osx.tgz# cd chloe-0.0.3# ./bin/chloe start# ./bin/chloe stop
  70. 70. It’s Easy!# wget http://bit.ly/oqyQfL# tar xzvf chloe-0.0.3-osx.tgz# cd chloe-0.0.3# ./bin/chloe start# ./bin/chloe stop
  71. 71. It’s Easy!# wget http://bit.ly/oqyQfL# tar xzvf chloe-0.0.3-osx.tgz# cd chloe-0.0.3# ./bin/chloe start# ./bin/chloe stop
  72. 72. ./etc/app.config{chloe, [ {application_server, "http://localhost:4567"}, {application_server_url, "http://localhost:4567/updates"}, {port, 8901}, {doc_root, "./public"}, {log_dir, "/var/log/chloe"}, {secret, “SEKRET PASSFRASE”} ]}
  73. 73. ./etc/app.config{chloe, For XHR [ {application_server, "http://localhost:4567"}, {application_server_url, "http://localhost:4567/updates"}, {port, 8901}, {doc_root, "./public"}, {log_dir, "/var/log/chloe"}, {secret, “SEKRET PASSFRASE”} ]}
  74. 74. ./etc/app.config{chloe, [ Callback url on your application {application_server, "http://localhost:4567"}, {application_server_url, "http://localhost:4567/updates"}, {port, 8901}, {doc_root, "./public"}, {log_dir, "/var/log/chloe"}, {secret, “SEKRET PASSFRASE”} ]}
  75. 75. ./etc/app.config{chloe, [ Chloe port {application_server, "http://localhost:4567"}, {application_server_url, "http://localhost:4567/updates"}, {port, 8901}, {doc_root, "./public"}, {log_dir, "/var/log/chloe"}, {secret, “SEKRET PASSFRASE”} ]}
  76. 76. ./etc/app.config{chloe, [ Where Chloe’s JavaScript Lives {application_server, "http://localhost:4567"}, {application_server_url, "http://localhost:4567/updates"}, {port, 8901}, {doc_root, "./public"}, {log_dir, "/var/log/chloe"}, {secret, “SEKRET PASSFRASE”} ]}
  77. 77. ./etc/app.config{chloe, [ {application_server, "http://localhost:4567"}, Directory for Logs {application_server_url, "http://localhost:4567/updates"}, {port, 8901}, {doc_root, "./public"}, {log_dir, "/var/log/chloe"}, {secret, “SEKRET PASSFRASE”} ]}
  78. 78. ./etc/app.config{chloe, [ {application_server, "http://localhost:4567"}, {application_server_url, "http://localhost:4567/updates"}, {port, 8901}, {doc_root, "./public"}, {log_dir, "/var/log/chloe"}, {secret, “SEKRET PASSFRASE”} ]} For security (not required)...
  79. 79. Signing RequestsSECRET = "SEKRET PASSFRASE”post /updates do  data = URI.decode_www_form(request.body.read) message = Hash[data]["message"] sig = Digest::MD5.hexdigest(message + SECRET) uri = URI.parse("http://localhost:8901/send")  Net::HTTP.post_form(uri,             {"data" => message, "sig" => sig})  okend
  80. 80. Signing RequestsSECRET = "SEKRET PASSFRASE”post /updates do  data = URI.decode_www_form(request.body.read) message = Hash[data]["message"] sig = Digest::MD5.hexdigest(message + SECRET) uri = URI.parse("http://localhost:8901/send")  Net::HTTP.post_form(uri,             {"data" => message, "sig" => sig})  okend
  81. 81. Signing RequestsSECRET = "SEKRET PASSFRASE”post /updates do From ./etc/app.config  data = URI.decode_www_form(request.body.read) message = Hash[data]["message"] sig = Digest::MD5.hexdigest(message + SECRET) uri = URI.parse("http://localhost:8901/send")  Net::HTTP.post_form(uri,             {"data" => message, "sig" => sig})  okend
  82. 82. Signing RequestsSECRET = "SEKRET PASSFRASE”post /updates do Concat t wo strings  data = URI.decode_www_form(request.body.read) message = Hash[data]["message"] sig = Digest::MD5.hexdigest(message + SECRET) uri = URI.parse("http://localhost:8901/send")  Net::HTTP.post_form(uri,             {"data" => message, "sig" => sig})  okend
  83. 83. Signing RequestsSECRET = "SEKRET PASSFRASE”post /updates do Hash them  data = URI.decode_www_form(request.body.read) message = Hash[data]["message"] sig = Digest::MD5.hexdigest(message + SECRET) uri = URI.parse("http://localhost:8901/send")  Net::HTTP.post_form(uri,             {"data" => message, "sig" => sig})  okend
  84. 84. Signing RequestsSECRET = "SEKRET PASSFRASE”post /updates do  data = URI.decode_www_form(request.body.read) message = Hash[data]["message"] sig = Digest::MD5.hexdigest(message + SECRET) uri = URI.parse("http://localhost:8901/send")  Net::HTTP.post_form(uri,             {"data" => message, "sig" => sig})  okend Add signature to request
  85. 85. If `secret` is in yourconfig, all requests to`/send` must be signed
  86. 86. Coming SoonImproved PerformanceBi-directional channelsPer-channel callback urlsRuntime configurationSSL Support
  87. 87. Coming LaterImproved monitoringExplore switch to mochiweb internallyClient side authentication
  88. 88. InternalsErlang Nerdery Time!
  89. 89. Session Manager TransportsYaws Callback Sessions Channel Store
  90. 90. Session Manager TransportsYaws Callback Sessions Channel Store
  91. 91. Session Manager TransportsYaws Callback Sessions Channel Store
  92. 92. Session Manager TransportsYaws Callback Sessions Channel Store
  93. 93. Session Manager TransportsYaws Callback Sessions Channel Store
  94. 94. SessionYaws Websocket Manager Session
  95. 95. Session Yaws Websocket Manager SessionBrowser
  96. 96. Session Yaws Websocket Manager SessionBrowser New Conn
  97. 97. Session Yaws Websocket Manager SessionBrowser New Conn Session?
  98. 98. Session Yaws Websocket Manager SessionBrowser New Conn Session? Session Pid
  99. 99. Session Yaws Websocket Manager SessionBrowser New Conn Session? Session Pid Message!
  100. 100. Session Yaws Websocket Manager SessionBrowser New Conn Session? Session Pid Message! Server
  101. 101. ChannelYaws Store Session Websocket
  102. 102. Channel Yaws Store Session WebsocketServer
  103. 103. Channel Yaws Store Session WebsocketServer Sessions?
  104. 104. Channel Yaws Store Session WebsocketServer Sessions? Session Pid
  105. 105. Channel Yaws Store Session WebsocketServer Sessions? Session Pid Message!
  106. 106. Channel Yaws Store Session WebsocketServer Sessions? Session Pid Message! Message!
  107. 107. Channel Yaws Store Session WebsocketServer Sessions? Session Pid Message! Message! Browser
  108. 108. Message Structure{ data, version, type, channel, id, sessionId}
  109. 109. Message Structure{ data, version, type,The message itself channel, id, sessionId}
  110. 110. Message Structure{ data, version, type, Version of the message protocol channel, id, sessionId}
  111. 111. Message Structure{ data, version, type, channel, Four types: connect, message, id, channel-subscribe, poll sessionId}
  112. 112. Message Structure{ data, version, type, channel, id, sessionId the message is going Where}
  113. 113. Message Structure{ data, version, type, channel, id, sessionId} No Idea...
  114. 114. Message Structure{ data, version, type, channel, id, sessionId} Session id for connection
  115. 115. Please Go Play With It http://github.com/mashion/chloe http://mashion.net http://trottercashion.com @cashion
  116. 116. Moved to Mountain View Be my friend?
  117. 117. Thank You! Good luck w/ Chloe
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×