場景:
如今須要開發一個先後端分離的應用,後端採用 RESTful API 最爲方便,可是若是這個後端服務會在一天中的某些時候有高併發的狀況,使用什麼樣的架構最爲簡單呢?html
剛思考這個問題的時候我想到的解決方案可能有如下幾種:python
使用CDN內容分發網絡,減小主服務器的壓力git
使用LVS服務器負載均衡編程
使用緩存json
硬件層 提升帶寬,使用SSD 硬盤,使用更好的服務器後端
代碼層,優化代碼(使用性能更好的語言等緩存
但以上的幾個方法都須要關注服務器的存儲和計算資源,以便隨時調整以知足更高的性能,而且高併發的請求也是分時段的,配置了更高性能的服務器在訪問量變低的時候也是資源浪費。bash
這個時候可使用 FaaS(Functions as a Service) 架構,跟傳統架構不一樣在於,他們運行於無狀態的容器中,能夠由事件觸發,短暫的,徹底被第三方管理,功能上FaaS就是不須要關心後臺服務器或者應用服務,只需關心本身的代碼便可。其中AWS Lambda是目前最佳的FaaS實現之一。服務器
AWS Lambda 是一項計算服務,使用時無需預配置或管理服務器便可運行代碼。AWS Lambda 只在須要時執行代碼並自動縮放。藉助 AWS Lambda,幾乎能夠爲任何類型的應用程序或後端服務運行代碼,並且無需執行任何管理。如今 AWS Lambda 支持 Node.js、Java、C# 和 Python。網絡
Lambda 常見的應用場景有如下幾種:
下圖是將Lambda 做爲事件源用於 AWS 服務案例的一個執行流程圖:
這篇文章主要介紹 將 Lambda 做爲事件源用於 AWS 服務 和 配合 API Gateway 建立簡單的微服務。
接下來將使用一個案例介紹如何使用 Lambda。
須要注意的是:處理程序填寫部分爲 代碼文件名+文件中函數名,這裏咱們文件名lambda_function, 函數名是 lambda_handler,處理程序部分填寫爲 lambda_function.lambda_handler。
登陸 aws 控制檯,打開 API Gateway,選擇咱們剛剛選用的 API,點擊測試,咱們將會看到如下輸出
詳細信息能夠參考 官方文檔(https://docs.aws.amazon.com/zh_cn/lambda/latest/dg/getting-started.html)
經過上面的步驟,咱們瞭解瞭如何使用一個 Lambda 函數,如今咱們看下如何構建 Lambda 函數。
在建立 Lambda 函數時,須要指定一個處理程序(此處理程序是代碼中的函數),AWS Lambda 可在服務執行代碼時調用它。在 Python 中建立處理程序函數時,使用如下通常語法結構。
def handler_name(event, context):
...
return some_value
複製代碼
在該語法中,須要注意如下方面:
event
- AWS Lambda 使用此參數將事件數據傳遞處處理程序。此參數一般是 Python dict
類型。它也能夠是 list
、str
、int
、float
或 NoneType
類型。
context
- AWS Lambda 使用此參數向處理程序提供運行時信息。此參數爲 LambdaContext
類型。
(可選)處理程序可返回值。返回的值所發生的情況取決於調用 Lambda 函數時使用的調用類型:
若是使用 RequestResponse
調用類型(同步執行),AWS Lambda 會將 Python 函數調用的結果返回到調用 Lambda 函數的客戶端(在對調用請求的 HTTP 響應中,序列化爲 JSON)。例如,AWS Lambda 控制檯使用 RequestResponse
調用類型,所以當您使用控制檯調用函數時,控制檯將顯示返回的值。
若是處理程序返回 NONE
,AWS Lambda 將返回 null。
若是使用 Event
調用類型(異步執行),則丟棄該值。
在執行 Lambda 函數時,它能夠與 AWS Lambda 服務進行交互以獲取有用的運行時信息,例如:
context 對象提供瞭如下方法:
返回在 AWS Lambda 終止函數前剩餘的執行時間(以毫秒爲單位)。
context 對象提供瞭如下屬性:
正在執行的 Lambda 函數的名稱。
正在執行的 Lambda 函數版本。若是別名用於調用函數,function_version
將爲別名指向的版本。
ARN 用於調用此函數。它能夠是函數 ARN 或別名 ARN。非限定的 ARN 執行 $LATEST
版本,別名執行它指向的函數版本。
爲 Lambda 函數配置的內存限制(以 MB 爲單位)。您在建立 Lambda 函數時設置內存限制,而且隨後可更改此限制。
與請求關聯的 AWS 請求 ID。這是返回到調用了 invoke
方法的客戶端的 ID。 注意若是 AWS Lambda 重試調用(例如,在處理 Kinesis 記錄的 Lambda 函數引起異常的狀況下)時,請求 ID 保持不變。
CloudWatch 日誌組的名稱,可從該日誌組中查找由 Lambda 函數寫入的日誌。
CloudWatch 日誌流的名稱,可從該日誌流中查找由 Lambda 函數寫入的日誌。每次調用 Lambda 函數時,日誌流可能會更改,也可能不更改。若是 Lambda 函數沒法建立日誌流,則該值爲空。當向 Lambda 函數授予必要權限的執行角色未包括針對 CloudWatch Logs 操做的權限時,可能會發生這種狀況。
經過 AWS 移動軟件開發工具包進行調用時的 Amazon Cognito 身份提供商的相關信息。它能夠爲空。identity.cognito_identity_ididentity.cognito_identity_pool_id
經過 AWS 移動軟件開發工具包進行調用時的客戶端應用程序和設備的相關信息。它能夠爲空。client_context.client.installation_idclient_context.client.app_titleclient_context.client.app_version_nameclient_context.client.app_version_codeclient_context.client.app_package_nameclient_context.custom由移動客戶端應用程序設置的自定義值的 dict
。client_context.env由 AWS 移動軟件開發工具包提供的環境信息的 dict
。
查看如下 Python 示例。它有一個函數,此函數也是處理程序。處理程序經過做爲參數傳遞的 context
對象接收運行時信息。
from __future__ import print_function
import time
def get_my_log_stream(event, context):
print("Log stream name:", context.log_stream_name)
print("Log group name:", context.log_group_name)
print("Request ID:",context.aws_request_id)
print("Mem. limits(MB):", context.memory_limit_in_mb)
# Code will execute quickly, so we add a 1 second intentional delay so you can see that in time remaining value.
time.sleep(1)
print("Time remaining (MS):", context.get_remaining_time_in_millis())
複製代碼
此示例中的處理程序代碼只打印部分運行時信息。每一個打印語句均在 CloudWatch 中建立一個日誌條目。若是您使用 Lambda 控制檯調用函數,則控制檯會顯示日誌。
您的 Lambda 函數可包含日誌記錄語句。AWS Lambda 將這些日誌寫入 CloudWatch。若是您使用 Lambda 控制檯調用 Lambda 函數,控制檯將顯示相同的日誌。
如下 Python 語句生成日誌條目:
print
語句。logging
模塊中的 Logger
函數(例如,logging.Logger.info
和 logging.Logger.error
)。print
和 logging.*
函數將日誌寫入 CloudWatch Logs 中,而 logging.*
函數將額外信息寫入每一個日誌條目中,例如時間戳和日誌級別。
可查找 Lambda 函數寫入的日誌,以下所示:
在 AWS Lambda 控制檯中 - AWS Lambda 控制檯中的 ** Log output** 部分顯示這些日誌。
在響應標頭中,當您以編程方式調用 Lambda 函數時 - 若是您以編程方式調用 Lambda 函數,則可添加 LogType
參數以檢索已寫入 CloudWatch 日誌的最後 4 KB 的日誌數據。AWS Lambda 在響應的 x-amz-log-results
標頭中返回該日誌信息。有關更多信息,請參閱Invoke。
若是您使用 AWS CLI 調用該函數,則可指定帶有值 Tail
的 --log-type parameter
來檢索相同信息。
在 CloudWatch 日誌中 - 要在 CloudWatch 中查找您的日誌,您須要知道日誌組名稱和日誌流名稱。可使用代碼中的 context.logGroupName
和 context.logStreamName
屬性來獲取此信息。在運行 Lambda 函數時,控制檯或 CLI 中生成的日誌將會向您顯示日誌組名稱和日誌流名稱。
若是 Lambda 函數引起異常,AWS Lambda 會識別失敗,將異常信息序列化爲 JSON 並將其返回。考慮如下示例:
def always_failed_handler(event, context):
raise Exception('I failed!')
複製代碼
在調用此 Lambda 函數時,它將引起異常,而且 AWS Lambda 返回如下錯誤消息:
{
"errorMessage": "I failed!",
"stackTrace": [
[
"/var/task/lambda_function.py",
3,
"my_always_fails_handler",
"raise Exception('I failed!')"
]
],
"errorType": "Exception"
}
複製代碼
詳細信息參考官方文檔:https://docs.aws.amazon.com/zh_cn/lambda/latest/dg/lambda-app.html
AWS Lambda 在使用中會強加一些限制,例如,程序包的大小或 Lambda 函數在每次調用中分得的內存量。
每一個調用的 AWS Lambda 資源限制
資源 | 限制 |
---|---|
內存分配範圍 | 最小值 = 128 MB/最大值 = 1536 MB (增量爲 64 MB). 若是超過最大內存使用量,則函數調用將會終止。 |
臨時磁盤容量(「/tmp」空間) | 512MB |
文件描述符數 | 1024 |
過程和線程數(合併總數量) | 1024 |
每一個請求的最大執行時長 | 300 秒 |
Invoke 請求正文有效負載大小 (RequestResponse/同步調用) | 6MB |
Invoke 請求正文有效負載大小 (Event/異步調用) | 128 K |
每一個區域的 AWS Lambda 帳戶限制
資源 | 默認限制 |
---|---|
併發執行數 | 1000 |
併發執行是指在任意指定時間對您的函數代碼的執行數量。您能夠估計併發執行計數,可是,根據 Lambda 函數是否處理來自基於流的事件源的事件,併發執行計數會有所不一樣。
基於流的事件源 - 若是您建立 Lambda 函數處理來自基於流的服務(Amazon Kinesis Data Streams 或 DynamoDB 流)的事件,則每一個流的分區數量是併發度單元。若是您的流有 100 個活動分區,則最多會有 100 個 Lambda 函數調用併發運行。而後,每一個 Lambda 函數按照分區到達的順序處理事件。
並不是基於流的事件源 - 若是您建立 Lambda 函數處理來自並不是基於流的事件源(例如,Amazon S3 或 API 網關)的事件,則每一個發佈的事件是一個工做單元。所以,這些事件源發佈的事件數(或請求數)影響併發度。
您可使用如下公式來估算併發 Lambda 函數調用數。
events (or requests) per second * function duration
複製代碼
例如,考慮一個處理 API Gateway 的 Lambda 函數。假定 Lambda 函數平均用時 0.3 秒,API Gateway 每秒請求 1000 次。所以,Lambda 函數有 300 個併發執行。
具體信息參考Lambda 函數並行執行
**AWS Lambda 部署限制 **
項目 | 默認限制 |
---|---|
Lambda 函數部署程序包大小 (壓縮的 .zip/.jar 文件) | 50 MB |
每一個區域能夠上傳的全部部署程序包的總大小 | 75GB |
可壓縮到部署程序包中的代碼/依賴項的大小 (未壓縮的 .zip/.jar 大小).注意每一個 Lambda 函數都會在其的 /tmp 目錄中接收到額外的 500 MB 的非持久性磁盤空間。該 /tmp 目錄可用於在函數初始化期間加載額外的資源,如依賴關係庫或數據集。 |
250MB |
環境變量集的總大小 | 4 KB |
本文內容主要參考 AWS Lambda 官方文檔,詳細信息請訪問 https://docs.aws.amazon.com/zh_cn/lambda/latest/dg/welcome.html
最後,感謝女友支持。
歡迎關注(April_Louisa) | 請我喝芬達 |
---|---|