©2016 AKAMAI | FASTER FORWARD™
HTTP/2 Web Performance
Promise of Push
@ColinBendell
Director, CTO Office
©2016 AKAMAI | FASTER FORWARD™
Desktop
90th50thBudget
Mobile
©2016 AKAMAI | FASTER FORWARD™
Improving Perf:
Blame the content
©2016 AKAMAI | FASTER FORWARD™
WebPageTest
Looking for culprits
©2016 AKAMAI | FASTER FORWARD™
Time-To-First-Byte
25% of Perf. Budget is waiting
Many causes: User (Network, Device,
CPU), App Server, etc
©2016 AKAMAI | FASTER FORWARD™
Introducing
Network Waste
1.48s (full
throughput)
87.6% WASTE
©2016 AKAMAI | FASTER FORWARD™
Network Waste
An opportunity to PUSH content
Move the
experience
87.6% WASTE
©2016 AKAMAI | FASTER FORWARD™
Chapter 1: PUSH on the Web
©2016 AKAMAI | FASTER FORWARD™
Direct TCP
Poll/Long Poll
Pushlets
SSE
Hasn't Push
been solved?
How to PUSH
TCP/IP Socket (eg: XMPP)
<stream:stream
to='example.com'
xmlns='jabber:client'
version='1.0'>
<stream:stream
from='example.com'
id='someid'
xmlns='jabber:client'
version='1.0'>
<message from='juliet@capulet.com'
to='romeo@montague.net'>
<body>Art thou not Romeo,
and a Montague?</body>
</message> <message from='romeo@montague.net'
to='juliet@capulet.com'>
<body>Neither, fair saint,
if either thee dislike.</body>
</message>
<message from='juliet@capulet.com'
to='romeo@montague.net'>
<body>How camest thou hither,
tell me, and wherefore? </body>
</message>
©2016 AKAMAI | FASTER FORWARD™
How to PUSH
TCP/IP Socket (eg: XMPP)
• Proprietary & efficient
• Any content could be sent
• But requires app logic to encode/decode
• Likely ports blocked by firewall rules
How to PUSH
Polling / Long Polling
GET /messages HTTP/1.1
Host: queue.example.com
Authorization: ...
HTTP/1.1 200 OK
Content-Length: 100
{ "from": "adbram@montague.net",
"to": "sampson@capulet.com",
"message: "Do you bite your
thumb at us, sir?
}
©2016 AKAMAI | FASTER FORWARD™
How to PUSH
Polling / Long Polling
• Ports 80/443
• Polling is chatty; has battery impacts
• Custom protocol: requires app logic
• Connection timeouts
• Must manually handle disconnect & resume
©2016 AKAMAI | FASTER FORWARD™
How to PUSH
Pushlet
GET /messages HTTP/1.1
Host: queue.example.com
Authorization: ... HTTP/1.1 200 OK
Transfer-Encoding: Chunked
Connection: keep-alive
Content-Type: text/html
<html><head/><body>
<h1>Messages</h1>
<p>From: sampson@capulet.com</p>
<p>To: adbram@montague.net</p>
<p>I do bite my thumb, sir.</p>
<p>From: sampson@capulet.com</p>
<p>To: adbram@montague.net</p>
<p>No, sir, I do not bite my thumb at
you, sir, but I bite my thumb, sir.<p>
©2016 AKAMAI | FASTER FORWARD™
How to PUSH
Pushlet
• No app logic required
• Continuously "loading" UX
• CPU/Network/Battery impacts?
• Text only
• Client must must detect connection loss
©2016 AKAMAI | FASTER FORWARD™
How to PUSH
Server-Side-Events
GET /messages HTTP/1.1
Host: api.example.com
Accept: text/event-stream
Authorization: ...
Last-Event-ID: 41
HTTP/1.1 200 OK
Connection: keep-alive
Content-Type: text/event-stream
Transfer-Encoding: chunked
id: 42
event: receiveMessage
data: { "from": "adbram@montague.net",
"to": "sampson@capulet.com",
"message: "Do you bite your
thumb at us, sir?}
id: 43
event: stageAction
data: { "from": "adbram@montague.net",
"to": "sampson@capulet.com",
"message: "Do you bite your
thumb at us, sir?}
©2016 AKAMAI | FASTER FORWARD™
How to PUSH
Server-Side-Events
HTTP/1.1 200 OK
Connection: keep-alive
Content-Type: text/event-stream
Transfer-Encoding: chunked
id: 42
event: recieveMessage
data: { "from": "adbram@montague.net",
"to": "sampson@capulet.com",
"message: "Do you bite your
thumb at us, sir?}
id: 43
event: stageAction
data: { "from": "adbram@montague.net",
"to": "sampson@capulet.com",
"message: "Do you bite your
thumb at us, sir?}
<script type="text/javascript">
var evtSource = new EventSource(
"//api.example.com/messages",
{ withCredentials: true } );
evtSource.addEventListener("receiveMessage",
function(e) {
var newElement = document.createElement("p");
var obj = JSON.parse(e.data);
newElement.innerHTML = "Message: " + obj.message;
eventList.appendChild(newElement);
}, false);
</script>
©2016 AKAMAI | FASTER FORWARD™
How to PUSH
Server-Side-Events
• HTML5 browsers or Polyfill
• Standard APIs
• Text only messages
• Intermediates must support flushing
©2016 AKAMAI | FASTER FORWARD™
HTTP/1.1
State of Push
• Build it yourself
• Requires app logic to be loaded
• (generally) Text only
• Messaging focused, not performance
©2016 AKAMAI | FASTER FORWARD™
WebRTC
WebSocket
HTTP/2 Push
(Do we need yet
another technology?)
Wait!
What about:
©2016 AKAMAI | FASTER FORWARD™
Peer-to-Peer with
WebRTC
• Peer to Peer
• UDP (+FlowControl)
• Web APIs
• BYOA (bring your own app)
• Usually: Audio/Video
Flexibility: High
RealTime: High
Complexity: High
©2016 AKAMAI | FASTER FORWARD™
One-to-One with
WebSockets
• One-to-One (User to Server)
• Bidirectional socket
• Web APIs
• BYOA (bring your own app)
• Can by binary or text
• Not cacheable
Flexibility: Medium
RealTime: High
Complexity: Medium-High
var ws = new WebSocket('wss://example.com/socket');
ws.onerror = function (error) { }
ws.onclose = function () { }
ws.onopen = function () { }
ws.onmessage = function(msg) {
if(msg.data instanceof Blob) {
processBlob(msg.data);
} else {
processText(msg.data);
}
}
Function sendMessage(msgText) {
ws.send(msgText);
}
©2016 AKAMAI | FASTER FORWARD™
One-to-Many with
HTTP/2 Push
• Many-to-One (Users to Server)
• H2 standard
• Cacheable
• Transparent to app
Flexibility: Medium
RealTime: Low
Complexity: Low
[ 0.270] recv (stream_id=13) :method: GET
[ 0.270] recv (stream_id=13) :path: /demo/h2/push.css
[ 0.271] recv (stream_id=13) accept: */*
[ 0.271] recv PUSH_PROMISE frame <length=72,
flags=0x04, stream_id=13>
; END_HEADERS
(padlen=0, promised_stream_id=2)
©2016 AKAMAI | FASTER FORWARD™
9 (8+)6+ (4.4)
©2016 AKAMAI | FASTER FORWARD™
Overview
HTTP/2 Basics
Fix HTTP/1.1 Performance Other?
├ Head of Line Blocking
├ Parallelism
├ Header compression
└ Backward Compatible
├ Prioritization
├ Flow Control
└ Binary Protocol
└ Server Push
©2016 AKAMAI | FASTER FORWARD™
Chapter 2: PUSH_PROMISE
HTTP/2 PUSH_PROMISE
Frame Basics
PUSH_PROMISE
:url: /push.css
user-agent: chrome
RST_STREAM
DATA
promised-stream-id: 2
a:hover {color: blue}
…
2
2
… or ...
13
©2016 AKAMAI | FASTER FORWARD™
HTTP/2
Reading the Matrix
$ nghttp https://www.colinbendell.com/demo/h2/pushtest.html -vv
[ 0.135] Connected
The negotiated protocol: h2
[ 0.230] send SETTINGS frame <length=12, flags=0x00, stream_id=0>
(niv=2)
[SETTINGS_MAX_CONCURRENT_STREAMS(0x03):100]
[SETTINGS_INITIAL_WINDOW_SIZE(0x04):65535]
[ 0.230] send PRIORITY frame <length=5, flags=0x00, stream_id=3>
(dep_stream_id=0, weight=201, exclusive=0)
[ 0.230] send PRIORITY frame <length=5, flags=0x00, stream_id=5>
(dep_stream_id=0, weight=101, exclusive=0)
[ 0.230] send PRIORITY frame <length=5, flags=0x00, stream_id=7>
(dep_stream_id=0, weight=1, exclusive=0)
Frame Name Bytes
Odd = Client
Initiated
©2016 AKAMAI | FASTER FORWARD™
[ 0.230] send HEADERS frame <length=60, flags=0x25, stream_id=13>
; END_STREAM | END_HEADERS | PRIORITY
(padlen=0, dep_stream_id=11, weight=16, exclusive=0)
; Open new stream
:method: GET
:path: /demo/h2/pushtest.html
:scheme: https
:authority: www.colinbendell.com
accept: */*
accept-encoding: gzip, deflate
user-agent: nghttp2/1.6.0
Familiar
HTTP Request
Pseudo
Headers
©2016 AKAMAI | FASTER FORWARD™
[ 0.267] recv SETTINGS frame <length=30, flags=0x00, stream_id=0>
(niv=5)
[SETTINGS_HEADER_TABLE_SIZE(0x01):4096]
[SETTINGS_MAX_CONCURRENT_STREAMS(0x03):100]
[SETTINGS_INITIAL_WINDOW_SIZE(0x04):65535]
[SETTINGS_MAX_FRAME_SIZE(0x05):16384]
[SETTINGS_MAX_HEADER_LIST_SIZE(0x06):16384]
[ 0.267] recv SETTINGS frame <length=0, flags=0x01, stream_id=0>
; ACK
(niv=0)
[ 0.267] send SETTINGS frame <length=0, flags=0x01, stream_id=0>
; ACK
(niv=0)
Flow Control
©2016 AKAMAI | FASTER FORWARD™
HTTP/2
PUSH_PROMISE
[ 0.270] recv (stream_id=13) :method: GET
[ 0.270] recv (stream_id=13) :path: /demo/h2/push.css
[ 0.270] recv (stream_id=13) :authority: www.colinbendell.com
[ 0.270] recv (stream_id=13) :scheme: https
[ 0.270] recv (stream_id=13) host: www.colinbendell.com
[ 0.271] recv (stream_id=13) accept: */*
[ 0.271] recv (stream_id=13) user-agent: nghttp2/1.6.0
[ 0.271] recv (stream_id=13) accept-encoding: gzip, deflate
[ 0.271] recv PUSH_PROMISE frame <length=72, flags=0x04, stream_id=13>
; END_HEADERS
(padlen=0, promised_stream_id=2)
Existing Stream
Even: Server Initiated
©2016 AKAMAI | FASTER FORWARD™
[ 0.313] recv (stream_id=2, sensitive) :status: 200
[ 0.313] recv (stream_id=2, sensitive) server: Apache
[ 0.313] recv (stream_id=2, sensitive) etag: "e00af44aba37028e02014b684
[ 0.313] recv (stream_id=2, sensitive) last-modified: Fri, 22 Apr 2016
[ 0.313] recv (stream_id=2, sensitive) accept-ranges: bytes
[ 0.313] recv (stream_id=2, sensitive) content-length: 64
[ 0.313] recv (stream_id=2, sensitive) content-type: text/css
[ 0.313] recv (stream_id=2, sensitive) cache-control: max-age=3571
[ 0.313] recv (stream_id=2, sensitive) expires: Sun, 24 Apr 2016 16:22:
[ 0.313] recv (stream_id=2, sensitive) date: Sun, 24 Apr 2016 15:23:02
[ 0.313] recv HEADERS frame <length=469, flags=0x04, stream_id=2>
; END_HEADERS
(padlen=0)
[ 0.313] recv (stream_id=2, length=64, srecv=64, crecv=621) DATA
Lorem;ipsum
[ 0.313] recv DATA frame <length=64, flags=0x00, stream_id=2>
[ 0.313] recv DATA frame <length=0, flags=0x01, stream_id=2>
; END_STREAM
Delay, Push Response
©2016 AKAMAI | FASTER FORWARD™
HTTP/2
PUSH_PROMISE
$ nghttp https://www.colinbendell.com/demo/h2/pushtest.html -vv --no-push
[ 0.123] Connected
The negotiated protocol: h2
[ 0.518] send SETTINGS frame <length=18, flags=0x00, stream_id=0>
(niv=3)
[SETTINGS_MAX_CONCURRENT_STREAMS(0x03):100]
[SETTINGS_INITIAL_WINDOW_SIZE(0x04):65535]
[SETTINGS_ENABLE_PUSH(0x02):0]
Push Not Supported
[ 0.230] send RST_STREAM frame <length=5, flags=0x07, stream_id=4>
Push not accepted
chrome://net-internals
©2016 AKAMAI | FASTER FORWARD™
Invoking
©2016 AKAMAI | FASTER FORWARD™
HTTP/2 PUSH
How do I enable?
HTTP/1.1 200 OK
Content-Type: text/html
Link: /jquery.js; rel=preload; as=script
Link: /global.css; rel=preload; as=style
1. Use the ` Link: <URL>; rel=preload; as=style` notation
Pros:
• Easy to implement
• H2O / nginX support
Cons:
• Too-Late; Is TTFB
• Status & headers committed
• Interferes with Browser's Pre-Loader
©2016 AKAMAI | FASTER FORWARD™
HTTP/2 PUSH
How do I enable?
public class MyServlet extends HttpServlet
{
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
String uri = request.getRequestURI();
if ("/index.html".equals(uri))
{
String resourceToPush = "/js/jquery.js";
RequestDispatcher dispatcher =
request.getRequestDispatcher(resourceToPush);
dispatcher.push(request);
}
}
}
2. Manually Instrument
©2016 AKAMAI | FASTER FORWARD™
HTTP/2 PUSH
How do I enable?
2. Manually Instrument
Pros:
• Before TTFB
• Not impacted by page
• Can extend to Next Page
Cons:
• Another layer to maintain
©2016 AKAMAI | FASTER FORWARD™
Visualizing & Debug
©2016 AKAMAI | FASTER FORWARD™
Visualizing Results
©2016 AKAMAI | FASTER FORWARD™
Delayed Push with
Link=preload
©2016 AKAMAI | FASTER FORWARD™
Manual Instrument (Jetty)
©2016 AKAMAI | FASTER FORWARD™
Push headers are 'provisional'
©2016 AKAMAI | FASTER FORWARD™
Timeline not helpful (Chrome 50)
©2016 AKAMAI | FASTER FORWARD™
Canary (52) shows PUSH in Timeline
©2016 AKAMAI | FASTER FORWARD™
HTTP/2 (Chrome)
Adopted Push Stream
chrome://net-internals to find unclaimed pushes
Adopted pushes are logged (not a frame)
* PUSH is kept in memory for 5 minutes and then get deleted if unclaimed
©2016 AKAMAI | FASTER FORWARD™
Debugging PUSH
• Terminal: nghttp
• Chrome: look for provisional header
or use net-internals
• Firefox: enabling logging
• PUSHed content isn't added to cache until
used in the page
©2016 AKAMAI | FASTER FORWARD™
Browser Behavior
Browser support
Testing PUSH
©2016 AKAMAI | FASTER FORWARD™
HTTP/2
Connection Coalescing
Coalescing is ignored by Chrome/FF
©2016 AKAMAI | FASTER FORWARD™
HTTP/2 Chrome
Connection coalescing not avail
if (!HostPortPair::FromURL(gurl).Equals(host_port_pair())) {
if (proxy_delegate_ &&
proxy_delegate_->IsTrustedSpdyProxy(
ProxyServer(ProxyServer::SCHEME_HTTPS, host_port_pair()))) {
if (gurl.SchemeIs("https")) {
EnqueueResetStreamFrame(
stream_id, request_priority, RST_STREAM_REFUSED_STREAM,
base::StringPrintf("Rejected push of cross origin HTTPS
content %d "
"from trusted proxy",
associated_stream_id));
return false;
}
Only Host + Port considered! Boo!
©2016 AKAMAI | FASTER FORWARD™
Browser Support
Implementation notes
• PUSHed content from different hosts are
rejected instead of coalescing
• Only used PUSHes hit cache
• FF uses init flow control of 64kb
©2016 AKAMAI | FASTER FORWARD™
Chapter 3: PUSH opportunity
©2016 AKAMAI | FASTER FORWARD™
www.rakuten.co.uk
TTFB: Network Waste
TTFB: 330ms
95.9% Waste
©2016 AKAMAI | FASTER FORWARD™
www.rakuten.co.uk
Time-to-First-Resource
TTFR: 762ms
91.1% Waste
©2016 AKAMAI | FASTER FORWARD™
www.rakuten.co.uk
33.7% Perf Waste
1.48s (full
throughput)
87.6% WASTE Vis. Complete:
4.38s
©2016 AKAMAI | FASTER FORWARD™
www.forever21.com
WPT: Network Waste
81.7%
0.6s (full
throughput)
©2016 AKAMAI | FASTER FORWARD™
Browser Support
Implementation notes
• Measures opportunity to use the network
ahead of DOM/Browser load
• Indicator metric – NOT silver bullet
• Examines WPT results
• Tool to be released later this month
©2016 AKAMAI | FASTER FORWARD™
Chapter 4: Results
©2016 AKAMAI | FASTER FORWARD™
PUSH Results
Insurance Site
Original CSS/JSOriginal
Everything Images
©2016 AKAMAI | FASTER FORWARD™
PUSH Results
Cosmetics Site
Original
CSS/JS Everything
Images
©2016 AKAMAI | FASTER FORWARD™
Automatic PUSH_PROMISE
But when you get it Right:
5.27s 8.59s
©2016 AKAMAI | FASTER FORWARD™
PUSH Results
Conclusions
• Bad: too much, slows DOM complete
• Bad: too much can compete with preloader
• Bad: Wrong order congests network
• Good: Critical CSS & JS (& some images)
• Awesome: Network + Resource Timing
©2016 AKAMAI | FASTER FORWARD™
PUSH Results
Implementation questions
• Impact on Set-Cookie session tracking?
• REsponsive ServerSide?
• Client Hints?
©2016 AKAMAI | FASTER FORWARD™
Chapter 5: Epilogue
©2016 AKAMAI | FASTER FORWARD™
HTTP/2 PUSH_PROMISE
Programmatic accept
<?php
$transfers = 1;
​
$callback = function() use (&$transfers) {
$transfers++;
return CURL_PUSH_OK;
};
​
$mh = curl_multi_init();
​
curl_multi_setopt($mh, CURLMOPT_PIPELINING, CURLPIPE_MULTIPLEX);
curl_multi_setopt($mh, CURLMOPT_PUSHFUNCTION, $callback);
​
$ch = curl_init();
curl_setopt($ch, CURLOPT_VERBOSE, 1);
©2016 AKAMAI | FASTER FORWARD™
PUSH
What's Next:
• Browser & OS Support
• Automated PUSH using analytics
• Next page resources
• Host coalescing
©2016 AKAMAI | FASTER FORWARD™
PUSH
What about?
• Javascript / CSS / Image early processing?
• 3rd Party Content & Link=PreConnect ?
• PUSH to surrogate but not client?
• Delay & FlowControl: PUSH + Priorities
• Cache Management / Invalidation
©2016 AKAMAI | FASTER FORWARD™
PUSH
10? 10?7??
©2016 AKAMAI | FASTER FORWARD™
Thanks!
@ColinBendell

More Related Content

PDF
Developing the fastest HTTP/2 server
PDF
H2O - making the Web faster
PDF
Reorganizing Website Architecture for HTTP/2 and Beyond
PDF
How happy they became with H2O/mruby and the future of HTTP
PPTX
Programming TCP for responsiveness
PDF
HTTP/2で 速くなるとき ならないとき
PDF
H2O - the optimized HTTP server
PPTX
Cache aware-server-push in H2O version 1.5
Developing the fastest HTTP/2 server
H2O - making the Web faster
Reorganizing Website Architecture for HTTP/2 and Beyond
How happy they became with H2O/mruby and the future of HTTP
Programming TCP for responsiveness
HTTP/2で 速くなるとき ならないとき
H2O - the optimized HTTP server
Cache aware-server-push in H2O version 1.5

What's hot (20)

PDF
Programming TCP for responsiveness
PPTX
Recent Advances in HTTP, controlling them using ruby
PDF
HTTP2:新的机遇与挑战
PDF
HTTP/2: What no one is telling you
PDF
Make gRPC great again
PDF
IETF 100: Surviving IPv6 fragmentation
PPTX
HTTP/2 for Developers
PDF
Revisiting HTTP/2
PPTX
Are we really ready to turn off IPv4?
PPTX
Grpc present
PPTX
HTTP2 and gRPC
PDF
Nginx, PHP, Apache and Spelix
PDF
Enabling Googley microservices with HTTP/2 and gRPC.
PDF
Teach your (micro)services talk Protocol Buffers with gRPC.
PPTX
Introduction to Haproxy
PDF
Introduction to gRPC: A general RPC framework that puts mobile and HTTP/2 fir...
PPTX
Microservices summit talk 1/31
ODT
Load Balancing with HAproxy
PDF
Http2 right now
PDF
RIPE 71 and IETF 94 reports webinar
Programming TCP for responsiveness
Recent Advances in HTTP, controlling them using ruby
HTTP2:新的机遇与挑战
HTTP/2: What no one is telling you
Make gRPC great again
IETF 100: Surviving IPv6 fragmentation
HTTP/2 for Developers
Revisiting HTTP/2
Are we really ready to turn off IPv4?
Grpc present
HTTP2 and gRPC
Nginx, PHP, Apache and Spelix
Enabling Googley microservices with HTTP/2 and gRPC.
Teach your (micro)services talk Protocol Buffers with gRPC.
Introduction to Haproxy
Introduction to gRPC: A general RPC framework that puts mobile and HTTP/2 fir...
Microservices summit talk 1/31
Load Balancing with HAproxy
Http2 right now
RIPE 71 and IETF 94 reports webinar
Ad

Viewers also liked (11)

PDF
Edge 2016 h2 in the real world
PDF
Edge 2016 keeping tls secure
PDF
Quick primer on http2
PDF
Http2.0 Guide 2013-08-14 #http2study
PDF
Fluentd - road to v1 -
PPTX
Introducing HTTP/2
ODP
HTTP/2 and Java: Current Status
PDF
더 빠른 웹을 위해: HTTP/2
PDF
HTTP/2の課題と将来
PDF
H2O - making HTTP better
PDF
AWS Black Belt Tech シリーズ 2015 - Amazon Elastic MapReduce
Edge 2016 h2 in the real world
Edge 2016 keeping tls secure
Quick primer on http2
Http2.0 Guide 2013-08-14 #http2study
Fluentd - road to v1 -
Introducing HTTP/2
HTTP/2 and Java: Current Status
더 빠른 웹을 위해: HTTP/2
HTTP/2の課題と将来
H2O - making HTTP better
AWS Black Belt Tech シリーズ 2015 - Amazon Elastic MapReduce
Ad

Similar to Promise of Push (HTTP/2 Web Performance) (20)

PPTX
Load Balancing and Scaling with NGINX
PDF
Simpler Web Architectures Now! (At The Frontend 2016)
PPTX
Brug - Web push notification
PDF
Comet from JavaOne 2008
PDF
2nd AMIMOTO: WordPress + Amazon Web Services Singapore
PDF
WordPress + Amazon Web Services Hands-on WARSAW
PDF
AMIMOTO: WordPress + Amazon Web Services Hands-on WARSAW
PPTX
Chicago Tech Day Jan 2015: Foundry - HTTP2
PDF
Sencha Roadshow 2017: Build Progressive Web Apps with Ext JS and Cmd
PDF
Make It Fast - Using Modern Browser Performance APIs to Monitor and Improve t...
PPTX
Chanhao Jiang And David Wei Presentation Quickling Pagecache
PDF
Progressive web apps
PDF
Introducing Spring Cloud Gateway and API Hub for VMware Tanzu
PDF
4Developers 2018: Real-time capabilities in ASP.NET Core web applications (To...
PPTX
SenchaCon 2016: A Look Ahead: Survey Next-Gen Modern Browser APIs - Shikhir S...
KEY
The HTML5 WebSocket API
PDF
Ajax Push For Revolutionary Enterprise Applications
PDF
AMIMOTO: WordPress + Amazon Web Services MANILA
PPTX
NetScaler Web2.0 Push Technology Overview
KEY
DVWA BruCON Workshop
Load Balancing and Scaling with NGINX
Simpler Web Architectures Now! (At The Frontend 2016)
Brug - Web push notification
Comet from JavaOne 2008
2nd AMIMOTO: WordPress + Amazon Web Services Singapore
WordPress + Amazon Web Services Hands-on WARSAW
AMIMOTO: WordPress + Amazon Web Services Hands-on WARSAW
Chicago Tech Day Jan 2015: Foundry - HTTP2
Sencha Roadshow 2017: Build Progressive Web Apps with Ext JS and Cmd
Make It Fast - Using Modern Browser Performance APIs to Monitor and Improve t...
Chanhao Jiang And David Wei Presentation Quickling Pagecache
Progressive web apps
Introducing Spring Cloud Gateway and API Hub for VMware Tanzu
4Developers 2018: Real-time capabilities in ASP.NET Core web applications (To...
SenchaCon 2016: A Look Ahead: Survey Next-Gen Modern Browser APIs - Shikhir S...
The HTML5 WebSocket API
Ajax Push For Revolutionary Enterprise Applications
AMIMOTO: WordPress + Amazon Web Services MANILA
NetScaler Web2.0 Push Technology Overview
DVWA BruCON Workshop

Recently uploaded (20)

PPTX
AI Tools Revolutionizing Software Development Workflows
PDF
Difference Between Website and Web Application.pdf
PPTX
Post-Migration Optimization Playbook: Getting the Most Out of Your New Adobe ...
PDF
DOWNLOAD—IOBit Uninstaller Pro Crack Download Free
PPTX
oracle_ebs_12.2_project_cutoveroutage.pptx
PDF
Mobile App for Guard Tour and Reporting.pdf
PDF
MaterialX Virtual Town Hall - August 2025
PDF
10 Mistakes Agile Project Managers Still Make
PDF
Software Development Company - swapdigit | Best Mobile App Development In India
PPTX
Advanced Heap Dump Analysis Techniques Webinar Deck
PDF
OpenTimelineIO Virtual Town Hall - August 2025
PDF
OpenEXR Virtual Town Hall - August 2025
PPTX
ESDS_SAP Application Cloud Offerings.pptx
PDF
Ragic Data Security Overview: Certifications, Compliance, and Network Safegua...
PDF
How to Set Realistic Project Milestones and Deadlines
PDF
Science is Not Enough SPLC2009 Richard P. Gabriel
PDF
OpenImageIO Virtual Town Hall - August 2025
PDF
solman-7.0-ehp1-sp21-incident-management
PPTX
Hexagone difital twin solution in the desgining
PPTX
Phoenix Marketo User Group: Building Nurtures that Work for Your Audience. An...
AI Tools Revolutionizing Software Development Workflows
Difference Between Website and Web Application.pdf
Post-Migration Optimization Playbook: Getting the Most Out of Your New Adobe ...
DOWNLOAD—IOBit Uninstaller Pro Crack Download Free
oracle_ebs_12.2_project_cutoveroutage.pptx
Mobile App for Guard Tour and Reporting.pdf
MaterialX Virtual Town Hall - August 2025
10 Mistakes Agile Project Managers Still Make
Software Development Company - swapdigit | Best Mobile App Development In India
Advanced Heap Dump Analysis Techniques Webinar Deck
OpenTimelineIO Virtual Town Hall - August 2025
OpenEXR Virtual Town Hall - August 2025
ESDS_SAP Application Cloud Offerings.pptx
Ragic Data Security Overview: Certifications, Compliance, and Network Safegua...
How to Set Realistic Project Milestones and Deadlines
Science is Not Enough SPLC2009 Richard P. Gabriel
OpenImageIO Virtual Town Hall - August 2025
solman-7.0-ehp1-sp21-incident-management
Hexagone difital twin solution in the desgining
Phoenix Marketo User Group: Building Nurtures that Work for Your Audience. An...

Promise of Push (HTTP/2 Web Performance)

  • 1. ©2016 AKAMAI | FASTER FORWARD™ HTTP/2 Web Performance Promise of Push @ColinBendell Director, CTO Office
  • 2. ©2016 AKAMAI | FASTER FORWARD™ Desktop 90th50thBudget Mobile
  • 3. ©2016 AKAMAI | FASTER FORWARD™ Improving Perf: Blame the content
  • 4. ©2016 AKAMAI | FASTER FORWARD™ WebPageTest Looking for culprits
  • 5. ©2016 AKAMAI | FASTER FORWARD™ Time-To-First-Byte 25% of Perf. Budget is waiting Many causes: User (Network, Device, CPU), App Server, etc
  • 6. ©2016 AKAMAI | FASTER FORWARD™ Introducing Network Waste 1.48s (full throughput) 87.6% WASTE
  • 7. ©2016 AKAMAI | FASTER FORWARD™ Network Waste An opportunity to PUSH content Move the experience 87.6% WASTE
  • 8. ©2016 AKAMAI | FASTER FORWARD™ Chapter 1: PUSH on the Web
  • 9. ©2016 AKAMAI | FASTER FORWARD™ Direct TCP Poll/Long Poll Pushlets SSE Hasn't Push been solved?
  • 10. How to PUSH TCP/IP Socket (eg: XMPP) <stream:stream to='example.com' xmlns='jabber:client' version='1.0'> <stream:stream from='example.com' id='someid' xmlns='jabber:client' version='1.0'> <message from='[email protected]' to='[email protected]'> <body>Art thou not Romeo, and a Montague?</body> </message> <message from='[email protected]' to='[email protected]'> <body>Neither, fair saint, if either thee dislike.</body> </message> <message from='[email protected]' to='[email protected]'> <body>How camest thou hither, tell me, and wherefore? </body> </message>
  • 11. ©2016 AKAMAI | FASTER FORWARD™ How to PUSH TCP/IP Socket (eg: XMPP) • Proprietary & efficient • Any content could be sent • But requires app logic to encode/decode • Likely ports blocked by firewall rules
  • 12. How to PUSH Polling / Long Polling GET /messages HTTP/1.1 Host: queue.example.com Authorization: ... HTTP/1.1 200 OK Content-Length: 100 { "from": "[email protected]", "to": "[email protected]", "message: "Do you bite your thumb at us, sir? }
  • 13. ©2016 AKAMAI | FASTER FORWARD™ How to PUSH Polling / Long Polling • Ports 80/443 • Polling is chatty; has battery impacts • Custom protocol: requires app logic • Connection timeouts • Must manually handle disconnect & resume
  • 14. ©2016 AKAMAI | FASTER FORWARD™ How to PUSH Pushlet GET /messages HTTP/1.1 Host: queue.example.com Authorization: ... HTTP/1.1 200 OK Transfer-Encoding: Chunked Connection: keep-alive Content-Type: text/html <html><head/><body> <h1>Messages</h1> <p>From: [email protected]</p> <p>To: [email protected]</p> <p>I do bite my thumb, sir.</p> <p>From: [email protected]</p> <p>To: [email protected]</p> <p>No, sir, I do not bite my thumb at you, sir, but I bite my thumb, sir.<p>
  • 15. ©2016 AKAMAI | FASTER FORWARD™ How to PUSH Pushlet • No app logic required • Continuously "loading" UX • CPU/Network/Battery impacts? • Text only • Client must must detect connection loss
  • 16. ©2016 AKAMAI | FASTER FORWARD™ How to PUSH Server-Side-Events GET /messages HTTP/1.1 Host: api.example.com Accept: text/event-stream Authorization: ... Last-Event-ID: 41 HTTP/1.1 200 OK Connection: keep-alive Content-Type: text/event-stream Transfer-Encoding: chunked id: 42 event: receiveMessage data: { "from": "[email protected]", "to": "[email protected]", "message: "Do you bite your thumb at us, sir?} id: 43 event: stageAction data: { "from": "[email protected]", "to": "[email protected]", "message: "Do you bite your thumb at us, sir?}
  • 17. ©2016 AKAMAI | FASTER FORWARD™ How to PUSH Server-Side-Events HTTP/1.1 200 OK Connection: keep-alive Content-Type: text/event-stream Transfer-Encoding: chunked id: 42 event: recieveMessage data: { "from": "[email protected]", "to": "[email protected]", "message: "Do you bite your thumb at us, sir?} id: 43 event: stageAction data: { "from": "[email protected]", "to": "[email protected]", "message: "Do you bite your thumb at us, sir?} <script type="text/javascript"> var evtSource = new EventSource( "//api.example.com/messages", { withCredentials: true } ); evtSource.addEventListener("receiveMessage", function(e) { var newElement = document.createElement("p"); var obj = JSON.parse(e.data); newElement.innerHTML = "Message: " + obj.message; eventList.appendChild(newElement); }, false); </script>
  • 18. ©2016 AKAMAI | FASTER FORWARD™ How to PUSH Server-Side-Events • HTML5 browsers or Polyfill • Standard APIs • Text only messages • Intermediates must support flushing
  • 19. ©2016 AKAMAI | FASTER FORWARD™ HTTP/1.1 State of Push • Build it yourself • Requires app logic to be loaded • (generally) Text only • Messaging focused, not performance
  • 20. ©2016 AKAMAI | FASTER FORWARD™ WebRTC WebSocket HTTP/2 Push (Do we need yet another technology?) Wait! What about:
  • 21. ©2016 AKAMAI | FASTER FORWARD™ Peer-to-Peer with WebRTC • Peer to Peer • UDP (+FlowControl) • Web APIs • BYOA (bring your own app) • Usually: Audio/Video Flexibility: High RealTime: High Complexity: High
  • 22. ©2016 AKAMAI | FASTER FORWARD™ One-to-One with WebSockets • One-to-One (User to Server) • Bidirectional socket • Web APIs • BYOA (bring your own app) • Can by binary or text • Not cacheable Flexibility: Medium RealTime: High Complexity: Medium-High var ws = new WebSocket('wss://example.com/socket'); ws.onerror = function (error) { } ws.onclose = function () { } ws.onopen = function () { } ws.onmessage = function(msg) { if(msg.data instanceof Blob) { processBlob(msg.data); } else { processText(msg.data); } } Function sendMessage(msgText) { ws.send(msgText); }
  • 23. ©2016 AKAMAI | FASTER FORWARD™ One-to-Many with HTTP/2 Push • Many-to-One (Users to Server) • H2 standard • Cacheable • Transparent to app Flexibility: Medium RealTime: Low Complexity: Low [ 0.270] recv (stream_id=13) :method: GET [ 0.270] recv (stream_id=13) :path: /demo/h2/push.css [ 0.271] recv (stream_id=13) accept: */* [ 0.271] recv PUSH_PROMISE frame <length=72, flags=0x04, stream_id=13> ; END_HEADERS (padlen=0, promised_stream_id=2)
  • 24. ©2016 AKAMAI | FASTER FORWARD™ 9 (8+)6+ (4.4)
  • 25. ©2016 AKAMAI | FASTER FORWARD™ Overview HTTP/2 Basics Fix HTTP/1.1 Performance Other? ├ Head of Line Blocking ├ Parallelism ├ Header compression └ Backward Compatible ├ Prioritization ├ Flow Control └ Binary Protocol └ Server Push
  • 26. ©2016 AKAMAI | FASTER FORWARD™ Chapter 2: PUSH_PROMISE
  • 27. HTTP/2 PUSH_PROMISE Frame Basics PUSH_PROMISE :url: /push.css user-agent: chrome RST_STREAM DATA promised-stream-id: 2 a:hover {color: blue} … 2 2 … or ... 13
  • 28. ©2016 AKAMAI | FASTER FORWARD™ HTTP/2 Reading the Matrix $ nghttp https://www.colinbendell.com/demo/h2/pushtest.html -vv [ 0.135] Connected The negotiated protocol: h2 [ 0.230] send SETTINGS frame <length=12, flags=0x00, stream_id=0> (niv=2) [SETTINGS_MAX_CONCURRENT_STREAMS(0x03):100] [SETTINGS_INITIAL_WINDOW_SIZE(0x04):65535] [ 0.230] send PRIORITY frame <length=5, flags=0x00, stream_id=3> (dep_stream_id=0, weight=201, exclusive=0) [ 0.230] send PRIORITY frame <length=5, flags=0x00, stream_id=5> (dep_stream_id=0, weight=101, exclusive=0) [ 0.230] send PRIORITY frame <length=5, flags=0x00, stream_id=7> (dep_stream_id=0, weight=1, exclusive=0) Frame Name Bytes Odd = Client Initiated
  • 29. ©2016 AKAMAI | FASTER FORWARD™ [ 0.230] send HEADERS frame <length=60, flags=0x25, stream_id=13> ; END_STREAM | END_HEADERS | PRIORITY (padlen=0, dep_stream_id=11, weight=16, exclusive=0) ; Open new stream :method: GET :path: /demo/h2/pushtest.html :scheme: https :authority: www.colinbendell.com accept: */* accept-encoding: gzip, deflate user-agent: nghttp2/1.6.0 Familiar HTTP Request Pseudo Headers
  • 30. ©2016 AKAMAI | FASTER FORWARD™ [ 0.267] recv SETTINGS frame <length=30, flags=0x00, stream_id=0> (niv=5) [SETTINGS_HEADER_TABLE_SIZE(0x01):4096] [SETTINGS_MAX_CONCURRENT_STREAMS(0x03):100] [SETTINGS_INITIAL_WINDOW_SIZE(0x04):65535] [SETTINGS_MAX_FRAME_SIZE(0x05):16384] [SETTINGS_MAX_HEADER_LIST_SIZE(0x06):16384] [ 0.267] recv SETTINGS frame <length=0, flags=0x01, stream_id=0> ; ACK (niv=0) [ 0.267] send SETTINGS frame <length=0, flags=0x01, stream_id=0> ; ACK (niv=0) Flow Control
  • 31. ©2016 AKAMAI | FASTER FORWARD™ HTTP/2 PUSH_PROMISE [ 0.270] recv (stream_id=13) :method: GET [ 0.270] recv (stream_id=13) :path: /demo/h2/push.css [ 0.270] recv (stream_id=13) :authority: www.colinbendell.com [ 0.270] recv (stream_id=13) :scheme: https [ 0.270] recv (stream_id=13) host: www.colinbendell.com [ 0.271] recv (stream_id=13) accept: */* [ 0.271] recv (stream_id=13) user-agent: nghttp2/1.6.0 [ 0.271] recv (stream_id=13) accept-encoding: gzip, deflate [ 0.271] recv PUSH_PROMISE frame <length=72, flags=0x04, stream_id=13> ; END_HEADERS (padlen=0, promised_stream_id=2) Existing Stream Even: Server Initiated
  • 32. ©2016 AKAMAI | FASTER FORWARD™ [ 0.313] recv (stream_id=2, sensitive) :status: 200 [ 0.313] recv (stream_id=2, sensitive) server: Apache [ 0.313] recv (stream_id=2, sensitive) etag: "e00af44aba37028e02014b684 [ 0.313] recv (stream_id=2, sensitive) last-modified: Fri, 22 Apr 2016 [ 0.313] recv (stream_id=2, sensitive) accept-ranges: bytes [ 0.313] recv (stream_id=2, sensitive) content-length: 64 [ 0.313] recv (stream_id=2, sensitive) content-type: text/css [ 0.313] recv (stream_id=2, sensitive) cache-control: max-age=3571 [ 0.313] recv (stream_id=2, sensitive) expires: Sun, 24 Apr 2016 16:22: [ 0.313] recv (stream_id=2, sensitive) date: Sun, 24 Apr 2016 15:23:02 [ 0.313] recv HEADERS frame <length=469, flags=0x04, stream_id=2> ; END_HEADERS (padlen=0) [ 0.313] recv (stream_id=2, length=64, srecv=64, crecv=621) DATA Lorem;ipsum [ 0.313] recv DATA frame <length=64, flags=0x00, stream_id=2> [ 0.313] recv DATA frame <length=0, flags=0x01, stream_id=2> ; END_STREAM Delay, Push Response
  • 33. ©2016 AKAMAI | FASTER FORWARD™ HTTP/2 PUSH_PROMISE $ nghttp https://www.colinbendell.com/demo/h2/pushtest.html -vv --no-push [ 0.123] Connected The negotiated protocol: h2 [ 0.518] send SETTINGS frame <length=18, flags=0x00, stream_id=0> (niv=3) [SETTINGS_MAX_CONCURRENT_STREAMS(0x03):100] [SETTINGS_INITIAL_WINDOW_SIZE(0x04):65535] [SETTINGS_ENABLE_PUSH(0x02):0] Push Not Supported [ 0.230] send RST_STREAM frame <length=5, flags=0x07, stream_id=4> Push not accepted
  • 35. ©2016 AKAMAI | FASTER FORWARD™ Invoking
  • 36. ©2016 AKAMAI | FASTER FORWARD™ HTTP/2 PUSH How do I enable? HTTP/1.1 200 OK Content-Type: text/html Link: /jquery.js; rel=preload; as=script Link: /global.css; rel=preload; as=style 1. Use the ` Link: <URL>; rel=preload; as=style` notation Pros: • Easy to implement • H2O / nginX support Cons: • Too-Late; Is TTFB • Status & headers committed • Interferes with Browser's Pre-Loader
  • 37. ©2016 AKAMAI | FASTER FORWARD™ HTTP/2 PUSH How do I enable? public class MyServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String uri = request.getRequestURI(); if ("/index.html".equals(uri)) { String resourceToPush = "/js/jquery.js"; RequestDispatcher dispatcher = request.getRequestDispatcher(resourceToPush); dispatcher.push(request); } } } 2. Manually Instrument
  • 38. ©2016 AKAMAI | FASTER FORWARD™ HTTP/2 PUSH How do I enable? 2. Manually Instrument Pros: • Before TTFB • Not impacted by page • Can extend to Next Page Cons: • Another layer to maintain
  • 39. ©2016 AKAMAI | FASTER FORWARD™ Visualizing & Debug
  • 40. ©2016 AKAMAI | FASTER FORWARD™ Visualizing Results
  • 41. ©2016 AKAMAI | FASTER FORWARD™ Delayed Push with Link=preload
  • 42. ©2016 AKAMAI | FASTER FORWARD™ Manual Instrument (Jetty)
  • 43. ©2016 AKAMAI | FASTER FORWARD™ Push headers are 'provisional'
  • 44. ©2016 AKAMAI | FASTER FORWARD™ Timeline not helpful (Chrome 50)
  • 45. ©2016 AKAMAI | FASTER FORWARD™ Canary (52) shows PUSH in Timeline
  • 46. ©2016 AKAMAI | FASTER FORWARD™ HTTP/2 (Chrome) Adopted Push Stream chrome://net-internals to find unclaimed pushes Adopted pushes are logged (not a frame) * PUSH is kept in memory for 5 minutes and then get deleted if unclaimed
  • 47. ©2016 AKAMAI | FASTER FORWARD™ Debugging PUSH • Terminal: nghttp • Chrome: look for provisional header or use net-internals • Firefox: enabling logging • PUSHed content isn't added to cache until used in the page
  • 48. ©2016 AKAMAI | FASTER FORWARD™ Browser Behavior
  • 50. ©2016 AKAMAI | FASTER FORWARD™ HTTP/2 Connection Coalescing Coalescing is ignored by Chrome/FF
  • 51. ©2016 AKAMAI | FASTER FORWARD™ HTTP/2 Chrome Connection coalescing not avail if (!HostPortPair::FromURL(gurl).Equals(host_port_pair())) { if (proxy_delegate_ && proxy_delegate_->IsTrustedSpdyProxy( ProxyServer(ProxyServer::SCHEME_HTTPS, host_port_pair()))) { if (gurl.SchemeIs("https")) { EnqueueResetStreamFrame( stream_id, request_priority, RST_STREAM_REFUSED_STREAM, base::StringPrintf("Rejected push of cross origin HTTPS content %d " "from trusted proxy", associated_stream_id)); return false; } Only Host + Port considered! Boo!
  • 52. ©2016 AKAMAI | FASTER FORWARD™ Browser Support Implementation notes • PUSHed content from different hosts are rejected instead of coalescing • Only used PUSHes hit cache • FF uses init flow control of 64kb
  • 53. ©2016 AKAMAI | FASTER FORWARD™ Chapter 3: PUSH opportunity
  • 54. ©2016 AKAMAI | FASTER FORWARD™ www.rakuten.co.uk TTFB: Network Waste TTFB: 330ms 95.9% Waste
  • 55. ©2016 AKAMAI | FASTER FORWARD™ www.rakuten.co.uk Time-to-First-Resource TTFR: 762ms 91.1% Waste
  • 56. ©2016 AKAMAI | FASTER FORWARD™ www.rakuten.co.uk 33.7% Perf Waste 1.48s (full throughput) 87.6% WASTE Vis. Complete: 4.38s
  • 57. ©2016 AKAMAI | FASTER FORWARD™ www.forever21.com WPT: Network Waste 81.7% 0.6s (full throughput)
  • 58. ©2016 AKAMAI | FASTER FORWARD™ Browser Support Implementation notes • Measures opportunity to use the network ahead of DOM/Browser load • Indicator metric – NOT silver bullet • Examines WPT results • Tool to be released later this month
  • 59. ©2016 AKAMAI | FASTER FORWARD™ Chapter 4: Results
  • 60. ©2016 AKAMAI | FASTER FORWARD™ PUSH Results Insurance Site Original CSS/JSOriginal Everything Images
  • 61. ©2016 AKAMAI | FASTER FORWARD™ PUSH Results Cosmetics Site Original CSS/JS Everything Images
  • 62. ©2016 AKAMAI | FASTER FORWARD™ Automatic PUSH_PROMISE But when you get it Right: 5.27s 8.59s
  • 63. ©2016 AKAMAI | FASTER FORWARD™ PUSH Results Conclusions • Bad: too much, slows DOM complete • Bad: too much can compete with preloader • Bad: Wrong order congests network • Good: Critical CSS & JS (& some images) • Awesome: Network + Resource Timing
  • 64. ©2016 AKAMAI | FASTER FORWARD™ PUSH Results Implementation questions • Impact on Set-Cookie session tracking? • REsponsive ServerSide? • Client Hints?
  • 65. ©2016 AKAMAI | FASTER FORWARD™ Chapter 5: Epilogue
  • 66. ©2016 AKAMAI | FASTER FORWARD™ HTTP/2 PUSH_PROMISE Programmatic accept <?php $transfers = 1; ​ $callback = function() use (&$transfers) { $transfers++; return CURL_PUSH_OK; }; ​ $mh = curl_multi_init(); ​ curl_multi_setopt($mh, CURLMOPT_PIPELINING, CURLPIPE_MULTIPLEX); curl_multi_setopt($mh, CURLMOPT_PUSHFUNCTION, $callback); ​ $ch = curl_init(); curl_setopt($ch, CURLOPT_VERBOSE, 1);
  • 67. ©2016 AKAMAI | FASTER FORWARD™ PUSH What's Next: • Browser & OS Support • Automated PUSH using analytics • Next page resources • Host coalescing
  • 68. ©2016 AKAMAI | FASTER FORWARD™ PUSH What about? • Javascript / CSS / Image early processing? • 3rd Party Content & Link=PreConnect ? • PUSH to surrogate but not client? • Delay & FlowControl: PUSH + Priorities • Cache Management / Invalidation
  • 69. ©2016 AKAMAI | FASTER FORWARD™ PUSH 10? 10?7??
  • 70. ©2016 AKAMAI | FASTER FORWARD™ Thanks! @ColinBendell