SlideShare ist ein Scribd-Unternehmen logo
1 von 118
Downloaden Sie, um offline zu lesen
Chloe and the RTW
      Trotter Cashion
    Strange Loop 2011
For those
looking 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%26h%3D318
We can Haz?
 http://utterinsanity.files.wordpress.com/2008/09/funny-pictures-cat-drives-an-invisible-racecar.jpg%3Fw%3D497%26h%3D318
We can Haz?
 http://utterinsanity.files.wordpress.com/2008/09/funny-pictures-cat-drives-an-invisible-racecar.jpg%3Fw%3D497%26h%3D318
Got me thinking...
Chloe
A 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" 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>
<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>
<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>
$(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>");
    });
  });

});
$(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>");
    });
  });

});
$(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>");
    });
  });

});
$(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>");
    });
  });

});
$(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>");
    });
  });

});
get '/' do
  erubis :index
end

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"]})
  'ok'
end
get '/' do
  erubis :index
end

post '/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"]})
  'ok'
end
get '/' do
  erubis :index
end
                     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"]})
  'ok'
end
get '/' do
  erubis :index
end

post '/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"]})
  'ok'
end
get '/' do
  erubis :index
end

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"]})
        Chloe broadcast/multicast url
  'ok'
end
get '/' do
  erubis :index
end

post '/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"]})
  'ok'
end
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, Scala, Clojure, Node...
Chrome                Server *                Chloe
           GET /
         index.html
          /chloe.js




              *could be Java, Ruby, Scala, Clojure, Node...
Chrome                Server *                Chloe
           GET /
         index.html
          /chloe.js
     “Hey Everyone”




              *could be Java, Ruby, Scala, Clojure, Node...
Chrome                Server *                Chloe
           GET /
         index.html
          /chloe.js
     “Hey Everyone”
                      POST /updates “Hey Everyone”




              *could be Java, Ruby, Scala, Clojure, Node...
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...
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...
Fallbacks

Websockets
Long 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 + "</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 Name
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
chloe.connect(function () {
  chloe.subscribe('chat-room-5', function (message) {
    $("#messages").prepend("<li>" + message + "</li>")
  });
});
                   Called when message arrives


post '/updates' do
  uri = URI.parse("http://localhost:8901/send")
  Net::HTTP.post_form(uri,
       { "data" => "Hello room!",
         "channel" => "chat-room-5"})
  "ok"
end
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
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
What’s left for Channels


 Bi-directionality
 Per Channel callbacks
Performance
 Difficult to determine...
50
                                          50



              40


                                 33.5
Memory (MB)




              30


              20
                       17

              10


              0
                   0         500        1000
                            Sessions
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
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
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
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
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
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
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
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
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
How much Overhead?
How much Overhead?


       ?
Up and Running
Binaries Available

Mac, Ubuntu 32bit, Ubuntu 64bit
Fully 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/chloe stop
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
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
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
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
./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”}
  ]}
./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”}
  ]}
./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”}
  ]}
./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”}
  ]}
./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”}
  ]}
./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”}
  ]}
./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)...
Signing Requests
SECRET = "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})
  'ok'
end
Signing Requests
SECRET = "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})
  'ok'
end
Signing Requests
SECRET = "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})
  'ok'
end
Signing Requests
SECRET = "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})
  'ok'
end
Signing Requests
SECRET = "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})
  'ok'
end
Signing Requests
SECRET = "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})
  'ok'
end
                   Add signature to request
If `secret` is in your
config, all requests to
`/send` must be signed
Coming Soon
Improved Performance
Bi-directional channels
Per-channel callback urls
Runtime configuration
SSL Support
Coming Later

Improved monitoring
Explore switch to mochiweb internally
Client side authentication
Internals
Erlang Nerdery Time!
Session Manager
       Transports
Yaws
        Callback
                    Sessions




                    Channel Store
Session Manager
       Transports
Yaws
        Callback
                    Sessions




                    Channel Store
Session Manager
       Transports
Yaws
        Callback
                    Sessions




                    Channel Store
Session Manager
       Transports
Yaws
        Callback
                    Sessions




                    Channel Store
Session Manager
       Transports
Yaws
        Callback
                    Sessions




                    Channel Store
Session
Yaws   Websocket
                   Manager   Session
Session
     Yaws   Websocket
                        Manager   Session
Browser
Session
     Yaws      Websocket
                           Manager   Session
Browser
          New Conn
Session
     Yaws      Websocket
                            Manager   Session
Browser
          New Conn
                      Session?
Session
     Yaws      Websocket
                             Manager   Session
Browser
          New Conn
                      Session?
                     Session Pid
Session
     Yaws      Websocket
                             Manager   Session
Browser
          New Conn
                      Session?
                     Session Pid

                            Message!
Session
     Yaws      Websocket
                             Manager   Session
Browser
          New Conn
                      Session?
                     Session Pid

                            Message!
                                            Server
Channel
Yaws    Store    Session   Websocket
Channel
     Yaws    Store    Session   Websocket

Server
Channel
     Yaws        Store    Session   Websocket

Server
         Sessions?
Channel
     Yaws         Store    Session   Websocket

Server
         Sessions?
         Session Pid
Channel
     Yaws         Store    Session   Websocket

Server
         Sessions?
         Session Pid
                Message!
Channel
     Yaws         Store    Session    Websocket

Server
         Sessions?
         Session Pid
                Message!
                                Message!
Channel
     Yaws         Store    Session    Websocket

Server
         Sessions?
         Session Pid
                Message!
                                Message!
                                           Browser
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-subscribe, poll
  sessionId
}
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

Weitere ähnliche Inhalte

Was ist angesagt?

Consul ou comment bien tirer sur l’élastique
 Consul ou comment bien tirer sur l’élastique Consul ou comment bien tirer sur l’élastique
Consul ou comment bien tirer sur l’élastiqueNicolas Ledez
 
Async. and Realtime Geo Applications with Node.js
Async. and Realtime Geo Applications with Node.jsAsync. and Realtime Geo Applications with Node.js
Async. and Realtime Geo Applications with Node.jsShoaib Burq
 
Introducing ruby on rails
Introducing ruby on railsIntroducing ruby on rails
Introducing ruby on railsPriceen
 
The promise of asynchronous php
The promise of asynchronous phpThe promise of asynchronous php
The promise of asynchronous phpWim Godden
 
Introduction to ECMAScript 2015
Introduction to ECMAScript 2015Introduction to ECMAScript 2015
Introduction to ECMAScript 2015Tomasz Dziuda
 
Asynchronous PHP and Real-time Messaging
Asynchronous PHP and Real-time MessagingAsynchronous PHP and Real-time Messaging
Asynchronous PHP and Real-time MessagingSteve Rhoades
 
Apache CouchDB talk at Ontario GNU Linux Fest
Apache CouchDB talk at Ontario GNU Linux FestApache CouchDB talk at Ontario GNU Linux Fest
Apache CouchDB talk at Ontario GNU Linux FestMyles Braithwaite
 
Zepto.js, a jQuery-compatible mobile JavaScript framework in 2K
Zepto.js, a jQuery-compatible mobile JavaScript framework in 2KZepto.js, a jQuery-compatible mobile JavaScript framework in 2K
Zepto.js, a jQuery-compatible mobile JavaScript framework in 2KThomas Fuchs
 
My app is secure... I think
My app is secure... I thinkMy app is secure... I think
My app is secure... I thinkWim Godden
 
React PHP: the NodeJS challenger
React PHP: the NodeJS challengerReact PHP: the NodeJS challenger
React PHP: the NodeJS challengervanphp
 
An opinionated intro to Node.js - devrupt hospitality hackathon
An opinionated intro to Node.js - devrupt hospitality hackathonAn opinionated intro to Node.js - devrupt hospitality hackathon
An opinionated intro to Node.js - devrupt hospitality hackathonLuciano Mammino
 
Symfony: Your Next Microframework (SymfonyCon 2015)
Symfony: Your Next Microframework (SymfonyCon 2015)Symfony: Your Next Microframework (SymfonyCon 2015)
Symfony: Your Next Microframework (SymfonyCon 2015)Ryan Weaver
 
ZeroMQ: Messaging Made Simple
ZeroMQ: Messaging Made SimpleZeroMQ: Messaging Made Simple
ZeroMQ: Messaging Made SimpleIan Barber
 
Interceptors: Into the Core of Pedestal
Interceptors: Into the Core of PedestalInterceptors: Into the Core of Pedestal
Interceptors: Into the Core of PedestalKent Ohashi
 
Stubる - Mockingjayを使ったHTTPクライアントのテスト -
Stubる - Mockingjayを使ったHTTPクライアントのテスト -Stubる - Mockingjayを使ったHTTPクライアントのテスト -
Stubる - Mockingjayを使ったHTTPクライアントのテスト -Kenji Tanaka
 

Was ist angesagt? (20)

Server Side Swift: Vapor
Server Side Swift: VaporServer Side Swift: Vapor
Server Side Swift: Vapor
 
Consul ou comment bien tirer sur l’élastique
 Consul ou comment bien tirer sur l’élastique Consul ou comment bien tirer sur l’élastique
Consul ou comment bien tirer sur l’élastique
 
Async. and Realtime Geo Applications with Node.js
Async. and Realtime Geo Applications with Node.jsAsync. and Realtime Geo Applications with Node.js
Async. and Realtime Geo Applications with Node.js
 
Introducing ruby on rails
Introducing ruby on railsIntroducing ruby on rails
Introducing ruby on rails
 
A Gentle Introduction to Event Loops
A Gentle Introduction to Event LoopsA Gentle Introduction to Event Loops
A Gentle Introduction to Event Loops
 
JavaScript Promise
JavaScript PromiseJavaScript Promise
JavaScript Promise
 
The promise of asynchronous php
The promise of asynchronous phpThe promise of asynchronous php
The promise of asynchronous php
 
Introduction to ECMAScript 2015
Introduction to ECMAScript 2015Introduction to ECMAScript 2015
Introduction to ECMAScript 2015
 
Asynchronous PHP and Real-time Messaging
Asynchronous PHP and Real-time MessagingAsynchronous PHP and Real-time Messaging
Asynchronous PHP and Real-time Messaging
 
Apache CouchDB talk at Ontario GNU Linux Fest
Apache CouchDB talk at Ontario GNU Linux FestApache CouchDB talk at Ontario GNU Linux Fest
Apache CouchDB talk at Ontario GNU Linux Fest
 
Zepto.js, a jQuery-compatible mobile JavaScript framework in 2K
Zepto.js, a jQuery-compatible mobile JavaScript framework in 2KZepto.js, a jQuery-compatible mobile JavaScript framework in 2K
Zepto.js, a jQuery-compatible mobile JavaScript framework in 2K
 
My app is secure... I think
My app is secure... I thinkMy app is secure... I think
My app is secure... I think
 
React PHP: the NodeJS challenger
React PHP: the NodeJS challengerReact PHP: the NodeJS challenger
React PHP: the NodeJS challenger
 
Play á la Rails
Play á la RailsPlay á la Rails
Play á la Rails
 
An opinionated intro to Node.js - devrupt hospitality hackathon
An opinionated intro to Node.js - devrupt hospitality hackathonAn opinionated intro to Node.js - devrupt hospitality hackathon
An opinionated intro to Node.js - devrupt hospitality hackathon
 
Symfony: Your Next Microframework (SymfonyCon 2015)
Symfony: Your Next Microframework (SymfonyCon 2015)Symfony: Your Next Microframework (SymfonyCon 2015)
Symfony: Your Next Microframework (SymfonyCon 2015)
 
ZeroMQ: Messaging Made Simple
ZeroMQ: Messaging Made SimpleZeroMQ: Messaging Made Simple
ZeroMQ: Messaging Made Simple
 
Interceptors: Into the Core of Pedestal
Interceptors: Into the Core of PedestalInterceptors: Into the Core of Pedestal
Interceptors: Into the Core of Pedestal
 
Stubる - Mockingjayを使ったHTTPクライアントのテスト -
Stubる - Mockingjayを使ったHTTPクライアントのテスト -Stubる - Mockingjayを使ったHTTPクライアントのテスト -
Stubる - Mockingjayを使ったHTTPクライアントのテスト -
 
Solr @ Etsy - Apache Lucene Eurocon
Solr @ Etsy - Apache Lucene EuroconSolr @ Etsy - Apache Lucene Eurocon
Solr @ Etsy - Apache Lucene Eurocon
 

Andere mochten auch

LXC, Docker, and the future of software delivery | LinuxCon 2013
LXC, Docker, and the future of software delivery | LinuxCon 2013LXC, Docker, and the future of software delivery | LinuxCon 2013
LXC, Docker, and the future of software delivery | LinuxCon 2013dotCloud
 
Blazes: coordination analysis for distributed programs
Blazes: coordination analysis for distributed programsBlazes: coordination analysis for distributed programs
Blazes: coordination analysis for distributed programspalvaro
 
Hyperdex - A closer look
Hyperdex - A closer lookHyperdex - A closer look
Hyperdex - A closer lookDECK36
 
Riak Search - Erlang Factory London 2010
Riak Search - Erlang Factory London 2010Riak Search - Erlang Factory London 2010
Riak Search - Erlang Factory London 2010Rusty Klophaus
 
ElasticSearch - index server used as a document database
ElasticSearch - index server used as a document databaseElasticSearch - index server used as a document database
ElasticSearch - index server used as a document databaseRobert Lujo
 
(Functional) reactive programming (@pavlobaron)
(Functional) reactive programming (@pavlobaron)(Functional) reactive programming (@pavlobaron)
(Functional) reactive programming (@pavlobaron)Pavlo Baron
 
Complex Legacy System Archiving/Data Retention with MongoDB and Xquery
Complex Legacy System Archiving/Data Retention with MongoDB and XqueryComplex Legacy System Archiving/Data Retention with MongoDB and Xquery
Complex Legacy System Archiving/Data Retention with MongoDB and XqueryDATAVERSITY
 
Spring Cleaning for Your Smartphone
Spring Cleaning for Your SmartphoneSpring Cleaning for Your Smartphone
Spring Cleaning for Your SmartphoneLookout
 
Web-Oriented Architecture (WOA)
Web-Oriented Architecture (WOA)Web-Oriented Architecture (WOA)
Web-Oriented Architecture (WOA)thetechnicalweb
 
In Pursuit of the Holy Grail: Building Isomorphic JavaScript Apps
In Pursuit of the Holy Grail: Building Isomorphic JavaScript AppsIn Pursuit of the Holy Grail: Building Isomorphic JavaScript Apps
In Pursuit of the Holy Grail: Building Isomorphic JavaScript AppsSpike Brehm
 
Scalable XQuery Processing with Zorba on top of MongoDB
Scalable XQuery Processing with Zorba on top of MongoDBScalable XQuery Processing with Zorba on top of MongoDB
Scalable XQuery Processing with Zorba on top of MongoDBWilliam Candillon
 
Interoperability With RabbitMq
Interoperability With RabbitMqInteroperability With RabbitMq
Interoperability With RabbitMqAlvaro Videla
 
Erlang plus BDB: Disrupting the Conventional Web Wisdom
Erlang plus BDB: Disrupting the Conventional Web WisdomErlang plus BDB: Disrupting the Conventional Web Wisdom
Erlang plus BDB: Disrupting the Conventional Web Wisdomguest3933de
 
Shrinking the Haystack" using Solr and OpenNLP
Shrinking the Haystack" using Solr and OpenNLPShrinking the Haystack" using Solr and OpenNLP
Shrinking the Haystack" using Solr and OpenNLPlucenerevolution
 
Scaling Gilt: from Monolithic Ruby Application to Distributed Scala Micro-Ser...
Scaling Gilt: from Monolithic Ruby Application to Distributed Scala Micro-Ser...Scaling Gilt: from Monolithic Ruby Application to Distributed Scala Micro-Ser...
Scaling Gilt: from Monolithic Ruby Application to Distributed Scala Micro-Ser...C4Media
 
AST - the only true tool for building JavaScript
AST - the only true tool for building JavaScriptAST - the only true tool for building JavaScript
AST - the only true tool for building JavaScriptIngvar Stepanyan
 
Erlang as a cloud citizen, a fractal approach to throughput
Erlang as a cloud citizen, a fractal approach to throughputErlang as a cloud citizen, a fractal approach to throughput
Erlang as a cloud citizen, a fractal approach to throughputPaolo Negri
 
Pregel: A System for Large-Scale Graph Processing
Pregel: A System for Large-Scale Graph ProcessingPregel: A System for Large-Scale Graph Processing
Pregel: A System for Large-Scale Graph ProcessingChris Bunch
 

Andere mochten auch (20)

LXC, Docker, and the future of software delivery | LinuxCon 2013
LXC, Docker, and the future of software delivery | LinuxCon 2013LXC, Docker, and the future of software delivery | LinuxCon 2013
LXC, Docker, and the future of software delivery | LinuxCon 2013
 
Brunch With Coffee
Brunch With CoffeeBrunch With Coffee
Brunch With Coffee
 
Blazes: coordination analysis for distributed programs
Blazes: coordination analysis for distributed programsBlazes: coordination analysis for distributed programs
Blazes: coordination analysis for distributed programs
 
Hyperdex - A closer look
Hyperdex - A closer lookHyperdex - A closer look
Hyperdex - A closer look
 
Riak Search - Erlang Factory London 2010
Riak Search - Erlang Factory London 2010Riak Search - Erlang Factory London 2010
Riak Search - Erlang Factory London 2010
 
ElasticSearch - index server used as a document database
ElasticSearch - index server used as a document databaseElasticSearch - index server used as a document database
ElasticSearch - index server used as a document database
 
(Functional) reactive programming (@pavlobaron)
(Functional) reactive programming (@pavlobaron)(Functional) reactive programming (@pavlobaron)
(Functional) reactive programming (@pavlobaron)
 
Complex Legacy System Archiving/Data Retention with MongoDB and Xquery
Complex Legacy System Archiving/Data Retention with MongoDB and XqueryComplex Legacy System Archiving/Data Retention with MongoDB and Xquery
Complex Legacy System Archiving/Data Retention with MongoDB and Xquery
 
Spring Cleaning for Your Smartphone
Spring Cleaning for Your SmartphoneSpring Cleaning for Your Smartphone
Spring Cleaning for Your Smartphone
 
NkSIP: The Erlang SIP application server
NkSIP: The Erlang SIP application serverNkSIP: The Erlang SIP application server
NkSIP: The Erlang SIP application server
 
Web-Oriented Architecture (WOA)
Web-Oriented Architecture (WOA)Web-Oriented Architecture (WOA)
Web-Oriented Architecture (WOA)
 
In Pursuit of the Holy Grail: Building Isomorphic JavaScript Apps
In Pursuit of the Holy Grail: Building Isomorphic JavaScript AppsIn Pursuit of the Holy Grail: Building Isomorphic JavaScript Apps
In Pursuit of the Holy Grail: Building Isomorphic JavaScript Apps
 
Scalable XQuery Processing with Zorba on top of MongoDB
Scalable XQuery Processing with Zorba on top of MongoDBScalable XQuery Processing with Zorba on top of MongoDB
Scalable XQuery Processing with Zorba on top of MongoDB
 
Interoperability With RabbitMq
Interoperability With RabbitMqInteroperability With RabbitMq
Interoperability With RabbitMq
 
Erlang plus BDB: Disrupting the Conventional Web Wisdom
Erlang plus BDB: Disrupting the Conventional Web WisdomErlang plus BDB: Disrupting the Conventional Web Wisdom
Erlang plus BDB: Disrupting the Conventional Web Wisdom
 
Shrinking the Haystack" using Solr and OpenNLP
Shrinking the Haystack" using Solr and OpenNLPShrinking the Haystack" using Solr and OpenNLP
Shrinking the Haystack" using Solr and OpenNLP
 
Scaling Gilt: from Monolithic Ruby Application to Distributed Scala Micro-Ser...
Scaling Gilt: from Monolithic Ruby Application to Distributed Scala Micro-Ser...Scaling Gilt: from Monolithic Ruby Application to Distributed Scala Micro-Ser...
Scaling Gilt: from Monolithic Ruby Application to Distributed Scala Micro-Ser...
 
AST - the only true tool for building JavaScript
AST - the only true tool for building JavaScriptAST - the only true tool for building JavaScript
AST - the only true tool for building JavaScript
 
Erlang as a cloud citizen, a fractal approach to throughput
Erlang as a cloud citizen, a fractal approach to throughputErlang as a cloud citizen, a fractal approach to throughput
Erlang as a cloud citizen, a fractal approach to throughput
 
Pregel: A System for Large-Scale Graph Processing
Pregel: A System for Large-Scale Graph ProcessingPregel: A System for Large-Scale Graph Processing
Pregel: A System for Large-Scale Graph Processing
 

Ähnlich wie Chloe and the Realtime Web

Selenium sandwich-3: Being where you aren't.
Selenium sandwich-3: Being where you aren't.Selenium sandwich-3: Being where you aren't.
Selenium sandwich-3: Being where you aren't.Workhorse Computing
 
Dirty Secrets of the PHP SOAP Extension
Dirty Secrets of the PHP SOAP ExtensionDirty Secrets of the PHP SOAP Extension
Dirty Secrets of the PHP SOAP ExtensionAdam Trachtenberg
 
Kamailio and VoIP Wild World
Kamailio and VoIP Wild WorldKamailio and VoIP Wild World
Kamailio and VoIP Wild World2600Hz
 
Puppet and the HashiStack
Puppet and the HashiStackPuppet and the HashiStack
Puppet and the HashiStackBram Vogelaar
 
AnyMQ, Hippie, and the real-time web
AnyMQ, Hippie, and the real-time webAnyMQ, Hippie, and the real-time web
AnyMQ, Hippie, and the real-time webclkao
 
Websockets talk at Rubyconf Uruguay 2010
Websockets talk at Rubyconf Uruguay 2010Websockets talk at Rubyconf Uruguay 2010
Websockets talk at Rubyconf Uruguay 2010Ismael Celis
 
Core web vitals meten om je site sneller te maken - Combell Partner Day 2023
Core web vitals meten om je site sneller te maken - Combell Partner Day 2023Core web vitals meten om je site sneller te maken - Combell Partner Day 2023
Core web vitals meten om je site sneller te maken - Combell Partner Day 2023Thijs Feryn
 
8 Minutes On Rack
8 Minutes On Rack8 Minutes On Rack
8 Minutes On Rackdanwrong
 
Eve - REST API for Humans™
Eve - REST API for Humans™Eve - REST API for Humans™
Eve - REST API for Humans™Nicola Iarocci
 
Introduction to Vert.x
Introduction to Vert.xIntroduction to Vert.x
Introduction to Vert.xYiguang Hu
 
REST with Eve and Python
REST with Eve and PythonREST with Eve and Python
REST with Eve and PythonPiXeL16
 
Node.js for PHP developers
Node.js for PHP developersNode.js for PHP developers
Node.js for PHP developersAndrew Eddie
 
Mojolicious. Веб в коробке!
Mojolicious. Веб в коробке!Mojolicious. Веб в коробке!
Mojolicious. Веб в коробке!Anatoly Sharifulin
 
Great Developers Steal
Great Developers StealGreat Developers Steal
Great Developers StealBen Scofield
 

Ähnlich wie Chloe and the Realtime Web (20)

Selenium sandwich-3: Being where you aren't.
Selenium sandwich-3: Being where you aren't.Selenium sandwich-3: Being where you aren't.
Selenium sandwich-3: Being where you aren't.
 
Dirty Secrets of the PHP SOAP Extension
Dirty Secrets of the PHP SOAP ExtensionDirty Secrets of the PHP SOAP Extension
Dirty Secrets of the PHP SOAP Extension
 
Kamailio and VoIP Wild World
Kamailio and VoIP Wild WorldKamailio and VoIP Wild World
Kamailio and VoIP Wild World
 
Kamailio and VoIP Wild World
Kamailio and VoIP Wild WorldKamailio and VoIP Wild World
Kamailio and VoIP Wild World
 
Puppet and the HashiStack
Puppet and the HashiStackPuppet and the HashiStack
Puppet and the HashiStack
 
JSON and the APInauts
JSON and the APInautsJSON and the APInauts
JSON and the APInauts
 
AnyMQ, Hippie, and the real-time web
AnyMQ, Hippie, and the real-time webAnyMQ, Hippie, and the real-time web
AnyMQ, Hippie, and the real-time web
 
Websockets talk at Rubyconf Uruguay 2010
Websockets talk at Rubyconf Uruguay 2010Websockets talk at Rubyconf Uruguay 2010
Websockets talk at Rubyconf Uruguay 2010
 
Node.js - A Quick Tour
Node.js - A Quick TourNode.js - A Quick Tour
Node.js - A Quick Tour
 
Mojo as a_client
Mojo as a_clientMojo as a_client
Mojo as a_client
 
Core web vitals meten om je site sneller te maken - Combell Partner Day 2023
Core web vitals meten om je site sneller te maken - Combell Partner Day 2023Core web vitals meten om je site sneller te maken - Combell Partner Day 2023
Core web vitals meten om je site sneller te maken - Combell Partner Day 2023
 
Intro to Sail.js
Intro to Sail.jsIntro to Sail.js
Intro to Sail.js
 
8 Minutes On Rack
8 Minutes On Rack8 Minutes On Rack
8 Minutes On Rack
 
Eve - REST API for Humans™
Eve - REST API for Humans™Eve - REST API for Humans™
Eve - REST API for Humans™
 
Introduction to Vert.x
Introduction to Vert.xIntroduction to Vert.x
Introduction to Vert.x
 
REST with Eve and Python
REST with Eve and PythonREST with Eve and Python
REST with Eve and Python
 
Node.js for PHP developers
Node.js for PHP developersNode.js for PHP developers
Node.js for PHP developers
 
Mojolicious. Веб в коробке!
Mojolicious. Веб в коробке!Mojolicious. Веб в коробке!
Mojolicious. Веб в коробке!
 
ApacheCon 2005
ApacheCon 2005ApacheCon 2005
ApacheCon 2005
 
Great Developers Steal
Great Developers StealGreat Developers Steal
Great Developers Steal
 

Kürzlich hochgeladen

Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdfHyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdfPrecisely
 
How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.Curtis Poe
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLScyllaDB
 
unit 4 immunoblotting technique complete.pptx
unit 4 immunoblotting technique complete.pptxunit 4 immunoblotting technique complete.pptx
unit 4 immunoblotting technique complete.pptxBkGupta21
 
Advanced Computer Architecture – An Introduction
Advanced Computer Architecture – An IntroductionAdvanced Computer Architecture – An Introduction
Advanced Computer Architecture – An IntroductionDilum Bandara
 
SAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxSAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxNavinnSomaal
 
SALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICESSALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICESmohitsingh558521
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .Alan Dix
 
Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Mattias Andersson
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebUiPathCommunity
 
DevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenDevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenHervé Boutemy
 
Take control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteTake control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteDianaGray10
 
The State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxThe State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxLoriGlavin3
 
What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024Stephanie Beckett
 
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Mark Simos
 
What is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdfWhat is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdfMounikaPolabathina
 
The Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsThe Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsPixlogix Infotech
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsSergiu Bodiu
 
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxUse of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxLoriGlavin3
 

Kürzlich hochgeladen (20)

Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdfHyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
 
How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQL
 
unit 4 immunoblotting technique complete.pptx
unit 4 immunoblotting technique complete.pptxunit 4 immunoblotting technique complete.pptx
unit 4 immunoblotting technique complete.pptx
 
Advanced Computer Architecture – An Introduction
Advanced Computer Architecture – An IntroductionAdvanced Computer Architecture – An Introduction
Advanced Computer Architecture – An Introduction
 
SAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxSAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptx
 
SALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICESSALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICES
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .
 
Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio Web
 
DevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenDevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache Maven
 
Take control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteTake control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test Suite
 
The State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxThe State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptx
 
What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024
 
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
 
What is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdfWhat is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdf
 
The Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsThe Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and Cons
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platforms
 
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxUse of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
 

Chloe and the Realtime Web

  • 1. Chloe and the RTW Trotter Cashion Strange Loop 2011
  • 5. github.com/ trotter
  • 10. Knockout! Made me cry :-(
  • 11. We can Haz? http://utterinsanity.files.wordpress.com/2008/09/funny-pictures-cat-drives-an-invisible-racecar.jpg%3Fw%3D497%26h%3D318
  • 12. We can Haz? http://utterinsanity.files.wordpress.com/2008/09/funny-pictures-cat-drives-an-invisible-racecar.jpg%3Fw%3D497%26h%3D318
  • 13. We can Haz? http://utterinsanity.files.wordpress.com/2008/09/funny-pictures-cat-drives-an-invisible-racecar.jpg%3Fw%3D497%26h%3D318
  • 15. Chloe A realtime web-server... that doesn’t suck.
  • 16. Cool History, Right? http://github.com/mashion/chloe
  • 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. <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. <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. $(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. $(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. $(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. $(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. $(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. get '/' do   erubis :index end 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"]})   'ok' end
  • 27. get '/' do   erubis :index end post '/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"]})   'ok' end
  • 28. get '/' do   erubis :index end 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"]})   'ok' end
  • 29. get '/' do   erubis :index end post '/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"]})   'ok' end
  • 30. get '/' do   erubis :index end 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"]}) Chloe broadcast/multicast url   'ok' end
  • 31. get '/' do   erubis :index end post '/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"]})   'ok' end
  • 33.
  • 35. Chrome Server
  • 36. Chrome Server * *could be Java, Ruby, Scala, Clojure, Node...
  • 37. Chrome Server * Chloe *could be Java, Ruby, Scala, Clojure, Node...
  • 38. Chrome Server * Chloe GET / *could be Java, Ruby, Scala, Clojure, Node...
  • 39. Chrome Server * Chloe GET / index.html *could be Java, Ruby, Scala, Clojure, Node...
  • 40. Chrome Server * Chloe GET / index.html /chloe.js *could be Java, Ruby, Scala, Clojure, Node...
  • 41. Chrome Server * Chloe GET / index.html /chloe.js “Hey Everyone” *could be Java, Ruby, Scala, Clojure, Node...
  • 42. Chrome Server * Chloe GET / index.html /chloe.js “Hey Everyone” POST /updates “Hey Everyone” *could be Java, Ruby, Scala, Clojure, Node...
  • 43. 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...
  • 44. 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...
  • 45. Fallbacks Websockets Long polling (jsonp) Cross domain xhr - SOON! This seems to be enough for now...
  • 47. 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
  • 48. Channel Name 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
  • 49. chloe.connect(function () {   chloe.subscribe('chat-room-5', function (message) {     $("#messages").prepend("<li>" + message + "</li>")   }); }); Called when message arrives 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. 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
  • 51. 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
  • 52. What’s left for Channels Bi-directionality Per Channel callbacks
  • 53. Performance Difficult to determine...
  • 54. 50 50 40 33.5 Memory (MB) 30 20 17 10 0 0 500 1000 Sessions
  • 55. 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
  • 56. 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
  • 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 # 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
  • 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 # 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
  • 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 # 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
  • 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 Increase maximum receive window -w net.ipv4.tcp_syncookies=1 From cometd: http://cometd.org/documentation/2.x/howtos/loadtesting
  • 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 Increase send window From cometd: http://cometd.org/documentation/2.x/howtos/loadtesting
  • 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 How many SYN requests to keep in memory From cometd: http://cometd.org/documentation/2.x/howtos/loadtesting
  • 63. 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
  • 67. Binaries Available Mac, Ubuntu 32bit, Ubuntu 64bit Fully self-contained (Erlang included) .deb and .rpm will be coming soon...
  • 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. 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. 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. 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. 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
  • 73. ./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”} ]}
  • 74. ./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”} ]}
  • 75. ./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”} ]}
  • 76. ./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”} ]}
  • 77. ./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”} ]}
  • 78. ./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”} ]}
  • 79. ./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)...
  • 80. Signing Requests SECRET = "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})   'ok' end
  • 81. Signing Requests SECRET = "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})   'ok' end
  • 82. Signing Requests SECRET = "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})   'ok' end
  • 83. Signing Requests SECRET = "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})   'ok' end
  • 84. Signing Requests SECRET = "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})   'ok' end
  • 85. Signing Requests SECRET = "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})   'ok' end Add signature to request
  • 86. If `secret` is in your config, all requests to `/send` must be signed
  • 87. Coming Soon Improved Performance Bi-directional channels Per-channel callback urls Runtime configuration SSL Support
  • 88. Coming Later Improved monitoring Explore switch to mochiweb internally Client side authentication
  • 90. Session Manager Transports Yaws Callback Sessions Channel Store
  • 91. Session Manager Transports Yaws Callback Sessions Channel Store
  • 92. Session Manager Transports Yaws Callback Sessions Channel Store
  • 93. Session Manager Transports Yaws Callback Sessions Channel Store
  • 94. Session Manager Transports Yaws Callback Sessions Channel Store
  • 95. Session Yaws Websocket Manager Session
  • 96. Session Yaws Websocket Manager Session Browser
  • 97. Session Yaws Websocket Manager Session Browser New Conn
  • 98. Session Yaws Websocket Manager Session Browser New Conn Session?
  • 99. Session Yaws Websocket Manager Session Browser New Conn Session? Session Pid
  • 100. Session Yaws Websocket Manager Session Browser New Conn Session? Session Pid Message!
  • 101. Session Yaws Websocket Manager Session Browser New Conn Session? Session Pid Message! Server
  • 102. Channel Yaws Store Session Websocket
  • 103. Channel Yaws Store Session Websocket Server
  • 104. Channel Yaws Store Session Websocket Server Sessions?
  • 105. Channel Yaws Store Session Websocket Server Sessions? Session Pid
  • 106. Channel Yaws Store Session Websocket Server Sessions? Session Pid Message!
  • 107. Channel Yaws Store Session Websocket Server Sessions? Session Pid Message! Message!
  • 108. Channel Yaws Store Session Websocket Server Sessions? Session Pid Message! Message! Browser
  • 109. Message Structure { data, version, type, channel, id, sessionId }
  • 110. Message Structure { data, version, type,The message itself channel, id, sessionId }
  • 111. Message Structure { data, version, type, Version of the message protocol channel, id, sessionId }
  • 112. Message Structure { data, version, type, channel, Four types: connect, message, id, channel-subscribe, poll sessionId }
  • 113. Message Structure { data, version, type, channel, id, sessionId the message is going Where }
  • 114. Message Structure { data, version, type, channel, id, sessionId } No Idea...
  • 115. Message Structure { data, version, type, channel, id, sessionId } Session id for connection
  • 116. Please Go Play With It http://github.com/mashion/chloe http://mashion.net http://trottercashion.com @cashion
  • 117. Moved to Mountain View Be my friend?
  • 118. Thank You! Good luck w/ Chloe