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
490
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
StorybookのUI Testing Handbookを読んだ
zakiyama
31
6.9k
SEO for Brand Visibility & Recognition
aleyda
0
4.8k
Unsuck your backbone
ammeep
672
58k
Bash Introduction
62gerente
615
220k
Being A Developer After 40
akosma
91
590k
Building Applications with DynamoDB
mza
96
7.2k
More Than Pixels: Becoming A User Experience Designer
marktimemedia
3
540
The Curious Case for Waylosing
cassininazir
1
540
A brief & incomplete history of UX Design for the World Wide Web: 1989–2019
jct
2
510
CoffeeScript is Beautiful & I Never Want to Write Plain JavaScript Again
sstephenson
162
16k
Paper Plane (Part 1)
katiecoart
PRO
2
11k
Prompt Engineering for Job Search
mfonobong
0
460
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