Wordpress skálázás Varnish segítségével

Gergely Pál Dávid - night[w]

Statzup Kft.

@nightw17

Cloud Budapest - 2015. 03. 04. ​​

A probléma

  • Eredeti alkalmazáshoz nem akarsz/nem lehet hozzányúlni

  • Az alkalmazás lecserélése nem opció

  • Kellene horizontális skálázódás, de ezzel az alkalmazással azt nem igazán lehet 

Megoldási lehetőségek

  • SaaS (wordpress.com)

  • PHP + MySQL skálázás

  • Caching

Mi kell a harmadikhoz?

  • Legalább részben statikus alkalmazás

    • Amit lehet tegyél statikussá, ha még nem az

Tegyem statikussá?

  • Kommentek outsource-olása

    • Facebook

    • Disquis

    • Egyéb javascriptes megoldás

  • Admin felület leválasztása

És milyen cache?

  • Rugalmas és nagy teljesítményű megoldás: Varnish

  • Saját konfigurációs nyelv (VCL)

    • Bármilyen egyedi logika írható benne

    • És a végén közvetlen c kódra fordul

  • Sok plugin

Varnish alapok

  • Tulajdonképpen egy HTTP proxy + cache megoldás
  • Egy nagy állapotgép
  • Fontos állapotok:
    • vcl_recv
    • vcl_fetch (Varnish4: vcl_backend_response)

Default vcl_recv

sub vcl_recv {
    if (req.method == "PRI") {
        /* We do not support SPDY or HTTP/2.0 */
        return (synth(405));
    }
    if (req.method != "GET" &&
      req.method != "HEAD" &&
      req.method != "PUT" &&
      req.method != "POST" &&
      req.method != "TRACE" &&
      req.method != "OPTIONS" &&
      req.method != "DELETE") {
        /* Non-RFC2616 or CONNECT which is weird. */
        return (pipe);
    }
    if (req.method != "GET" && req.method != "HEAD") {
        /* We only deal with GET and HEAD by default */
        return (pass);
    }
    if (req.http.Authorization || req.http.Cookie) {
        /* Not cacheable by default */
        return (pass);
    }
    return (hash);
}

Default vcl_backend_response

sub vcl_backend_response {
    if (beresp.ttl <= 0s ||
      beresp.http.Set-Cookie ||
      beresp.http.Surrogate-control ~ "no-store" ||
      (!beresp.http.Surrogate-Control &&
        beresp.http.Cache-Control ~ "no-cache|no-store|private") ||
      beresp.http.Vary == "*") {
        /*
        * Mark as "Hit-For-Pass" for the next 2 minutes
        */
        set beresp.ttl = 120s;
        set beresp.uncacheable = true;
    }
    return (deliver);
}

Egyedi konfigurációs dolgok

  • Security
  • Hibatűrés
  • HTTPS
  • CORS

Security

sub vcl_recv {
    [...]
    # Deny every "non-read" requests
    if (req.method != "GET" &&
            req.method != "HEAD" &&
            req.method != "OPTIONS") {
        return (synth(405, "Method Not Allowed"));
    }
    # Do not serve wp-admin folder, wp-cron.php, any XMLRPC or login requests, just deny it
    if (req.url ~ "^/wp-admin" || req.url ~ "^/wp-cron.php" ||
        req.url ~ "^/xmlrpc\.php" || req.url ~ "^/wp-login\.php") {
        return (synth(403, "Forbidden"));
    }
    [...]
}
sub vcl_synth {
    # If it's a 403 then we add some HTML content decribing the error
    # Also add some nice HTML text for the browsers
    if (resp.status == 403) {
        set resp.http.Content-Type = "text/html; charset=utf-8";
        synthetic( {"<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
                "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
            <html><head><title>403 Forbidden</title></head>
                [...]
            </html>
        "} );
        return (deliver);
    }
}

Hibatűrés

sub vcl_backend_response {
    # The normal TTL should be 10 minutes, since the pages/images usually don't change often
    set beresp.ttl = 10m;

    # We want the object's max grace to be high to be able to serve old
    # content during a backend outage, since that's much better than no
    # content in our case
    set beresp.grace = 36h;
}

HTTPS

sub vcl_hash {
    # Also store different versions of a page based on X-Forwarded-Proto
    # header, since that means different css/js/etc. urls for seemingly the
    # same page (Wordpress inner logic decides it)
    hash_data(req.http.X-Forwarded-Proto);
}
  • Varnish alapból nem tudja
  • Pl. Nginx vagy Haproxy a Varnish elé
  • Wordpress támogatás (plugin?) az X-Forwarded-Proto header-höz

CORS

sub vcl_recv {
    # If we got an Origin header which we do not expect, than we just simply
    # ignore it to make sure the cache will not explode because of Origin
    # headers (since it will be used in hash a bit below)
    if (req.http.Origin !~ "^.*[\.\/]domain\.com$" && req.http.Origin !~ "^domain\.com$") {
        unset req.http.Origin;
    }
}
sub vcl_backend_response {
    # Adding CORS headers to the response if an Origin header was present in
    # the incoming request. Basically just following the W3C recommendation
    # (santizing/cleaning is done in vcl_recv to avoid enabling access to every source)
    if (bereq.http.Origin) {
        set beresp.http.Access-Control-Allow-Origin = bereq.http.Origin;
        set beresp.http.Access-Control-Allow-Headers = "Content-Type, Accept";
        set beresp.http.Access-Control-Allow-Methods = "GET, OPTIONS";
    }
}
sub vcl_hash {
    # Store different responses regarding to the Origin header (which was
    # stripped/cleaned in vcl_recv to make sure users cannot explode the cache
    # size with sending in different, "non-valid"/not accepted Origin headers)
    hash_data(req.http.Origin);
}

Köszönöm szépen

Kérdések?

Gergely Pál Dávid - night[w]

Statzup Kft.

@nightw17

Cloud Budapest - 2015. 03. 04. ​​

Wordpress skálázása Varnish segítségével

By Pál Dávid Gergely (nightw)

Wordpress skálázása Varnish segítségével

Hogyan skálázzunk fel egy "átlagos" PHP alkalmazást a kód módosítása nélkül?

  • 692