標籤

Lambda

Day25 - Lambda 好像有時候一開始回應很久?用 warm-up 來熱機吧

前言

本篇會介紹 npm 套件庫裡的 Serverless-plugin-warmup,裡面介紹了很多參數可以使用,以下會簡介如何引入它。

實作

透過npm來安裝套件

npm install --save-dev serverless-plugin-warmup

serverless.ymlplugin加入套件

plugins:
  - serverless-plugin-warmup

custom加入warm up的設定參數

custom:
  warmup:
    enabled: true
    cleanFolder: false
    memorySize: 128
    name: "LINE-warmup-pop"
    events:
      - schedule: "cron(0/5 0-12 ? * MON-FRI *)"
    timeout: 10

.gitignore加入以下兩個_warmup/以及.requirements.zip,他在部署前建立一個_warp的資料夾並放一個 Lambda 來打已建立的 api 以及 Lambda 們,部署後會建立.requirements.zip,所以這邊就加入這兩行來防止被 git 推上去。

或許會有疑問不是cleanFolder設定 true 就可以,這邊我自己實測時在部署會因為 Size 過大而無法上傳,把這參數設定掉他才會乖乖的上傳成功,但這部分有待驗證。

加入 decorator

這邊我在lib/下新增一個decorator.py,加入以下的 code

from functools import wraps
from logging import Logger

def lambda_warm_up(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        source = args[0].get('source')
        if (source == 'serverless-plugin-warmup'):
            Logger.info('WarmUp - Lambda is warm!')
            return {}
        return func(*args, **kwargs)
    return wrapper

主要功能是透過 python decorator 的特性讓我們在 function 之前用個前綴符號就可以引用它,很像 po 文在 tag 別人一樣 🤣 warm-up 建立的 Lambda 會固定對其他的 Lambda 打serverless-plugin-warmup的字串,這邊就寫個判斷式判斷掉後直接 return

你以為這樣就結束了?還有 IAM role 的問題呢,詳細問題已不可考,想試看看的可以把 IAM 拔掉再部署一次,問題就會出現了,以下為設定檔:

iamRoleStatements:
  - Effect: "Allow"
    Action:
      - "lambda:InvokeFunction"
    Resource:
      - Fn::Join:
          - ":"
          - - arn:aws:lambda
            - Ref: AWS::Region
            - Ref: AWS::AccountId
            - function:*

如果你的目錄結構跟我一樣,或是跟到今天的實作,加入以下的 code,這邊主要是告訴你的 Lambda 要在每次的 warm-up 字串來的時候呼叫這個 decorator 來幫忙處理一下

from lib.decorator import lambda_warm_up

@lambda_warm_up
def xxx():
    pass

我的 Lambda 都加了,那原本的 flask 建立的 api 我要加在哪?

看看這個網址,serverless-wsgi 在實作的時候已經有考慮到這件事了,所以 api 這邊就不用管他,他自己會去把它處理掉!

結論

Warm-up 的機制就是透過建立一個 Lambda 來打一個 flag 到其他 Lambda 來他們別進入睡眠模式,但總是會有人考慮費用的問題,可以參考下圖,若是你建立了一個簡單的服務然後上線了,AWS 給你了一百萬個請求的量,我覺得一個月的請求可以到 100 萬應該是服務有點規模的情況,一個月能到這個量相信你也有一定的能力養它 🤣,爾後每一百萬個請求才六塊台幣,可能比 GCP 還貴,但其實以我來說這樣已經很夠用,而且還扛得住

參考

serverless-wsgi Warm-up code Serverless-plugin-warmup

繼續閱讀

Day18 - 在 Serverless 上設定個排程來發送空氣污染檢測吧

前言

過往寫了這麼多的 api,總是會有特定的功能會需要輪詢資料庫或是監聽某些事件,以前還要到弄個虛擬機寫腳本用 crontab,這時候 Lambda 的用處就來啦!不只可以處理 api 的事情,還可以設定排程做事,太舒服啦,以下就來介紹一下~

實作

首先在 consumer 資料夾下line_bot_alert.py,再寫一段需要定時跑的程式,這邊我去抓中央氣象局的資料,大概簡單判斷一下區域以及算出他的範圍:

import json
import requests

def alert_handler(event, context):
    air = requests.get(
        'http://opendata.epa.gov.tw/webapi/Data/REWIQA/?$orderby=SiteName&$skip=0&$top=1000&format=json')
    air_body = json.loads(air.text)
    air_status = ["良好",	"普通",	"對敏感族群不健康",	"對所有族群不健康",	"非常不健康",	"危害", "資料有誤"]
    total, count = 0, 0
    for fetch in air_body:
        if (fetch['County'] == "臺中市" and (fetch['SiteName'] == "西屯" or fetch['SiteName'] == "沙鹿")):
            count += 1
            if fetch['AQI'] != 0:
                total = total + int(fetch['AQI'])
    switch = 0
    pm = int(total / count)
    print(pm)
    if pm in range(0, 50):
        switch = 0
    elif pm in range(51, 100):
        switch = 1
    elif pm in range(101, 150):
        switch = 2
    elif pm in range(151, 200):
        switch = 3
    elif pm in range(201, 250):
        switch = 4
    elif pm in range(251, 300):
        switch = 5
    else:
        switch = 6
    payload = f"\n空氣品質: {air_status[switch]}"
    r = requests.post('https://1uv2o723o4.execute-api.us-east-1.amazonaws.com/dev/notify/sqs',
                      data={'message': payload})
    print(r)

serverless.yml的 function 下面加入 Lambda,handler 就是 資料夾/檔案.類別,設定事件(event)排程一分鐘一次

function:
  line_bot_alert:
    handler: consumer/line_bot_alert_handler.alert_handler
    events:
      - schedule: rate(1 minute)

AWS Lambda 有兩種設定排程的方法,rate以及cron,若是比較固定時建議用rate,比較複雜的排程就可以讓cron來,下面兩張圖分別是來自 AWS >


sls deploy部署之後就會看到剛剛做line_bot_alertfunction,他每分鐘都在跑,若玩完之後不想用了可以下sls remove把上面有的東西刪掉嚕!

結論

其實還有很多應用可以實作排程,像是有朋友就用 GCP 的來定時發文 🤣,而且可以把腳本寫得像是 api 一樣,讓整個靈活性都增加了不少,下一篇就帶大家來做 LINE Login 嚕!

參考

AWS document

繼續閱讀

Day17 - 看一下自己寫的東西都去哪了

前言

用 Serverless 用得這麼爽,也是時候來看一下他的資源在哪,距離我上次自己手動上傳 python 檔已經是 N 個月之前的事了(遠望),當時也沒用過什麼Api Gateway相關的服務,以下就帶大家來介紹一下嚕!

介紹

CloudFormation

CloudFormation 是一個 AWS 所提供的 JSON-base 服務,主要是用來讓使用者能夠快速建立 AWS 的服務。

這邊也不用擔心設定的問題,Serverless 再 deploy 的過程中會幫忙 CloudFormation 的 json 檔

透過 CloudFormation 建立 JSON-based 的 template 你可以快速建立所需要的資源堆疊(stack)。

按下Template後如下圖所示,他會顯示你已經有建立的服務 Map,整個線牽起來看起來就很爽 XD

Api Gateway

Serverless 建立過程中也會透過 CloudFormation 幫忙建立 Api Gateway,因為我們是用 WSGI,所以只會看到兩個ANY的路由。 點進去後就可以看到 Client 是怎麼進出的,最右邊是打到 AWS Lambda 上,可以點選上面的字進入 Lambda 所在地。

Lambda

點選進來之後可以看到 Lambda 接了什麼服務,以我到目前的程式就會有API GatewaySQS以及預設的CloudWatch(都是透過這個來看 log) 接著往下會看到之前設定的環境變數以及STAGE,這些都是托Serverless的福免去這些麻煩的設定

S3

Serverless 在過程中會在 S3 幫忙建立一個 Bucket,並在後面加個 hash key 以免 bucket 重複。

Cloud Watch Log

在開始測試後 AWS 會幫忙在這個地方輸出 Log,

Serverless deploy 紀錄

這邊使用 Serverless deploy --verbose 就可以看到所有部署中的基本資訊了

首先因為我們有使用.env,所以在一開始時會先設定環境變數,接著就是把相依套件的東西都放進去,再去啟動 CloudFormation


接著會建立一個 S3 的 Bucket,將程式透過 CloudFormation 處理成 zip的檔案格式並上傳到 S3 上面


接著就會部署到 Lambda 以及 Api Gateway 上,並做對應 CloudFormation JSON 檔的設定


在最後部署完之後就可以看到所有的基本資訊,物件名稱、部署階段、區域、網域以及 Function 們(因為 Lambda 是 Function-base 的服務)等等的基本資訊都會在此

結論

以目前的架構基本上到這麼基本資訊都顯示出來了,若是有使用像是Route 53CloudFront等等的服務它就會顯示在這邊了。雖然說 CloudFormation 在設定上已經很方便了,但不得不說 Serverless 真的幫忙做了很多事,讓開發者又更能專注在打 Code 上了~

參考

使用 CloudFormation 快速部署 AWS 資源

繼續閱讀

Day1 - serverless 介紹

前言

那因為現任公司的服務都是基於 AWS,如此這般我就接觸到 Serverless(以下簡稱 sls) 這個框架啦 (想更深入了解 FaaS 架構可以參考 AWS)


為什麼要 Serverless

Serverless 架構是一個基於 FaaS(Function as a Service) 實作的一個服務,讓開發者可以更專注在開發功能,將 yml 檔設定好其餘維運的問題都交給 AWS、Google、Azure 這些服務商去處理,只要把信用卡準備好就好(?),讓開發者在寫完程式之後不用煩惱部署得問題,減少的不少的麻煩事。

以用一個 Ruby on Rails 寫的機器人為例,在寫完個 webhook function 後,設定路由然後部署,一般主機或是虛擬機就很麻煩,要安裝佈署環境以及一安裝堆相關套件,完了之後設定 Domain 什麼的有夠花時間。但若是使用 heroku 部署就很方便,Login-Create-Deploy 馬上就結束,機器人馬上就上線了,實在是俗又大碗呀~

但我覺得像是 LINE Message 這種 stateless 的服務,且只要一個 function + route 就能實作的程式最適合 Serverless 了,讓專案可以簡潔有力,只要寫一個 function+yml 設定並打個指令就部署了,而且 domain 還附贈 SSL,將服務交給 AWS 也不需要擔心,整個就是超級方便啊!

serverless.yaml 是該專案的設定檔,可以把它想像成是 CloudFormation 的 wrapper,事實上也的確是這樣,serverless 背後會把他轉成 CloudFormation 的 template 去發佈。這個設定檔是 serverless 的精髓所在,一切有關 API Gateway 和 Lambda 的設定都在這邊,而底層所需要的資源,他都幫你配置好了,不需要操心。 ref


Cold start 問題

依照我目前使用的結果下來,在 heroku 以及 AWS Lambda 同時睡著的情況下,AWS 起床的回應速度大概 1 秒左右,而 heroku 則大概落在 10~15 秒(參考)。

如下圖所示的免費方案,基本上開發階段應該是不至於到 100 萬/月 個請求吧 ?,所以這部分就別擔新大力地給他用下去!

AWS Lambda 限制

安裝與使用

serverless.yaml 的設定參考 serverless.yaml 的變數傳遞


結論

接下來會是使用 Serverless 這個框架去實作的,使用的語言為 Python,至於為什麼會選它呢,最主要原因還是在官網上有很多 plugin 可以用 ( NodeJS & Python ),開發時資源相對多,接著是 AWS Lambda 的 Code-start 最快的就屬於 NodeJS & Python 了,而我原本就是寫 Ruby 來的,自然就選一個寫法相近的語言啦(好像有點牽強),如果說你想了解 runtimes 相關的問題的話可以參考這篇

環境

參考

繼續閱讀