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

Webperf: PHP after Server Push

Webperf: PHP after Server Push

Google recently announced that it will remove Server Push support from its flagship browser. Server Push is a technology that is part of the HTTP/2 and HTTP/3 standards. Server Push is designed to improve the performance of websites and web applications. Server Push is widely implemented in the PHP ecosystem: it is natively supported by most web servers as well as popular tools such as Symfony and API Platform. It is also the core of the Vulcan specification which allows creating very powerful and easy to cache web APIs.

The engineers at Google propose to use three technologies to replace Server Push, which they believe would be easier to use and implement and would allow performance gains almost similar to those of Server Push. These technologies are the Preload links, the HTTP return code "103 Early Hints" and the WebTransport JavaScript API. The PHP ecosystem and Vulcain already support the first two. The third one could eventually - if adopted by browsers and web servers - provide a modern (though low-level) alternative to WebSocket.

In this presentation, we will discover the use cases of each of these technologies, we will compare them with Server Push, and we will see how to use them in PHP (both client and server side). We will then see how Vulcain takes advantage of them.

Kévin Dunglas

May 28, 2021
Tweet

More Decks by Kévin Dunglas

Other Decks in Programming

Transcript

  1. @dunglas Kévin Dunglas ❏ Co-founder of Les-Tilleuls.coop ❏ Creator of

    API Platform, Vulcain, Mercure... ❏ Symfony Core Team WebLink, Panther, Serializer, PropertyInfo, autowiring, PSR-7 Bridge… 2 @dunglas
  2. @dunglas web, API and cloud experts ✊ Self-managed since 2011

    ⬆ 50 people, Lille, Paris, Nantes, Lyon, ... 👷 ➡ [email protected] Les-Tilleuls.coop 3
  3. @dunglas , powering the web since 1989 Hypertext Transfer Protocol,

    initiated by Tim Berners Lee at CERN… when I was 1 year old. 4
  4. @dunglas HTTP/1.1 : back to the basics ❏ RFC 2068

    (1997), replaced by RFC 7230 (2014) ❏ Client-server / Request-response ❏ Text protocol (ASCII) ❏ On top of TCP/IP ❏ Designed for performance at web-scale: cache 5
  5. @dunglas 6 $ telnet les-tilleuls.coop 80 GET /en/jobs HTTP/1.1 Host:

    les-tilleuls.coop User-Agent: MyBrowser Accept: text/html HTTP/1.1 200 OK Content-Type: text/html … <h1>Hi, AFUP folks!</h1> Connection closed by foreign host.
  6. @dunglas HTTP/2 : from text to binary ❏ RFC 7540

    (2015) ❏ Goal: a faster web ❏ same semantic and high level features as HTTP/1 ❏ Improved performance: binary protocol, multiplexing ❏ Server Push 7
  7. @dunglas HTTP/3 : from TCP to QUIC ❏ 🧪 Still

    an Internet Draft (RFC in 2021?) ❏ Goal: a faster web ❏ Same features as HTTP/2 ❏ Improved performance: new transport using QUIC (built on top of UDP) instead of TCP ❏ Server Push 11
  8. @dunglas HTTP/2, HTTP/3 and PHP 16 1. The web server

    manages the HTTP connection 2. The web server uses the (Fast)CGI protocol to call the PHP scripts 3. PHP sends a (Fast)CGI response, the web server converts it in an HTTP (1, 2 or 3) response ➡ keep this in mind: PHP doesn’t handle the HTTP (nor TCP/QUIC) connection directly
  9. @dunglas 18 ✌ Good news: no changes needed to your

    PHP apps to support HTTP/2 & 3 ✌
  10. @dunglas Caddy ❤ 19 { php_fastcgi unix//php-fpm.sock } ❏ Automatic

    HTTP/2 support, automatic TLS ❏ 💪 Server Push support ❏ Experimental HTTP/3 support (no server push support)
  11. @dunglas NGINX 20 server { listen 443 ssl http2; #

    ssl_certificate config # fastcgi_pass config } ❏ 💪 Server Push support ❏ HTTP/3 support under development
  12. @dunglas Apache 21 Listen 443 SSLEngine on # SSL config

    Protocols h2 http/1.1 ❏ 💪 Server Push support ❏ Currently no HTTP/3 support
  13. @dunglas h2/3 and PHP: at edge Edge servers natively supporting

    HTTP/2 and h3: ❏ Fastly ❏ Akamai ❏ Cloudflare When using one of these services, your origin server doesn’t have to support HTTP/2 or h3. 22
  14. @dunglas Server Push: internals ❏ Server Push is supported only

    with HTTP/2 and 3 ❏ The server sends to the client: ❏ A request 🤯, with headers, in a special frame: PUSH_PROMISE ❏ The response, in a new stream ❏ The client use the response if it matches a future request (headers are also checked) ❏ The client can refuse or cancel a push ❏ Push support is optional ❏ Supported by all major browsers (for now…) 26
  15. @dunglas 32 😱 Bad news: as PHP doesn’t handle the

    HTTP connection, it cannot create PUSH_PROMISE frames directly 😱
  16. @dunglas W3C Preload ❏ Keyword for the Link HTTP header

    to hint web servers to push resources to clients ❏ Supported by Caddy, NGINX, Apache, Cloudflare, Fastly, Akamai... 34
  17. @dunglas 35 The web server and the proxy will (may)

    push the linked resource using HTTP/2 or HTTP/3 Link: </build/app.css>; rel=preload; as=style Link: </build/app.js>; rel=preload; as=script
  18. @dunglas Removing Server Push? Why? 38 Why removing the iconic

    feature of HTTP/2? ❏ Rarely used in the wild (0,05% of the HTTP/2 conns) ❏ Footgun/“Over pushing”: only 40% of pushed requests are used: ❏ Resource pushed but already in the local cache ❏ Pushed request doesn’t match the actual one ❏ Invalid pushes ❏ Complexity in Chrome’s code base
  19. @dunglas Could we save Server Push? 39 ❏ The Internet

    Draft “Cache Digests for HTTP/2” (2019) proposes to fix the over-pushing problem ❏ It introduces a special frame using a Cuckoo-filter to allow the client to inform the server of its cache contents ❏ It’s unlikely to be implemented ❏ Similar solutions using cookies exist (ex: CASPer)
  20. @dunglas Alternatives? 41 In the mail thread proposing the withdrawal

    of Server Push, the Google team mentions 3 alternatives: ❏ WebTransport ❏ Preload and Resource Hints ❏ The 103 Status Code
  21. @dunglas WebTransport 43 ❏ W3C Editor Draft introducing a new

    JavaScript API to send data between a browser and a server using HTTP/3 and QUIC ❏ Replacement for WebSockets (compatible with HTTP/3, and more powerful) ❏ It’s a low level network API ❏ It’s not really comparable with Server Push: low level, verbose, requires JavaScript code
  22. @dunglas WebTransport Example async function receiveData(url, processTheData) { const wt

    = new WebTransport(url); for await (const readable of wt.incomingUnidirectionalStreams) { // consume streams individually, reporting per-stream errors (async () => { try { for await (const chunk of readable) { processTheData(chunk); } } catch (e) { console.error(e); } })(); } } 44
  23. @dunglas Preload / Resource Hints ❏ Two specs: Resource Hints

    and Preload ❏ W3C Working Drafts, widely implemented ❏ Keywords for the Link HTTP header to hint clients about resources they should load ❏ Hints the browser to preconnect/prerender/prefetch a resource ❏ Also work with the <link> HTML element 46 Link: </build/app.css>; rel=preload; as=style; nopush Link: </build/app.js>; rel=preload; as=script; nopush
  24. @dunglas Preload ❏ Preload links can be handled directly by

    the client (without a push) ❏ Fix the over-pushing/cache problem ❏ Also work with the <link> HTML element 47 Link: </build/app.css>; rel=preload; as=style; nopush Link: </build/app.js>; rel=preload; as=script; nopush
  25. @dunglas Relation types ❏ preload: early, mandatory, high priority download

    ❏ prefetch: early, optional, low priority, download ❏ prerender: early, optional, low priority, rendering by the browser (example: next page) ❏ dns_prefetch: early DNS lookup ❏ preconnect: early DNS lookup, TCP handshake and (optional) TLS negotiation 48
  26. @dunglas Preload vs Server Push Benefits ❏ Takes the local

    cache into account (no over pushing) ❏ Works with HTTP 1, 2 and 3 ❏ Already implemented by major browsers ❏ Supported by all servers (simple header) Disadvantage ❏ The browser must wait for all headers to be received before downloading the resource 49
  27. @dunglas Symfony WebLink Component ❏ Manages and serializes any HTTP

    Link headers ❏ Uses the PSR-13 (Link interface) ❏ Standalone PHP library ❏ But also integrated in Symfony Full Stack ❏ Implements W3C Preload and Resource Hints specs ❏ Provides a bunch of useful Twig helpers 52
  28. @dunglas In the Browser 58 A push will be triggered

    by the web server if supported by the browser and if there is no nopush directive. Otherwise, fallback on preload Link.
  29. @dunglas Other Built-in Twig Helpers ❏ link() ❏ preload() ❏

    dns_prefetch() ❏ preconnect() ❏ prefetch() ❏ prerender() 59
  30. @dunglas 103 Early Hints 61 ❏ Experimental spec (RFC 8297)

    introducing a new HTTP Status Code: 103 ❏ Informational response that contains headers that are likely to be included in the final response ❏ Can be sent before knowing the final status code and headers ❏ Designed to be used with Preload ❏ Designed from the ground up as an alternative to Server Push
  31. @dunglas 103 Early Hints HTTP/1.1 103 Early Hints Link: </style.css>;

    rel=preload; as=style Link: </script.js>; rel=preload; as=script HTTP/1.1 200 OK ... Link: </style.css>; rel=preload; as=style Link: </script.js>; rel=preload; as=script <!doctype html>... 62
  32. @dunglas 103 vs Server Push Benefits ❏ Takes the local

    cache into account (no over pushing) ❏ Works with HTTP 1, 2 and 3 ❏ Low latency, only 1 RTT ❏ Less complex to implement Disadvantage ❏ 1 more RTT (SP = 0 RTT) 63
  33. @dunglas Other implementations ❏ Already supported by Apache (configurable) ❏

    Experimental module for NGINX (no signal regarding an official support) ❏ Not implemented by Firefox, but likely to happen ❏ Not implemented by Safari 66
  34. @dunglas PHP and the 103 status code Problem ❏ CGI/FastCGI

    doesn’t support sending multiple HTTP responses ❏ Putting the final response in the body of the CGI response doesn’t work with h2 and h3 (binary protocol) Possible solutions ❏ Replace FastCGI by a pure HTTP server (ex: AMPHP HTTP Server) ❏ Hack FastCGI (ex: using extension headers) ❏ Publish a new revision of the CGI RFC (unlikely) 69
  35. @dunglas Upgrade Path 72 ❏ Use “Preload” links ❏ Send

    a 103 response ❏ Configure the web server fallback on Server Push if browser doesn’t support Early Hints ❏ Measure to check that it works as expected ❏ Profit!
  36. @dunglas The Future of Vulcain 74 ❏ Vulcain-style APIs works

    equally well with Server Push and Early Hints ❏ The Vulcain spec supports Preload links and Early Hints since day 1 ❏ Vulcain APIs benefit from a better local cache ❏ The Vulcain Gateway Server support Preload links since day 1 ❏ The dev version for VGS supports Early Hints with HTTP/3 (h1 and h2 support in progress)
  37. @dunglas Summary ❏ Server Push was promising and is widely

    available, but it has issues and Chrome is killing it ❏ Preload links are widely available, and better than nothing ❏ Early Hints are the new kids on the block, and there is an upgrade path from Server Push! Use HTTP/2 and HTTP/3 and Preload right now Vulcain is more relevant than ever, expect some exciting news soon! 76