Architektura zorientowana na usługi z AWS Lambda: samouczek krok po kroku
Opublikowany: 2022-03-11Tworząc aplikacje internetowe, należy dokonać wielu wyborów, które mogą pomóc lub utrudnić twoją aplikację w przyszłości, gdy się do nich zobowiążesz. Kluczowe są wybory, takie jak język, struktura, hosting i baza danych.
Jednym z takich wyborów jest utworzenie aplikacji opartej na usługach przy użyciu architektury zorientowanej na usługi (SOA) lub tradycyjnej, monolitycznej aplikacji. Jest to powszechna decyzja architektoniczna, która dotyczy zarówno start-upów, przedsiębiorstw typu scale-up, jak i przedsiębiorstw.
Architektura zorientowana na usługi jest wykorzystywana przez wiele znanych jednorożców i czołowych firm technologicznych, takich jak Google, Facebook, Twitter, Instagram i Uber. Pozornie ten wzorzec architektury sprawdza się w dużych firmach, ale czy może zadziałać dla Ciebie?
W tym artykule przedstawimy temat architektury zorientowanej na usługi oraz w jaki sposób można wykorzystać AWS Lambda w połączeniu z Pythonem do łatwego tworzenia skalowalnych, efektywnych kosztowo usług. Aby zademonstrować te pomysły, zbudujemy prostą usługę przesyłania i zmiany rozmiaru obrazów za pomocą Pythona, AWS Lambda, Amazon S3 i kilku innych odpowiednich narzędzi i usług.
Czym jest architektura zorientowana na usługi?
Architektura zorientowana na usługi (SOA) nie jest nowa i ma korzenie sprzed kilkudziesięciu lat. W ostatnich latach jego popularność jako wzorca rośnie, ponieważ oferuje wiele korzyści dla aplikacji internetowych.
SOA jest w istocie abstrakcją jednej dużej aplikacji na wiele mniejszych komunikujących się aplikacji. Wynika to z kilku najlepszych praktyk inżynierii oprogramowania, takich jak oddzielenie, oddzielenie problemów i architektura pojedynczej odpowiedzialności.
Implementacje SOA różnią się pod względem szczegółowości: od bardzo niewielu usług obejmujących duże obszary funkcjonalności do wielu dziesiątek lub setek małych aplikacji w tak zwanej architekturze „mikrousług”. Niezależnie od poziomu szczegółowości, co jest ogólnie przyjęte wśród praktyków SOA, to w żadnym wypadku nie jest to darmowy lunch. Podobnie jak wiele dobrych praktyk w inżynierii oprogramowania, jest to inwestycja, która będzie wymagała dodatkowego planowania, rozwoju i testowania.
Co to jest Lambda AWS?
AWS Lambda to usługa oferowana przez platformę Amazon Web Services. AWS Lambda umożliwia wgranie kodu, który będzie uruchamiany na kontenerze na żądanie zarządzanym przez Amazon. AWS Lambda będzie zarządzać udostępnianiem i zarządzaniem serwerami do uruchamiania kodu, więc wszystko, czego potrzebujesz od użytkownika, to spakowany zestaw kodu do uruchomienia i kilka opcji konfiguracyjnych do zdefiniowania kontekstu, w którym działa serwer. Te zarządzane aplikacje są nazywane funkcjami Lambda.
AWS Lambda ma dwa główne tryby pracy:
Asynchroniczne/sterowane zdarzeniami:
Funkcje lambda mogą być uruchamiane w odpowiedzi na zdarzenie w trybie asynchronicznym. Żadne źródło zdarzeń, takie jak S3, SNS itp., nie będzie blokować, a funkcje Lambda mogą to wykorzystać na wiele sposobów, na przykład ustanawiając potok przetwarzania dla jakiegoś łańcucha zdarzeń. Źródeł informacji jest wiele i w zależności od źródła zdarzenia zostaną przekazane do funkcji Lambda ze źródła zdarzenia lub odpytane o zdarzenia przez AWS Lambda.
Synchroniczne/Żądanie->Odpowiedź:
W przypadku aplikacji, które wymagają synchronicznego zwrócenia odpowiedzi, Lambda można uruchomić w trybie synchronicznym. Zazwyczaj jest to używane w połączeniu z usługą API Gateway do zwracania odpowiedzi HTTP z AWS Lambda do użytkownika końcowego, jednak funkcje Lambda mogą być również wywoływane synchronicznie poprzez bezpośrednie wywołanie AWS Lambda.
Funkcje AWS Lambda są ładowane jako plik zip zawierający kod handlera oprócz wszelkich zależności wymaganych do działania handlera. Po przesłaniu AWS Lambda wykona ten kod w razie potrzeby i skaluje liczbę serwerów od zera do tysięcy w razie potrzeby, bez dodatkowej interwencji wymaganej przez konsumenta.
Funkcje lambda jako ewolucja SOA
Podstawowa SOA to sposób na uporządkowanie bazy kodu w małe aplikacje w celu uzyskania korzyści dla aplikacji w sposób opisany wcześniej w tym artykule. W związku z tym zwraca się uwagę na sposób komunikacji między tymi aplikacjami. SOA sterowana zdarzeniami (inaczej SOA 2.0) pozwala nie tylko na tradycyjną bezpośrednią komunikację między usługami, jak w przypadku SOA 1.0, ale także na propagację zdarzeń w całej architekturze w celu komunikowania zmian.
Architektura sterowana zdarzeniami to wzorzec, który w naturalny sposób promuje luźne łączenie i komponowanie. Tworząc i reagując na zdarzenia, usługi mogą być dodawane ad hoc, aby dodać nową funkcjonalność do istniejącego zdarzenia, a kilka zdarzeń można skomponować w celu zapewnienia bogatszej funkcjonalności.
AWS Lambda może służyć jako platforma do łatwego budowania aplikacji SOA 2.0. Istnieje wiele sposobów na wywołanie funkcji Lambda; od tradycyjnego podejścia do kolejki wiadomości z Amazon SNS, po zdarzenia utworzone przez przesłanie pliku do Amazon S3 lub wiadomość e-mail wysyłaną za pomocą Amazon SES.
Wdrażanie prostej usługi przesyłania obrazów
Zbudujemy prostą aplikację do przesyłania i pobierania obrazów przy użyciu stosu AWS. Ten przykładowy projekt będzie zawierał dwie funkcje lambda: jedną działającą w trybie żądanie->odpowiedź, która posłuży do obsługi naszego prostego interfejsu internetowego, oraz drugą, która będzie wykrywać przesłane obrazy i zmieniać ich rozmiar.
Pierwsza funkcja lambda będzie działać asynchronicznie w odpowiedzi na zdarzenie przesyłania pliku wyzwolone w zasobniku S3, w którym będą przechowywane przesłane obrazy. Przejmie dostarczony obraz i zmieni jego rozmiar, aby zmieścił się w obrazie 400x400.
Druga funkcja lambda będzie obsługiwała stronę HTML, zapewniając użytkownikowi zarówno funkcjonalność przeglądania obrazów przeskalowanych przez naszą inną funkcję Lambda, jak i interfejs do przesyłania obrazu.
Wstępna konfiguracja AWS
Zanim zaczniemy, będziemy musieli skonfigurować niektóre niezbędne usługi AWS, takie jak IAM i S3. Zostaną one skonfigurowane za pomocą internetowej konsoli AWS. Jednak większość konfiguracji można również uzyskać za pomocą narzędzia wiersza poleceń AWS, którego użyjemy później.
Tworzenie zasobników S3
S3 (lub Simple Storage Service) to usługa magazynu obiektów Amazon, która oferuje niezawodne i ekonomiczne przechowywanie dowolnych danych. Będziemy używać S3 do przechowywania obrazów, które zostaną przesłane, a także przetworzonych przez nas wersji obrazów o zmienionym rozmiarze.
Usługę S3 można znaleźć w menu rozwijanym „Usługi” w konsoli AWS w podsekcji „Przechowywanie i dostarczanie treści”. Podczas tworzenia zasobnika zostaniesz poproszony o podanie zarówno nazwy zasobnika, jak i o wybranie regionu. Wybranie regionu blisko użytkowników pozwoli S3 na optymalizację pod kątem opóźnień i kosztów, a także niektórych czynników regulacyjnych. W tym przykładzie wybierzemy region „US Standard”. Ten sam region będzie później używany do obsługi funkcji AWS Lambda.
Warto zauważyć, że nazwy wiader S3 muszą być unikalne, więc jeśli wybrana nazwa zostanie zajęta, będziesz musiał wybrać nową, unikalną nazwę.
W tym przykładowym projekcie utworzymy dwa zasobniki pamięci o nazwach „przesyłanie testowe” i „przesyłanie testowe”. Zasobnik „przesyłanie testowe” będzie używany do przesyłania obrazów i przechowywania przesłanego obrazu przed jego przetworzeniem i zmianą rozmiaru. Po zmianie rozmiaru obraz zostanie zapisany w zasobniku „testowa zmiana rozmiaru”, a przesłany nieprzetworzony obraz zostanie usunięty.
Uprawnienia do przesyłania S3
Domyślnie uprawnienia S3 są restrykcyjne i nie pozwalają użytkownikom zewnętrznym ani nawet użytkownikom bez uprawnień administracyjnych na odczytywanie, zapisywanie, aktualizowanie lub usuwanie jakichkolwiek uprawnień lub obiektów w zasobniku. Aby to zmienić, musimy być zalogowani jako użytkownik z uprawnieniami do zarządzania uprawnieniami zasobnika AWS.
Zakładając, że jesteśmy w konsoli AWS, możemy wyświetlić uprawnienia do naszego zasobnika przesyłania, wybierając zasobnik według nazwy, klikając przycisk „Właściwości” w prawym górnym rogu ekranu i otwierając zwiniętą sekcję „Uprawnienia”.
Aby umożliwić anonimowym użytkownikom przesyłanie do tego zasobnika, musimy edytować zasady zasobnika, aby zezwolić na określone uprawnienia umożliwiające przesyłanie. Jest to realizowane za pomocą zasad konfiguracji opartych na JSON. Tego rodzaju zasady JSON są powszechnie używane w AWS w połączeniu z usługą IAM. Po kliknięciu przycisku „Edytuj zasady zasobnika” po prostu wklej następujący tekst i kliknij „Zapisz”, aby zezwolić na przesyłanie obrazów publicznych:
{ "Version": "2008-10-17", "Id": "Policy1346097257207", "Statement": [ { "Sid": "Allow anonymous upload to /", "Effect": "Allow", "Principal": { "AWS": "*" }, "Action": "s3:PutObject", "Resource": "arn:aws:s3:::test-upload/*" } ] }Po wykonaniu tej czynności możemy zweryfikować poprawność zasad zasobnika, próbując przesłać obraz do zasobnika. Poniższe polecenie cURL załatwi sprawę:
curl https://test-upload.s3.amazonaws.com -F 'key=test.jpeg' -F '[email protected]'Jeśli zostanie zwrócona odpowiedź z zakresu 200, będziemy wiedzieć, że konfiguracja zasobnika przesyłania została pomyślnie zastosowana. Nasze zasobniki S3 powinny być teraz (w większości) skonfigurowane. Wrócimy później do tej usługi w konsoli, aby połączyć nasze zdarzenia przesyłania obrazu z wywołaniem naszej funkcji zmiany rozmiaru.
Uprawnienia IAM dla Lambda
Wszystkie role Lambda działają w kontekście uprawnień, w tym przypadku „roli” zdefiniowanej przez usługę IAM. Ta rola definiuje wszelkie uprawnienia, jakie posiada funkcja Lambda podczas jej wywołania. Na potrzeby tego przykładowego projektu utworzymy ogólną rolę, która będzie używana między obiema funkcjami Lambda. Jednak w scenariuszu produkcyjnym zaleca się większą szczegółowość definicji uprawnień, aby zapewnić, że wszelkie sposoby wykorzystania zabezpieczeń są izolowane tylko do zdefiniowanego kontekstu uprawnień.
Usługę IAM można znaleźć w podsekcji „Bezpieczeństwo i tożsamość” w menu „Usługi”. Usługa IAM jest bardzo potężnym narzędziem do zarządzania dostępem do usług AWS, a dostarczony interfejs może być początkowo nieco przytłaczający, jeśli nie znasz podobnych narzędzi.
Po wejściu na stronę panelu uprawnień, po lewej stronie znajdziesz podsekcję „Role”. Stąd możemy użyć przycisku „Utwórz nową rolę”, aby wywołać wieloetapowego kreatora, aby zdefiniować uprawnienia roli. Użyjmy „lambda_role” jako nazwy naszego ogólnego zezwolenia. Po przejściu ze strony definicji nazwy zostanie wyświetlona opcja wyboru typu roli. Ponieważ wymagamy tylko dostępu do S3, kliknij „AWS Service Roles” i w polu wyboru wybierz „AWS Lambda”. Zostanie wyświetlona strona z politykami, które można dołączyć do tej roli. Wybierz politykę „AmazonS3FullAccess” i przejdź do następnego kroku, aby potwierdzić rolę, która ma zostać utworzona.
Należy zwrócić uwagę na nazwę i ARN (Amazon Resource Name) utworzonej roli. Będzie to użyte podczas tworzenia nowej funkcji Lambda w celu zidentyfikowania roli, która ma być użyta do wywołania funkcji.
Uwaga: AWS Lambda automatycznie rejestruje wszystkie dane wyjściowe z wywołań funkcji w AWS Cloudwatch, usłudze rejestrowania. Jeśli ta funkcjonalność jest pożądana, co jest zalecane dla środowiska produkcyjnego, uprawnienia do zapisu w strumieniu dziennika Cloudwatch muszą być dodane do polityk dla tej roli.
Kod!
Przegląd
Teraz jesteśmy gotowi do rozpoczęcia kodowania. Założymy, że w tym momencie skonfigurowałeś polecenie „awscli”. Jeśli nie, możesz postępować zgodnie z instrukcjami na https://aws.amazon.com/cli/, aby skonfigurować awscli na swoim komputerze.
Uwaga: kod użyty w tych przykładach został skrócony, aby ułatwić przeglądanie ekranu. Pełniejszą wersję można znaleźć w repozytorium pod adresem https://github.com/gxx/aws-lambda-python/.
Najpierw stwórzmy szkielet dla naszego projektu.
aws-lambda-python/ - image_list/ - handler.py - list.html - Makefile - requirements.txt - image_resize/ - handler.py - resize.py - Makefile - requirements.txt - .pydistutils.cfgW naszej strukturze mamy dwa podkatalogi, po jednym dla każdej funkcji lambda. W każdym z nich mamy wspólne pliki handler.py, Makefile i Requirements.txt. Plik handler.py będzie zawierał metodę do wywołania każdej z funkcji lambda i może być uważany za punkt wejścia funkcji. Plik wymagania.txt będzie zawierał listę naszych zależności, dzięki czemu będziemy mogli łatwo określić i zaktualizować wymagania. Na koniec polecenie Makefile, którego użyjemy, aby zapewnić łatwy mechanizm interakcji z awscli. Ułatwi to proces tworzenia i aktualizowania naszej funkcji lambda.
Zauważysz plik .pydistutils.cfg w katalogu głównym naszego katalogu projektu. Ten plik jest wymagany, jeśli pracujesz z Pythonem w Homebrew. Ze względu na sposób wdrażania funkcji Lambda (opisany w następnym rozdziale) plik ten jest potrzebny. Zobacz repozytorium po więcej szczegółów.
Funkcja zmiany rozmiaru obrazu Lambda
Kod
Zaczynając od funkcji resize_image, zamrozimy zależność Wand, naszą bibliotekę przetwarzania obrazu, zapisując Wand==0.4.2 w pliku Requirements.txt. Będzie to jedyna zależność dla naszej funkcji lambda image_resize. Funkcja resize_image w resize.py będzie musiała obsłużyć zasób obrazu z biblioteki Wand i zmienić jego rozmiar zgodnie z określonymi parametrami szerokości i wysokości. Aby zachować obraz, którego rozmiar jest zmieniany, użyjemy algorytmu „najlepszego dopasowania”, który zachowa proporcje oryginalnego obrazu, jednocześnie zmniejszając rozmiar obrazu, aby pasował do określonej szerokości i wysokości.
def resize_image(image, resize_width, resize_height): ... original_ratio = image.width / float(image.height) resize_ratio = resize_width / float(resize_height) # We stick to the original ratio here, regardless of what the resize ratio is if original_ratio > resize_ratio: # If width is larger, we base the resize height as a function of the ratio of the width resize_height = int(round(resize_width / original_ratio)) else: # Otherwise, we base the width as a function of the ratio of the height resize_width = int(round(resize_height * original_ratio)) if ((image.width - resize_width) + (image.height - resize_height)) < 0: filter_name = 'mitchell' else: filter_name = 'lanczos2' image.resize(width=resize_width, height=resize_height, filter=filter_name, blur=1) return image Pomijając to, funkcja obsługi jest wymagana do zaakceptowania zdarzenia wygenerowanego przez obraz przesłany do S3, przekazania go funkcji resize_image i zapisania wynikowego obrazu o zmienionym rozmiarze.

from __future__ import print_function import boto3 from wand.image import Image from resize import resize_image def handle_resize(event, context): # Obtain the bucket name and key for the event bucket_name = event['Records'][0]['s3']['bucket']['name'] key_path = event['Records'][0]['s3']['object']['key'] response = boto3.resource('s3').Object(bucket_name, key_path).get() # Retrieve the S3 Object # Perform the resize operation with Image(blob=response['Body'].read()) as image: resized_data = resize_image(image, 400, 400).make_blob() # And finally, upload to the resize bucket the new image s3_connection.Object('test-resized', key_path).put(ACL='public-read', Body=resized_data) # Finally remove, as the bucket is public and we don't want just anyone dumping the list of our files! s3_object.delete()Wdrażam
Po ukończeniu kodu należy go przesłać do Amazon Lambda jako nową funkcję Lambda. W tym miejscu do gry wchodzi Makefile, który został dodany do struktury katalogów. Ten plik Makefile zostanie użyty do wdrożenia definicji funkcji Lambda, które tworzymy.
ROLE_ARN = arn:aws:iam::601885388019:role/lambda_role FUNCTION_NAME = ResizeImage REGION = us-west-1 TIMEOUT = 15 MEMORY_SIZE = 512 ZIPFILE_NAME = image_resize.zip HANDLER = handler.handle_resize clean_pyc : find . | grep .pyc$ | xargs rm install_deps : pip install -r requirements.txt -t . build : install_deps clean_pyc zip $(ZIPFILE_NAME) -r * create : build aws lambda create-function --region $(REGION) \ --function-name $(FUNCTION_NAME) \ --zip-file fileb://$(ZIPFILE_NAME) \ --role $(ROLE_ARN) \ --handler $(HANDLER) \ --runtime python2.7 \ --timeout $(TIMEOUT) \ --memory-size $(MEMORY_SIZE) update : build aws lambda update-function-code --region $(REGION) \ --function-name $(FUNCTION_NAME) \ --zip-file fileb://$(ZIPFILE_NAME) \ --publish Główne funkcje tego Makefile to „tworzenie” i „aktualizacja”. Te funkcje najpierw pakują bieżący katalog, który reprezentuje cały kod niezbędny do uruchomienia funkcji Lambda. Następnie wszelkie zależności określone w pliku requirements.txt zostaną zainstalowane w bieżącym podkatalogu, który ma zostać spakowany. Etap pakowania zip zawartości katalogu do późniejszego załadowania za pomocą polecenia „awscli”. Nasz Makefile można dostosować do użycia w innych definicjach funkcji Lambda.
W narzędziu Makefile definiujemy kilka zmiennych niezbędnych do tworzenia/aktualizacji naszego obrazu. Skonfiguruj je w razie potrzeby, aby polecenia Makefile działały poprawnie.
-
ROLE_ARN: To jest nazwa zasobu Amazon, która identyfikuje naszą rolę, w ramach której uruchamiamy funkcję Lambda. -
FUNCTION_NAME: Nazwa funkcji Lambda, którą tworzymy/aktualizujemy. -
REGION: Region, w którym zostanie utworzona/zaktualizowana funkcja Lambda. -
TIMEOUT: Limit czasu w sekundach przed zabiciem wywołania Lambda. -
MEMORY_SIZE: Rozmiar pamięci w megabajtach, do której funkcja Lambda będzie miała dostęp po wywołaniu. -
ZIPFILE_NAME: nazwa spakowanego pakietu zawierającego kod i zależności funkcji Lambda. -
HANDLER: Bezwzględna ścieżka importu, w notacji kropkowej, funkcji obsługi.
Po skonfigurowaniu uruchomienie polecenia make create wygeneruje coś podobnego do następującego wyniku:
$ make create pip install -r requirements.txt -t . ... find . | grep .pyc| xargs rm zip image_resize.zip -r * ... aws lambda create-function --region ap-northeast-1 \ --function-name ResizeImage2 \ --zip-file fileb://image_resize.zip \ --role arn:aws:iam::11111111111:role/lambda_role \ --handler handler.handle_resize \ --runtime python2.7 \ --timeout 15 \ --memory-size 512 { "CodeSha256": "doB1hsujmZnxZHidnLKP3XG2ifHM3jteLEBvsK1G2nasKSo=", "FunctionName": "ResizeImage", "CodeSize": 155578, "MemorySize": 512, "FunctionArn": "arn:aws:lambda:us-west-1:11111111111:function:ResizeImage", "Version": "$LATEST", "Role": "arn:aws:iam::11111111111:role/lambda_role", "Timeout": 15, "LastModified": "2016-01-10T11:11:11.000+0000", "Handler": "handler.handle_resize", "Runtime": "python2.7", "Description": "" }Testowanie
Po wykonaniu polecenia tworzenia, funkcja zmiany rozmiaru dla naszych obrazów jest dostępna do użycia, jednak nie została podłączona do wiadra S3 w celu odbierania zdarzeń. Nadal możemy przetestować funkcję za pomocą konsoli AWS, aby potwierdzić, że funkcja prawidłowo obsługuje zdarzenia przesyłania plików S3. W panelu AWS Lambda, który znajduje się w podsekcji „Oblicz” w menu „Usługi”, wybierz nazwę utworzonej przez nas funkcji. Ta strona szczegółów funkcji Lambda zawiera menu rozwijane oznaczone „Działania” zawierające opcję „Konfiguruj zdarzenie testowe”.
Kliknięcie na to otworzy modalne, pozwalające określić zdarzenie testowe i kilka przykładowych szablonów. Wybierz przykład „S3 Put” i zastąp wszelkie wzmianki o nazwie zasobnika nazwą zasobnika, który został skonfigurowany. Po skonfigurowaniu, kolejne użycie przycisku „Test” na stronie funkcji Lambda spowoduje wywołanie funkcji Lambda tak, jakby wcześniej skonfigurowane zdarzenie rzeczywiście wystąpiło.
Aby monitorować wszelkie ślady stosu błędów lub komunikaty dziennika, możesz wyświetlić strumień dziennika w Cloudwatch. Nowa grupa logów zostanie utworzona w tym samym czasie co funkcja Lambda. Te strumienie dzienników są przydatne i mogą być przesyłane do innych usług.
Łączenie ze zdarzeniami zasobnika S3
Wróć do pulpitu nawigacyjnego S3, rozwiń zwiniętą sekcję „Zdarzenia” znajdującą się w menu „Właściwości”, aby wyświetlić formularz „Powiadomienia o zdarzeniach”. Pola obowiązkowe do wypełnienia to pola „Zdarzenia” i „Wyślij do”. W sekcji „Zdarzenia” wybierz zdarzenie „Utworzono obiekt (wszystkie)”. Umożliwi to przechwycenie wszystkich zdarzeń, które tworzą obiekt w zasobniku przesyłania. Dla wejścia „Wysłane do” wybierz przycisk radiowy „Funkcja Lambda”. Pojawi się nowa sekcja z listą rozwijaną zawierającą funkcję lambda „ResizeImage”, którą skonfigurowaliśmy jako opcję. Po kliknięciu „Zapisz”, wszelkie zdarzenia „Utworzono obiekt” będą teraz kierowane jako dane wejściowe do wywołania funkcji Lambda „ResizeImage”.
Mamy teraz podstawową funkcjonalność aplikacji. Uruchommy kolejny test cURL, aby upewnić się, że wszystko działa zgodnie z oczekiwaniami. Użyj cURL, aby przesłać obraz do zasobnika S3, i ręcznie sprawdź, czy obraz został przesłany do zasobnika zmiany rozmiaru.
curl https://test-upload.s3.amazonaws.com -F 'key=test.jpeg' -F '[email protected]'Po wykonaniu tego polecenia obraz o zmienionym rozmiarze powinien zostać utworzony w wiadrze „test-resize” po 50-1000ms w zależności od tego, czy funkcja Lambda była już „rozgrzana”.
Wyświetlanie listy funkcji lambda obrazu
Kod
Funkcja ListImage Lambda pobierze listę obrazów o zmienionym rozmiarze i wyświetli je na stronie HTML dla użytkownika. Ta strona HTML zapewnia również użytkownikowi możliwość przesyłania własnych obrazów. Jinja2 jest używany w funkcji do renderowania kodu HTML z definicji szablonu. Tak jak poprzednio, requirements.txt te są określone w pliku Requirements.txt.
from __future__ import print_function import os import boto3 from jinja2 import Environment from jinja2 import FileSystemLoader def _render_template(image_urls): env = Environment(loader=FileSystemLoader(os.path.abspath(os.path.dirname(__file__)))) template = env.get_template('list.html') rendered_template = template.render(image_urls=image_urls) return rendered_template def handle_list_image(event, context): bucket = boto3.resource('s3').Bucket('test-resized') image_summaries = sorted((image_summary for image_summary in bucket.objects.all()), key=lambda o: o.last_modified) image_urls = [] for summary in image_summaries: image_urls.append( boto3.client('s3').generate_presigned_url( 'get_object', Params={ 'Bucket': summary.bucket_name, 'Key': summary.key } ) ) return {'htmlContent': _render_template(image_urls)} <html> <head> <title>List Images</title> <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script> <script> var uploadImage = (function () { var inProgress = false; return function () { if (inProgress) { return; } inProgress = true; var formData = new FormData(); var fileData = $('#image-file').prop('files')[0]; formData.append('key', parseInt(Math.random() * 1000000)); formData.append('acl', 'public-read'); formData.append('file', fileData); $.ajax({ url: 'https://test-upload.s3.amazonaws.com/', type: 'POST', data: formData, processData: false, contentType: false, success: function (data) { window.location.reload(); } }); } })(); </script> <style type="text/css"> .image__container { float: left; width: 30%; margin-left: 2.5%; margin-right: 2.5%; max-width: 400px; } </style> </head> <body> <nav> <input type="file" onchange="uploadImage()" value="Upload Image" /> </nav> <section> {% for image_url in image_urls %} <div class="image__container"> <img src="{{ image_url }}" /> </div> {% endfor %} </section> </body> </html>Po raz kolejny możemy zmienić poprzedni plik Makefile i użyć polecenia create, aby wdrożyć naszą funkcję lambda.
Brama API
Funkcja ImageList Lambda jest kompletna, jednak nie można jej udostępnić żadnym użytkownikom. Dzieje się tak, ponieważ funkcje Lambda mogą być wywoływane tylko w odpowiedzi na zdarzenie z innej usługi lub programowo. W tym miejscu pojawia się usługa Amazon AWS API Gateway. API Gateway znajduje się w podsekcji „Application Services”.
API Gateway to sposób modelowania punktów końcowych jako zestawu zasobów i metod, zasadniczo interfejsu REST. Oprócz zapewniania funkcji sprawdzania poprawności i przekształcania żądań, API Gateway wykonuje inne funkcje, takie jak udostępnianie żądań ograniczania przepustowości/ograniczania szybkości.
W panelu API Gateway utwórz nowy interfejs API do obsługi funkcji ListImage. Nazwę i opis można ustawić według własnych preferencji. Po utworzeniu kliknij nazwę nowego interfejsu API, aby uzyskać dostęp do szczegółów interfejsu API. Utwórz nowy zasób dla głównego adresu URL „/”. Ten adres URL będzie używany do obsługi strony HTML.
Podczas przeglądania szczegółów strony zasobu głównego dodaj metodę GET. Ustaw „Typ integracji” na „Funkcja Lambda”, ustaw „Region Lambda” na „us-west-1” lub wybrany region i wpisz nazwę funkcji ListImage Lambda.
Zanim zaczniemy mapować naszą odpowiedź na wynik HTML, musimy zdefiniować „model”, który zdefiniuje schemat odpowiedzi z serwera, oprócz mapowania tej odpowiedzi na typ zawartości. Wybierz sekcję „Modele” dla interfejsu API i kliknij „Utwórz”, aby utworzyć nowy model. Nadaj modelowi nazwę „HTML” z typem treści „text/html” i zdefiniuj schemat w następujący sposób:
{ "$schema": "http://json-schema.org/draft-04/schema#", "title" : "HTML", "type" : "object" }Wróć do pulpitu API, wybierz utworzony przez nas zasób i przejdź do sekcji „Odpowiedź na temat integracji”. Ta sekcja definiuje każdą transformację do przetworzenia po otrzymaniu odpowiedzi z funkcji Lambda przed przesłaniem odpowiedzi do ostatniego kroku.
Otwórz sekcję „Szablony mapowania” i dodaj nowy „Typ treści” „text/html”. Usuń jednocześnie stary „Typ treści”. Po prawej stronie zmień listę rozwijaną z „Przekazywanie wyjścia” na „Szablon mapowania”. Pozwoli nam to zmienić nieprzetworzony JSON zaakceptowany przez API Gateway i zamiast tego użyć treści HTML we właściwości „htmlContent” zwróconych danych. W przypadku szablonu mapowania jako szablon określ „$input.htmlContent”. Na koniec zmień sekcję „Metoda odpowiedzi”, usuwając „application/json” z „Modele odpowiedzi dla 200” i dodając zamiast tego „text/html”.
Wracając do pulpitu nawigacyjnego API, w lewym górnym rogu strony znajduje się przycisk oznaczony „Wdróż API”. Kliknij ten przycisk, aby zaktualizować lub utworzyć interfejs API z określonymi zasobami, metodami, modelami i mapowaniami. Po wykonaniu tej czynności zostanie wyświetlony adres URL dla wybranego etapu wdrażania (domyślnie przemieszczanie). Wreszcie przykład jest kompletny! Możesz przesłać kilka plików, aby przetestować i wyświetlić obrazy o zmienionym rozmiarze.
Zawijanie
AWS to duża usługa i niedługo zniknie. Chociaż zawsze należy uważać na uzależnienie od dostawcy, AWS Lambda oferuje stosunkowo cienką usługę z bogatym zestawem pomocniczych opcji konfiguracyjnych. Wykorzystanie usług świadczonych przez AWS do wdrożenia łatwo skalowalnych i konserwowalnych aplikacji zapewni największe korzyści z korzystania z platformy AWS. AWS Lambda zapewnia eleganckie, skalowalne i ekonomiczne rozwiązanie wspierane przez platformę klasy korporacyjnej, z której korzysta bardzo duża liczba konsumentów. Wierzę, że aplikacje „bezserwerowe” są drogą na przyszłość. Daj nam znać, co myślisz w komentarzach poniżej.
