Strona Główna / Blog

Bliżej i Szybciej w Globalnej Skali. Prześwietlamy Usługę [email protected]

Przemek Malak

Przemek Malak

AWS Architect (Development) w Chmurowisku. Ponad 18 lat w branży IT. Architekt rozwiązań chmurowych i mobilnych oraz Programista (przez duże P). Entuzjasta rozwiązań Serverless, posiadacz kilku certyfikacji AWS (Architect, Developer, SysOps).

Serverless. Słowo, o którym w ubiegłym roku słyszał chyba każdy programista i architekt systemów IT. Wszystko wskazuje na to, że rok 2019 będzie dla architektury bezserwerowej jeszcze ciekawszy. Wiele osób sądzi, że właśnie w ciągu najbliższych kilku miesięcy rozwiązania serverless będą rozwijały się szybciej niż jakakolwiek inna dziedzina IT. No, może poza kolejnymi frameworkami Node.Js ;-)

Kiedy pada hasło serverless, pierwsze, co przychodzi mi do głowy, to usługa AWS Lambda. Praktycznie każdy o niej słyszał, nie każdy jednak wie, że Lambdę można uruchamiać także w usłudze CloudFront, czyli w oferowanym przez Amazon rozwiązaniu content delivery network. Dzieje się tak dzięki usłudze [email protected].

Jak uruchomić funkcję [email protected]?

Funkcję [email protected] możemy wywołać za pomocą czterech eventów, które mamy do dyspozycji w CloudFront:

  • Viewer Request. Zachodzi, kiedy CloudFront otrzymuje żądanie od użytkownika przed sprawdzeniem, czy dane są w schowku.
  • Origin Request to event, który wywoływany jest jedynie, kiedy żądanie przekazane jest do źródła. Jeżeli dane są już w schowku, ten event nie jest uruchamiany.
  • Origin Response uruchamiany jest pomiędzy momentem, w którym CloudFront otrzymuje odpowiedź od źródła, a chwilą, gdy odpowiedź ląduje w schowku. Co istotne, Origin Response zachodzi także wtedy, gdy źródło zwróci błąd.
  • Viewer Response uruchamiany jest z kolei przed zwróceniem obiektu do użytkownika. Niezależnie od tego, czy był w schowku, czy nie.
Lambda at Edge events

Kiedy użyć danego eventu?

Wybór metod uruchamiających [email protected] jest całkiem spory. Nasuwa się zatem pytanie, kiedy użyć poszczególnych eventów. W każdym przypadku trzeba do tej kwestii podejść indywidualnie. Przygotowałem jednak kilka wskazówek, które mogą pomóc Ci w wyborze.

  • Jeżeli chcemy uruchomić naszą funkcję dla każdego żądania, skorzystajmy z eventu ViewerRequest lub ViewerResponse. Pierwszy będzie uruchomiony zawsze, drugi prawie za każdym razem.
  • W przypadku gdy chcemy zmodyfikować samo żądanie tak, że zmieni ono odpowiedź źródła, użyjmy eventu OriginRequest.
  • Chcąc zmienić obiekt, który zostanie zapisany w schowku CloudFront, użyjmy eventu OriginRequest lub OriginResponse.

Ograniczenia [email protected]

[email protected] w porównaniu z klasycznymi funkcjami Lambda posiada wiele ograniczeń. Najważniejszym z nich, przynajmniej dla mnie, jest fakt, że funkcje [email protected] możemy pisać tylko w Node.Js. O innych językach możemy jak na razie zapomnieć. Mam jednak nadzieję, że wkrótce to się zmieni.

Drugą kwestią są warstwy i zmienne środowiskowe. Zapomnijcie o nich! Te drugie możemy zastąpić AWS Systems Manager Parameter Store. Ale zawsze wprowadzi to jakieś opóźnienia. A maksymalne timeouty w [email protected] też mamy krótsze. Dla OriginRequest i OriginResponse to 30 sekund. Dla eventów ViewerRequest oraz ViewerResponse to tylko 5 sekund.

Do tego dochodzi jeszcze więcej limitów. Na szczęście sporo z nich to tak zwane ograniczenia miękkie, co oznacza, że możemy poprosić o ich zwiększenie. Także sama wielkość funkcji, rozmiar odpowiedzi oraz maksymalna ilość pamięci, którą możemy przydzielić funkcjom @Edge, są mniejsze od standardowych.

A jak korzystać z [email protected]? Oto przykład

Spróbujemy zaimplementować przykładową funkcję [email protected] Nasze rozwiązanie pozwoli na generowanie za pomocą Lambdy strony www. Jej treść będziemy zmieniali w zależności od kraju, z którego łączy się nasz użytkownik.

Jeżeli wykorzystamy usługę CloudFront, czy to bezpośrednio, czy też implementując nasze API w usłudze API Gateway jako Edge Optimized, w żądaniu zostaną nam przekazane różne nagłówki. Między innymi nagłówek CloudFront-Viewer-Country.

Na podstawie tego nagłówka funkcja [email protected] będzie generowała kod HTML zwracany do użytkownika.

Nasze rozwiązanie będzie składało się z kilku elementów:

  • statycznej strony www w usłudze S3
  • dystrybucji CloudFront
  • funkcji Lambda podpiętej pod event OriginRequest

Proponuję utworzyć zarówno koszyk S3 jak i funkcję Lambda w regionie N. Virginia. Funkcje [email protected] możemy tworzyć tylko w tym regionie!

1.   Piszemy kod strony WWW

W pierwszym kroku musimy utworzyć bucket S3, wgrać do niego poniższy kod i uruchomić w tym koszyku hosting. Kod strony www, która będzie wyświetlana z S3 jest bardzo prosty.

Hello unknown from S3

Strona będzie po prostu nas informowała, że nie można rozpoznać kraju, z którego użytkownik łączy się z naszą usługą. Do tej strony „podepniemy” też dystrybucję CloudFront.

Cała magia będzie się działa w funkcji [email protected] umieszczonej w CloudFront. To ona będzie generowała właściwą odpowiedź w zależności od kraju, z którego pochodzi nasz użytkownik.

1.   Tworzymy funkcję Lambda

W kolejnym kroku musimy utworzyć funkcję Lambda. Pamiętajcie o regionie – N. Virginia.

Tworzymy zwykłą Lambdę, jako runtime wybieramy Node.Js 8.10. Wystarczy nam domyślna rola, która nada uprawnienia do zapisu logów w usłudze CloudWatch.

Teraz musimy dodać [email protected] do zaufanych (Trust relationships).

Po wprowadzeniu tych zmian nasza polityka powinna wyglądać tak:

Kod samej funkcji jest prosty. W nagłówkach wyszukuje kraj, z którego łączy się nasz użytkownik i wstawia go do kodu HTML, który jest zwracany do użytkownika. Jeżeli nagłówka nie ma, zwraca po prostu żądanie.

Hello ${cloudFrontCountryCode} from Lambda @Edge!

3.   Ustalamy wersję

O wersjach i aliasach funkcji Lambda pisałem już na naszym blogu. Aby nasza Lambda mogła być wykorzystana jako funkcja [email protected], musimy opublikować jej wersję. W usłudze CloudFront podepniemy później ARN opublikowanej wersji.

W konsoli wybieramy menu Actions i opcję Publish new version. Możemy dodać też jakiś opis. Po chwili nasza wersja będzie gotowa.

Po utworzeniu wersji w górnej części konsoli wyświetli nam się ARN dla naszej funkcji.

Skopiujmy go sobie, będzie potrzebny za chwilę.

4.   Dystrybucja CloudFront

Mamy nasz bucket, mamy Lambdę, stwórzmy teraz powiązaną z nimi dystrybucję CloudFront.

  1. Jako Origin Domain Name wybieramy nasz bucket. To z niego będą pobierane w razie potrzeby dane.
  2. Przekierowujemy też wywołania HTTP na HTTPS w sekcji Default Cache Behavior Settings.
  1. W kolejnym kroku musimy dodać do białej listy nagłówek, którym będziemy się posługiwali.
  1. Teraz najważniejsze. Musimy podpiąć funkcję Lambda pod dystrybucję. Wybieramy interesujący nas event, czyli OriginRequest i wklejamy ARN do naszej funkcji Lambda. Pamiętajcie, że powinien to być ARN opublikowanej wersji.
  1. I to właściwie wszystko. Klikamy [Create Distribution] i nasza dystrybucja zaczyna się tworzyć.

Po 15-30 minutach dystrybucja powinna być gotowa. Możemy przejść do testowania naszego rozwiązania.

CloudFront – Testy i logi

Każda dystrybucja CloudFront ma swoje DomainName. Skorzystajmy z przeglądarki i przetestujmy jej działanie.

Włączamy narzędzia programisty w Chrome, wklejamy adres naszej dystrybucji w przeglądarce i… voilà!

Dostaliśmy odpowiedź od naszej funkcji [email protected]

W przeglądarce, w zakładce Network, klikamy w odpowiedź z serwera i sprawdzamy nagłówki.

Sprawdźmy teraz, co mamy w logach. Wchodzimy do usługi CloudWatch w regionie N. Virginia i… nic tam nie ma.

Na początku mnie to także zdziwiło. [email protected] zapisuje bowiem logi w regionie, w którym jest wywoływana (albo najbliższym). Ja łączyłem się z Polski, sprawdźmy więc, co słychać we Frankfurcie.

Jak widać, wszystko jest w porządku. Nasza Lambda zadziałała, a logi zostały zapisane.

Odświeżmy stronę i sprawdźmy, co się stanie:

Tym razem nasza strona została załadowana ze schowka, bez uruchamiania funkcji [email protected] W logach nie będziemy mieli zatem nic nowego.

Spróbujmy połączyć się teraz z innego kraju. Najlepiej wykorzystać do tego jakieś połączenie VPN. Ja użyję PureVPN ale możecie użyć np. TunnelBear. Na potrzeby naszego testu wystarczy, a jest darmowy. Połączyłem się z serwerem VPN w Holandii.

Kolejna próba w Chrome i przenosimy się do kraju tulipanów.

Tym razem nagłówek x-cache miał wartość Miss from cloudfront. Dlaczego? Było to pierwsze wywołanie z Holandii i CloudFront nie miał jeszcze w schowku właściwej odpowiedzi. Ponownie zadziałała nasza [email protected]:

Usuwamy zasoby

Usuwanie zasobów związanych z [email protected] przysparza nieco problemów. Pamiętajmy, że nasze funkcje replikowane są do poszczególnych miejsc docelowych. W moim przypadku przy kasowaniu [email protected] zadziałał taki scenariusz:

  1. Odłączyłem funkcję od dystrybucji CloudFront. Można to zrobić w ustawieniach dystrybucji w sekcji Behavior.
  2. Dałem CloudFrontowi trochę czasu. Przynajmniej 30 minut. (Raz musiałem czekać prawie 2 godziny!)
  3. Usunąłem funkcję.

Jeżeli używamy CloudFormation, prawie na pewno będzie konieczna dwukrotna próba usunięcia stacka. Za pierwszym razem operacja usunięcia funkcji się nie powiedzie.

Co z tą Lambdą@Edge?

Udostępniona w 2017 roku usługa [email protected] jest potężnym narzędziem o wielu zastosowaniach.

Za jej pomocą możemy na przykład sprawdzać wartości cookies w żądaniach i na tej podstawie przekierowywać użytkowników na inne adresy URL. Korzystając z nagłówka user-agent, możemy obługiwać różne rozmiary zdjęć. Nie będzie także wielkim problemem wykonanie autoryzacji żądań.

Jeśli chcielibyście odkryć jeszcze więcej zastosowań [email protected], w oficjalnej dokumentacji można znaleźć wiele przykładów na ciekawe wykorzystanie tej usługi. Miłej zabawy!

Dołącz do listy mailingowej!

Dołącz do naszego newslettera

Staramy się wysyłać tylko wartościowe informacje, np. co miesiąc dostaniesz spis najważniejszych nowości z chmur Azure, AWS i GCP, z krótkimi opisami i linkami.