標籤

SQS

Day9 - SQS 串接 Notify 實作!

首先先建立一個consumer/資料夾,新增__init__.py以及notify_handler.py

notify_handler.py輸入以下程式碼

import json
import requests


def line_notify_handler(event, context):
    print(event)
    body = json.loads(event['Records'][0]['body'])
    print(body)
    headers = {
        'Authorization': f"Bearer {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)

# AWS record sample
# {'Records': [{'messageId': 'fddc42ba-a122-4581-965e-d0144ac8a5ad', 'receiptHandle': 'AQEBjO32gY5pXOfOrmDR0hD4k1av9KyjbHFpc+rIBPV2Brif7Lo+jqnGevSjfFwlICyGf+BhWwKaxFw8XdB3QTzRbw0vnLURjnQeDSBrJHa/S57SRs9TOLRBq38maycAVg69iZbetg9VhLMBCcLtOtPHTzKkmo+/Sosm51WA5CzXK7A0rteikx6nxS1CUIpq6MAujodupP0Hgr5RjK5nH/nmxA4Db0leWEmLokalZbtlx4W14tp7PZxPOrQOLDaGrH//p4h32tY8IN3MkCqi+gyNT7kCU4KwCGOIrybb07ZWyKBTKw+KOMNr/Ykj4z2N1qxIvTM55UY9d8V29YsH32OjrZTei5P7Nke/51E2tWkmkqoFAlqzxDjQPvpP+Pvvr8aazeeZ6opkr59UefAiiyM71Q==', 'body': 'hi', 'attributes': {'ApproximateReceiveCount': '9', 'SentTimestamp': '1566621263072', 'SenderId': '901588721449', 'ApproximateFirstReceiveTimestamp': '1566621263072'}, 'messageAttributes': {}, 'md5OfBody': '49f68a5c8493ec2c0bf489821c21fc3b', 'eventSource': 'aws:sqs', 'eventSourceARN': 'arn:aws:sqs:us-east-1:901588721449:LINE_notify_consumer', 'awsRegion': 'us-east-1'}]}

接著在requirements.txt加入boto3,他是一個使用 python 介接 AWS 的套件

boto3==1.9.189

加入SQS_URL以及SQS_ARN.env裡面

SQS_URL=sqs url
SQS_ARN=your sqs arn

add controller/notify_sqs_controller.py

from flask_restful import Resource, reqparse
import json
from lib.db import Database
import psycopg2.extras
import os
import boto3


def send_message(url, attr, body, delay=0):
    cli.send_message(
        QueueUrl=url,
        DelaySeconds=0,
        MessageAttributes=attr,
        MessageBody=body,
    )


class SendNotifyBySQSController(Resource):
    cli = boto3.client("sqs", region_name=os.environ("region"))

    def post(self):
        parser = reqparse.RequestParser()
        parser.add_argument(
            'message', required=True, help='message can not be blank!')
        args = parser.parse_args()
        msg = args['message']
        with Database() as db, db.connect() as conn:
            with conn.cursor(cursor_factory=psycopg2.extras.RealDictCursor) as cur:
                cur.execute(
                    f"SELECT token FROM notify")
                fetch = cur.fetchall()
        for f in fetch:
            body = {
                'token': f"Bearer {f['token']}",
                'message': f"Hello everyone, {msg}"
            }
            cli.send_message(
                QueueUrl=os.environ("SQS_URL"),
                DelaySeconds=0,
                MessageAttributes={},
                MessageBody=json.dumps(body),
            )
        return {'result': 'ok'}, 200

程式寫完了就是要加一條路由/notify/sqs

from controller.notify_sqs_controller import SendNotifyBySQSController
api.add_resource(SendNotifyBySQSController, '/notify/sqs')

接著透過wsgi在本地起一個 server

sls wsgi serve

再搭配 postman 來做測試,測試內容如下

{
  "message": "test Content"
}

接著透過sls deploy部署上會遇到一個問題,會有 Access Denied,所以要在serverless.yml加入 IAM role 的設定

add iam in provider

iamRoleStatements:
  - Effect: Allow
    Action:
      - sqs:SendMessage
    Resource:
      - ${env:SQS_ARN}

測試

結論

使用 SQS 這類服務都會需要透過boto3來幫忙串接,最需要注意的就是 IAM role,因為在本地端的 key 通常權限都是最大的,但上到 AWS 上就會有權限的問題,所以要記得加入 IAM 哦!

Code is here

專案也會持續更新,更多詳情可以 follow 我的專案 aws-python-line-api

繼續閱讀

Day8 - SQS 簡單介紹 & 建立

詳細介紹

以前自己在架伺服器的時候,提到訊息佇列不外乎都是 RabbitMQ 或是 Kafka,只是現在 AWS、GCP 這類的雲端平台都越來越火紅了,手動按一下服務就建好了(信用卡也在哭泣),省去很多建立服務的時間,只是說一般時候根本找不到項目練習 😓,剛好最近在複習 LINE Notfiy,就趁這個機會順便練習並記錄一下 ✌️

你需要先了解…

當 Http requests 非常大量到一定程度,database 已經跟不上處理的速度,尤其是 relational database,這時就需要 queue 來緩衝;所以社群網站像 Facebook or LinkedIn 都使用大量的 message queue and cache. By -> Leonard Lee

SQS 就是 managed queue service,主要就是 async, central messaging (對相對應的程式來說,通常處理 api 的會有多個 instances 同時存在,像是 auto-scaling),像是 fb 通知、寄送 email 認證信這種不用即時處理的情況,只要給訊息給 queue 讓其他服務或程式去處理,可以把原本的邏輯簡化(以及責任區分),甚至些事件是預期同時會有多個 listener 會需要處理的情況,在一個 api 裡面去處理這些會讓邏輯變很複雜/不好維護。 By -> Bill Chung

還有就是如果負責處理 request 的 host 有問題,message queue 可以用來短暫儲存還未被處理的 requests 使他們不至於丟失,直到 host 回復正常或是換了一個好的 host 後,message queue 裡面的的 requests 就可以繼續被處理 By -> 盧元駿

以上來自我之前寫過的文章 使用 Serverless 讓 AWS SQS 幫你發送 LINE Notify

今天在需要發個請求去呼叫 LINE API(或是其他服務的 API),都可能會碰到圖片,圖片不管他怎麼壓縮,終究還是比文字肥,在數量多的情況下可能就會發現 API 罷工(就會像被斷詠唱一樣)。雖然平常使用可能不會這麼平凡呼叫,但若在商業用途上使用者多的時候一次呼叫就會有一大筆,這時候用 Queue 讓他們排隊一個一個來就在適合不過了 🎉。

為什麼選擇 AWS SQS

Amazon Simple Queue Service (SQS) 是全受管訊息佇列服務,可讓您分離和擴展微型服務、分散式系統及無伺服器應用程式。SQS 可免除與管理和操作訊息導向中介軟體相關的複雜性及開銷,也可讓開發人員專注在與眾不同的工作上。您可以使用 SQS 在軟體元件之間傳送、存放和接收不限數量的訊息,不會遺失訊息或需要其他服務可用。使用 AWS 主控台、命令列界面或自選的 SDK 以及三個簡單的命令,即可在幾分鐘內開始使用 SQS。(參考 AWS)

SQS 有在免費方案裡面,只要一個月別高於 100 萬個請求就不會被收錢啦 💪

AWS 的免費方案可以參考 -> LINK

建立 SQS

接著就要開始引入 SQS 嚕,首先到 AWS 上的 SQS 頁面,如下


接著選左邊的Standard Queue並填入 name 就好


建立完之後就可以看到下面有建立完的資訊

ARN 以及 URL 接下來都會用到哦

結論

接下來會帶各位使用 Notify 接在 SQS 上,這篇就先帶各位介紹並先手動建立一個 Queue,之後會在大家使用 python 的 boto3 的套件來搭配使用 AWS 服務使用 👏

繼續閱讀