Upgrade to Pro — share decks privately, control downloads, hide ads and more …

30,000,000 Requests in a Hour in the Cloud

Terrence Ryan
September 03, 2016
320

30,000,000 Requests in a Hour in the Cloud

Terrence Ryan

September 03, 2016
Tweet

Transcript

  1. ‹#› @tpryan App Engine • Writes to Firebase • Writes

    to Cloud Storage • Run the Visualizer
  2. ‹#› @tpryan Planned / //Write to Firebase //Write to Cloud

    Storage //Receive realtime
 //updates /visualizer /storage //Write to Firebase //Display updates //Store file //Send Notification http://load-demo.appspot.com
  3. ‹#› @tpryan Actual / //Write to Firebase //Write to Cloud

    Storage //Receive realtime
 //updates /visualizer /storage //Write to Firebase //Display updates //Store file //Send Notification http://load-demo.appspot.com
  4. ‹#› @tpryan Source Code $instance = $_SERVER['INSTANCE_ID']; $urlToPatch = $fbBaseURL

    . "appengine/" . $instance . ".json"; $urlToPost = $fbBaseURL . "appengine/" . $instance . “/sessions.json"; $instance_data = new stdClass(); $instance_data->instance = $instance; $instance_data->updated = time(); $instance_json = json_encode($instance_data); $ch = curl_init(); $output = patch($ch, $urlToPatch, $instance_json); $output = post($ch, $urlToPost, $instance_json); $name = json_decode($output)->name; $filename = $gcsBaseURL . $instance . "/file" . $name . ".txt"; file_put_contents($filename, $name); $instance = $_SERVER['INSTANCE_ID']; $urlToPatch = $fbBaseURL . "appengine/" . $instance . ".json"; $urlToPost = $fbBaseURL . "appengine/" . $instance . “/sessions.json"; $instance_data = new stdClass(); $instance_data->instance = $instance; $instance_data->updated = time(); $instance_json = json_encode($instance_data); $ch = curl_init(); $output = patch($ch, $urlToPatch, $instance_json); $output = post($ch, $urlToPost, $instance_json); $name = json_decode($output)->name; $filename = $gcsBaseURL . $instance . "/file" . $name . ".txt"; file_put_contents($filename, $name);
  5. ‹#› @tpryan Source Code function patch($ch, $url, $json){ curl_setopt($ch, CURLOPT_URL,

    $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PATCH"); curl_setopt($ch, CURLOPT_POSTFIELDS, $json); return curl_exec($ch); } function post($ch, $url, $json){ curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST"); curl_setopt($ch, CURLOPT_POSTFIELDS, $json); return curl_exec($ch); }
  6. ‹#› @tpryan Reasons for failure • Sockets are lighter •

    But implementation is not configurable • So write your own socket client?
  7. ‹#› @tpryan Pseudo Code // store instances request count //

    Get list of keys // Display request counts Bad Idea
  8. ‹#› @tpryan Source Code $memcache = new Memcached; $instance =

    $_SERVER['INSTANCE_ID']; $request = $_SERVER['REQUEST_LOG_ID']; $result = $memcache->increment($instance); if ($result == 1 ){ $result = $memcache->append("instances", "|" . $instance); if ($memcache->getResultCode() == 14){ $result = $memcache->set("instances", $instance); } } $filename = $gcsBaseURL . $instance . "/file" . $request . ".txt"; file_put_contents($filename, $filename);
  9. ‹#› @tpryan Close but no cigar • Losing instances •

    Analysis revealed: • All requests were firing • All requests were registering • Cause: Memcache strings were getting too long
  10. ‹#› @tpryan Source Code $memcache = new Memcached; $instance =

    $_SERVER['INSTANCE_ID']; $request = $_SERVER['REQUEST_LOG_ID']; $memcache->increment("total"); $result = $memcache->increment($instance); if ($result == 1 ){ $result = $memcache->append("instances", "|" . $instance); if ($memcache->getResultCode() == 14){ $result = $memcache->set("instances", $instance); } } $filename = $gcsBaseURL . $instance . "/file" . $request . ".txt"; file_put_contents($filename, $filename); $memcache = new Memcached; $instance = $_SERVER['INSTANCE_ID']; $request = $_SERVER['REQUEST_LOG_ID']; $memcache->increment("total"); $result = $memcache->increment($instance); if ($result == 1 ){ $result = $memcache->append("instances", "|" . $instance); if ($memcache->getResultCode() == 14){ $result = $memcache->set("instances", $instance); } } $filename = $gcsBaseURL . $instance . "/file" . $request . ".txt"; file_put_contents($filename, $filename);
  11. ‹#› @tpryan Current / //Write to Memcache //Write to Cloud

    Storage //Receive realtime
 //updates /visualizer http://load-demo.appspot.com //Display Updates //Store request details
  12. ‹#› @tpryan Current / //Write to Memcache //Write to Cloud

    Storage //Receive realtime
 //updates /visualizer http://load-demo.appspot.com //Display Updates //Store request details //Read memcache //Write to Firebase /realtime.php
  13. ‹#› @tpryan Pseudo Code // Get list of instances //

    Get list of number of requests for each instance // Send data for each request to firebase Bad Idea
  14. ‹#› @tpryan How Firebase works • appengine • instance1 •

    request1 • request2 • request3 • request4 • request5 • request6 • instance2
  15. ‹#› @tpryan How Firebase works { "appengine": { "instance1": {

    "request1": "", "request2": "", "request3": "", "request4": "", "request5": "", "request6": "" }, "instance2": {} } }
  16. ‹#› @tpryan How Firebase works { "appengine": { "instance1": {

    "request1": "", "request2": "", "request3": "", "request4": "", "request5": "", "request6": "" }, "instance2": {} } } /appengine/instance1/request2.json GET POST PATCH
  17. ‹#› @tpryan How Firebase works { "appengine": { "instance1": {

    "request1": "", "request2": "", "request3": "", "request4": "", "request5": "", "request6": "" }, "instance2": {} } } /appengine/instance1.json GET POST PATCH
  18. ‹#› @tpryan How Firebase works { "appengine": { "instance1": {

    "request1": "", "request2": "", "request3": "", "request4": "", "request5": "", "request6": "" }, "instance2": {} } } /appengine.json GET POST PATCH
  19. ‹#› @tpryan Let’s send too much stuff • appengine •

    00c61b117c1d99526c06775beef85526a00dbdd295ffef80dbe702a836b0 • request1 • 00c61b117c1d99526c06775beef85526a00dbdd295ffef80dbe702a836b0 • request2 • 00c61b117c1d99526c06775beef85526a00dbdd295ffef80dbe702a836b0 • request3 • 00c61b117c1d99526c06775beef85526a00dbdd295ffef80dbe702a836b0 • request4 • 00c61b117c1d99526c06775beef85526a00dbdd295ffef80dbe702a836b0 • request5 • 00c61b117c1d99526c06775beef85526a00dbdd295ffef80dbe702a836b0 • request6 • 00c61b117c1d99526c06775beef85526a00dbdd295ffef80dbe702a836b0 • 00c61b117cf44784cd0c142018b2ada185ce6d3472a963342388ef123a30
  20. ‹#› @tpryan Let’s send too much stuff • appengine •

    00c61b117c1d99526c06775beef85526a00dbdd295ffef80dbe702a836b0 • 6 • 00c61b117cf44784cd0c142018b2ada185ce6d3472a963342388ef123a30 • 1