没有 web 接口开发经验,只会简单写一写功能函数,有没有办法写一个收集客户端数据的接口呢?本文将一步步带你如何在没有接口开发经验的状况下轻松的使用 AWS 服务器服务构建本身定制化的 API 接口。html
假设 T 公司有一个全球性的网站,每一个国家站点都有一个下载页面。公司想要去监测全球用户的下载状况,须要对下载按钮进行埋点,那咱们就须要有一个接口能够监测到用户的下载状况,须要记录的数据有以下:python
咱们不可能针对每一个站点都作一个连接做为借口,最好的方式就是建立一个连接,经过传递不一样的参数来埋到不一样的下载按钮,连接相似下面结构:linux
https://down.wzlinux.com?type=CN https://down.wzlinux.com?type=US https://down.wzlinux.com?type=IN
看到这个需求,一个专业的开发人员可能很快能够解决,须要较高的开发技能,还须要运维购买服务器,部署等,相对来讲比较麻烦,而且管理起来相对复杂。本文所展现的就是你只会简单的功能函数开发便可完成这个需求的开发部署,并且所有使用 AWS 的无服务器组件,用户不须要再关系底层硬件,来多少请求量咱们就花多少钱,也能够节省没必要要的支出。web
咱们知道在 web 里面重要的一个组合 LAMP(Linux + Apache + MySQL + PHP)。在 AWS 中呢,也有一个无服务器架构组合 Lambda + API Gateway + DynamoDB,这个组合正好知足咱们的需求。API Gateway 用来接收用户的请求数据,是实现 web api 的重要组件,Lambda 用来实现逻辑处理,选择用户须要的数据,DynamoDB 用来存储 Lambda 的数据。数据库
整个架构有一些依赖关系,Lambda 依赖 DynamoDB,API Gateway 依赖 Lambda,因此咱们先去建立 DynamoDB 表,而后去建立 Lambda 函数,最后建立 API Gateway。json
全部的操做均选择在 AWS us-east-1 区域。api
建立 DynamoDB 很是简单,在 Console 简单点几下就能够,由于 DynamoDB 须要一个主键,咱们把生成的 uuid 做为主键,填写完成建立便可。安全
是否是很简单,就这样建立好了,若是你使用 awscli 建立的话,那更简单:bash
aws dynamodb create-table \ --table-name wzlinux-down \ --attribute-definitions AttributeName=id,AttributeType=S \ --key-schema AttributeName=id,KeyType=HASH \ --billing-mode PAY_PER_REQUEST \ --region us-east-1
就这样简单的建立好了,下面咱们开始建立比较重要的 Lambda。服务器
由于 Lambda 须要有权限向 DynamoDB 写入数据,咱们能够本身建立一个 Lambda 角色,赋予对呀的权限,在建立的时候,把咱们所建立的 Role 赋予 Lambda,我这里给的资源范围大了一些,安全要求高的,能够给予最小的权限,权限 json 以下:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "logs:CreateLogStream", "logs:PutLogEvents", "logs:CreateLogGroup", "dynamodb:PutItem", "dynamodb:Scan", "dynamodb:Query", "dynamodb:UpdateItem" ], "Resource": "*" } ] }
建立 Lambda 也比较简单,大部分参数选择默认便可,注意在 Permissions 里面选择咱们上面建立好的 Role,运行环境咱们选择 Python,固然 Lambda 也支持 .NET、Go、Java、Node.js、Ruby,甚至还支持用户自定义运行环境。
我这里已经把 Lambda 函数写好了,文件命名为lambda_function.py
。
import boto3 import os import uuid import time from requests import get def lambda_handler(event, context): recordId = str(uuid.uuid4()) ctime = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) sourceIP = event["headers"]["x-forwarded-for"] url = "https://api.ipdata.co/{0}/country_name?api-key=40b58339be0ec3ba64fb936da37dbab9c9d1677f335c50910c52aeb7".format(sourceIP) country = get(url).text try: referer = event["headers"]["referer"] except: referer = "NULL" try: site = event["queryStringParameters"]["type"] except: site = "NULL" # Createing new record in DynamoDB table dynamodb = boto3.resource('dynamodb') table = dynamodb.Table(os.environ['DB_TABLE_NAME']) table.put_item( Item={ 'id': recordId, 'site': site, 'create_time': ctime, 'ip': sourceIP, 'country': country, 'referer' : referer } ) return {"statusCode": 200, "body": "OK"}
大体介绍一下函数,咱们从 API Gateway 传入的参数获取用户来源 IP,而后经过一个接口把 IP 转换为国家。
再一个就是获取连接从哪一个页面请求过来的,还有一个就是给我上面传入的参数 type 的取值。
Lambda 获取的参数主要经过 event 传递进来,event 是 API Gateway 传过来的参数,咱们使用最简单的 HTTP API,我这边记录了传过来的 event,详细信息能够参照官方文档,这样你们就能够更加理解 Lambda 函数是怎么截取的数据。
{ "version": "2.0", "routeKey": "GET /", "rawPath": "/", "rawQueryString": "type=CN", "headers": { "accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9", "accept-encoding": "gzip, deflate, br", "accept-language": "zh-CN,zh;q=0.9", "content-length": "0", "host": "49imv2pyz1.execute-api.us-east-1.amazonaws.com", "sec-fetch-dest": "document", "sec-fetch-mode": "navigate", "sec-fetch-site": "none", "sec-fetch-user": "?1", "upgrade-insecure-requests": "1", "user-agent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.105 Safari/537.36", "x-amzn-trace-id": "Root=1-5f2f6066-93614fb0bb62a21428cb8508", "x-forwarded-for": "52.221.86.56", "x-forwarded-port": "443", "x-forwarded-proto": "https" }, "queryStringParameters": { "type": "CN" }, "requestContext": { "accountId": "921283538843", "apiId": "49imv2pyz1", "domainName": "49imv2pyz1.execute-api.us-east-1.amazonaws.com", "domainPrefix": "49imv2pyz1", "http": { "method": "GET", "path": "/", "protocol": "HTTP/1.1", "sourceIp": "52.221.86.56", "userAgent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.105 Safari/537.36" }, "requestId": "Q-wAChzJoAMESlQ=", "routeKey": "GET /", "stage": "$default", "time": "09/Aug/2020:02:33:10 +0000", "timeEpoch": 1596940390575 }, "isBase64Encoded": "False" }
由于 python 函数有依赖包,咱们须要把依赖包一并打包传到 Lambda,关于打包的过程以下,咱们这里用到的依赖包为 requests。
pip
的 --target
选项在新的项目本地 package
目录中安装库。~/my-function$ pip install --target ./package requests
~/my-function$ cd package ~/my-function/package$ zip -r9 ${OLDPWD}/wzlinux-down.zip .
~/my-function/package$ cd $OLDPWD ~/my-function$ zip -g wzlinux-down.zip lambda_function.py
打包好的代码包wzlinux-down.zip
能够直接传到 Lambda,也能够先传到 S3,再上传到 Lambda,上传完成以后以下:
注意:由于咱们代码中有环境变量,就是咱们前面建立的 DynamoDB,在环境变量这一列建立好便可。
DB_TABLE_NAME:wzlinux-down
点击右上角的测试,咱们发送测试的 json,这里咱们就模拟 HTTP API,直接把上面的示例数据帖进去便可。
选择执行,查看到已经执行成功了。
而后再去查看 DynamoDB 中,是否已经有数据写入。
至此,咱们的 Lambda 已经打通,一样附上使用 awscli 建立 Lambda 的命令,须要咱们提早把代码和依赖库打包上传到 S3。
aws lambda create-function \ --function-name wzlinux-down \ --runtime python3.8 \ --role arn:aws:iam::921283538843:role/wzlinux-down-role \ --handler lambda_function.lambda_handler \ --code S3Bucket=code.wzlinux.com,S3Key=wzlinux-down.zip \ --environment Variables={DB_TABLE_NAME=wzlinux-down} \ --region us-east-1
--role:选择你建立好的 Role
--code:这里是我打包好的代码,上传到了个人 S3 中
建立好以后,咱们直接请求这个连接访问看看效果,固然咱们能够再连接后面传递参数 type,如请求地址:
https://jat553o58l.execute-api.us-east-1.amazonaws.com/?type=CN https://jat553o58l.execute-api.us-east-1.amazonaws.com/?type=US
一样查看一下 DynamoDB 数据库,查看数据是否入库:
为了方便记录,咱们可使用本身的域名,在 Custom domain names 里面进行建立。
建立好以后,咱们为域名添加 CNAME 解析,解析值为 API Gateway domain name。
解析完成以后,咱们须要为自定义域名配置一个 API mapping。
而后咱们就可使用咱们最开始规划的地址进行访问了。
https://down.wzlinux.com?type=CN https://down.wzlinux.com?type=US https://down.wzlinux.com?type=IN
咱们经过一个 URL,传递不一样的参数,为各个国家生成了不一样的接口,只须要埋到对应的页面,当用户访问的时候,咱们就会捕获到数据,进而能够进行分析。
AWS 这一套服务器架构(API Gateway + Lambda + DynamoDB),极大的减轻了咱们开发 API 接口的工做量,使得只是简单懂得处理逻辑的函数开发人员便可完成 API 的开发,而且无服务器架构还有不少传统应用不具备的优点,能够预见无服务器架构会成为云计算的下一个纪元:
在第一次配置调试过程当中,注定会遇到各式各样的问题,你们必定要充分利用 CloudWatch Logs 这个服务,咱们的不少报错均可以在里面找到,最后,若是你们都已经学会了,那就开启你的无服务之旅吧,充分利用云原生的一些功能,把咱们的应用进行现代化。