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!

Już 22.11 zapraszamy na webinar
o chmurze Google Cloud Platform

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.