Event-driven architecture
is a design pattern where events are utilized to trigger and facilitate communication between decoupled services, making it a common choice for modern applications built with microservices. Serverless architecture, on the other hand, provides a model for building and running applications and services without the need to provision or manage underlying infrastructure.
Objective of the Lab
- Configure an HTTP API on API Gateway to redirect requests to EventBridge.
- Create event bus rules that match incoming requests and route events to Lambda functions.
- Process events with Lambda functions and send the processed events back to the event bus as new events.
- Publish events to the event bus, triggering separate Lambda functions.
- Lambda functions receive events and post them back to the client application via a WebSocket connection hosted on API Gateway.
High Level Architecture Diagram
Step 1
Implement five Lambda functions using below configurations and code and deploy each lambda
-
Function name, enter: make_pizza
- For Runtime, select: Python 3.12
- For Change default execution role, choose - lab_lambda_make_pizza
- Environment variable: Key: EVENT_BUS, Value: lab_event_bus
-
Function name, enter: cook_pizza
- For Runtime, select: Python 3.12
- For Change default execution role, choose - lab_lambda_cook_pizza
- Environment variable: Key: EVENT_BUS, Value: lab_event_bus
-
Function name, enter: deliver_pizza
- For Runtime, select: Python 3.12
- For Change default execution role,choose - lab_lambda_deliver_pizza
- Environment variable: Key: EVENT_BUS, Value: lab_event_bus
-
Function name, enter: websocket_connect
- For Runtime, select: Python 3.12
- For Change default execution role,choose - lab_lambda_websocket_connection
- Environment variable: Key: TABLENAME, Value: websocket_connections
-
Function name, enter: receive_events
- For Runtime, select: Python 3.12
- For Change default execution role,choose - lab_lambda_receive_events
- Environment variable: Key: TABLENAME, Value: receive_events
Sample Lambda function code for Make Pizza:
import json
import boto3
import os
from botocore.exceptions import ClientError
client = boto3.client('events')
def lambda_handler(event, context):
try:
detail = event["detail"]
detail["item"]["eventtype"]="cook_pizza"
response = client.put_events(
Entries=[
{
'DetailType': 'eventtype',
'Detail': json.dumps(detail),
'EventBusName': os.environ.get('EVENT_BUS'),
'Source':"make_pizza"
},
]
)
print(response)
except ClientError as err:
print(err)
Sample Lambda function code for Cook Pizza:
import json
import boto3
import os
from botocore.exceptions import ClientError
client = boto3.client('events')
def lambda_handler(event, context):
try:
detail = event["detail"]
detail["item"]["eventtype"]="deliver_pizza"
response = client.put_events(
Entries=[
{
'DetailType': 'eventtype',
'Detail': json.dumps(detail),
'EventBusName': os.environ.get('EVENT_BUS'),
'Source':"cook_pizza"
},
]
)
print(response)
except ClientError as err:
print(err)
Sample Lambda function code for Deliver Pizza:
import json
import boto3
import os
from botocore.exceptions import ClientError
client = boto3.client('events')
def lambda_handler(event, context):
try:
detail = event["detail"]
detail["item"]["eventtype"]="delivered"
response = client.put_events(
Entries=[
{
'DetailType': 'eventtype',
'Detail': json.dumps(detail),
'EventBusName': os.environ.get('EVENT_BUS'),
'Source':"deliver_pizza"
},
]
)
except ClientError as err:
print(err)
Sample Lambda function code for Websocket Connect:
import boto3
import json
import os
from botocore.exceptions import ClientError
dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table(os.environ.get('TABLENAME'))
def lambda_handler(event, context):
try:
order_id=event['queryStringParameters']['order_id']
response = table.put_item(
Item={
'order_id': order_id,
'connection_id': event["requestContext"]["connectionId"]
})
return {
"statusCode": 200,
"headers": {
"Content-Type": "application/json"
}
}
except ClientError as err:
print(err)
Sample Lambda function code for Receive Events:
import boto3
import json
import os
from botocore.exceptions import ClientError
dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table(os.environ.get('TABLENAME'))
management = boto3.client('apigatewaymanagementapi', endpoint_url=os.getenv('APIGW_ENDPOINT'))
def lambda_handler(event, context):
try:
response = table.get_item(
Key={
'order_id': event["detail"]['item']['order_id']
}
)
management.post_to_connection(
Data=json.dumps(event["detail"]),
ConnectionId=response["Item"]["connection_id"]
)
except ClientError as err:
print(err)
Step 2
Configure EventBridge
- Configure the rules with the following settings and select Next .
- Build event pattern screen, under the Creation method section, select Custom pattern (JSON editor) for the Method.
- Copy and paste the json object into the Event pattern editor,
- On the Select target(s) page, from the Target 1 section under Target types, choose AWS service.
- From the Select a target drop-down list, choose Lambda function.
- From the Function drop-down list, choose make_pizza.
- Choose the correspondoing role
- Select Next and select Next again on the Configure tags - optional screen.
- On the Review and create screen, select Create rule.
Configurations for each rule
Name: lab_make_pizza_rule
Event bus: lab_event_bus
{
"detail": {
"item": {
"eventtype": ["make_pizza"]
}
}
}
Name: lab_cook_pizza_rule
Event bus: lab_event_bus
{
"detail": {
"item": {
"eventtype": ["cook_pizza"]
}
}
}
Name: lab_deliver_pizza_rule
Event bus: lab_event_bus
{
"detail": {
"item": {
"eventtype": ["deliver_pizza"]
}
}
}
Name: lab_receive_events_rule
Event bus: lab_event_bus
{
"detail": {
"item": {
"eventtype": ["make_pizza","cook_pizza","deliver_pizza"]
}
}
}
Step 4
Configure API Gateway
- In the console Choose API Gateway.
- In the Choose an API type select Build from the HTTP API section.
- In the API Name field, enter lab_http_api
Select Next until you get to the Review and Create screen, then choose Create.
Under the Develop section in the left-hand navigation pane, select Routes, then choose Create .
Select POST from the drop-down list, and select Create.
Under the Develop select Integrations, choose the POST route link and then select Create and attach an integration.
For Integration target, configure the following options.
Integration type: Amazon EventBridge
Integration action: PutEvents
EventBridge - PutEvents, configure the following options.
Detail: $request.body
Detail type: eventtype
Source: lab_http_api
Invocation role, copy the APIExecutionRoleARN
Expand Advanced settings, and configure the remaining fields. Select Create when you are finished.
For Event bus name - optional, enter the event bus ARN you saved in Task 2.
Region - optional.
From the left-hand navigation pane, select CORS and choose Configure in the top right corner.
Access-Control-Allow-Origin enter *.
Access-Control-Allow-Methods select, POST.
Access-Control-Allow-Headers, enter *.
Save.
From the navigation menu on the left-hand side of the screen, navigate to the endpoint details screen by selecting API: lab_http_api. Copy and save the Invoke URL from the Stages for lab_http_api section of the API: lab_api screen. The URL is needed in Task 4.
Now create the web socket API endpoint, which is used to send events back to the web application. Web socket connections are two-way persistent connections allowing bi-directional communication and are often used by chat applications.
At the top of the left-hand navigation pane, select APIs, then select Create API .
In the Choose an API type select **Build from the WebSocket API **section.
Configure the following fields and select Next .
API Name field: lab_websocket_api
Route selection expression: request.body.action
On the Add routes page choose Add $connect route and select Next .
The websocket_connect function invokes when the application establishes the connection. This function saves the connection ID to a DynamoDB table.
Integration type: Lambda.
Lambda function websocket_connect.
Select Next .
On the Add Stages page select Next, followed by Create and deploy .
Select Stages from the left-hand navigation page and choose the Production stage.
Copy and save the WebSocket URL, as it is needed shortly.
Copy the Connection URL up to, but do not include the @connections text.
Navigate back to the Lambda console and open the receive_events Lambda function.
On the configuration tab select Environment variables, choose Edit and select Add environment variable.
Configure the variable with the following settings, and select Save when you are finished.
Key:
APIGW_ENDPOINT
Value: the copied Connection URL
Testing the ED Architecture
Top comments (0)