Amazon API GateWay 簡介
Amazon API Gateway 是由 AWS 提供的完全託管服務,使開發者可以創建、發佈、維護、監控和保護任意規模的 API,可以使用它來創建充當應用程式前門的 RESTful 和 WebSocket API。這樣,應用程式可以從後端服務訪問數據、業務邏輯或功能,例如在 Amazon Elastic Compute Cloud (Amazon EC2)上運行的應用程式、在 AWS Lambda 上運行的代碼、任何 Web 應用程式或即時通信應用程式。
API Gateway 負責處理所有任務,涉及接受和處理成千上萬個併發 API 調用,包括流量管理、授權和訪問控制、監控,以及 API 版本管理。更重要的是,API Gateway 沒有最低費用或啟動成本,只需為收到的 API 調用以及傳出的數據量付費。
下圖說明 Amazon API Gateway 的架構,在此架構圖中,前端用戶端應用程式和應用程式服務通過網際網路向API Gateway 發送 API 請求。API Gateway 負責管理所有這些請求並將其發送到 EC2 實例上運行的伺服器、Virtual Private Cloud (VPC)中或網際網路上的任何位置。
使用 API Gateway 與其他 AWS 託管服務就可以為我們的應用程式構建無伺服器後端,這意味著開發者無需維護任何伺服器。比方說,API Gateway 可以將請求代理到 Lambda 函數,該函數運行代碼並生成回應。
圖 1、Amazon API Gateway 架構
一般的 API 介面,直接面對的就是伺服器後端,所以直接就是以 HTTP 請求/回應 (Request/Response) 格式,作為前後端溝通的協定,但因為 Amazon API Gateway 對應到的後端可能是各式各樣的 AWS 服務(終端節點),所以 Amazon API Gateway 提供了多一層的轉換對應,以方便將 HTTP 請求/回應 轉換成不同的 AWS 服務可以接受的格式,這一層稱之為整合請求/回應,也就是內部介面所涵蓋的部份。Amazon API Gateway 和 AWS 服務的整合圖形如下。
圖 2、Amazon API Gateway 和 AWS 服務的整合
考慮構建的 Amazon API Gateway 要提供服務的對象,我們可以把 API 終端節點分為以下三類:
圖 3、Amazon API Gateway 終端節點類型
Amazon API Gateway 開發和部署步驟:
實作 Amazon API GateWay 整合
接著要將 Day 29 - AWS Lambda 接收參數查詢 Dynamodb 所設計的 AWS Lambda 整合到 Amazon API GateWay,需要完成的事情如下:
整合最大的問題 Amazon API GateWay 最大的問題是執行出現問題,看不到報錯的訊息,所以在整合之前一定要先把除錯功能先打開,而 CloudWatch 就是 AWS 提供最重要的除錯服務之一 (Cloud Trail也是不錯的選擇),所以要先把 Day 29 - AWS Lambda 接收參數查詢 Dynamodb 所設計的 Lambda 函數 getDataFromDynamoDB,把它所屬的執行角色 LambdaDynamoDB,新增寫入 CloudWatch 日誌群組 (Log groups) 的許可權。
打開 AWS Lambda 控制台,選擇 getDataFromDynamoDB Lambda 函數,在下方的操作視窗中,選擇 組態 頁籤,單擊 許可 功能,就可以看到本函數的執行角色 LambdaDynamoDB,如下圖所示。
圖 4、Lambda 函數的執行角色
點擊 LambdaDynamoDB 會打開 Identity and Access Management (IAM) 控制台,在 許可 頁籤中,單擊 連接政策,如下圖所示。
圖 5、IAM 控制台進行角色連接政策
在連接許可畫面中,在查詢文字框中輸入 AWSLambdaBasicExecutionRole ,選取後,點擊下方的 連接政策。
圖 6、IAM 角色連接 AWSLambdaBasicExecutionRole 許可政策
回到圖 5的角色進行連接政策畫面,這時候會看到 Permissions policies 變成是 Permissions policies (2 套用的多個政策),點擊 AWSLambdaBasicExecutionRole 許可政策,可以看到許可政策內容,都是針對 CloudWatch Logs 的存取權限,如下圖所示。
圖 7、檢視 AWSLambdaBasicExecutionRole 許可政策的內容
打開 API Gateway 控制台,點選左側功能選單的 API,接著在右手邊的主畫面點擊 建立API,如下圖所示。
圖 8、建立新的 API
在選擇 API 類型畫面中,要選第一個 REST API,後一個是針對私有的 REST API,選擇完畢後,點擊 建置,如下圖所示。
圖 9、選擇 API 類型
在選擇通訊協定畫面中,配置設定如下:
結果如下圖所示。
圖 10、選擇 API 通訊協定設定畫面
進入 API: dynamodb 設定畫面,在資源窗格中,選擇資源根,其以一條正斜線表示 (/),然後點擊 操作 按鈕,選擇 建立資源。在右手邊的操作 新的子資源 設定介面中,設定如下:
結果如下圖所示。
圖 11、建立 API: dynamodb 新資源
在 資源窗格中,選擇 /fish,然後點擊 操作 按鈕,選擇 建立方法,對於 HTTP 方法,選擇 ANY,然後儲存,ANY 方法表示它可以接受任何的 HTTP 請求,不論是 GET, POST, PUT 還是其他,主要的判斷是在接受這個請求的 AWS 服務,以這個案例來說,就是 Lambda 函數。操作畫面如下圖所示。
圖 12、建立 API: dynamodb 新方法
在方法設定畫面中,設定如下:
確認後,點擊 儲存,操作畫面如下。
圖 13、建立 API: dynamodb 新方法的設定
此時會彈出一個 新增Lambda函數的許可 畫面,只要是要授權給 API Gateway 允許它調用 Lambda 函數,畫面如下圖所示。
圖 14、新增 API: dynamodb 調用 Lambda 的許可權
完成了 API Gateway 的所有設定,最後要做的就是部署 API,透過部署讓其他使用者可以調用,部署階段為 新階段,階段名稱為 v1 (自行決定),畫面如下圖所示。
圖 15、部署 API: dynamodb
部署 API 完成後,會出現給外部使用者呼叫用的 URL,使用者可以透過這個網址,來調用 Lambda 函數的服務,畫面如下圖所示。
圖 16、v1 的部署組態
最簡單的測試方式是使用 curl 的命令列方式直接呼叫,這種方式最大的好處是可以看到傳輸中的所有請求跟回應訊息。以下指令是透過 curl 發出 get 請求,對象是先前部署好的 API [APIGATEWAY_DEPLOY],並傳遞參數 key=1 ,希望能讓 Lambda 函數可以回傳編號為 1 的觀賞魚訊息。
curl -v -X GET 'https://[APIGATEWAY_DEPLOY]/fish?key=1' -H 'content-type: application/json'
執行命令後,我們得到一連串的輸出,前面有 * 號的訊息可以不用理會,出現句首有 > 符號的才是實際的請求跟回應,透過 curl 發出 HTTP 2.0 格式的請求,而 API Gateway 回傳的訊息是 502,伺服器內部錯誤,通常這種錯誤都是後端程式執行失敗所造成,詳細輸出可以檢視下圖。
圖 17、使用 curl 檢驗 API
很幸運的,Lambda 函數執行錯誤了,但問題是我們看不到錯誤訊息,到底是哪一行導致的,於是,來到 AWS Lambda 的控制台,進到 getDataFromDynamoDB 這個 Lambda 函數的主畫面中,再下方找到 監控 頁籤,並點擊 日誌 按鈕,可以在下方的列表中找到最近的幾筆記錄訊息,點擊該筆記錄,或是點擊 檢視 CloudWatch 中的日誌 按鈕,就可以進入 CloudWatch logs 控制台。請參照下圖。
圖 18、檢驗 AWS Lambda 監控的日誌功能
在 CloudWatch 控制台中,找到左手邊導覽功能列中的 日誌群組,找到對應到 getDataFromDynamoDB 這個 Lambda 函數的紀錄,通常都是 /aws/lambda/[函數名稱],接著確認一下記錄的日期時間,再看看發生錯誤的訊息,原來是第 14 行中的 qry = event['Mark']
發生錯誤,因為傳遞參數的方式不同了,所以 event['Mark']
變成是無效的變數,導致出錯。
圖 19、使用 CloudWatch Logs 進行除錯
將 Lambda 函數的內容修改如下,透過 event['httpMethod']
取得呼叫的方法是 GET 還是 POST,如果是 get 使用 event['queryStringParameters']
來取得傳遞過來的參數,如果是 post ,則用 event['body']
。
import json
import boto3
from boto3.dynamodb.conditions import Key
dynamodb = boto3.resource('dynamodb')
def lambda_handler(event, context):
print("Received event: " + json.dumps(event, indent=2))
if event['httpMethod']=='POST':
key = json.loads(event['body'])['key']
else:
key = event['queryStringParameters']['key']
qry = key # event['Mark']
table = dynamodb.Table('fishInfoTbl')
data = table.query(
IndexName='Mark-index',
KeyConditionExpression = Key('Mark').eq(qry)
)
print('data=',data['Items'][0])
if key:
data['Items'][0]['key']=key
response = {
'statusCode': 200,
'body': json.dumps(data['Items'][0]),
'headers': {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*'
},
}
return response
下圖是使用 ARC 來檢驗 API GET 功能,主要是這樣可以看到中文,因為 ARC 會做解碼回來。
圖 20、使用 ARC 檢驗 API GET 功能
下圖是使用 ARC 來檢驗 API POST 功能,記得 POST 的請求內容會放在主體內 (BODY),所以需要在主體內寫,而請還需要指定編碼格式,這樣後端才能理解內容為何。
圖 21、使用 ARC 檢驗 API POST 功能