標籤

Serverless

在 Cloud Functions 上部署有 Open Data 功能的 LINE Bot | 摘要王, 天氣, 紅外線

繼續閱讀

如何建立 fly.toml 並快速佈署至 Fly.io

介紹

最近因為有些專案需要有 local Volume,但在 Serverless 上要用偏麻煩,除機器上的本身功能以外,還需要另外開 VM 讓 Container 能夠 mount volume,因此需要類似 Heroku、Fly.io 這類的 SaaS 的服務,可以用很少量的費用去使用到 Database/Volume 的功能...

繼續閱讀

在 Fly.io 上架設 Uptime Kuma 監控 Side Project

前言

由於近期自己蓋了幾隻 side project,慢慢發現有些服務倒了我自己也不知道,但時間久了其實當下也會忘了要修哪...

也因公司內有 status page 可以看每個服務狀態,想想這需求我也需要,因此萌生了架 status page 來幫忙確認健康狀態,接下來看看怎麼操作吧

繼續閱讀

【Google I/O】筆記 | Firebase & 其他紀錄 🥷

前言

今年也是一個 AI 元年,Google IO 上也講了許多與 AI 的結合,當然 Firebase 也不意外,剛好近期在 Side Project 中使用了比較多 Firebase 相關的開發,因此本篇會先紀錄較多 Firebase,也同步把 Keynote 中聽到的內容給記下來。

繼續閱讀

【GCP】如何讓 Cloud Run 持續執行背景程式

冷啟動(Cold start) & Cloud Run 如何處理?

Serverless 架構的冷啟動(cold start)是指當一個沒有被使用的函式需要被調用時,需要先啟動一個新的容器或虛擬機器來執行該函式,這個啟動的期間被稱為冷啟動時間。

但我們在寫應用的時候通常都會帶有一些 cronjob 在背景跑(備份、爬蟲...),但在 Serverless 上都會遇到 Cold Start 的問題,在這種情況下因為資源都會被釋放掉,如果這些 cronjob 是比較重的且 Severless RAM&CPU 又放比較少, cronjob 時邊爬蟲邊異地備份又讀寫資料庫(~~ 誇張了點 ~~),這情況下可能會因為資源瞬間不夠導致功能異常。

繼續閱讀

【GCP】將 FastAPI 佈署上 Cloud Run

前言

近年來,隨著雲端計算的普及和發展,越來越多的企業和開發者正在尋找一種更簡單、更高效的方式來佈署和運營應用程式。而 Severless 技術正是一種流行的解決方案。Google Cloud Run 是一個強大的 Severless 平台,可以幫助開發人員快速地佈署和運營。接著,本文將介紹 Google Cloud Run 的優點和如何在其中佈署。

繼續閱讀

【Podcast】Kubernetes vs Serverless with Matt Ward - Software Engineering Daily

📸 by WFranz

前言

Kubernetes 在分散式系統中已經成為一個高可用性平台,並且有許多人都會將程式部署在上面,雖然部署在 Kubernetes 上很好,但本身的管理以及學習都不那麼簡單,因此也有許多人會使用 Serverless 來解決需求。

而今天介紹這個集節目就邀請到 Mux 的 Matt Ward,他們家的產品主要是在做 video streaming APIs,現今他們有自己的 Kubernetes 也曾經在 Serverless 中使用過,以下就分享我從這集 podcast 學到的東西以及心得囉!

繼續閱讀

使用 Serverless/Flask/Swagger 在 AWS 上搭建打造 Open API

前言

約在一年前,當時公司的同事帶我玩過 Swagger,只是當時的我寫得不太習慣,直到寫這篇之前都還只是寫 markdown 來做 API 文件 😓,不過寫 API 到最後總是要開放給其他人需要測試以及用文件來描述功能,但只是寫 Readme.md 給其他人看感覺有點不負責任 (?),所以這個時候 Swagger 就發揮它的作用啦~

但是看著下面這張圖… 左邊那是怎樣!怎麼設定了一大堆右邊才出現一點點東西,估且不論還要設定 Model、Payload 什麼的,我想光寫左邊這份文件加測試的時間我都可以寫一份 Markdown 給其他同仁用 Postman 測試了…🤣🤣🤣 這時候套件就出動啦,這次要介紹的是 flask-restful-swagger-2.0,他是延續原版套件並加以更新的,不得不說再搭更新完後整體寫起來人性多了,像是文先寫法用 decorator 的寫法在路由之前、宣告 Schema 時只要用類別包起來之類的,讓寫文件可以用 python 的寫法去寫,除了特殊的設定需要比對 Swagger 官方文件外,在建一個 Swagger 格式的文件這樣已經超快了 💪 既然如此那就介紹一下他的相關設定並把它記錄下來吧!

繼續閱讀

【AWS】使用 API Gateway Authorizer 做使用者驗證 feat. Serverless

API Gateway Lambda authorization workflow

前言

在 AWS 的 API gateway 上就有一個項目(Authorizer)是支援 Cognito 以及客制認證的方法,好處就是在進我們寫的 API 之前有個可以做身份確認的 Lambda Function 幫我們好前處理,而本篇則會介紹如何在 Serverless framework 上設定 API gateway 的 Authorizer 以及成功讓 API 回應,串接 Cognito 做使用部分就留給之後吧!

👉 本篇的範例全都在 GitHub

繼續閱讀

【LINE API】- 使用 Icon Switch 讓你的機器人同時有多個角色! feat. Python

最近 LINE 釋出了一個我很喜歡的功能 - Icon Switch🎚,從字面上的意思就是可以切換機器人的 Icon (名稱以及大頭貼),過往開發者在使用時都只能較死板的使用同一個頭像或暱稱來回應使用者,而現在只要使用這個這個功能就可以很輕易地切換你想要的大頭貼以及暱稱了 😇

據可靠消息指出這以前是需要收費的功能,而現在則是免費推出來給大家使用,讓大家可以有更多的彈性去開發新功能~

繼續閱讀

使用 Sentry 收集錯誤並將訊息送至 Slack

前言

大家好,我是 Chatbot TW 的 NiJia

當產品開發完上線後難免會遇到可能是邏輯上的 Bug、例外錯誤或是想記錄使用上的錯誤,當沒有工具時都只能等錯誤出來時乖乖的去翻 Log 找問題,對於每次出錯要 Debug 的我就覺得很困擾 😭。

公司強者寫 APP 的同事他們都很開心的在使用 Crashlytics 幫他們將 APP 出問題時將錯誤訊息丟上去,看了實在時羨慕,但那們寫 Web 的朋友要怎麼辦!

最近就發現了Sentry這個玩意兒(應該是有段時間的產品了),支援了幾乎支持現在市場上主流的各種框架以及語言,且串接上也都很簡單就能實現,文件也都清楚解釋每個 API 的功能如何使用,以下就來介紹如何使用它吧 😎

這邊顯示較常用的語言,還有支援很多其他種類的框架及語言

說明

如何使用

首先先到 https://sentry.io/welcome/ Get start


這邊可以整合了GitHub或者Azure DevOps兩種 OAuth 的登入方式


接著就照著步驟來囉!


選擇自己所使用的語言,這邊我使用 Flask(python) 框架來實作


接著官方會有個簡單的文件告訴你要如何實作這塊,這邊就先使用pip在本地安裝套件

pip install --upgrade "sentry-sdk[flask]==0.13.2"

若是使用雲端服務的話需要將sentry-sdk[flask]==0.13.2放入 requirements.txt 中

將以下 init code 放入 api.py 裡,在 app = Flask(__name__) 之前

這邊我將 Sentry 的 DSN 放入 .env 裡,若有參考這部分的朋友需要注意環境變數的地方喔!

import sentry_sdk
from sentry_sdk.integrations.flask import FlaskIntegration

sentry_sdk.init(
    dsn=os.environ.get('SENTRY_DSN'),
    integrations=[FlaskIntegration()]
)


接著就開始丟錯誤上去看看狀態,我的專案上是串著 LINE Bot,功能只是當個應聲蟲,在這情況下只需要丟個貼圖給它就會出錯

當錯誤丟出來之後原本監聽的紅色燈號就會打勾囉 ✅

Sentry 預設都會寄信通知,所以若有錯誤記得看信箱哦!


點進去後就可以很清楚的看到程式是錯在第幾行,寫到這有種莫名的感動,平常都是在 LOG 海裡找看看到底報錯在哪邊,終於有個地方能幫我接下來了 🎉

到這邊基本串接已經完成了,但身為免費導向的工程師怎麼能讓 5000/月 限制我!接下來就要去過濾一下來的錯誤內容,若不是系統造成的錯誤就不上傳。

我選擇判斷 Log 達到Waring或是Internal就回報,並照著官方的指示新增以下內容:

import sentry_sdk
from sentry_sdk.integrations.flask import FlaskIntegration
+ import logging
+ from http.client import HTTPException
+ from sentry_sdk.integrations.logging import LoggingIntegration


+ def strip_sensitive_data(event, hint):
+     if "exc_info" in hint:
+         instance = hint['exc_info'][1]
+         if isinstance(instance, HTTPException) and instance.code < 500:
+             return None
+     return event


+ sentry_logging = LoggingIntegration(
+     level=logging.INFO,
+     event_level=logging.WARNING
+ )

sentry_sdk.init(
    dsn=os.environ.get('SENTRY_DSN'),
+    before_send=strip_sensitive_data,
+    integrations=[FlaskIntegration(), sentry_logging]
)
  • strip_sensitive_data: 過濾來自 Http 的 Exception 錯誤碼是否大於500,否則不回傳。
  • sentry_logging: 使用 SDK 的 LoggingIntegration 來定義 log 回傳事件時的層級到哪層才上傳錯誤訊息,這邊我設定Waring等級,並加入到 init 的 integrations 裡。

此時不管你打上都會將訊息送上 Sentry:

logging.waring("i am waring")
logging.error("i am error")

或者是

raise InternalServerError("Hi Error")

或者!!自己手殘讓程式崩潰也會送通知

到這基本上已經完成串接完成並能過濾錯誤訊息,接下來則為將服務串至 Slack 上。

Slack bot 串接

首先來到Settings按下Integrations會看到以下畫面,並安裝一下Slack


接著就要跟 Slack 連動囉


連動完成後再按下configure來設定以下內容


到了Alerts頁面後就開始設定以下內容囉,這部分參考官方文件


可以指定透過哪個group去傳送至哪個tag,我就直接送到預設的#general


測試就直接送出貼圖來讓 bot 報錯,結果就收到key的錯誤啦~

結論

最後就能透過sls deploy將專案部署到 AWS 上,透過這次的紀錄對 Sentry SDK 運作在框架上的問題更加了解,同時也找到了一個不僅可以紀錄錯誤還能通知我錯誤訊息的地方,可以在第一時間直接進去分析 log,若完成了可以直接在 slack 上按Reslove來完成這個 issue。

本來有在考慮要串接LINE Notify,不過看著 Sentry 對 Slack 的整合比較好,也就放棄了這個念頭了 🤣,但串接哪個平台其實就看公司的需求,Sentry 一樣可以透過 webhook 將錯誤訊息傳至 Server。

此外它一樣可以整合GithubGitLabAzure DevOps...等等,若錯誤處理好的話可以讓 Sentry 幫你送 Issue 上去,不僅整個超炫砲 😎,若是 open source 的專案也可以大家一起去修這個問題,真的是一舉兩得啊!!!

繼續閱讀

續篇 — serverless + WSGI + flask + chatbot 的開發指南

前言

如果還不知道 Serverless (以下簡稱 sls )的朋友可以先看我上篇文章,裡頭有介紹 Python 以及 Ruby 的範例。 還沒接觸 Serverless 之前,當開發完一包程式時就將它部署至 Heroku,實在是有夠方便又快速(還是免費的)。不過有個問題是當程式沒在運行時他會睡覺,身為一個免費仔做的小專案這樣是夠的,做為一個貪心的免費仔怎能容許睡覺睡這麼久 🤤!但若是照著我上篇分享的文章做,佈署程式沒問題,但就開發機器人我都要佈署才能測試,這未免也太不人性了 😒。

繼續閱讀

使用 Serverless & LINE Message API 在 AWS 上打造一個 Echo bot

前言

Serverless 架構是一個基於 FaaS(Function as a Service) 實作的一個服務,讓開發者可以更專注在開發功能,將 yml 檔設定好其餘維運的問題都交給 AWS、Google、Azure 這些服務商去處理,只要把信用卡準備好就好(?),讓開發者在寫完程式之後不用煩惱部署得問題,減少的不少的麻煩事。 那因為現任公司的服務都是基於 AWS,如此這般我就接觸到 Serverless(以下簡稱 sls) 這個框架啦 (想更深入了解 FaaS 架構可以參考 AWS) [2019/07/04 更新] 若已經暸解的朋友可以參考我的 python 版本: louis70109/aws-line-echo-bot Ruby 的範例版本: louis70109/aws-ruby-line-echo-bot

為什麼要 Serverless

[2019/06/29 更新] 以用一個 Ruby on Rails 寫的機器人為例,在寫完個 webhook function 後,設定路由然後部署,一般主機或是虛擬機就很麻煩,要安裝佈署環境以及一安裝堆相關套件,完了之後設定 Domain 什麼的有夠花時間。但若是使用 heroku 部署就很方便,Login — Create-Deploy 馬上就結束,機器人馬上就上線了,實在是俗又大碗呀~ 但我覺得像是 LINE Message 這種 stateless 的服務,且只要一個 function + route 就能實作的程式最適合 Serverless 了,讓專案可以簡潔有力,只要寫一個 function+yml 設定並打個指令就部署了,而且 domain 還附贈 SSL,將服務交給 AWS 也不需要擔心,整個就是超級方便啊! Cold start time 問題,依照我目前使用的結果下來,在 heroku 以及 AWS Lambda 同時睡著的情況下,AWS 起床的回應速度大概 1 秒左右,而 heroku 則大概落在 10~15 秒(參考)。如下圖所示的免費方案,基本上開發階段應該是不至於到 100 萬/月 個請求吧 😆,所以這部分就別擔新大力地給他用下去~ (感謝 petertc 幫忙找這方面的問題 💪)

AWS Lambda 免費方案 接下來就讓我介紹如何使用 sls + LINE Message API 建立一個 Echo bot 吧!

環境

npm 6.9.0 python 3.7.3 serverless 1.45.1

建立 AWS 存取金鑰

首先要先有個 AWS 帳號(廢話) ,如果沒有綁定信用卡記得去綁定才能繼續,接下來就可以去就可以去建立鑰匙囉! 如上圖,按下紅色框框的部分,接著按箭頭指的按鈕,就會建立一個我們要的金鑰囉! AWS secret & ID key

如上圖所示,可以下載 key,AWS 不會幫忙保存 Secret key,若這視窗關掉的話 key 就不見了,所以使用者可以自行下載檔案保存,以免哪天要部署的時候找不到 key。 接著就將這兩個參數加入環境變數中:

export AWS_ACCESS_KEY_ID=<your-key-here>
export AWS_SECRET_ACCESS_KEY=<your-secret-key-here>

Serverless 建立與部署

首先先透過以下指令讓 npm 幫忙安裝 sls 的指令。

npm install serverless -g

安裝完之後就透過 sls 指令來建立專案嚕!

serverless create — template aws-python — path aws-line-echo-bot

severless 指令可以縮寫成 sls template = 想用什麼平台以及語言就在此模板了 (參考) path = 檔案名稱

透過 severless 建立專案指令 依照不同的 template 可能會建立 N 個檔案,但主要還是以下三個檔案

.gitignore
handler.py = 主程式的地方
serverless.yml = 所有設定都在這裡,funtion 參數會對應到指定的路由

在部署前須至 serverless.yml 裡,把 runtime 的 python2.7 改至 3.7,否則會因版本問題導致錯誤。

serverless deploy # sls deploy

Serverless 部署畫面

接著到 AWS Lambda 以及 S3 就可以看到第一次部署完的程式以及檔案囉!

加入 LINE Message API

既然是寫 python,那一定是要用 line-python-sdk 照著官方用法應該是要執行以下指令安裝套件

pip install line-bot-sdk

不過我們是要部署到 AWS 的 Lambda 上,且因為他是無伺服器運算的服務,所以他沒辦法跑 pip 去幫我安裝套件。 此時就要出動 requirements.txt 來管理相依套件 ,但只有加入它 sls 根本不認識,因此我們需要安裝 pulgin 來讓 sls 認得(requirements.txt)。

sls plugin install -n serverless-python-requirements


安裝指令 & package.json 如圖,安裝過程中會自動建立 package.json,且會幫忙在 serverless.yml 裡面加入 pulgin,這樣 sls 在部署時就認得 requirements.txt 囉! 接著將 LINE SDK 加入 requirements.txt, AWS 就會幫忙安裝套件了。

echo "line-bot-sdk==1.12.1" > requirements.txt

然後新增一個 setup.cfg 並加入以下內容:

[install]
prefix=

由於 AWS Lambda 上都會將套件安裝在本地端(Lambda 上),因此在執行 pip install -t . -r requirements.txt 時會需要 setup.cfg。 至於詳細原因嘛~還有請各位大大幫小弟解答 🙏 最後就處理 handler.py 以及 serverless.yml 囉! 將上述兩個 gist 分別貼到自己的 handler.py & serverless.yml,在 hanlder.py 裡的 CHANNEL KEY & TOKEN 記得換成自己的機器人 👾 哦! 佈屬完狀態 接著在執行一次 sls deploy,將程式部署上去,如上圖所示,在 endpoints 那行會有一個網址,將那網址放到 LINE Webhook URL 上並 Verify 看看有沒有成功,如下圖所示。 最後對著自己的機器人發個話,看他有沒有回應你一模一樣的文字,若成功了就能往下一步應用層繼續開發囉!若失敗了就要檢查一下是不是有哪個步驟做錯了~

結論

因為公司的緣故讓我能夠接觸到這神奇的 Serverless,經過這次的分享加深我對於 FaaS 的架構更加了熟悉,由於我也是初碰,我認為使用上可以把它當作是一個 Docker 的容器或許概念上會比較好理解,後續還有很多的設定檔都還沒詳細研究,最近讓我先研究研究一下再上來分享。

文章中有任何勘誤歡迎指正

如果覺得這篇文章有幫助的話請給我個掌聲鼓勵我一下 👋 下列是我的這次實作的專案,如果有幫助也來顆星星吧! louis70109/aws-line-echo-bot

參考

繼續閱讀

鐵人賽-文章列表

大家好,我是 NiJia

以下是我最近參加 IT 邦幫忙 30 天鐵人賽的文章列表,主要是紀錄從我進入新公司後學到的Serverless,並透過結合 LINE API 實現在 AWS 上,歡迎大家參考取用 😃


繼續閱讀

Day27 - Use CDN (2) - CloudFront

前言

不管是建立虛擬機(EC2),又或是像我們建立 Serverless 的服務(Lambda),總會挑選離自己家近的節點(東京),又或者可能因為價錢的關係選擇相對便宜的地點,但不管機器在哪,對於在台灣的我們來說都是一樣跨海啊!但好險台灣擁有 CloudFront 的節點,透過快取讓使用者可以更快的取得服務器上的資源,可能第一次都會比較慢,但只要讓 CloudFront 看過一次就會幫忙快取起來,下次使用者在用的時候就不會那麼慢囉!

建立 CDN

首先我們先進去 CloudFront 的頁面,按下左欄的Distribution後並 Create的藍色按鈕 因為我們是做 Web API 相關的,這邊當然就是選 Web 囉! 到了這邊,AWS 很有心的在這些輸入框大多都有下拉式選單,這邊就選建立完的那個專案名稱 選完之後下面三個就照著這樣點選,Comment 會幫你自動填入 CNAMEs 的部分這邊我填入我在 serverless.yml裡 create_domain 所設定的 line.nijia.lin 字串,SSL 就選擇上一篇所建立的 Certificate 建立完成之後就會看到他 In progress,CloudFront 就開始撒點告訴其他節點有建立這個名為 line.nijia.lin,有看到他的時候記得幫他做個 Cache 等個大概 15 分鐘後他就部署完成啦~ 點進來可以確認自己剛剛設定的資訊對不對,若有設定錯誤在按 Edit 來修正

結論

現在每個服務都很流行 CDN,若有在寫前端的朋友常常就會用到 jQuery、Bootstrap、Vue 等等可以再標頭檔就引入的 CDN 路徑,CDN 不僅加速我們平常在抓伺服器資料的速度,也便利了我們有時候需要寫一些簡單的靜態頁面時可以透過抓取 CDN 路徑來快速取得需要的資源,但是像是 AWS 他們都是收取流量費,用得很爽時別忘了看一下自己的帳單是不是在哀嚎 🤣

繼續閱讀

Day26 - Use CDN (1) - 建立 Certificate 與 Domain

簡介

繼上一篇 warm-up 機制之後來了解一下如何使用 AWS 的 CDN 服務 - cloudfont,CDN 顧名思義就是要讓使用者可以到最接近的主機上去拉到對應的資料,透過撒點的方式讓主機去挑選離自己近的服務據點,藉此加速服務。

像我之前部署在 ohio,想想光網路的時間 + Cold start 的時間就已經去了一大半,即便我們有熱開機,服務沒有 Timeout 我該慶幸了,既然如此就不得不認識一下 CDN 服務,而 AWS 的 CDN 服務就是 cloudfont 啦!

只是說原本的 domain 已經有 SSL 了,但是代理沒有這個東西,所以我們要 ban 出一個 Certificate,那在在建立 cloudfont 以前需要先到 Certificate Manager,接著會用圖片帶大家一步一步做

開始之前

我已經有先在 Route53 註冊了一個 nijialin.com 的 domain,.com大概 10 美金左右,若是有在其他地方註冊域名的話要找一下相關文章把它導進 Route53 哦!

註冊 Certificate

  • 先來到 Certificate Manager 頁面,按下左下角的這個

  • 接著就直接按右下角啦,但是要確定是不是 public

  • 這裡輸入你在 route53 註冊的 domain,這邊我是輸入 *.nijialin.com

  • 到第四部之後就會看到申請的 SSL Pending

  • 最後回首頁之後就會看到 SSL 簽證正在送簽中

最後就等他完成嚕!將將 接著我們到 API Gateway 找到左邊的 Custom Domain Name,我們要來建立屬於這個 API 的 Domain 了 按下藍色的按鈕之後,輸入Domain name以及選擇剛剛註冊的 Certificate 後按下 Save 他就會開始初始化剛剛的設定,這邊大概需要等 15 分鐘左右 在此同時我們就去新增專案裡的套件 Domain-Manager

npm install serverless-domain-manager --save-dev

並且在plugin下加入套件

plugins:
  - serverless-domain-manager

custom底下加入

custom:
  domainName:
    default:
      domainName: line.nijialin.com
      certificateName: "*.nijialin.com"
      createRoute53Record: true
      endpointType: edge

等待前面初始化成功之後部署這個專案sls deploy之後就會看到剛剛註冊的域名啟動囉!

結論

在建立 Certificate 那邊倒沒什麼問題,畢竟需要一個 SSL,只是到了建立 domain 這邊遇到了很怪的問題,一般來說使用 serverless 框架來跑的話只要照的文件裡說的 serverless create_domain就會幫忙註冊,而且可以依照自己開發環境去自動設定,在公司的專案中這樣使用是沒問題的,在是在寫這篇文章時卻只能使用以上的方法來替代使用,雖然結果是一樣的,但是用起來實在是很不符合邏輯,google 也沒找到類似的問題,或許這個問題還要多實測幾次才夠...😭

繼續閱讀

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 資源

繼續閱讀

Day7 - 在 serverless 裡使用環境變數讓這些 key 好管理

前言

看著前幾天的文章,像我們 notify 驗證的 API 有使用到 REDIRECT_URICLIENT_ID 以及 CLIENT_SECRET,或是像 PostgreSQL 的帳號密碼, 只是說若今天當程式碼變多的時候,抑或是這個參數有給其他 API 使用,那在尋找的時候不僅費工又浪費時間 那接下來就帶著大家在 serverless.yml 一步步加入變數值,並更改 code。

動手吧!

用 npm 安裝 serverless 的 dotenv 套件

npm i -D serverless-dotenv-plugin

接著加入新的套件到serverless.yml

plugins:
  - serverless-dotenv-plugin

新增dotenv到 requirements.txt

python-dotenv==0.10.3

到 api.py 加入下面內容

from dotenv import load_dotenv
env_path = Path('.') / '.env'
load_dotenv(dotenv_path=env_path)

接著新增.env並輸入對應的內容

NOTIFY_REDIRECT_URI=
NOTIFY_CLIENT_ID=
NOTIFY_CLIENT_SECRET=
REGION=us-east-2
SQS_URL=
SQS_ARN=
PG_DB=
PG_HOST=
PG_NAME=
PG_PWD=
PG_PORT=

接著修改有使用到他們的地方,範例如下

import os
os.getenv("SQS_ARN")

既然有安裝 serverless 的套件了,那 yml 檔也可以使用哦!

provider:
  name: aws
  runtime: python3.7
  region: ${env:REGION}

後記

有時候把專案抓下來的時候要找到這些輸入的地方很容易找不到(我有點癡呆),一般 open source 也都會有一個.env的,用serverless-dotenv-plugin來幫忙弄就方便許多了,後續有需要再繼續往裡面新增就好了~

最後在搭配 python 的 dot env 套件使用就讓整個好用多了 🤣,只是說 html 因為目前還不是透過 serverless 來幫忙部署,所以這邊的參數就沒辦法吃設定檔了 😓

參考

os.environ env setting

繼續閱讀

Day4 - 認識與使用 S3 容器

前言

Amazon Simple Storage Service(簡稱 AWS S3)是 AWS 的一個線上儲存服務,用戶能夠輕易把檔案儲存到網路伺服器上,可能有些朋友會把它當成雲端硬碟看待,但其實還能像是傳靜態檔案上去,若有寫前端框架的朋友通常都會需要把程式碼打包成靜態檔案再部署,然而這邊把他打包送上去後,S3 會給一個名為 Object Url 的網址,可以透過這個網址去執行網頁裡面的內容(如 AJAX、Axios...),並可以透過 cloudfont 去弄成 CDN(扯遠了),簡單說他還有很多不一樣的功能應用等著大家去用~

因為 serverless 只能放關於 API 的程式碼,因此我們需要把 html 靜態檔案放在 S3 裡,

接下來就來建立一個公開的 S3 容器,這邊就不會提到權限如何控管哦!

建立一個公開的 S3 容器

建立一個名為2019-it-30-bucket的容器,地區就選與 Lambda 同樣的地區,直接按下左下角的create來建立。

建立完會像這樣 接著點進去後在點到第三個選項會看到 Block of public access 是啟動的狀態,因為我們接下來需要讓我們的頁面可以外部使用 就把 check box 的按掉,在按下 Save 要輸入confirm就修改完成嚕 接著一樣點到第三個個選項,選到Access Control List,看到Access for bucket owner這個選項的Canonical ID,選項都全部打勾之後再來調整,這樣之後的 HTML 檔案外面就看得到了。

測試

接著上傳一個index.html的檔案來測試

<html>
<h1>Hello world</h1>
</html>

上傳後下拉式選單選擇public read的選項,因為一個檔案在 S3 就算是一個 Object,所以一定要讓它能對外,然後按下左下的 Upload

成功後點進這個檔案,並按下方的Object URL,看到 Hello World 的話就代表成功囉,這時可以開個無痕測一次,確認一下沒有錯誤 😃

參考

AWS S3 wiki

繼續閱讀

Day2 - 安裝並使用 wsgi 以及 flask 建立第一個 Serverless 的專案

透過 npm 全域安裝 serverless 指令

npm install serverless -g

因為我是用 python3 在 AWS 上實作

  • --template可以選擇你想要的模板 (參考)
  • name service 的名稱
  • --path 專案路徑,若找不到資料夾時會自動新增
serverless create --template aws-python3 --name aws-wsgi-flask --path aws-wsgi-flask

加入套件

接著後面會需要使用套件,而 python 這邊會認得 requirements.txt 這個檔案,因此我們需要用 serverless 的 plugin 幫我們處理,讓專案在 deploy 上去之後會透過 requirements.txt 去安裝套件。

而接下來我們會需要一個介面幫我們處理一些麻煩事,這邊就選用 wsgi 來處理。詳細參考

sls plugin install -n serverless-python-requirements
sls plugin install -n serverless-wsgi

接著去看 serverless.yml 檔案最後出現下面這樣就成功安裝了。

plugins:
  - serverless-python-requirements
  - serverless-wsgi

然後新增一個 setup.cfg 並加入以下內容:

[install]
prefix=

由於 AWS Lambda 上都會將套件安裝在本地端(Lambda 上),因此在執行 pip install -t . -r requirements.txt 時會需要 setup.cfg。

接著選用 Flask 框架作我們開發的

echo "Flask==1.0.2" > requirements.txt
pip install -r requirements.txt -—user

serverless-python-requirements 同樣也支持 pipenv 哦,如果想完全擋掉的話可以參考

更改設定檔

置換以下內容至 serverless.yml,讓 WSGI 去處理路由。

service: aws-wsgi-flask
provider:
  name: aws
  runtime: python3.7
functions:
  api:
    handler: wsgi_handler.handler
    events:
      - http: ANY /
      - http: ANY {proxy+}
custom:
  wsgi:
    app: api.app
plugins:
  - serverless-python-requirements
  - serverless-wsgi

測試 wsgi

因為我們不是單純只用 python 架設,所以要將 handler.py 替換成 api.py,並加入以下內容

from flask import Flask
app = Flask(__name__)

@app.route("/", methods=['GET'])
def handler():
    return 'hello world'

if __name__ == '__main__':
    app.run(debug=True)

到這邊基礎設施都弄好了,但總不能部署才測試吧,所以這時候我們就出動

serverless wsgi serve

透過 wsgi 去幫忙起一個 local server 供使用者可以測試,而且每次儲存都重新整理一次哦!詳細用法請參考

接著用 postman 來測試一下

燈燈,hello world 出來了~

最後也是最重要的一個步驟『部署』 只是說部署前需要有 AWS 的 secret key & token

建立 AWS 存取金鑰

首先要先有個 AWS 帳號(廢話) ,如果沒有綁定信用卡記得去綁定才能繼續,接下來就可以去就可以去建立鑰匙囉! 如上圖,按下紅色框框的部分,接著按箭頭指的按鈕,就會建立一個我們要的金鑰囉! 如上圖所示,可以下載 key,AWS 不會幫忙保存 Secret key,若這視窗關掉的話 key 就不見了,所以使用者可以自行下載檔案保存,以免哪天要部署的時候找不到 key。 接著就將這兩個參數加入環境變數中:

export AWS_ACCESS_KEY_ID=<your-key-here>
export AWS_SECRET_ACCESS_KEY=<your-secret-key-here>

或是藉由 serverless 指令來幫忙加入參數:

serverless config credentials --provider aws --key <your-key-here> --secret <your-secret-key-here>

這步驟很重要哦,不然 AWS 不認識你就不給你上傳了 ?

最後就是下 serverlesss deploy進行部署

這邊 AWS 幫忙建立一個含有 SSL 的 domain,可以直接對這個網址下

endpoints: ANY - https://4omvn4z7re.execute-api.us-east-1.amazonaws.com/dev
  ANY - https://4omvn4z7re.execute-api.us-east-1.amazonaws.com/dev/{proxy+}

接著把網址丟到瀏覽器上來試試看 出現 hello world就成功囉!

參考

繼續閱讀

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 相關的問題的話可以參考這篇

環境

參考

繼續閱讀