Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
30,000,000 Requests in a Hour in the Cloud
Search
Terrence Ryan
September 03, 2016
410
2
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
30,000,000 Requests in a Hour in the Cloud
Terrence Ryan
September 03, 2016
More Decks by Terrence Ryan
See All by Terrence Ryan
Vms, Serverless, or Containers
tpryan
0
670
Go for PHP Developers
tpryan
2
1.1k
Navigating Google Cloud Platform
tpryan
0
480
Which Engine?
tpryan
0
420
Introduction to Containers and Kubernetes
tpryan
2
420
Cloud Next 2017 Roundup
tpryan
2
200
LAMP in Containers
tpryan
1
330
GCP and IoT
tpryan
0
520
Introduction to Machine Learning
tpryan
0
310
Featured
See All Featured
The Organizational Zoo: Understanding Human Behavior Agility Through Metaphoric Constructive Conversations (based on the works of Arthur Shelley, Ph.D)
kimpetersen
PRO
0
440
CSS Pre-Processors: Stylus, Less & Sass
bermonpainter
360
30k
Paper Plane (Part 1)
katiecoart
PRO
1
11k
The Cult of Friendly URLs
andyhume
79
7k
Measuring Dark Social's Impact On Conversion and Attribution
stephenakadiri
2
270
Evolution of real-time – Irina Nazarova, EuRuKo, 2024
irinanazarova
9
1.5k
Leo the Paperboy
mayatellez
9
2.3k
The Art of Programming - Codeland 2020
erikaheidi
57
14k
Visualizing Your Data: Incorporating Mongo into Loggly Infrastructure
mongodb
49
10k
エンジニアに許された特別な時間の終わり
watany
108
250k
Balancing Empowerment & Direction
lara
6
1.3k
RailsConf & Balkan Ruby 2019: The Past, Present, and Future of Rails at GitHub
eileencodes
141
35k
Transcript
‹#› @tpryan Terrence Ryan Developer Advocate 30,000,000 Requests An Hour
In The Cloud
‹#› @tpryan Who are you?
‹#› @tpryan 01 Introduction What was I trying to do
None
‹#› @tpryan Demo: App Engine
‹#› @tpryan App Engine • Writes to Firebase • Writes
to Cloud Storage • Run the Visualizer
‹#› @tpryan Compute Engine • Load Generators • Apache Bench
• Remote Command Execution
‹#› @tpryan Firebase • Realtime Display • Tracking all load
‹#› @tpryan Cloud Storage • Proof of activity • Object
notification
‹#› @tpryan App Engine • Process Notifications from Cloud Storage
‹#› @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
‹#› @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
@briandorsey 30,000,000 requests in one hour
@briandorsey What do you call a site that gets 30,000,000
hits an hour?
@briandorsey
@briandorsey I should try and do that and mean it
‹#› @tpryan 02 Ramping up What is Google Cloud Platform
@briandorsey 30,000,000 qph /60/60 8,333 qps
@briandorsey Ramp the demo up to 8,333 qps
‹#› @tpryan Demo: App Engine
‹#› @tpryan URLFetch • Network abstraction layer for http •
Most service calls
‹#› @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);
‹#› @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); }
‹#› @tpryan
‹#› @tpryan
‹#› @tpryan
@briandorsey 660,000 qpm /60 11,000 qps /3 3,666 qps
‹#› @tpryan 03 Fix 1 Sockets
‹#› @tpryan
‹#› @tpryan
‹#› @tpryan
‹#› @tpryan Demo: App Engine
‹#› @tpryan Reasons for failure • Sockets are lighter •
But implementation is not configurable • So write your own socket client?
‹#› @tpryan 04 Fix 2 Memcache
‹#› @tpryan Assumptions • Visualization needs to be realtime •
But does it?
‹#› @tpryan Memcache on App Engine
‹#› @tpryan Pseudo Code // store instances request count //
Get list of keys // Display request counts Bad Idea
‹#› @tpryan
‹#› @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);
‹#› @tpryan Close but no cigar • Losing instances •
Analysis revealed: • All requests were firing • All requests were registering • Cause: Memcache strings were getting too long
‹#› @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);
‹#› @tpryan Source Code function whichInstanceList($instance){ $last = substr($instance, -1);
return "instances-" . $last; }
‹#› @tpryan Demo: App Engine
‹#› @tpryan 05 Conclusion What did I learn
@briandorsey Wait, you’re giving up realtime without a fight?
‹#› @tpryan 05 Fix 3 Brining back the realtime
‹#› @tpryan Current / //Write to Memcache //Write to Cloud
Storage //Receive realtime //updates /visualizer http://load-demo.appspot.com //Display Updates //Store request details
‹#› @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
‹#› @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
‹#› @tpryan How Firebase works • appengine • instance1 •
request1 • request2 • request3 • request4 • request5 • request6 • instance2
‹#› @tpryan How Firebase works { "appengine": { "instance1": {
"request1": "", "request2": "", "request3": "", "request4": "", "request5": "", "request6": "" }, "instance2": {} } }
‹#› @tpryan How Firebase works { "appengine": { "instance1": {
"request1": "", "request2": "", "request3": "", "request4": "", "request5": "", "request6": "" }, "instance2": {} } } /appengine/instance1/request2.json GET POST PATCH
‹#› @tpryan How Firebase works { "appengine": { "instance1": {
"request1": "", "request2": "", "request3": "", "request4": "", "request5": "", "request6": "" }, "instance2": {} } } /appengine/instance1.json GET POST PATCH
‹#› @tpryan How Firebase works { "appengine": { "instance1": {
"request1": "", "request2": "", "request3": "", "request4": "", "request5": "", "request6": "" }, "instance2": {} } } /appengine.json GET POST PATCH
‹#› @tpryan
‹#› @tpryan Batch Memcache calls getMulti()
‹#› @tpryan Let’s send too much stuff • appengine •
00c61b117c1d99526c06775beef85526a00dbdd295ffef80dbe702a836b0 • request1 • 00c61b117c1d99526c06775beef85526a00dbdd295ffef80dbe702a836b0 • request2 • 00c61b117c1d99526c06775beef85526a00dbdd295ffef80dbe702a836b0 • request3 • 00c61b117c1d99526c06775beef85526a00dbdd295ffef80dbe702a836b0 • request4 • 00c61b117c1d99526c06775beef85526a00dbdd295ffef80dbe702a836b0 • request5 • 00c61b117c1d99526c06775beef85526a00dbdd295ffef80dbe702a836b0 • request6 • 00c61b117c1d99526c06775beef85526a00dbdd295ffef80dbe702a836b0 • 00c61b117cf44784cd0c142018b2ada185ce6d3472a963342388ef123a30
‹#› @tpryan Let’s send too much stuff • appengine •
00c61b117c1d99526c06775beef85526a00dbdd295ffef80dbe702a836b0 • 6 • 00c61b117cf44784cd0c142018b2ada185ce6d3472a963342388ef123a30 • 1
‹#› @tpryan
‹#› @tpryan
‹#› @tpryan
‹#› @tpryan
‹#› @tpryan
‹#› @tpryan Source Code $task1 = new PushTask('/realtime.php'); $task1->add("realtimesynch");
‹#› @tpryan Demo: App Engine
‹#› @tpryan 06 Conclusion What did I learn
@briandorsey Safety Quotas are not just something to be gotten
around
@briandorsey Bundle up data calls when you can
@briandorsey Be prepared to make compromises
@briandorsey Time for a language change?
‹#› @tpryan Thank You terrenceryan.com @tpryan This preso: http://bit.ly/tpryan-30m