AWS - dostarczanie treści za pomocą CloudFront
06.VII.2017

Spis treści

  1. Czym jest CloudFront
  2. Przygotowanie do konfiguracji CloudFront
  3. Przygotowanie S3
  4. Konfiguracja CloudFront
  5. Test treści dynamicznych
  6. Treści statyczne serwowane z S3
  7. Problemy z komunikacją
  8. Pliki logów

Czym jest CloudFront

AWS Clo­ud­Front wy­glą­da jak dość roz­bu­do­wa­ny CDN (Con­tent De­li­ve­ry Ne­twork). Po­zwa­la nie tylko na do­star­cza­nie tre­ści sta­tycz­nych naj­bli­żej, pod wzglę­dem po­ło­że­nia na kuli ziem­skiej, użyt­kow­ni­ka (czyli to co po­tra­fi stan­dar­do­wy CDN) ale rów­nież można w niego nie­ja­ko wpleść tre­ści do­star­cza­ne dy­na­micz­nie.

Wszyst­kie tre­ści po­bie­ra­ne są za­wsze z ser­we­ra źró­dło­we­go (ori­gin se­rver) i na pod­sta­wie usta­wień w na­głów­kach 'Cache-Con­trol' w od­po­wie­dzi od ser­we­ra, którą uzy­ska Clo­ud­Front, prze­cho­wy­wa­ne są przez wska­za­ny czas w lo­ka­li­za­cjach brze­go­wych. Zatem dla po­niż­szych usta­wień Clo­ud­Front za­cho­wa się:

Wię­cej in­for­ma­cji na temat na­głów­ka Cache-Con­trol znaj­du­je się w do­ku­men­ta­cji MDN: Cache-Con­trol.

Przygotowanie do konfiguracji CloudFront

Sta­wia­my ser­wer WWW np. na EC2 (in­struk­cja w AWS:Hello EC2 lub do­wol­ny inny). Do tego przy­kła­du po­słu­ży pusty ser­wer na Ubun­tu z No­deJs na po­kła­dzie. Po za­lo­go­wa­niu do ser­we­ra uru­cha­mia­my plik se­rver.js z po­niż­szą za­war­to­ścią. Wszyst­kie wy­ni­ki jego dzia­ła­nia będą przed­sta­wia­ne na kon­so­li.

// \> nodejs server.js 80
//
var http = require('http');

var app = http.createServer(function(req,res) {

    // zeby Chrome ciagle nie pytal
    if ('/favicon.ico' === req.url) {
        res.statusCode = 404;
        res.end();
        return;
    }

    if ('/' === req.url || '/initgo' === req.url) {
        // dane prywatne bez buforowania
        res.setHeader('Cache-Control', 'no-cache, no-store, must-revalidate');
        // dane statyczne-publiczne
        //res.setHeader('Cache-Control', 'public, max-age=60');
    }

    var now = (new Date()).toISOString();
    console.log(`${now} >>`, `url:${req.url}`);

    res.statusCode = 200;
    res.end('Teraz mamy: ' + now);
    // Teraz mamy: 2017-07-06T17:36:01.640Z
});

app.listen(process.argv[2] || 1337);

Przygotowanie S3

W AWS S3 two­rzy­my nowy po­jem­nik (jeśli do tej pory nie ist­niał) ja­ka­sna­zwa.s3.​amazonaws.​com a w nim po­niż­szą struk­tu­rę ka­ta­lo­gów.

Kli­ka­my pra­wym na ka­ta­log cf-sta­tic/ i wy­bie­ra­my opcję Make pu­blic tak aby wszyst­kie ele­men­ty w tym ka­ta­lo­gu były do­stęp­ne pu­blicz­nie. Ina­czej Clo­ud­Front nie bę­dzie ich w sta­nie prze­ka­zać użyt­kow­ni­ko­wi koń­co­we­mu.

Jeśli w me­ta­da­nych pliku pol.​png usta­wi­my klucz Cache-Con­trol to zo­sta­nie on wy­bra­ny za­miast usta­wie­nia do­myśl­ne­go w De­fault TTL.

Konfiguracja CloudFront

Aby usłu­ga Clo­ud­Front prze­ka­zy­wa­ła ser­we­ro­wi in­for­ma­cję o pań­stwie z któ­re­go po­cho­dzi żą­da­nie na­le­ży wska­zać aby do za­py­tań był do­łą­cza­ny na­głó­wek Clo­ud­Front-Vie­wer-Co­un­try.

Test treści dynamicznych

Wy­ni­ki dla wej­ścia na stro­nę http://​cf.​pieszynski.​com/ z ad­re­sów w Pol­sce i USA.

Ścież­ka wi­dzia­na przez ser­wer - /in­it­go - wy­ni­ka z usta­wie­nia do­myśl­ne­go De­fault Root Ob­ject. Do­ce­lo­wo pew­nie zna­la­zł­by się tam wpis index.​html.

ubuntu@ip:~$ nodejs server.js
2017-07-06T17:26:44.680Z >> url:/initgo, headers: {
  'user-agent': 'Amazon CloudFront',
  'x-forwarded-for': 'xxx.PL.IP.xxx',
  'cloudfront-viewer-country': 'PL',
  'x-pp-front': 'EC2_v1'
  }
2017-07-06T17:27:37.736Z >> url:/initgo, headers: {
  'user-agent': 'Amazon CloudFront',
  'x-forwarded-for': 'yyy.US.IP.yyy',
  'cloudfront-viewer-country': 'US',
  'x-pp-front': 'EC2_v1' 
  }

Za każ­dym razem na­głó­wek X-Cache ma war­tość Miss from clo­ud­front czyli za­war­tość mu­sia­ła być od­świe­żo­na z ser­we­ra źró­dło­we­go a na kon­so­li ser­we­ra WWW po­ja­wia­ją się wpisy dla każ­de­go wy­wo­ła­nia.

HTTP/1.1 200 OK
Content-Length: 36
Connection: keep-alive
Cache-Control: no-cache, no-store, must-revalidate
X-Cache: Miss from cloudfront
Via: 1.1 zzz.cloudfront.net (CloudFront)

Treści statyczne serwowane z S3

W tym przy­pad­ku na­le­ży zwró­cić uwagę, że po skon­fi­gu­ro­wa­niu Path Pat­tern na sta/* Clo­ud­Front bę­dzie uży­wał pod­ka­ta­lo­gu cf-sta­tic/ z wska­za­ne­go po­jem­ni­ka do­da­jąc do niego CAŁĄ ścież­kę z ad­re­su URL. Czyli dla ad­re­su http://​cf.​pieszynski.​com/​sta/​pol2.​png plik musi znaj­do­wać się w ka­ta­lo­gu bez­względ­nym w S3 cf-sta­tic/sta/pol2.​png a nie cf-sta­tic/pol2.​png!

Wy­ni­ki dla wej­ścia na stro­nę http://​cf.​pieszynski.​com/​sta/​pol2.​png.

HTTP/1.1 200 OK
Content-Type: image/png
ETag: "e0012d..."
Server: AmazonS3
X-Cache: Miss from cloudfront

HTTP/1.1 304 Not Modified
ETag: "e0012d..."
Server: AmazonS3
Age: 59
X-Cache: Hit from cloudfront

HTTP/1.1 304 Not Modified
ETag: "e0012d..."
Server: AmazonS3
X-Cache: RefreshHit from cloudfront

Problemy z komunikacją

Gdy Clo­ud­Front do­star­cza dane z ser­we­ra WWW a ten w pew­nym mo­men­cie prze­sta­nie od­po­wia­dać to Clo­ud­Front ser­wu­je dane z bu­fo­ra przez ko­lej­ne pięć minut nie od­py­tu­jąc w tym cza­sie ani razu ser­we­ra WWW (nie­za­leż­nie od tego co było usta­wio­ne w Cache-Con­trol). Wię­cej in­for­ma­cji na ten temat w do­ku­men­ta­cji: How Clo­ud­Front Pro­ces­ses and Ca­ches HTTP 4xx and 5xx Sta­tus Codes from Your Ori­gin

Pliki logów

#Version: 1.0
#Fields: date time x-edge-location sc-bytes c-ip cs-method cs(Host) cs-uri-stem sc-status cs(Referer) cs(User-Agent) cs-uri-query cs(Cookie) x-edge-result-type x-edge-request-id x-host-header cs-protocol cs-bytes time-taken x-forwarded-for ssl-protocol ssl-cipher x-edge-response-result-type cs-protocol-version
2017-07-06  17:35:55    WAW50   361 xxx.xxx.xxx.xxx GET dxxxxxxx.cloudfront.net /   200 -   Mozilla/    -   -   Miss    ==  cf.pieszynski.com   http    407 0.088   -   -   -   Miss    HTTP/1.1
2017-07-06  17:35:59    WAW50   361 xxx.xxx.xxx.xxx GET dxxxxxxx.cloudfront.net /   200 -   Mozilla/    -   -   Miss    ==  cf.pieszynski.com   http    433 0.053   -   -   -   Miss    HTTP/1.1
2017-07-06  17:36:01    WAW50   361 xxx.xxx.xxx.xxx GET dxxxxxxx.cloudfront.net /   200 -   Mozilla/    -   -   Miss    ==  cf.pieszynski.com   http    433 0.114   -   -   -   Miss    HTTP/1.1