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


  1. @dunglas Webperf: PHP after Server Push 1

  2. @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
  3. @dunglas web, API and cloud experts ✊ Self-managed since 2011

    ⬆ 50 people, Lille, Paris, Nantes, Lyon, ... 👷 ➡ jobs@les-tilleuls.coop Les-Tilleuls.coop 3
  4. @dunglas , powering the web since 1989 Hypertext Transfer Protocol,

    initiated by Tim Berners Lee at CERN… when I was 1 year old. 4
  5. @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
  6. @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.
  7. @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
  8. @dunglas HTTP/2: frames and streams 8 © Narayan Prustyq qnimate.com/what-is-multiplexing-in-http2/

  9. @dunglas HTTP/2 global support: 97% of all internet users 9

  10. @dunglas 10

  11. @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
  12. @dunglas HTTP/3 global support: 68% of all internet users 12

  13. @dunglas 13

  14. @dunglas 14

  15. @dunglas HTTP/2, HTTP/3 and PHP 15

  16. @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
  17. @dunglas 17 © Loginsoft

  18. @dunglas 18 ✌ Good news: no changes needed to your

    PHP apps to support HTTP/2 & 3 ✌
  19. @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)
  20. @dunglas NGINX 20 server { listen 443 ssl http2; #

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

    Protocols h2 http/1.1 ❏ 💪 Server Push support ❏ Currently no HTTP/3 support
  22. @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
  23. @dunglas Server Push 23

  24. @dunglas 24

  25. @dunglas 25 © Simone Border slideshare.net/SimoneBordet/http2-and-java-current-status

  26. @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
  27. @dunglas Server Push and web APIs 27

  28. @dunglas 28 Vulcain: API resources preloading

  29. @dunglas 29

  30. @dunglas Server Push and PHP 30

  31. @dunglas Reminder 31 © Loginsoft

  32. @dunglas 32 😱 Bad news: as PHP doesn’t handle the

    HTTP connection, it cannot create PUSH_PROMISE frames directly 😱
  33. @dunglas The Preload Spec ⚡ 33

  34. @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
  35. @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
  36. @dunglas Drama time 😱 36

  37. @dunglas 37

  38. @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
  39. @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)
  40. @dunglas What are the alternatives? 40

  41. @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
  42. @dunglas WebTransport 42

  43. @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
  44. @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
  45. @dunglas The Preload Spec (continued) ⚡ 45

  46. @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
  47. @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
  48. @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
  49. @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
  50. @dunglas Preload global support: 92% of all internet users 50

  51. @dunglas The Symfony WebLink Component Preload and Early Hints from

    any PHP app! 51
  52. @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
  53. @dunglas Install 53 composer req symfony/web-link Or with Flex: composer

    req web-link
  54. @dunglas Standalone usage 54

  55. @dunglas In a Symfony controller 55

  56. @dunglas In Twig 56

  57. @dunglas Resulting Header 57

  58. @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.
  59. @dunglas Other Built-in Twig Helpers ❏ link() ❏ preload() ❏

    dns_prefetch() ❏ preconnect() ❏ prefetch() ❏ prerender() 59
  60. @dunglas 103 Early Hints 🤩 60

  61. @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
  62. @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
  63. @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
  64. @dunglas Chrome is implementing it 64

  65. @dunglas Go is working on it (Vulcain/Caddy) 65 dunglas.fr/2021/02/using-the-103-early-hints-status-code-in-go-applications/

  66. @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
  67. @dunglas PHP is working on it 67

  68. @dunglas 68 © Loginsoft But we have a problem

  69. @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
  70. @dunglas Upgrade Path 70

  71. @dunglas Upgrade path: Chrome will not remove Server Push until

    103 is rolling out 71
  72. @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!
  73. @dunglas The Future of Vulcain 73

  74. @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)
  75. @dunglas 75

  76. @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
  77. @dunglas 77 Thanks! @dunglas @coopTilleuls