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
    Webperf:
    PHP after
    Server Push
    1

    View full-size slide

  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

    View full-size slide

  3. @dunglas
    web, API and cloud experts
    ✊ Self-managed since 2011
    ⬆ 50 people, Lille, Paris, Nantes, Lyon, ...
    👷 ➡ [email protected]
    Les-Tilleuls.coop
    3

    View full-size slide

  4. @dunglas
    , powering
    the web since 1989
    Hypertext Transfer Protocol, initiated by Tim Berners Lee at CERN…
    when I was 1 year old.
    4

    View full-size slide

  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

    View full-size slide

  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

    Hi, AFUP folks!
    Connection closed by foreign host.

    View full-size slide

  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

    View full-size slide

  8. @dunglas
    HTTP/2: frames and streams
    8
    © Narayan Prustyq
    qnimate.com/what-is-multiplexing-in-http2/

    View full-size slide

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

    View full-size slide

  10. @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

    View full-size slide

  11. @dunglas
    HTTP/3 global support: 68%
    of all internet users
    12

    View full-size slide

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

    View full-size slide

  13. @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

    View full-size slide

  14. @dunglas 17
    © Loginsoft

    View full-size slide

  15. @dunglas 18
    ✌ Good news:
    no changes needed
    to your PHP apps to
    support
    HTTP/2 & 3 ✌

    View full-size slide

  16. @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)

    View full-size slide

  17. @dunglas
    NGINX
    20
    server {
    listen 443 ssl http2;
    # ssl_certificate config
    # fastcgi_pass config
    }
    ❏ 💪 Server Push support
    ❏ HTTP/3 support under development

    View full-size slide

  18. @dunglas
    Apache
    21
    Listen 443
    SSLEngine on
    # SSL config
    Protocols h2 http/1.1
    ❏ 💪 Server Push support
    ❏ Currently no HTTP/3 support

    View full-size slide

  19. @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

    View full-size slide

  20. @dunglas
    Server Push
    23

    View full-size slide

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

    View full-size slide

  22. @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

    View full-size slide

  23. @dunglas
    Server Push and
    web APIs
    27

    View full-size slide

  24. @dunglas 28
    Vulcain: API resources preloading

    View full-size slide

  25. @dunglas
    Server Push and PHP
    30

    View full-size slide

  26. @dunglas
    Reminder
    31
    © Loginsoft

    View full-size slide

  27. @dunglas 32
    😱 Bad news:
    as PHP doesn’t handle the HTTP
    connection,
    it cannot create
    PUSH_PROMISE frames
    directly 😱

    View full-size slide

  28. @dunglas
    The Preload Spec ⚡
    33

    View full-size slide

  29. @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

    View full-size slide

  30. @dunglas
    35
    The web server and the proxy will (may) push the
    linked resource using HTTP/2 or HTTP/3
    Link: ; rel=preload; as=style
    Link: ; rel=preload; as=script

    View full-size slide

  31. @dunglas
    Drama time 😱
    36

    View full-size slide

  32. @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

    View full-size slide

  33. @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)

    View full-size slide

  34. @dunglas
    What are the
    alternatives?
    40

    View full-size slide

  35. @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

    View full-size slide

  36. @dunglas
    WebTransport
    42

    View full-size slide

  37. @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

    View full-size slide

  38. @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

    View full-size slide

  39. @dunglas
    The Preload Spec
    (continued) ⚡
    45

    View full-size slide

  40. @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 HTML element
    46
    Link: ; rel=preload; as=style; nopush
    Link: ; rel=preload; as=script; nopush

    View full-size slide

  41. @dunglas
    Preload
    ❏ Preload links can be handled directly by the client
    (without a push)
    ❏ Fix the over-pushing/cache problem
    ❏ Also work with the HTML element
    47
    Link: ; rel=preload; as=style; nopush
    Link: ; rel=preload; as=script; nopush

    View full-size slide

  42. @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

    View full-size slide

  43. @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

    View full-size slide

  44. @dunglas
    Preload global support: 92% of
    all internet users
    50

    View full-size slide

  45. @dunglas
    The Symfony WebLink
    Component
    Preload and Early Hints from any PHP app!
    51

    View full-size slide

  46. @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

    View full-size slide

  47. @dunglas
    Install
    53
    composer req symfony/web-link
    Or with Flex:
    composer req web-link

    View full-size slide

  48. @dunglas
    Standalone usage
    54

    View full-size slide

  49. @dunglas
    In a Symfony controller
    55

    View full-size slide

  50. @dunglas
    In Twig
    56

    View full-size slide

  51. @dunglas
    Resulting Header
    57

    View full-size slide

  52. @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.

    View full-size slide

  53. @dunglas
    Other Built-in Twig Helpers
    ❏ link()
    ❏ preload()
    ❏ dns_prefetch()
    ❏ preconnect()
    ❏ prefetch()
    ❏ prerender()
    59

    View full-size slide

  54. @dunglas
    103 Early Hints 🤩
    60

    View full-size slide

  55. @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

    View full-size slide

  56. @dunglas
    103 Early Hints
    HTTP/1.1 103 Early Hints
    Link: ; rel=preload; as=style
    Link: ; rel=preload; as=script
    HTTP/1.1 200 OK
    ...
    Link: ; rel=preload; as=style
    Link: ; rel=preload; as=script
    ...
    62

    View full-size slide

  57. @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

    View full-size slide

  58. @dunglas
    Chrome is implementing it
    64

    View full-size slide

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

    View full-size slide

  60. @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

    View full-size slide

  61. @dunglas
    PHP is working on it
    67

    View full-size slide

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

    View full-size slide

  63. @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

    View full-size slide

  64. @dunglas
    Upgrade Path
    70

    View full-size slide

  65. @dunglas
    Upgrade path: Chrome will not remove
    Server Push until 103 is rolling out
    71

    View full-size slide

  66. @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!

    View full-size slide

  67. @dunglas
    The Future of
    Vulcain
    73

    View full-size slide

  68. @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)

    View full-size slide

  69. @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

    View full-size slide

  70. @dunglas 77
    Thanks!
    @dunglas
    @coopTilleuls

    View full-size slide