零基础5分钟上手亚马逊云科技-开发云原生网站应用
简介:
欢迎来到小李哥全新亚马逊云科技AWS云计算知识学习系列,适用于任何无云计算或者亚马逊云科技技术背景的开发者,通过这篇文章大家零基础5分钟就能完全学会亚马逊云科技一个经典的服务开发架构方案。
我会每天介绍一个基于亚马逊云科技AWS云计算平台的全球前沿云开发/架构技术解决方案,帮助大家快速了解国际上最热门的云计算平台亚马逊云科技AWS最佳实践,并应用到自己的日常工作里。本次介绍的是如何利用亚马逊云科技上利用云原生计算服务Lambda,开发Python语言数据库交互模块,向DynamoDB托管NoSQL数据库写入和读取数据,提升云上应用程序的扩展性,降低运维维护难度。本方案架构图如下:
方案所需基础知识
什么是亚马逊云科技云原生 Lambda 服务?
亚马逊云科技 Lambda 是一项无服务器计算服务,专为帮助开发者运行代码而无需管理服务器基础设施而设计。通过 Lambda,开发者可以在不需要配置或维护服务器的情况下,自动运行代码以响应各种事件触发,如对 S3 存储桶的更改、API Gateway 请求、或数据库更新等。Lambda 支持多种编程语言,允许开发者只需上传代码并定义触发条件,AWS 会自动处理所有底层资源的管理,如计算资源的分配、扩展和监控。这个高度自动化的服务使得开发和部署变得更加简便和高效。
利用云原生服务开发应用的好处
无需管理基础设施:
利用 AWS Lambda,开发者不再需要担心服务器配置、操作系统维护、或扩展资源的复杂性。AWS 自动管理这些基础设施任务,使开发者能够专注于应用逻辑的编写和优化。这种无服务器的架构大大减少了运维工作量,同时降低了管理成本。
按需扩展:
Lambda 提供了内置的自动扩展能力,可以根据应用负载的变化动态调整资源。无论是处理高峰流量还是应对突发需求,Lambda 都能够快速扩展,以确保应用的稳定性和响应速度。用户只需为实际使用的计算时间付费,这种弹性扩展模式使得资源利用率更高,成本更为可控。
快速迭代与部署:
使用 Lambda,开发者可以快速测试和部署新功能,无需等待繁琐的部署流程。AWS 提供的持续集成和持续部署(CI/CD)工具链可以与 Lambda 无缝集成,帮助开发团队快速推送更新和修复,确保应用始终保持最新状态。
本方案包括的内容
1. 利用亚马逊云科技Python Boto3 SDK开发数据库交互应用代码
2. 了解DynamoDB数据库读写API
3. 部署云原生架构和应用代码实现交互功能,并利用API Gateway创建对外暴露API
项目搭建具体步骤
1. 首先进入亚马逊云科技控制台,点击Cloud 9云端IDE服务
2. 点击Open进入云端IDE
3. 创建一个空网页前端文件index.html,复制以下代码
<!doctype html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.3.1/dist/css/bootstrap.min.css"
integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<title>Lab Example</title>
<script>
// on page loaded
document.addEventListener('DOMContentLoaded', (event) => {
document.getElementById("send").addEventListener("click", async function(){
var qs = new URLSearchParams({
id: document.getElementById("id").value,
firstname: document.getElementById("firstname").value,
lastname: document.getElementById("lastname").value,
})
const apiEndpoint = document.getElementById("apiEndpoint").value;
const before = document.getElementById("send").textContent;
document.getElementById("send").textContent="...";
fetch(`${apiEndpoint}SaveCustomer?${qs}`, {method: "POST"})
.then(response => response.json())
.then(json => {
document.getElementById("send").textContent=before;
refreshTable();
});
});
function refreshTable() {
const apiEndpoint = document.getElementById("apiEndpoint").value;
fetch(`${apiEndpoint}ListCustomers`)
.then(response => response.json())
.then(jsonData => {
var tbody = document.getElementById("results")
tbody.innerHTML = '';
jsonData.result.forEach(element => {
var tr = document.createElement('tr');
tbody.appendChild(tr);
element.forEach(cell => {
var td1 = document.createElement('td');
td1.appendChild(document.createTextNode(cell));
tr.appendChild(td1);
});
});
});
}
refreshTable();
});
</script>
</head>
<body>
<main role="main" class="container">
<div class="pricing-header px-3 py-3 pt-md-5 pb-md-4 mx-auto text-center"></div>
<div class="card-deck mb-3">
<div class="card mb-4 box-shadow">
<!-- <div class="card-header">
<h4 class="my-0 font-weight-normal">Save Customer</h4>
</div> -->
<div class="card-body">
<div class="form-group">
<label for="apiEndpoint">API Endpoint</label>
<input type="text" readonly="readonly" class="form-control" id="apiEndpoint" value="https://r2ks79x6p1.execute-api.us-east-1.amazonaws.com/">
</div>
<div class="form-group">
<label for="id">Customer ID</label>
<input type="text" class="form-control" id="id" value="ABC123">
</div>
<div class="form-group">
<label for="firstname">First Name</label>
<input type="text" class="form-control" id="firstname" value="TestFirst">
</div>
<div class="form-group">
<label for="lastname">Last Name</label>
<input type="text" class="form-control" id="lastname" value="TestLast">
</div>
<button type="button" class="btn btn-lg btn-block btn-outline-primary" id="send">Put Item</button>
</div>
</div>
</div>
<div class="card-deck mb-3 text-center">
<div class="card mb-4 box-shadow">
<!-- <div class="card-header">
<h4 class="my-0 font-weight-normal">Save Customer</h4>
</div> -->
<div class="card-body">
<table class="table">
<thead>
<tr>
<th scope="col">Customer ID</th>
<th scope="col">First Name</th>
<th scope="col">Last Name</th>
</tr>
</thead>
<tbody id="results">
</tbody>
</table>
</div>
</div>
</div>
</main><!-- /.container -->
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js"
integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo"
crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.14.7/dist/umd/popper.min.js"
integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1"
crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.3.1/dist/js/bootstrap.min.js"
integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM"
crossorigin="anonymous"></script>
</body>
</html>
3. 创建一个空python文件“app.py”,用于构建代码逻辑从DynamoDB数据库读取数据,并用云原生服务Lambda托管该代码
import boto3
dynamodb = boto3.client("dynamodb")
def lambda_handler(event, context):
query_response = dynamodb.scan(TableName="LabCustomers")
lists = [ [item["ID"]["S"], item["Firstname"]["S"], item["Lastname"]["S"]] for item in query_response["Items"]]
return { "result": lists }
4. 创建一个空python文件“app_solution”,用于构建代码逻辑向DynamoDB数据库存入数据,并用云原生服务Lambda托管该代码
import boto3
dynamodb = boto3.client("dynamodb")
def lambda_handler(event, context):
print(event)
id = event["queryStringParameters"]["id"]
firstname = event["queryStringParameters"]["firstname"]
lastname = event["queryStringParameters"]["lastname"]
#####
# Solution...
#####
put_response = dynamodb.put_item(
TableName="LabCustomers",
Item={
"ID": {"S": id},
"Firstname": {"S": firstname},
"Lastname": {"S": lastname},
},
)
return {"result": "Saved"}
5. 创建一个云原生资源部署脚本“template.yaml”,复制以下内容,该脚本用于创建云资源基础设施,包括Lambda、API Gateway和Dynamodb数据库表。
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Resources:
SaveCustomer:
Type: AWS::Serverless::Function
Properties:
CodeUri: SaveCustomer/
Handler: app.lambda_handler
Runtime: python3.9
Architectures:
- x86_64
Policies:
- DynamoDBWritePolicy:
TableName: !Ref LabCustomers
Events:
Sum:
Type: HttpApi
Properties:
Path: /SaveCustomer
Method: post
ApiId: !Ref HttpApi
ListCustomers:
Type: AWS::Serverless::Function
Properties:
CodeUri: ListCustomers/
Handler: app.lambda_handler
Runtime: python3.9
Architectures:
- x86_64
Policies:
- DynamoDBReadPolicy:
TableName: !Ref LabCustomers
Events:
Sum:
Type: HttpApi
Properties:
Path: /ListCustomers
Method: get
ApiId: !Ref HttpApi
HttpApi:
Type: AWS::Serverless::HttpApi
Properties:
StageName: "$default"
CorsConfiguration:
AllowOrigins:
- "*"
AllowHeaders:
- "*"
AllowMethods:
- GET
- POST
LabCustomers:
Type: AWS::DynamoDB::Table
Properties:
TableName: LabCustomers
AttributeDefinitions:
- AttributeName: "ID"
AttributeType: "S"
KeySchema:
- AttributeName: "ID"
KeyType: "HASH"
ProvisionedThroughput:
ReadCapacityUnits: 1
WriteCapacityUnits: 1
Outputs:
SaveCustomer:
Description: URL of your API
Value:
Fn::Sub: 'https://${HttpApi}.execute-api.${AWS::Region}.${AWS::URLSuffix}/SaveCustomer'
ListCustomers:
Description: URL of your API
Value:
Fn::Sub: 'https://${HttpApi}.execute-api.${AWS::Region}.${AWS::URLSuffix}/ListCustomers'
ApiGatewayEndpoint:
Description: URL for API only
Value:
Fn::Sub: 'https://${HttpApi}.execute-api.${AWS::Region}.${AWS::URLSuffix}/'
6. 在Cloud9控制台中运行以下Shell命令“sam build”和“sam deploy”部署基础设施
cd ~/environment/sam-backend; sam build; sam deploy
部署成功后会收到如下回复,分别返回读取、写入DynamoDB的API节点URL。
******************************
**** This is OUTPUT ONLY. ****
******************************
Building codeuri: /home/ec2-user/environment/sam-backend/SaveCustomer runtime: python3.9 metadata: {} architecture: x86_64 functions: SaveCustomer
Running PythonPipBuilder:ResolveDependencies
Running PythonPipBuilder:CopySource
Building codeuri: /home/ec2-user/environment/sam-backend/ListCustomers runtime: python3.9 metadata: {} architecture: x86_64 functions: ListCustomers
Running PythonPipBuilder:ResolveDependencies
Running PythonPipBuilder:CopySource
Build Succeeded
Initiating deployment
=====================
Changeset created successfully.
CloudFormation outputs from deployed stack
----------------------------------------------------------------------------------------
Outputs
----------------------------------------------------------------------------------------
Key ListCustomers
Description URL of your API
Value https://rz3hwd1vjl.execute-api.us-west-2.amazonaws.com/ListCustomers
Key ApiGatewayEndpoint
Description URL for API only
Value https://rz3hwd1vjl.execute-api.us-west-2.amazonaws.com/
Key SaveCustomer
Description URL of your API
Value https://rz3hwd1vjl.execute-api.us-west-2.amazonaws.com/SaveCustomer
----------------------------------------------------------------------------------------
Successfully created/updated stack - customer-app in us-west-2
7. 最后我们打开部署好的前端URL,在网页UI上对数据库交互模块进行功能测试。点击“Put Item”开始存入数据,网页末尾显示出数据已经成功写入到数据库中,测试成功。
以上就是在亚马逊云科技上利用云原生服务Lambda,开发NoSQL数据库交互模块的全部步骤。欢迎大家关注0基础5分钟上手AWS系列,未来获取更多国际前沿的AWS云开发/云架构方案。