使用AWS Step Functions定制工作流

aafeng
·
·
IPFS

最近看上了一款Thinkpad的笔记本,但钱包不够鼓。于是想等价格降下来再考虑。难道去天天刷网页看价格吗?似乎不是一个程序猿该有的思维。最简单的方式就是写一个程序,检查该页面中的价格,然后设定为cron job,每天检查一下,给自己发邮件/短信通知。但这种方式实现起来一点刺激都没有,于是想到了AWS中的Step Functions。于是把整个过程用AWS实现了一下,通过一种无服务器的方式来实现这个功能。


首先做一个对比:

流程控制:在传统方式中,通过编码来实现。在AWS中,通过Step functions实现。

检查价格:在传统方式中,通过Python抓取网页并分析网页获得。当然,如果有API可用就更简单了。在AWS中,将这个步骤封装到Lambda。

消息通知:这里可以调用一些第三方库来实现。在AWS中,这部分都已经做好了,直接使用SNS就可以。

定时运行程序:在传统方式中,可以设定一个cron job。在AWS中,可以通过使用Eventbridge (过去叫做Cloudwatch)来实现。

可以看到,相对于传统方式,AWS栈的最大优势就是无需管理自己的服务器。安全补丁,系统升级等等都无需考虑。下面看看如何来实现这个功能把。

第一步:创建主题和订阅(Topic/subscription)

在AWS中创建一个Topic,比如:ThinkpadPriceAlert


针对这个Topic,添加一个订阅者。这里选择邮件订阅方式。


需要去邮箱中确认这个订阅。

第二步:创建Lambda

接下来创建Lambda,去读取最新价格。这里直接读取网页,然后使用正则表达式提取价格,再以json方式返回价格:

import json
import re
from urllib import request

def lambda_handler(event, context):
    req = request.Request('https://www.lenovo.com/gb/en/laptops/thinkpad/thinkpad-x1/X1-Carbon-Gen-8-/p/22TP2X1X1C8')
    req.add_header('User-Agent', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:77.0) Gecko/20100101 Firefox/77.0')
    response = request.urlopen(req)
    html = response.read().decode('utf-8')
    price = float(re.search('<dd itemprop=\"price\">(.*)<\/dd>', html).group(1).replace('£', '').replace(',',''))
    return {
        'statusCode': 200,
        'price': json.dumps(price)
    }

第三步:使用Step function创建价格查询流程

定义如下的Step functions:

{
  "Comment": "Thinkpad laptop price checker",
  "StartAt": "Check Thinkpad Price",
  "States": {
    "Check Thinkpad Price": {
      "Type": "Task",
      "Resource": "arn:aws:states:::lambda:invoke",
      "Parameters": {
        "FunctionName": "arn:aws:lambda:eu-west-1:xxxxxxxxxxxx:function:ThinkpadPriceChecker:$LATEST"
      },
      "Next": "Notify Me"
    },
    "Notify Me": {
      "Type": "Task",
      "Resource": "arn:aws:states:::sns:publish",
      "Parameters": {
        "Message.$": "$.Payload.price",
        "TopicArn": "arn:aws:sns:eu-west-1:xxxxxxxxxxxx:ThinkpadPriceAlert"
      },
      "End": true
    }
  }
}

需要注意,上面的$.Payload.price需要和前面Lambda中的返回值相匹配。至此,就可以运行这个Step Functions了,运行的结果就是收到一封包含最新价格的邮件。

第四步:创建EventBridge Rule来定期调用Step Functions。

类似于Cronjob,可以设定事件被调用的频率,还有在指定时间需要调用的目标,比如一个Lambda,我们这里可以选择前面创建的Step Functions。



至此整个程序就做好了,每天在邮件中都会收到价格提示。当然,Step Functions中可发掘的功能还有很多,比如:条件选择,并发执行,容错处理等等。讲了这么多,回到主题,希望哪天价格真降下来。。。

CC BY-NC-ND 2.0 授权

喜欢我的作品吗?别忘了给予支持与赞赏,让我知道在创作的路上有你陪伴,一起延续这份热忱!