0x00 前言
以前自己在架伺服器的時候,提到訊息佇列不外乎都是 RabbitMQ 或是 Kafka,只是現在 AWS、GCP 這類的雲端平台都越來越火紅了,手動按一下服務就建好了(信用卡也在哭泣),省去很多建立服務的時間,只是說一般時候根本找不到項目練習😓,剛好最近在複習 LINE Notfiy,就趁這個機會順便練習並記錄一下✌️
0x01 你需要先了解…
當 Http requests 非常大量到一定程度,database 已經跟不上處理的速度,尤其是 relational database,這時就需要 queue來緩衝;所以社群網站像Facebook or LinkedIn都使用大量的 message queue and cache
- Leonard LeeSQS就是 managed queue service,主要就是async, central messaging (對相對應的程式來說,通常處理api的會有多個instances同時存在,像是auto-scaling),像是fb通知、寄送email認證信這種不用即時處理的情況,只要給訊息給queue讓其他服務或程式去處理,可以把原本的邏輯簡化(以及責任區分),甚至些事件是預期同時會有多個listener會需要處理的情況,在一個api裡面去處理這些會讓邏輯變很複雜/不好維護。
- Bill Chung還有就是如果負責處理 request 的 host 有問題,message queue 可以用來短暫儲存還未被處理的requests 使他們不至於丟失,直到 host 回復正常或是換了一個好的host 後,message queue 裡面的的requests就可以繼續被處理
- 盧元駿
[ Updated ] 謝謝 python taiwan 的兩位大大熱情補充!
今天在需要發個請求去呼叫 LINE API(或是其他服務的 API),都可能會碰到圖片,圖片不管他怎麼壓縮,終究還是比文字肥,在數量多的情況下可能就會發現 API 罷工(就會像被斷詠唱一樣)。雖然平常使用可能不會這麼平凡呼叫,但若在商業用途上使用者多的時候一次呼叫就會有一大筆,這時候用 Queue 讓他們排隊一個一個來就在適合不過了🎉,本文就用 LINE Notify 當作範例來實作讓 SQS 幫忙發送。
0x02 為什麼選擇 AWS SQS
因為我公司都在用啊(被拖走)
Amazon Simple Queue Service (SQS) 是全受管訊息佇列服務,可讓您分離和擴展微型服務、分散式系統及無伺服器應用程式。SQS 可免除與管理和操作訊息導向中介軟體相關的複雜性及開銷,也可讓開發人員專注在與眾不同的工作上。您可以使用 SQS 在軟體元件之間傳送、存放和接收不限數量的訊息,不會遺失訊息或需要其他服務可用。使用 AWS 主控台、命令列界面或自選的 SDK 以及三個簡單的命令,即可在幾分鐘內開始使用 SQS。(參考 AWS)
SQS 有在免費方案裡面,只要一個月別高於 100 萬個請求就不會被收錢啦💪
0x03 建立專案
首先先透過我之前做的 repo 來做基底,用它來改改~
$ serverless install --url https://github.com/louis70109/aws-line-echo-bot -n <YOUR_FILE_NAME>
$ cd <YOUR_FILE_NAME>/
0x04 建立 Consumer lambda
還不知道怎麼新增 LINE Notify 的朋友可以參考 我的簡報 並搭配 LINE Notify API 服用
這邊假設你已經拿到了 Notify Token (需要搭配 Bearer) 了,接著將 handler.py 的程式改為以下
import json
import requests
def webhook(event, context):
print(event['body'])
headers = {
'Authorization': 'Bearer YOUR_NOTIFY_KEY',
'Content-Type': 'application/x-www-form-urlencoded'
}
r = requests.post('https://notify-api.line.me/api/notify',
headers=headers,
data={'message': event['body']})
然後修改一下 serverless.yml,先把這幾行刪掉(因為不是做 API)
events:
- http:
path: /webhook
method: POST
接著執行以下指令做本地端測試 (這邊的 -f 後面的名字若要修改的話從 serverless.yml -> functions 下面去修改即可)
sls invoke local -f line_bot --data '{"body": "Hell world QAQ"}'
到了這裡你的 Notify 第一步串接就成功囉!
0x05 建立 SQS
接著就要開始引入 SQS 嚕,首先到 AWS 上的 SQS 頁面,如下
0x06 修改 Consumer lambda
建立完 SQS 之後呢,我們需要先改一下原本 handler.py 的程式碼
import json
import requestsdef webhook(event, context):
print(event)
body = json.loads(event['Records'][0]['body'])
print(body)
headers = {
'Authorization': body['token'],
'Content-Type': 'application/x-www-form-urlencoded'
}
r = requests.post('https://notify-api.line.me/api/notify',
headers=headers,
data={'message': body['message']})
print(r)
並在 requirements.txt 裡加入 requests==2.22.0
部署的時候 Lambda才會知道要安裝套件喔!
接下來就是下 sls deploy
進行部署,結束應該會看到下面這張圖片的內容:
註記
Deploy 時可能會有類似的錯誤訊息需要你注意一下服務設定的位置哦
An error occurred: LineUnderscorebotEventSourceMappingSQSLINEnotifyqueue - Event source region must match Lambda region us-east-1 (Service: AWSLambda; Status Code: 400; Error Code: InvalidParameterValueException;
0x07 建立發送端
接著我們建立一個測試的檔案 (send.py),透過 boto3
來幫忙送訊息到 AWS SQS 🧚♀️
import json
import boto3
import syscli = boto3.client("sqs", region_name='us-east-1')def send_message(url, attr, body, delay=0):
cli.send_message(
QueueUrl=url,
DelaySeconds=0,
MessageAttributes=attr,
MessageBody=body,
)output = {
'message': sys.argv[1],
'token': 'Bearer YOUR_NOTIFY_TOKEN'
}#執行函式
send_message(
url="https://sqs.us-east-1.amazonaws.com/901588721449/LINE_notify_consumer",
attr={},
body=json.dumps(output)
)
url 裡的內容要參考你建立出來 SQS 資訊裡的 URL 哦!
python sender.py "Hello world"
如此一來就成功了(撒花🎉),代表寫的腳本有送進 SQS 並 trigger lambda 幫忙發送訊息到 LINE Notify 上面~
上述的 code 同步到 Github 上囉!
0x08 結論
前一陣子在公司學到的新技能,不過一直想不到有什麼好的例子去做紀錄,剛好最近重新複習了 LINE Notify,索性就乾脆寫在一起以後需要回來考古的時候有個依據,這次應用就到這邊,謝謝您的收看,我們下此見!
怎麼好像 youtube 看太多?