Inleiding tot het AWS Serverless Application Model

1. Overzicht

In ons vorige artikel hebben we al een full-stack serverloze applicatie geïmplementeerd op AWS, met behulp van API Gateway voor REST-endpoints, AWS Lambda voor bedrijfslogica en een DynamoDB als database.

De implementatie bestaat echter uit veel handmatige stappen, die onhandig kunnen worden naarmate de complexiteit toeneemt en het aantal omgevingen toeneemt.

In deze zelfstudie bespreken we nu hoe u de AWS Serverless Application Model (SAM), dat een op sjablonen gebaseerde beschrijving en geautomatiseerde implementatie van serverloze applicaties op AWS mogelijk maakt.

We zullen in detail de volgende onderwerpen bekijken:

  • Basisprincipes van het Serverless Application Model (SAM), evenals van de onderliggende CloudFormation
  • Definitie van een serverloze applicatie, met behulp van de SAM-sjabloonsyntaxis
  • Geautomatiseerde implementatie van de applicatie met behulp van de CloudFormation CLI

2. Basisprincipes

Zoals eerder besproken, stelt AWS ons in staat om volledig serverloze applicaties te implementeren, door gebruik te maken van API Gateway, Lambda-functies en DynamoDB. Dat biedt ongetwijfeld al veel voordelen op het gebied van prestaties, kosten en schaalbaarheid.

Het nadeel is echter dat we momenteel veel handmatige stappen in de AWS-console nodig hebben, zoals het maken van elke functie, het uploaden van code, het maken van de DynamoDB-tabel, het maken van IAM-rollen, het maken van een API- en API-structuur, enz.

Voor complexe toepassingen en met meerdere omgevingen zoals test, staging en productie, vermenigvuldigt die inspanning zich snel.

Dit is waar CloudFormation voor applicaties op AWS in het algemeen en Serverless Application Model (SAM) specifiek voor serverloze applicaties in het spel komen.

2.1. AWS CloudFormation

CloudFormation is een AWS-service voor de automatische voorziening van AWS-infrastructuurresources. Een gebruiker definieert alle vereiste bronnen in een blauwdruk (sjabloon genoemd) en AWS zorgt voor de inrichting en configuratie.

De volgende termen en concepten zijn essentieel om CloudFormation en SAM te begrijpen:

Een sjabloon is een beschrijving van een applicatie, hoe het tijdens runtime moet worden gestructureerd. We kunnen een set vereiste bronnen definiëren, evenals hoe deze bronnen zullen worden geconfigureerd. CloudFormation biedt een gemeenschappelijke taal voor het definiëren van sjablonen en ondersteunt JSON en YAML als een indeling.

Bronnen zijn de bouwstenen in CloudFormation. Een bron kan van alles zijn, zoals een RestApi, een fase van een RestApi, een batchopdracht, een DynamoDB-tabel, een EC2-instantie, een netwerkinterface, een IAM-rol en nog veel meer. De officiële documentatie bevat momenteel ongeveer 300 resourcetypen voor CloudFormation.

Een stapel is de instantiatie van een sjabloon. CloudFormation zorgt voor de inrichting en configuratie van de stack.

2.2. Serverloos toepassingsmodel (SAM)

Zoals zo vaak kan het gebruik van krachtige tools erg complex en onhandig worden, wat ook het geval is bij CloudFormation.

Daarom introduceerde Amazon het Serverless Application Model (SAM). SAM begon met de claim om een ​​schone en duidelijke syntaxis te bieden voor het definiëren van serverloze applicaties. Momenteel heeft het slechts drie resourcetypen, namelijk Lambda-functies, DynamoDB-tabellen en API's.

SAM is gebaseerd op de CloudFormation-sjabloonsyntaxis, dus we kunnen onze sjabloon definiëren met behulp van de eenvoudige SAM-syntaxis, en CloudFormation zal die sjabloon verder verwerken.

Meer details zijn beschikbaar in de officiële GitHub-repository en in de AWS-documentatie.

3. Vereisten

Voor de volgende tutorial hebben we een AWS-account nodig. Een gratis account zou voldoende moeten zijn.

Daarnaast moeten we de AWS CLI hebben geïnstalleerd.

Ten slotte hebben we een S3-bucket nodig in onze regio, die kan worden gemaakt via de AWS CLI met het volgende commando:

$> aws s3 mb s3: // baeldung-sam-bucket

Terwijl de tutorial gebruikt baeldung-sam-emmer Houd er in het volgende rekening mee dat bucketnamen uniek moeten zijn, dus u moet uw naam kiezen.

Als demo-applicatie gebruiken we de code van AWS Lambda gebruiken met API Gateway.

4. Het sjabloon maken

In deze sectie maken we onze SAM-sjabloon.

We kijken eerst naar de algemene structuur voordat we de individuele bronnen definiëren.

4.1. Structuur van de sjabloon

Laten we eerst eens kijken naar de algemene structuur van onze sjabloon:

AWSTemplateFormatVersion: '2010-09-09' Transform: 'AWS :: Serverless-2016-10-31' Beschrijving: Baeldung Serverless Application Model voorbeeld Bronnen: PersonTable: Type: AWS :: Serverless :: SimpleTable Eigenschappen: # Definieer hier tabeleigenschappen StorePersonFunction: Type: AWS :: Serverless :: Function Properties: # Definieer hier functie-eigenschappen GetPersonByHTTPParamFunction: Type: AWS :: Serverless :: Function Properties: # Definieer hier functie-eigenschappen MyApi: Type: AWS :: Serverless :: Api Properties: # Definieer hier API-eigenschappen

Zoals we kunnen zien, bestaat de sjabloon uit een koptekst en een hoofdtekst:

De header specificeert de versie van de CloudFormation-sjabloon (AWSTemplateFormatVersion) evenals de versie van onze SAM-sjabloon (Transformeren). We kunnen ook een Omschrijving.

De body bestaat uit een set resources: elke resource heeft een naam, een resource Type, en een set van Eigendommen.

De SAM-specificatie ondersteunt momenteel drie typen: AWS :: Serverloos :: Api, AWS :: Serverless :: Functie net zoals AWS :: Serverloos :: SimpleTable.

Omdat we onze voorbeeldtoepassing willen implementeren, moeten we er een definiëren SimpleTable, twee Functies, evenals een Api in onze sjabloon-body.

4.2. DynamoDB-tabeldefinitie

Laten we nu onze DynamoDB-tabel definiëren:

AWSTemplateFormatVersion: '2010-09-09' Transform: 'AWS :: Serverless-2016-10-31' Beschrijving: Baeldung Serverless Application Model-voorbeeld Bronnen: PersonTable: Type: AWS :: Serverless :: SimpleTable Eigenschappen: PrimaryKey: Naam: id Type: Nummer Tabelnaam: Persoon

We hoeven slechts twee eigenschappen voor ons te definiëren SimpleTable: de tabelnaam, evenals een primaire sleutel, die wordt aangeroepen ID kaart en heeft het type Aantal in ons geval.

Een volledige lijst met ondersteunde SimpleTable eigenschappen zijn te vinden in de officiële specificatie.

Opmerking: aangezien we alleen toegang tot de tabel willen hebben met de primaire sleutel, de AWS :: Serverloos :: SimpleTable is voldoende voor ons. Voor complexere vereisten, het native CloudFormation-type AWS :: DynamoDB :: Table kan in plaats daarvan worden gebruikt.

4.3. Definitie van de Lambda-functies

Laten we vervolgens onze twee functies definiëren:

AWSTemplateFormatVersion: '2010-09-09' Transform: 'AWS :: Serverless-2016-10-31' Beschrijving: Baeldung Serverless Application Model-voorbeeld Bronnen: StorePersonFunction: Type: AWS :: Serverless :: Function Properties: Handler: com.baeldung .lambda.apigateway.APIDemoHandler :: handleRequest Runtime: java8 Time-out: 15 Geheugengrootte: 512 CodeUri: ../target/aws-lambda-0.1.0-SNAPSHOT.jar Beleid: DynamoDBCrudPolicy Omgeving: Variabelen: TABLE_NAME:! Ref PersonTable-gebeurtenissen: StoreApi: Type: Api Eigenschappen: Pad: / personen Methode: PUT RestApiId: Ref: MyApi GetPersonByHTTPParam Functie: Type: AWS :: Serverless :: Functie-eigenschappen: Handler: com.baeldung.lambda.apigateway.APIDemoHandler :: handleGetByParam Runtime: java8 Time-out : 15 Geheugengrootte: 512 CodeUri: ../target/aws-lambda-0.1.0-SNAPSHOT.jar Beleid: DynamoDBReadPolicy Omgeving: Variabelen: TABLE_NAME:! Ref PersonTable-gebeurtenissen: GetByPathApi: Type: Api Eigenschappen: Pad: / personen / { id} Methode: GET RestApiId: Ref: MyApi GetByQueryApi: Type: Api Propertie s: Pad: / personen Methode: GET RestApiId: Ref: MyApi

Zoals we kunnen zien, heeft elke functie dezelfde eigenschappen:

Handler definieert de logica van de functie. Omdat we Java gebruiken, is dit de klassenaam inclusief het pakket, in verband met de naam van de methode.

Looptijd definieert hoe de functie is geïmplementeerd, wat in ons geval Java 8 is.

Time-out definieert hoe lang de uitvoering van de code maximaal mag duren voordat AWS de uitvoering beëindigt.

Geheugen groottedefinieert de grootte van het toegewezen geheugen in MB. Het is belangrijk om te weten dat AWS CPU-bronnen proportioneel toewijst aan Geheugen grootte. Dus in het geval van een CPU-intensieve functie, kan het nodig zijn om te verhogen Geheugen grootte, zelfs als de functie niet zoveel geheugen nodig heeft.

CodeUridefinieert de locatie van de functiecode. Het verwijst momenteel naar de doelmap in onze lokale werkruimte. Wanneer we onze functie later uploaden met CloudFormation, krijgen we een bijgewerkt bestand met een verwijzing naar een S3-object.

Beleidkan een set door AWS beheerd IAM-beleid of SAM-specifieke beleidssjablonen bevatten. We gebruiken het SAM-specifieke beleid DynamoDBCrudPolicy voor de StorePersonFunction en DynamoDBReadPolicy voor GetPersonByPathParamFunction en GetPersonByQueryParamFunction.

Milieudefinieert omgevingseigenschappen tijdens runtime. We gebruiken een omgevingsvariabele voor de naam van onze DynamoDB-tabel.

Evenementenkan een reeks AWS-evenementen bevatten, die de functie kunnen activeren. In ons geval definiëren we een Evenement van het type Api. De unieke combinatie van pad, een HTTP Methode, en een RestApiId koppelt de functie aan een methode van onze API, die we in de volgende sectie zullen definiëren.

Een volledige lijst met ondersteunde Functie eigenschappen zijn te vinden in de officiële specificatie.

4.4. API-definitie als Swagger-bestand

Nadat we de DynamoDB-tabel en -functies hebben gedefinieerd, kunnen we nu de API definiëren.

De eerste mogelijkheid is om onze API inline te definiëren met behulp van het Swagger-formaat:

AWSTemplateFormatVersion: '2010-09-09' Transform: 'AWS :: Serverless-2016-10-31' Beschrijving: Voorbeeld van Baeldung Serverless Application Model Bronnen: MyApi: Type: AWS :: Serverless :: Api Eigenschappen: StageName: test EndpointConfiguration: REGIONAAL Definitie Lichaam: branie: "2.0" info: titel: "TestAPI" paden: / personen: get: parameters: - naam: "id" in: "query" vereist: true type: "string" x-amazon-apigateway-request -validator: "Valideer queryparameters en \ \ headers" x-amazon-apigateway-integratie: uri: Fn :: Sub: arn: aws: apigateway: $ {AWS :: Region}: lambda: path / 2015-03- 31 / functions / $ {GetPersonByHTTPParamFunction.Arn} / aanroepantwoorden: {} httpMethod: "POST" type: "aws_proxy" put: x-amazon-apigateway-integratie: uri: Fn :: Sub: arn: aws: apigateway: $ {AWS :: Region}: lambda: path / 2015-03-31 / functions / $ {StorePersonFunction.Arn} / aanroepreacties: {} httpMethod: "POST" type: "aws_proxy" / personen / {id}: get: parameters: - naam: "id" in: "pad" vereist: waar type: "string" reacties: {} xa mazon-apigateway-integratie: uri: Fn :: Sub: arn: aws: apigateway: $ {AWS :: Region}: lambda: path / 2015-03-31 / functions / $ {GetPersonByHTTPParamFunction.Arn} / aanroepantwoorden: { } httpMethod: "POST" type: "aws_proxy" x-amazon-apigateway-request-validators: Valideer queryparameters en headers: validateRequestParameters: true validateRequestBody: false

Onze Api heeft drie eigenschappen: Artiestennaamdefinieert de fase van de API, EndpointConfigurationbepaalt of de API regionaal of edge-geoptimaliseerd is, en Definitie Lichaam bevat de feitelijke structuur van de API.

In de Definitie Lichaamdefiniëren we drie parameters: de branie versie als “2.0”, de info: titel: net zo "TestAPI", evenals een set van paden.

Zoals we kunnen zien, is de paden vertegenwoordigen de API-structuur, die we eerder handmatig moesten definiëren. De paden in Swagger zijn gelijk aan de bronnen in de AWS Console. Precies zo, elk pad kan een of meer HTTP-werkwoorden hebben, die equivalent zijn aan de methoden in de AWS-console.

Elke methode kan een of meer parameters hebben, evenals een verzoekvalidator.

Het meest opwindende deel is het attribuut x-amazon-apigateway-integratie, wat een AWS-specifieke extensie is voor Swagger:

uri specificeert welke Lambda-functie zal worden aangeroepen.

reacties specificeer regels voor het transformeren van de antwoorden die door de functie worden geretourneerd. Omdat we Lambda Proxy-integratie gebruiken, hebben we geen specifieke regel nodig.

type definieert dat we Lambda Proxy-integratie willen gebruiken, en daarbij moeten we instellen httpMethod naar "POST", aangezien dit is wat Lambda-functies verwachten.

Een volledige lijst met ondersteunde Api eigenschappen zijn te vinden in de officiële specificatie.

4.5. Impliciete API-definitie

Een tweede optie is om de API impliciet te definiëren binnen de functiebronnen:

AWSTemplateFormatVersion: '2010-09-09' Transform: 'AWS :: Serverless-2016-10-31' Beschrijving: Baeldung Serverless Application Model-voorbeeld met impliciete API-definitie Globals: Api: EndpointConfiguration: REGIONAL Naam: "TestAPI" Bronnen: StorePersonFunction: Type: AWS :: Serverless :: Functie-eigenschappen: Handler: com.baeldung.lambda.apigateway.APIDemoHandler :: handleRequest Runtime: java8 Time-out: 15 Geheugengrootte: 512 CodeUri: ../target/aws-lambda-0.1.0-SNAPSHOT .jar-beleid: - DynamoDBCrudPolicy: TableName:! Ref PersonTable-omgeving: Variabelen: TABLE_NAME:! Ref PersonTable-gebeurtenissen: StoreApi: Type: Api Eigenschappen: Pad: / personen Methode: PUT GetPersonByHTTPParam Functie: Type: AWS :: Serverloos :: Functie-eigenschappen: Handler: com.baeldung.lambda.apigateway.APIDemoHandler :: handleGetByParam Runtime: java8 Time-out: 15 Geheugengrootte: 512 CodeUri: ../target/aws-lambda-0.1.0-SNAPSHOT.jar Beleid: - DynamoDBReadPolicy: TableName:! Ref PersonTable-omgeving: variabelen: TABLE_NAME:! Zie PersonTable E ventilatieopeningen: GetByPathApi: Type: Api Eigenschappen: Pad: / personen / {id} Methode: GET GetByQueryApi: Type: Api Eigenschappen: Pad: / personen Methode: GET

Zoals we kunnen zien, is onze sjabloon nu iets anders: er is geen AWS :: Serverloos :: Api resource meer.

CloudFormation gebruikt echter de Evenementen attributen van het type Api als een impliciete definitie en creëert toch een API. Zodra we onze applicatie testen, zullen we zien dat deze zich hetzelfde gedraagt ​​als wanneer we de API expliciet definiëren met Swagger.

Bovendien is er een Globals sectie, waar we de naam van onze API kunnen definiëren, evenals dat ons eindpunt regionaal zal zijn.

Er doet zich slechts één beperking voor: wanneer we de API impliciet definiëren, kunnen we geen artiestennaam instellen. Dit is de reden waarom AWS een podium zal maken met de naam Prod in elk geval.

5. Implementatie en test

Nadat we de sjabloon hebben gemaakt, kunnen we doorgaan met het implementeren en testen.

Hiervoor uploaden we onze functiecode naar S3 voordat we de daadwerkelijke implementatie starten.

Uiteindelijk kunnen we onze applicatie testen met elke HTTP-client.

5.1. Code uploaden naar S3

In een eerste stap moeten we de functiecode uploaden naar S3.

Dat kunnen we doen door CloudFormation aan te roepen via de AWS CLI:

$> aws cloudformation-pakket --template-file ./sam-templates/template.yml --s3-bucket baeldung-sam-bucket --output-template-file ./sam-templates/packaged-template.yml

Met deze opdracht activeren we CloudFormation om de functiecode te gebruiken die is opgegeven in CodeUri: en om het te uploaden naar S3. CloudFormation zal een packaged-template.yml bestand, dat dezelfde inhoud heeft, behalve dat CodeUri: wijst nu naar het S3-object.

Laten we de CLI-uitvoer eens bekijken:

Uploaden naar 4b445c195c24d05d8a9eee4cd07f34d0 92702076 / 92702076.0 (100,00%) Artefacten met succes verpakt en uitvoersjabloon naar bestand packaged-template.yml geschreven. Voer de volgende opdracht uit om de verpakte sjabloon aws cloudformation deploy --template-file c: \ zz_workspace \ tutorials \ aws-lambda \ sam-templates \ packaged-template.yml --stack-name te implementeren 

5.2. Inzet

Nu kunnen we de daadwerkelijke implementatie activeren:

$> aws cloudformation deploy --template-file ./sam-templates/packaged-template.yml --stack-name baeldung-sam-stack --capabilities CAPABILITY_IAM

Aangezien onze stack ook IAM-rollen nodig heeft (zoals de rollen van de functies voor toegang tot onze DynamoDB-tabel), moeten we dat expliciet erkennen door de -Capaciteiten parameter.

En de CLI-uitvoer zou er als volgt uit moeten zien:

Wachten op het maken van wijzigingenset. Wachten tot het maken / bijwerken van de stapel is voltooid. Stapel met succes aangemaakt / bijgewerkt - baeldung-sam-stack

5.3. Implementatiebeoordeling

Na de implementatie kunnen we het resultaat bekijken:

$> aws cloudformation beschrijven-stack-resources --stack-naam baeldung-sam-stack

CloudFormation geeft een overzicht van alle bronnen die deel uitmaken van onze stapel.

5.4. Test

Ten slotte kunnen we onze applicatie testen met elke HTTP-client.

Laten we wat voorbeelden bekijken krullen commando's die we voor deze tests kunnen gebruiken.

StorePersonFunction:

$> curl -X PUT '//0skaqfgdw4.execute-api.eu-central-1.amazonaws.com/test/persons' \ -H 'content-type: application / json' \ -d '{"id": 1, "name": "John Doe"} '

GetPersonByPathParamFunction:

$> curl -X GET '//0skaqfgdw4.execute-api.eu-central-1.amazonaws.com/test/persons/1' \ -H 'content-type: application / json'

GetPersonByQueryParamFunction:

$> curl -X GET '//0skaqfgdw4.execute-api.eu-central-1.amazonaws.com/test/persons?id=1' \ -H 'content-type: application / json'

5.5. Schoonmaken

Uiteindelijk kunnen we opschonen door de stapel en alle meegeleverde bronnen te verwijderen:

aws cloudformation delete-stack --stack-name baeldung-sam-stack

6. Conclusie

In dit artikel hebben we gekeken naar het AWS Serverless Application Model (SAM), dat een op sjablonen gebaseerde beschrijving en geautomatiseerde implementatie van serverloze applicaties op AWS mogelijk maakt.

We hebben in detail de volgende onderwerpen besproken:

  • Basisprincipes van het Serverless Application Model (SAM), evenals de onderliggende CloudFormation
  • Definitie van een serverloze applicatie, met behulp van de SAM-sjabloonsyntaxis
  • Geautomatiseerde implementatie van de applicatie met behulp van de CloudFormation CLI

Zoals gewoonlijk is alle code voor dit artikel beschikbaar op GitHub.