如何看待 AWS Lambda ?

AWS Lambda_雲計算服務-AWS 雲服務

「AWS Lambda 是一個計算服務,依響應事件運行您的代碼並自動為您管理計算資源,因而容易構建快速響應新信息的應用程序。AWS Lambda 可在事件發生後幾毫秒內運行您的代碼,如圖像上傳、應用內活動、網站點擊或連接設備的輸出。您還可以使用 AWS Lambda 來創建新的後端服務,其中基於自定義的請求計算資源被自動觸發。使用 AWS Lambda,您只需為提供的請求以及運行您的代碼所需的計算時間付費。賬單以 100 毫秒的增量計費,從而能經濟高效且輕鬆地從每天幾個請求自動擴展到每秒數千個請求。」

這些 JavaScript Lambda 函數看起來是很 sexy,但不知道實際情況下會有什麼優劣。

對伺服器方面不在是很懂,希望有了解的朋友可以講一下看法,它的適用範圍,還有會出現什麼坑,等等。


我認為 AWS Lambda 將成為新的 AWS 基礎計算模塊,就像很多 AWS 服務都以 EC2 為基礎一樣,也會有很多服務以 Lambda 為基礎來提供。大家可能最關注的都是用 Lambda + API Gateway 來實現 API 服務,或者作為膠水服務來實現 AWS 不同服務之間的協作和自動化,但現在 Lambda 能做的事情已經遠遠不止這些了。

先說一說這次 re:Invent 新發布的東西吧。比如 Greengrass 讓 IoT 設備可以運行 Lambda 處理收集到的數據,這樣設備即使在離線狀態也可以完成部分功能;比如 Snowball Edge 不只是一個大一點的 Snowball 而已,它還有板載的計算和存儲單元,其中計算單元就是使用 Lambda 作為計算模型,可以讓 Snowball Edge 在運輸的過程中就完成數據的預處理工作,考慮到 Snowball Edge 還支持集群功能,應該還可以做更多的事情;比如 Lambda@Edge 可以讓 Lambda 運行在 CDN 的邊緣節點上,對於部分流量可以直接在邊緣節點進行處理,對於我司(上線了sxl.cn | 簡單易用?專業美觀)這樣使用 CDN 來加速用戶網站的需求來說,這意味著可以無限制地定義 CDN 邊緣節點的規則,簡直就是逆天的功能。

對於 API Gateway + Lambda 這個經典組合來說,在 2016 年發布的一些新功能也可以讓我們更好地利用 Lambda 來構建大一點的應用。現在 API Gateway 可以支持 Proxy 集成模式直接向 Lambda 傳遞原始的 HTTP 請求而不是 event,並且增加了二進位的支持。這些新功能配合 API Gateway 的路徑貪婪匹配(greedy path),可以允許我們直接遷移一個小型的 Web 應用到 Lambda 里去而不需要重寫代碼。AWS 官方發布了一個庫可以允許我們直接在 Lambda 里包裝一個 Express 應用:awslabs/aws-serverless-express,大家有興趣可以試一下。即使需要重新用 Lambda 和 API Gateway 搭建 API,現在也有官方提供的 SAM(Serverless Application Model)和第三方提供的 Serverless 框架可以用。

我個人感覺 Lambda 和 serverless 確實是需要密切關注的一個方向,但是不太可能完全替代 EC2 這樣的基礎服務,因為 Lambda 為了達到它保證的彈性和可用性,也有一些必要的限制。以下是使用 Lambda 的過程中需要注意的地方:

  • EC2 可以在啟動的時候安裝一些代碼庫,Lambda 理論也上可以這麼做,但是實踐中強烈不建議。Lambda 是無狀態的計算模型,這意味著每一次 Lambda 函數的運行都跟之前沒有任何依賴和關聯,因此每一次運行都需要重新安裝代碼庫,嚴重影響 Lambda 的運行效率。所有代碼運行過程中需要依賴的代碼庫及資源盡量都在部署的時候就打包上傳,只有跟每一次觸發的 Event 相關的資源才在運行時去獲取,這樣可以有效地保證 Lambda 的運行時間不被浪費。
  • Lambda 內部實現機制上包括了有效地流量預測演算法,從而可以對流量增長進行預判並提前準備好相應的計算資源。這個流量預測演算法有一個無法避免的盲點,就是在沒有流量的情況下,沒有任何依據進行預測,因此會導致 Lambda 函數在一段時間靜默之後第一次啟動的時候會有延時。如果你的服務可以接受輕微的延時,那這並不一定是個大問題,但如果你的服務實時性要求比較高,那就需要保持 Lambda 函數在一個熱身狀態。這個保持的方法就是用 scheduler 定時(比如每5分鐘)觸發一次 Lambda 的執行。
  • Lambda 默認的並行執行的上限為100,這個上限是 Region 的上限,也就是說你在某個 Region 里某個瞬間同時運行的所有 Lambda 實例的數目不能超過100,否則就需要排隊等候。這是 AWS 為了保護客戶在剛開始使用 Lambda 的時候不會因為一不小心犯了個錯誤(比如遞歸執行同一個Lambda函數)導致費用暴增。你可以通過提交ticket的方式來提升上限,強烈建議在項目正式上線之前估算可能的峰值流量並把上線提到相應的值。
  • Lambda內置了版本和別名機制,可以很方便地發布新版本的代碼和回滾到老版本的代碼。對於上傳的每一版本的代碼我們都需要添加版本號,這裡要注意的是,不要直接在某個版本的函數上設置觸發條件和監控,而是要充分利用別名機制,在別名上設置觸發條件和監控,然後將別名指向你需要發布的版本。比如我們設置了PRODUCTION和TEST等別名,假設我們現在新版本的代碼版本號是16,我們會先把TEST指向16,做測試,然後再把PRODUCTION指向16,就完成了新版本的發布。如果新版本有問題的話,我們可以把PRODUCTION指向15,就完成了回滾,非常簡單
  • Lambda 優點之一就是幾乎可以運行任何你已有的代碼。雖然 Lambda 的介面只支持幾種語言及版本,但如果通過這些語言來調用其他語言寫的代碼,甚至平台相關的代碼庫和二進位可執行文件,就具備了無限的可能性。對於平台相關的代碼庫和二進位可執行文件,我們需要在與 Lambda 相同的運行環境下進行編譯和鏈接,或者採用交叉編譯的方式針對 Lambda 的運行平台進行編譯和鏈接,然後打包上傳到 AWS。AWS 對於每個支持 Lambda 的 Region 都指定了 Lambda 運行環境的 AMI ID,只需要用對應的 AMI 啟動一個 EC2 就可以,具體可以參考 Lambda 的官方文檔。
  • Lambda 確實鼓勵並在技術上能支持任意代碼的部署,但是為了保證 Lambda 的快速伸縮的特性,還是設置了一些限制,比如上傳的代碼壓縮後不能超過50MB,解壓後不能超過250MB,運行環境中的臨時空間不超過500MB,最長運行時間不超過5分鐘,等等。因此 Lambda 並不適合部署大型應用,任何啟動時間長,或者代碼和資源量比較大的應用都不適合部署在 Lambda 上。

有些同學可能覺得開發調試太慢,這個其實有蠻多的工具和方案可以實現在本地調試 Lambda 函數了。我主要用 node.js 開發 Lambda 函數,這個框架還是蠻有用的 Claudia.js。另外如果用 API Gateway 的話確實從國內訪問會是個問題,但如果你在 AWS 國外的區域有計算基礎設施或者數據的話,Lambda 在 AWS 內部使用也是很方便的。具體可以參考一些這個 re:invent 主題演講提供的 serverless 編程模型和最佳實踐 https://youtu.be/b7UMoc1iUYw,演講的演示稿在這裡 http://www.slideshare.net/AmazonWebServices/aws-reinvent-2016-serverless-architectural-patterns-and-best-practices-arc402。

有興趣的同學也可以參考一下本人在 AWS Summit 2016 Beijing 上關於 AWS Lambda 的主題演講,PPT在這裡 http://www.slideshare.net/idanielglh/aws-lambdastrikingly。


最近寫了一個Demo用來處理簡單的地理空間數據(基於OGC Simple Features標準,目前僅支持GeoJSON格式和幾種地理處理方法)。

  • Demo地址: Serverless GIS
  • 測試數據下載:crabcanon/serverless-gis

這是對AWS無伺服器構架的一個實踐:

  • 資料庫 - DynamoDB
  • 文件存儲 - S3
  • 身份驗證 - Cognito
  • 核心計算 - Lambda(包括資料庫CRUD,文件池CRUD,GIS地理服務等)
  • 服務發布 - API Gateway
  • 域名管理 - Route 53
  • 網站託管 - 代碼包儲存在S3,用CloudFront加速和保護(CDN, HTTPS, HTTP/2等),SSL來自Certificate Manager。

總結了一些使用感受如下:

  • 無伺服器構架很適合某些用戶界面驅動(UI-driven)或者事件驅動(Event-driven或Message-driven)的應用。至於哪些以及如何決策,我覺得專門寫一篇文章討論都沒問題。不過如果你要開發類似應用,無伺服器構架是一個選項。上面demo就是本身需求與構架特色非常契合的例子。
  • 在FaaS(Function as a Service)以前,無伺服器構架已經存在很久了,那些第三方BaaS(Backend as a Service),比如Auth0、Firebase就是基於Serverless, 只是FaaS提供了一個方式讓你可以更深入的操控後端代碼。並且每個FaaS服務會被單獨部署在一個無狀態容器中(容器間沒有關聯,服務間沒有依賴)被事件激活,一旦結束,當前實例就會關閉。adrian cockcroft 有一個很形象的描述:如果你的PaaS可以在20ms內激活一個實例,並且運行半秒後關閉,就可以稱為serverless。這些特性能做什麼就給你很大想像空間了。前面提到它很適合事件驅動的場景,原因就是事物的天然屬性,事情不會旅行,只會發生,一件事又往往觸發許多別的事,之後便產生了結果,結果一旦出現,事件就成歷史,無需再監控和操作。由此可以看到用FaaS處理非同步事件是非常恰當的(但注意,不是所有事件都適用,比如需要龐大計算資源和長時間等待的複雜任務就不合適。目前對雲端空間大數據流的處理依舊建議採用傳統方式,比如Apache Spark,Apache Kafka和諸如PostGIS的空間資料庫結合的方案)。
  • 和傳統的容器相比,無伺服器FaaS最大特色是無需維護後端構架,並且自動縮放,按需分配。舉個例子,傳統容器就像能裝10公斤米的袋子,假設現在有52公斤米要裝,你得買6個袋子,雖然浪費了8公斤的空間,也可以接受。但無伺服器構架可以形容為米粒級別的袋子,52公斤有多少顆米,就給你多少袋子,幾乎不浪費一點資源。這對軟體開發商很有吸引,不僅精確控制資源需求,而且一旦任務完成就關閉服務,不再產生多餘花銷。從某種程度看,是達成用戶和開發商的雙贏。對於容器,目前還沒有這種級別的解決辦法,當然如Kubernetes提出的Horizontal Pod Autoscaling是發展趨勢。關於其他優勢,就不討論了,可以去看看別人的討論(JustServerless/awesome-serverless,anaibol/awesome-serverless)。
  • 無伺服器FaaS構架的缺點和它的優點一樣突出,比如(1)第三方廠商的系統無法控制,對方收費策略變更,進行無法預測的構架升級之類也不無可能(真實案例,有個大公司A在沒提前通報下游公司B的情況下,直接砍掉某個企業級產品,到全面停產的前一天才通知B,導致B權衡之下在公司內部停用所有A的企業級產品,轉投另一家供應商C),而且由於供應商要考量所有用戶的需求,就不可能給你最大的靈活度。(2)FaaS服務與供應商深度耦合。代碼如果想遷移到不同的無伺服器FaaS廠商,需要大量的改動重構。(3)安全性受到威脅而且很難優化伺服器,不可能像私有雲那樣實施全面的安全策略和優化措施。(4)目前執行的函數數量受到限制(不超過1000個),每個函數的運行時間受到限制(不高於5分鐘),函數的啟動會延遲(比如遇到用JVM實現的實例)。(5)雖然寫單元測試很簡單因為本身就是函數介面,但基於第三方平台寫集成測試很難,比如難道我所有集成測試都是基於第三方服務(如資料庫)?這會導致如場景無法控制,費用增高,沒法在本地離線測試系統等問題。(6)由於很難調用和集成其他私有資源或服務,包括前面提到的安全性和系統優化的靈活度,導致面向企業的產品很大程度不會選擇這種構架。


用 Amazon Lambda 可搭建一套無 EC2 的 Web / App 架構(無伺服器架構):

  • 核心計算:Amazon Lambda(編程模型 node.js、java、python)

  • ?資料庫存儲:Amazon DynamoDB
  • ?域名管理:Amazon Route 53

  • 前端 Web 資源存儲:Amazon S3

  • ?前後端 REST:Amazon API Gateway

  • ?網路加速:
    Amazon CloudFront - CDN
  • 身份驗證:Amazon IAM、Amazon Cognito

特點:

  • Amazon PAAS, 「event-driven」
  • 所有模塊均為分散式架構,按使用量 容量收費
  • 開發不產生過多的運維煩惱

  • 估計國內使用不便,開發方法、性能、穩定性需要評估
  • 測試與調試困難

腳手架:

  • Serverless · GitHub


用Lambda去動態添加EC2 instance, ECS Service/Task 尤其方便


關於實現原理可參考 AWS Lambda本身的架構和內部實現是怎樣的? - tobe 的回答


首先,你在國內的話要能翻牆,否則aws的控制後台都登錄不上。

lambda作為後端api服務的話,一般是lambda+dynamoDB+API Gateway,要配合API Gateway使用,配置起來稍微有點麻煩,而且這個貌似沒有和lambda、dynamoDB一樣的免費的額度,找個官方教程做一次就知道了。

另外用途主要是處理s3 的圖片、視頻等文件,處理DynamoDB數據流。處理一些aws自身服務還蠻方便。

個人覺得,理念技術都很先進,推崇的是微服務。國內的用戶,也就玩玩,真正生產環境肯定不行。


其實就是多了個觸發器。


大家還可以嘗試 Step function


開發 調試 方式過慢

寫個100行以內的nodejs 還好


部署單個服務確實方便了。

但是服務力度變到函數級別。如果要部署多個服務,服務之間的相互調用是不是很麻煩?

現在的微服務架構是container 級別的。lambda把這個粒度做到function級別了


推薦閱讀:

有哪些方式可以實現跨域?
为什么form表单提交没有跨域问题,但ajax提交有跨域问题?
用於驗證的 Passport.js 與 JsonWebToken 是什麼關係?
「遵循XXX開源協議」這句話規定了什麼,我要把某個js工具用在項目中,我具體要做哪些事情才算遵循協議?
什麼是JS跨域訪問?

TAG:物聯網 | JavaScript | 伺服器 | AmazonWebServicesAWS | Nodejs |